diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/binary-writer.cc | 109 | ||||
-rw-r--r-- | src/binary-writer.h | 27 | ||||
-rw-r--r-- | src/common.h | 8 | ||||
-rw-r--r-- | src/interpreter.cc | 8 | ||||
-rw-r--r-- | src/leb128.cc | 127 | ||||
-rw-r--r-- | src/leb128.h | 61 | ||||
-rw-r--r-- | src/tools/wasm-link.cc | 12 |
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; |