summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/binary-writer.cc16
-rw-r--r--src/leb128.cc14
-rw-r--r--src/leb128.h1
-rw-r--r--src/type.h2
-rw-r--r--test/roundtrip/multi-value-block-type.txt149
-rwxr-xr-xtest/run-roundtrip.py2
6 files changed, 182 insertions, 2 deletions
diff --git a/src/binary-writer.cc b/src/binary-writer.cc
index 5d75fca4..61b61b3b 100644
--- a/src/binary-writer.cc
+++ b/src/binary-writer.cc
@@ -134,6 +134,9 @@ class BinaryWriter {
void WriteU32Leb128WithReloc(Index index,
const char* desc,
RelocType reloc_type);
+ void WriteS32Leb128WithReloc(int32_t value,
+ const char* desc,
+ RelocType reloc_type);
template <typename T>
void WriteLoadStoreExpr(const Func* func, const Expr* expr, const char* desc);
void WriteExpr(const Func* func, const Expr* expr);
@@ -245,7 +248,7 @@ void BinaryWriter::WriteBlockDecl(const BlockDeclaration& decl) {
Index index = decl.has_func_type ? module_->GetFuncTypeIndex(decl.type_var)
: module_->GetFuncTypeIndex(decl.sig);
assert(index != kInvalidIndex);
- WriteU32Leb128WithReloc(index, "block type function index", RelocType::TypeIndexLEB);
+ WriteS32Leb128WithReloc(index, "block type function index", RelocType::TypeIndexLEB);
}
void BinaryWriter::WriteSectionHeader(const char* desc,
@@ -368,6 +371,17 @@ void BinaryWriter::WriteU32Leb128WithReloc(Index index,
}
}
+void BinaryWriter::WriteS32Leb128WithReloc(int32_t value,
+ const char* desc,
+ RelocType reloc_type) {
+ if (options_.relocatable) {
+ AddReloc(reloc_type, value);
+ WriteFixedS32Leb128(stream_, value, desc);
+ } else {
+ WriteS32Leb128(stream_, value, desc);
+ }
+}
+
Index BinaryWriter::GetLocalIndex(const Func* func, const Var& var) {
// func can be nullptr when using local.get/local.set/local.tee in an
// init_expr.
diff --git a/src/leb128.cc b/src/leb128.cc
index c3decac5..044aaf02 100644
--- a/src/leb128.cc
+++ b/src/leb128.cc
@@ -138,6 +138,20 @@ void WriteS64Leb128(Stream* stream, uint64_t value, const char* desc) {
WriteS64Leb128(stream, Bitcast<int64_t>(value), desc);
}
+void WriteFixedS32Leb128(Stream* stream, uint32_t value, const char* desc) {
+ uint8_t data[MAX_U32_LEB128_BYTES];
+ data[0] = (value & 0x7f) | 0x80;
+ data[1] = ((value >> 7) & 0x7f) | 0x80;
+ data[2] = ((value >> 14) & 0x7f) | 0x80;
+ data[3] = ((value >> 21) & 0x7f) | 0x80;
+ // The last byte needs to be sign-extended.
+ data[4] = ((value >> 28) & 0x0f);
+ if (static_cast<int32_t>(value) < 0) {
+ data[4] |= 0x70;
+ }
+ stream->WriteData(data, MAX_U32_LEB128_BYTES, desc);
+}
+
#undef LEB128_LOOP_UNTIL
#define BYTE_AT(type, i, shift) ((static_cast<type>(p[i]) & 0x7f) << (shift))
diff --git a/src/leb128.h b/src/leb128.h
index 4ec74774..5bf4e463 100644
--- a/src/leb128.h
+++ b/src/leb128.h
@@ -31,6 +31,7 @@ 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 WriteFixedS32Leb128(Stream* stream, uint32_t value, const char* desc);
void WriteFixedU32Leb128(Stream* stream, uint32_t value, const char* desc);
Offset WriteU32Leb128At(Stream* stream,
diff --git a/src/type.h b/src/type.h
index aaa8aba0..c44b54f1 100644
--- a/src/type.h
+++ b/src/type.h
@@ -33,7 +33,7 @@ using TypeVector = std::vector<Type>;
class Type {
public:
// Matches binary format, do not change.
- enum Enum {
+ enum Enum : int32_t {
I32 = -0x01, // 0x7f
I64 = -0x02, // 0x7e
F32 = -0x03, // 0x7d
diff --git a/test/roundtrip/multi-value-block-type.txt b/test/roundtrip/multi-value-block-type.txt
new file mode 100644
index 00000000..385a24c5
--- /dev/null
+++ b/test/roundtrip/multi-value-block-type.txt
@@ -0,0 +1,149 @@
+;;; TOOL: run-roundtrip
+;;; ARGS: --stdout --reloc
+(module
+ ;; 64 random types to force the block type below to get encoded as sleb
+ (type (func (param f32 f32 f32 f32 f32 f32)))
+ (type (func (param i32 f32 f32 f32 f32 f32)))
+ (type (func (param f32 i32 f32 f32 f32 f32)))
+ (type (func (param i32 i32 f32 f32 f32 f32)))
+ (type (func (param f32 f32 i32 f32 f32 f32)))
+ (type (func (param i32 f32 i32 f32 f32 f32)))
+ (type (func (param f32 i32 i32 f32 f32 f32)))
+ (type (func (param i32 i32 i32 f32 f32 f32)))
+ (type (func (param f32 f32 f32 i32 f32 f32)))
+ (type (func (param i32 f32 f32 i32 f32 f32)))
+ (type (func (param f32 i32 f32 i32 f32 f32)))
+ (type (func (param i32 i32 f32 i32 f32 f32)))
+ (type (func (param f32 f32 i32 i32 f32 f32)))
+ (type (func (param i32 f32 i32 i32 f32 f32)))
+ (type (func (param f32 i32 i32 i32 f32 f32)))
+ (type (func (param i32 i32 i32 i32 f32 f32)))
+ (type (func (param f32 f32 f32 f32 i32 f32)))
+ (type (func (param i32 f32 f32 f32 i32 f32)))
+ (type (func (param f32 i32 f32 f32 i32 f32)))
+ (type (func (param i32 i32 f32 f32 i32 f32)))
+ (type (func (param f32 f32 i32 f32 i32 f32)))
+ (type (func (param i32 f32 i32 f32 i32 f32)))
+ (type (func (param f32 i32 i32 f32 i32 f32)))
+ (type (func (param i32 i32 i32 f32 i32 f32)))
+ (type (func (param f32 f32 f32 i32 i32 f32)))
+ (type (func (param i32 f32 f32 i32 i32 f32)))
+ (type (func (param f32 i32 f32 i32 i32 f32)))
+ (type (func (param i32 i32 f32 i32 i32 f32)))
+ (type (func (param f32 f32 i32 i32 i32 f32)))
+ (type (func (param i32 f32 i32 i32 i32 f32)))
+ (type (func (param f32 i32 i32 i32 i32 f32)))
+ (type (func (param i32 i32 i32 i32 i32 f32)))
+ (type (func (param f32 f32 f32 f32 f32 i32)))
+ (type (func (param i32 f32 f32 f32 f32 i32)))
+ (type (func (param f32 i32 f32 f32 f32 i32)))
+ (type (func (param i32 i32 f32 f32 f32 i32)))
+ (type (func (param f32 f32 i32 f32 f32 i32)))
+ (type (func (param i32 f32 i32 f32 f32 i32)))
+ (type (func (param f32 i32 i32 f32 f32 i32)))
+ (type (func (param i32 i32 i32 f32 f32 i32)))
+ (type (func (param f32 f32 f32 i32 f32 i32)))
+ (type (func (param i32 f32 f32 i32 f32 i32)))
+ (type (func (param f32 i32 f32 i32 f32 i32)))
+ (type (func (param i32 i32 f32 i32 f32 i32)))
+ (type (func (param f32 f32 i32 i32 f32 i32)))
+ (type (func (param i32 f32 i32 i32 f32 i32)))
+ (type (func (param f32 i32 i32 i32 f32 i32)))
+ (type (func (param i32 i32 i32 i32 f32 i32)))
+ (type (func (param f32 f32 f32 f32 i32 i32)))
+ (type (func (param i32 f32 f32 f32 i32 i32)))
+ (type (func (param f32 i32 f32 f32 i32 i32)))
+ (type (func (param i32 i32 f32 f32 i32 i32)))
+ (type (func (param f32 f32 i32 f32 i32 i32)))
+ (type (func (param i32 f32 i32 f32 i32 i32)))
+ (type (func (param f32 i32 i32 f32 i32 i32)))
+ (type (func (param i32 i32 i32 f32 i32 i32)))
+ (type (func (param f32 f32 f32 i32 i32 i32)))
+ (type (func (param i32 f32 f32 i32 i32 i32)))
+ (type (func (param f32 i32 f32 i32 i32 i32)))
+ (type (func (param i32 i32 f32 i32 i32 i32)))
+ (type (func (param f32 f32 i32 i32 i32 i32)))
+ (type (func (param i32 f32 i32 i32 i32 i32)))
+ (type (func (param f32 i32 i32 i32 i32 i32)))
+ (type (func (param i32 i32 i32 i32 i32 i32)))
+
+ (func (result i32)
+ (i32.add
+ (block (result i32 i32)
+ (i32.const 32)
+ (i32.const 10)))))
+(;; STDOUT ;;;
+(module
+ (type (;0;) (func (param f32 f32 f32 f32 f32 f32)))
+ (type (;1;) (func (param i32 f32 f32 f32 f32 f32)))
+ (type (;2;) (func (param f32 i32 f32 f32 f32 f32)))
+ (type (;3;) (func (param i32 i32 f32 f32 f32 f32)))
+ (type (;4;) (func (param f32 f32 i32 f32 f32 f32)))
+ (type (;5;) (func (param i32 f32 i32 f32 f32 f32)))
+ (type (;6;) (func (param f32 i32 i32 f32 f32 f32)))
+ (type (;7;) (func (param i32 i32 i32 f32 f32 f32)))
+ (type (;8;) (func (param f32 f32 f32 i32 f32 f32)))
+ (type (;9;) (func (param i32 f32 f32 i32 f32 f32)))
+ (type (;10;) (func (param f32 i32 f32 i32 f32 f32)))
+ (type (;11;) (func (param i32 i32 f32 i32 f32 f32)))
+ (type (;12;) (func (param f32 f32 i32 i32 f32 f32)))
+ (type (;13;) (func (param i32 f32 i32 i32 f32 f32)))
+ (type (;14;) (func (param f32 i32 i32 i32 f32 f32)))
+ (type (;15;) (func (param i32 i32 i32 i32 f32 f32)))
+ (type (;16;) (func (param f32 f32 f32 f32 i32 f32)))
+ (type (;17;) (func (param i32 f32 f32 f32 i32 f32)))
+ (type (;18;) (func (param f32 i32 f32 f32 i32 f32)))
+ (type (;19;) (func (param i32 i32 f32 f32 i32 f32)))
+ (type (;20;) (func (param f32 f32 i32 f32 i32 f32)))
+ (type (;21;) (func (param i32 f32 i32 f32 i32 f32)))
+ (type (;22;) (func (param f32 i32 i32 f32 i32 f32)))
+ (type (;23;) (func (param i32 i32 i32 f32 i32 f32)))
+ (type (;24;) (func (param f32 f32 f32 i32 i32 f32)))
+ (type (;25;) (func (param i32 f32 f32 i32 i32 f32)))
+ (type (;26;) (func (param f32 i32 f32 i32 i32 f32)))
+ (type (;27;) (func (param i32 i32 f32 i32 i32 f32)))
+ (type (;28;) (func (param f32 f32 i32 i32 i32 f32)))
+ (type (;29;) (func (param i32 f32 i32 i32 i32 f32)))
+ (type (;30;) (func (param f32 i32 i32 i32 i32 f32)))
+ (type (;31;) (func (param i32 i32 i32 i32 i32 f32)))
+ (type (;32;) (func (param f32 f32 f32 f32 f32 i32)))
+ (type (;33;) (func (param i32 f32 f32 f32 f32 i32)))
+ (type (;34;) (func (param f32 i32 f32 f32 f32 i32)))
+ (type (;35;) (func (param i32 i32 f32 f32 f32 i32)))
+ (type (;36;) (func (param f32 f32 i32 f32 f32 i32)))
+ (type (;37;) (func (param i32 f32 i32 f32 f32 i32)))
+ (type (;38;) (func (param f32 i32 i32 f32 f32 i32)))
+ (type (;39;) (func (param i32 i32 i32 f32 f32 i32)))
+ (type (;40;) (func (param f32 f32 f32 i32 f32 i32)))
+ (type (;41;) (func (param i32 f32 f32 i32 f32 i32)))
+ (type (;42;) (func (param f32 i32 f32 i32 f32 i32)))
+ (type (;43;) (func (param i32 i32 f32 i32 f32 i32)))
+ (type (;44;) (func (param f32 f32 i32 i32 f32 i32)))
+ (type (;45;) (func (param i32 f32 i32 i32 f32 i32)))
+ (type (;46;) (func (param f32 i32 i32 i32 f32 i32)))
+ (type (;47;) (func (param i32 i32 i32 i32 f32 i32)))
+ (type (;48;) (func (param f32 f32 f32 f32 i32 i32)))
+ (type (;49;) (func (param i32 f32 f32 f32 i32 i32)))
+ (type (;50;) (func (param f32 i32 f32 f32 i32 i32)))
+ (type (;51;) (func (param i32 i32 f32 f32 i32 i32)))
+ (type (;52;) (func (param f32 f32 i32 f32 i32 i32)))
+ (type (;53;) (func (param i32 f32 i32 f32 i32 i32)))
+ (type (;54;) (func (param f32 i32 i32 f32 i32 i32)))
+ (type (;55;) (func (param i32 i32 i32 f32 i32 i32)))
+ (type (;56;) (func (param f32 f32 f32 i32 i32 i32)))
+ (type (;57;) (func (param i32 f32 f32 i32 i32 i32)))
+ (type (;58;) (func (param f32 i32 f32 i32 i32 i32)))
+ (type (;59;) (func (param i32 i32 f32 i32 i32 i32)))
+ (type (;60;) (func (param f32 f32 i32 i32 i32 i32)))
+ (type (;61;) (func (param i32 f32 i32 i32 i32 i32)))
+ (type (;62;) (func (param f32 i32 i32 i32 i32 i32)))
+ (type (;63;) (func (param i32 i32 i32 i32 i32 i32)))
+ (type (;64;) (func (result i32)))
+ (type (;65;) (func (result i32 i32)))
+ (func (;0;) (type 64) (result i32)
+ block (result i32 i32) ;; label = @1
+ i32.const 32
+ i32.const 10
+ end
+ i32.add))
+;;; STDOUT ;;)
diff --git a/test/run-roundtrip.py b/test/run-roundtrip.py
index 46e96430..8aef6f55 100755
--- a/test/run-roundtrip.py
+++ b/test/run-roundtrip.py
@@ -126,6 +126,7 @@ def main(args):
parser.add_argument('--enable-memory64', action='store_true')
parser.add_argument('--inline-exports', action='store_true')
parser.add_argument('--inline-imports', action='store_true')
+ parser.add_argument('--reloc', action='store_true')
parser.add_argument('file', help='test file.')
options = parser.parse_args(args)
@@ -145,6 +146,7 @@ def main(args):
'--enable-tail-call': options.enable_tail_call,
'--enable-reference-types': options.enable_reference_types,
'--enable-memory64': options.enable_memory64,
+ '--reloc': options.reloc,
'--no-check': options.no_check,
})