summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/binary-writer.cc109
-rw-r--r--src/binary-writer.h27
-rw-r--r--src/common.h8
-rw-r--r--src/interpreter.cc8
-rw-r--r--src/leb128.cc127
-rw-r--r--src/leb128.h61
-rw-r--r--src/tools/wasm-link.cc12
7 files changed, 208 insertions, 144 deletions
diff --git a/src/binary-writer.cc b/src/binary-writer.cc
index 8627e377..7eec73b6 100644
--- a/src/binary-writer.cc
+++ b/src/binary-writer.cc
@@ -28,112 +28,16 @@
#include "src/binary.h"
#include "src/cast.h"
#include "src/ir.h"
+#include "src/leb128.h"
#include "src/stream.h"
#include "src/string-view.h"
#include "src/writer.h"
#define PRINT_HEADER_NO_INDEX -1
#define MAX_U32_LEB128_BYTES 5
-#define MAX_U64_LEB128_BYTES 10
namespace wabt {
-// TODO(binji): move the LEB128 functions somewhere else.
-
-Offset U32Leb128Length(uint32_t value) {
- uint32_t size = 0;
- do {
- value >>= 7;
- size++;
- } while (value != 0);
- return size;
-}
-
-#define LEB128_LOOP_UNTIL(end_cond) \
- do { \
- uint8_t byte = value & 0x7f; \
- value >>= 7; \
- if (end_cond) { \
- data[length++] = byte; \
- break; \
- } else { \
- data[length++] = byte | 0x80; \
- } \
- } while (1)
-
-Offset WriteFixedU32Leb128At(Stream* stream,
- Offset offset,
- uint32_t value,
- const char* desc) {
- uint8_t data[MAX_U32_LEB128_BYTES];
- Offset length =
- WriteFixedU32Leb128Raw(data, data + MAX_U32_LEB128_BYTES, value);
- stream->WriteDataAt(offset, data, length, desc);
- return length;
-}
-
-void WriteU32Leb128(Stream* stream, uint32_t value, const char* desc) {
- uint8_t data[MAX_U32_LEB128_BYTES];
- Offset length = 0;
- LEB128_LOOP_UNTIL(value == 0);
- stream->WriteData(data, length, desc);
-}
-
-void WriteFixedU32Leb128(Stream* stream, uint32_t value, const char* desc) {
- uint8_t data[MAX_U32_LEB128_BYTES];
- Offset length =
- WriteFixedU32Leb128Raw(data, data + MAX_U32_LEB128_BYTES, value);
- stream->WriteData(data, length, desc);
-}
-
-/* returns the length of the leb128 */
-Offset WriteU32Leb128At(Stream* stream,
- Offset offset,
- uint32_t value,
- const char* desc) {
- uint8_t data[MAX_U32_LEB128_BYTES];
- Offset length = 0;
- LEB128_LOOP_UNTIL(value == 0);
- stream->WriteDataAt(offset, data, length, desc);
- return length;
-}
-
-Offset WriteFixedU32Leb128Raw(uint8_t* data, uint8_t* end, uint32_t value) {
- if (end - data < MAX_U32_LEB128_BYTES)
- return 0;
- data[0] = (value & 0x7f) | 0x80;
- data[1] = ((value >> 7) & 0x7f) | 0x80;
- data[2] = ((value >> 14) & 0x7f) | 0x80;
- data[3] = ((value >> 21) & 0x7f) | 0x80;
- data[4] = ((value >> 28) & 0x0f);
- return MAX_U32_LEB128_BYTES;
-}
-
-void WriteI32Leb128(Stream* stream, int32_t value, const char* desc) {
- uint8_t data[MAX_U32_LEB128_BYTES];
- Offset length = 0;
- if (value < 0)
- LEB128_LOOP_UNTIL(value == -1 && (byte & 0x40));
- else
- LEB128_LOOP_UNTIL(value == 0 && !(byte & 0x40));
-
- stream->WriteData(data, length, desc);
-}
-
-static void WriteI64Leb128(Stream* stream, int64_t value, const char* desc) {
- uint8_t data[MAX_U64_LEB128_BYTES];
- Offset length = 0;
- if (value < 0)
- LEB128_LOOP_UNTIL(value == -1 && (byte & 0x40));
- else
- LEB128_LOOP_UNTIL(value == 0 && !(byte & 0x40));
-
- stream->WriteData(data, length, desc);
-}
-
-
-#undef LEB128_LOOP_UNTIL
-
void WriteStr(Stream* stream,
string_view s,
const char* desc,
@@ -152,7 +56,7 @@ void WriteOpcode(Stream* stream, Opcode opcode) {
}
void WriteType(Stream* stream, Type type) {
- WriteI32Leb128Enum(stream, type, GetTypeName(type));
+ WriteS32Leb128(stream, type, GetTypeName(type));
}
void WriteLimits(Stream* stream, const Limits* limits) {
@@ -478,12 +382,12 @@ void BinaryWriter::WriteExpr(const Module* module,
switch (const_.type) {
case Type::I32: {
WriteOpcode(&stream_, Opcode::I32Const);
- WriteI32Leb128(&stream_, const_.u32, "i32 literal");
+ WriteS32Leb128(&stream_, const_.u32, "i32 literal");
break;
}
case Type::I64:
WriteOpcode(&stream_, Opcode::I64Const);
- WriteI64Leb128(&stream_, const_.u64, "i64 literal");
+ WriteS64Leb128(&stream_, const_.u64, "i64 literal");
break;
case Type::F32:
WriteOpcode(&stream_, Opcode::F32Const);
@@ -708,13 +612,12 @@ void BinaryWriter::WriteRelocSection(const RelocSection* reloc_section) {
wabt_snprintf(section_name, sizeof(section_name), "%s.%s",
WABT_BINARY_SECTION_RELOC, reloc_section->name);
BeginCustomSection(section_name, LEB_SECTION_SIZE_GUESS);
- WriteU32Leb128Enum(&stream_, reloc_section->section_code,
- "reloc section type");
+ WriteU32Leb128(&stream_, reloc_section->section_code, "reloc section type");
const std::vector<Reloc>& relocs = reloc_section->relocations;
WriteU32Leb128(&stream_, relocs.size(), "num relocs");
for (const Reloc& reloc : relocs) {
- WriteU32Leb128Enum(&stream_, reloc.type, "reloc type");
+ WriteU32Leb128(&stream_, reloc.type, "reloc type");
WriteU32Leb128(&stream_, reloc.offset, "reloc offset");
WriteU32Leb128(&stream_, reloc.index, "reloc index");
switch (reloc.type) {
diff --git a/src/binary-writer.h b/src/binary-writer.h
index 4e90e89b..1dff83fa 100644
--- a/src/binary-writer.h
+++ b/src/binary-writer.h
@@ -36,22 +36,6 @@ struct WriteBinaryOptions {
Result WriteBinaryModule(Writer*, const Module*, const WriteBinaryOptions*);
-/* returns the length of the leb128 */
-Offset U32Leb128Length(uint32_t value);
-
-void WriteU32Leb128(Stream* stream, uint32_t value, const char* desc);
-
-void WriteI32Leb128(Stream* stream, int32_t value, const char* desc);
-
-void WriteFixedU32Leb128(Stream* stream, uint32_t value, const char* desc);
-
-Offset WriteFixedU32Leb128At(Stream* stream,
- Offset offset,
- uint32_t value,
- const char* desc);
-
-Offset WriteFixedU32Leb128Raw(uint8_t* data, uint8_t* end, uint32_t value);
-
void WriteType(Stream* stream, Type type);
void WriteStr(Stream* stream,
@@ -63,17 +47,6 @@ void WriteOpcode(Stream* stream, Opcode opcode);
void WriteLimits(Stream* stream, const Limits* limits);
-/* Convenience functions for writing enums as LEB128s. */
-template <typename T>
-void WriteU32Leb128Enum(Stream* stream, T value, const char* desc) {
- WriteU32Leb128(stream, static_cast<uint32_t>(value), desc);
-}
-
-template <typename T>
-void WriteI32Leb128Enum(Stream* stream, T value, const char* desc) {
- WriteI32Leb128(stream, static_cast<int32_t>(value), desc);
-}
-
} // namespace wabt
#endif /* WABT_BINARY_WRITER_H_ */
diff --git a/src/common.h b/src/common.h
index 1f8ad771..d489d05d 100644
--- a/src/common.h
+++ b/src/common.h
@@ -100,6 +100,14 @@ static const Address kInvalidAddress = ~0;
static const Index kInvalidIndex = ~0;
static const Offset kInvalidOffset = ~0;
+template <typename Dst, typename Src>
+Dst Bitcast(Src value) {
+ static_assert(sizeof(Src) == sizeof(Dst), "Bitcast sizes must match.");
+ Dst result;
+ memcpy(&result, &value, sizeof(result));
+ return result;
+}
+
template<typename T>
void ZeroMemory(T& v) {
WABT_STATIC_ASSERT(std::is_pod<T>::value);
diff --git a/src/interpreter.cc b/src/interpreter.cc
index 4a8bb3c4..3ea17a71 100644
--- a/src/interpreter.cc
+++ b/src/interpreter.cc
@@ -214,14 +214,6 @@ void Thread::CopyResults(const FuncSignature* sig,
out_results->emplace_back(sig->result_types[i], value_stack_[i]);
}
-template <typename Dst, typename Src>
-Dst Bitcast(Src value) {
- static_assert(sizeof(Src) == sizeof(Dst), "Bitcast sizes must match.");
- Dst result;
- memcpy(&result, &value, sizeof(result));
- return result;
-}
-
uint32_t ToRep(bool x) { return x ? 1 : 0; }
uint32_t ToRep(uint32_t x) { return x; }
uint64_t ToRep(uint64_t x) { return x; }
diff --git a/src/leb128.cc b/src/leb128.cc
new file mode 100644
index 00000000..518ec3c1
--- /dev/null
+++ b/src/leb128.cc
@@ -0,0 +1,127 @@
+/*
+ * Copyright 2017 WebAssembly Community Group participants
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "src/leb128.h"
+
+#include "src/stream.h"
+
+#define MAX_U32_LEB128_BYTES 5
+#define MAX_U64_LEB128_BYTES 10
+
+namespace wabt {
+
+Offset U32Leb128Length(uint32_t value) {
+ uint32_t size = 0;
+ do {
+ value >>= 7;
+ size++;
+ } while (value != 0);
+ return size;
+}
+
+#define LEB128_LOOP_UNTIL(end_cond) \
+ do { \
+ uint8_t byte = value & 0x7f; \
+ value >>= 7; \
+ if (end_cond) { \
+ data[length++] = byte; \
+ break; \
+ } else { \
+ data[length++] = byte | 0x80; \
+ } \
+ } while (1)
+
+Offset WriteFixedU32Leb128At(Stream* stream,
+ Offset offset,
+ uint32_t value,
+ const char* desc) {
+ uint8_t data[MAX_U32_LEB128_BYTES];
+ Offset length =
+ WriteFixedU32Leb128Raw(data, data + MAX_U32_LEB128_BYTES, value);
+ stream->WriteDataAt(offset, data, length, desc);
+ return length;
+}
+
+void WriteU32Leb128(Stream* stream, uint32_t value, const char* desc) {
+ uint8_t data[MAX_U32_LEB128_BYTES];
+ Offset length = 0;
+ LEB128_LOOP_UNTIL(value == 0);
+ stream->WriteData(data, length, desc);
+}
+
+void WriteFixedU32Leb128(Stream* stream, uint32_t value, const char* desc) {
+ uint8_t data[MAX_U32_LEB128_BYTES];
+ Offset length =
+ WriteFixedU32Leb128Raw(data, data + MAX_U32_LEB128_BYTES, value);
+ stream->WriteData(data, length, desc);
+}
+
+// returns the length of the leb128.
+Offset WriteU32Leb128At(Stream* stream,
+ Offset offset,
+ uint32_t value,
+ const char* desc) {
+ uint8_t data[MAX_U32_LEB128_BYTES];
+ Offset length = 0;
+ LEB128_LOOP_UNTIL(value == 0);
+ stream->WriteDataAt(offset, data, length, desc);
+ return length;
+}
+
+Offset WriteFixedU32Leb128Raw(uint8_t* data, uint8_t* end, uint32_t value) {
+ if (end - data < MAX_U32_LEB128_BYTES)
+ return 0;
+ data[0] = (value & 0x7f) | 0x80;
+ data[1] = ((value >> 7) & 0x7f) | 0x80;
+ data[2] = ((value >> 14) & 0x7f) | 0x80;
+ data[3] = ((value >> 21) & 0x7f) | 0x80;
+ data[4] = ((value >> 28) & 0x0f);
+ return MAX_U32_LEB128_BYTES;
+}
+
+static void WriteS32Leb128(Stream* stream, int32_t value, const char* desc) {
+ uint8_t data[MAX_U32_LEB128_BYTES];
+ Offset length = 0;
+ if (value < 0)
+ LEB128_LOOP_UNTIL(value == -1 && (byte & 0x40));
+ else
+ LEB128_LOOP_UNTIL(value == 0 && !(byte & 0x40));
+
+ stream->WriteData(data, length, desc);
+}
+
+static void WriteS64Leb128(Stream* stream, int64_t value, const char* desc) {
+ uint8_t data[MAX_U64_LEB128_BYTES];
+ Offset length = 0;
+ if (value < 0)
+ LEB128_LOOP_UNTIL(value == -1 && (byte & 0x40));
+ else
+ LEB128_LOOP_UNTIL(value == 0 && !(byte & 0x40));
+
+ stream->WriteData(data, length, desc);
+}
+
+void WriteS32Leb128(Stream* stream, uint32_t value, const char* desc) {
+ WriteS32Leb128(stream, Bitcast<int32_t>(value), desc);
+}
+
+void WriteS64Leb128(Stream* stream, uint64_t value, const char* desc) {
+ WriteS64Leb128(stream, Bitcast<int64_t>(value), desc);
+}
+
+#undef LEB128_LOOP_UNTIL
+
+} // namespace wabt
diff --git a/src/leb128.h b/src/leb128.h
new file mode 100644
index 00000000..311c7dad
--- /dev/null
+++ b/src/leb128.h
@@ -0,0 +1,61 @@
+/*
+ * Copyright 2017 WebAssembly Community Group participants
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef WABT_LEB128_H_
+#define WABT_LEB128_H_
+
+#include <cstdint>
+
+#include "src/common.h"
+
+namespace wabt {
+
+class Stream;
+
+// Returns the length of the leb128.
+Offset U32Leb128Length(uint32_t value);
+
+void WriteU32Leb128(Stream* stream, uint32_t value, const char* desc);
+void WriteS32Leb128(Stream* stream, uint32_t value, const char* desc);
+void WriteS64Leb128(Stream* stream, uint64_t value, const char* desc);
+void WriteFixedU32Leb128(Stream* stream, uint32_t value, const char* desc);
+
+Offset WriteU32Leb128At(Stream* stream,
+ Offset offset,
+ uint32_t value,
+ const char* desc);
+
+Offset WriteFixedU32Leb128At(Stream* stream,
+ Offset offset,
+ uint32_t value,
+ const char* desc);
+
+Offset WriteFixedU32Leb128Raw(uint8_t* data, uint8_t* end, uint32_t value);
+
+// Convenience functions for writing enums as LEB128s.
+template <typename T>
+void WriteU32Leb128(Stream* stream, T value, const char* desc) {
+ WriteU32Leb128(stream, static_cast<uint32_t>(value), desc);
+}
+
+template <typename T>
+void WriteS32Leb128(Stream* stream, T value, const char* desc) {
+ WriteS32Leb128(stream, static_cast<uint32_t>(value), desc);
+}
+
+} // namespace wabt
+
+#endif // WABT_LEB128_H_
diff --git a/src/tools/wasm-link.cc b/src/tools/wasm-link.cc
index 6af713d1..5d6350c4 100644
--- a/src/tools/wasm-link.cc
+++ b/src/tools/wasm-link.cc
@@ -22,6 +22,7 @@
#include "src/binary-reader.h"
#include "src/binding-hash.h"
#include "src/binary-writer.h"
+#include "src/leb128.h"
#include "src/option-parser.h"
#include "src/stream.h"
#include "src/writer.h"
@@ -318,7 +319,7 @@ void Linker::WriteElemSection(const SectionPtrVector& sections) {
WriteU32Leb128(&stream_, 1, "segment count");
WriteU32Leb128(&stream_, 0, "table index");
WriteOpcode(&stream_, Opcode::I32Const);
- WriteI32Leb128(&stream_, 0, "elem init literal");
+ WriteS32Leb128(&stream_, 0U, "elem init literal");
WriteOpcode(&stream_, Opcode::End);
WriteU32Leb128(&stream_, total_elem_count, "num elements");
@@ -494,15 +495,14 @@ void Linker::WriteLinkingSection(uint32_t data_size, uint32_t data_alignment) {
WriteStr(&stream_, "linking", "linking section name");
{
- WriteU32Leb128Enum(&stream_, LinkingEntryType::DataSize, "subsection code");
+ WriteU32Leb128(&stream_, LinkingEntryType::DataSize, "subsection code");
Fixup fixup_subsection = WriteUnknownSize();
WriteU32Leb128(&stream_, data_size, "data size");
FixupSize(fixup_subsection);
}
{
- WriteU32Leb128Enum(&stream_, LinkingEntryType::DataAlignment,
- "subsection code");
+ WriteU32Leb128(&stream_, LinkingEntryType::DataAlignment, "subsection code");
Fixup fixup_subsection = WriteUnknownSize();
WriteU32Leb128(&stream_, data_alignment, "data alignment");
FixupSize(fixup_subsection);
@@ -528,12 +528,12 @@ void Linker::WriteRelocSection(BinarySection section_code,
stream_.WriteU8Enum(BinarySection::Custom, "section code");
Fixup fixup = WriteUnknownSize();
WriteStr(&stream_, section_name, "reloc section name");
- WriteU32Leb128Enum(&stream_, section_code, "reloc section");
+ WriteU32Leb128(&stream_, section_code, "reloc section");
WriteU32Leb128(&stream_, total_relocs, "num relocs");
for (Section* sec: sections) {
for (const Reloc& reloc: sec->relocations) {
- WriteU32Leb128Enum(&stream_, reloc.type, "reloc type");
+ WriteU32Leb128(&stream_, reloc.type, "reloc type");
Offset new_offset = reloc.offset + sec->output_payload_offset;
WriteU32Leb128(&stream_, new_offset, "reloc offset");
Index relocated_index = 0;