From 4674fa534d031aea142854e3fd7ca1c143af4682 Mon Sep 17 00:00:00 2001 From: Sam Clegg Date: Tue, 20 Jan 2026 18:08:46 -0800 Subject: [PATCH] Add Initial support for compact imports proposal. NFC. So far this is binary-only. We can add the text format support as a followup I think. https://github.com/WebAssembly/compact-import-section --- src/binaryen-c.cpp | 3 + src/binaryen-c.h | 1 + src/js/binaryen.js-post.js | 1 + src/tools/tool-options.h | 1 + src/wasm-binary.h | 8 + src/wasm-features.h | 7 +- src/wasm/wasm-binary.cpp | 64 ++++++- src/wasm/wasm.cpp | 1 + test/binaryen.js/kitchen-sink.js | 1 + test/binaryen.js/kitchen-sink.js.txt | 3 +- test/example/c-api-kitchen-sink.c | 2 + test/example/c-api-kitchen-sink.txt | 3 +- test/lit/help/wasm-as.test | 4 + test/lit/help/wasm-ctor-eval.test | 4 + test/lit/help/wasm-dis.test | 4 + test/lit/help/wasm-emscripten-finalize.test | 4 + test/lit/help/wasm-merge.test | 4 + test/lit/help/wasm-metadce.test | 4 + test/lit/help/wasm-opt.test | 4 + test/lit/help/wasm-reduce.test | 4 + test/lit/help/wasm-split.test | 4 + test/lit/help/wasm2js.test | 4 + ..._roundtrip_print-features_all-features.txt | 1 + .../binary-compact-imports.wast | 174 ++++++++++++++++++ test/unit/test_features.py | 1 + 25 files changed, 306 insertions(+), 5 deletions(-) create mode 100644 test/spec/compact-import-section/binary-compact-imports.wast diff --git a/src/binaryen-c.cpp b/src/binaryen-c.cpp index ed8ac938f43..038a049551a 100644 --- a/src/binaryen-c.cpp +++ b/src/binaryen-c.cpp @@ -511,6 +511,9 @@ BinaryenFeatures BinaryenFeatureCustomPageSizes(void) { BinaryenFeatures BinaryenFeatureWideArithmetic(void) { return static_cast(FeatureSet::WideArithmetic); } +BinaryenFeatures BinaryenFeatureCompactImports(void) { + return static_cast(FeatureSet::CompactImports); +} BinaryenFeatures BinaryenFeatureAll(void) { return static_cast(FeatureSet::All); } diff --git a/src/binaryen-c.h b/src/binaryen-c.h index cd2287b80dc..ded15aaf1d2 100644 --- a/src/binaryen-c.h +++ b/src/binaryen-c.h @@ -249,6 +249,7 @@ BINARYEN_API BinaryenFeatures BinaryenFeatureRelaxedAtomics(void); BINARYEN_API BinaryenFeatures BinaryenFeatureMultibyte(void); BINARYEN_API BinaryenFeatures BinaryenFeatureCustomPageSizes(void); BINARYEN_API BinaryenFeatures BinaryenFeatureWideArithmetic(void); +BINARYEN_API BinaryenFeatures BinaryenFeatureCompactImports(void); BINARYEN_API BinaryenFeatures BinaryenFeatureAll(void); // Modules diff --git a/src/js/binaryen.js-post.js b/src/js/binaryen.js-post.js index 67718aefd36..5a3c6e3f842 100644 --- a/src/js/binaryen.js-post.js +++ b/src/js/binaryen.js-post.js @@ -195,6 +195,7 @@ function initializeConstants() { 'RelaxedAtomics', 'CustomPageSizes', 'WideArithmetic', + 'CompactImports', 'All' ].forEach(name => { Module['Features'][name] = Module['_BinaryenFeature' + name](); diff --git a/src/tools/tool-options.h b/src/tools/tool-options.h index 1f3ec266bc7..2106fc66a49 100644 --- a/src/tools/tool-options.h +++ b/src/tools/tool-options.h @@ -113,6 +113,7 @@ struct ToolOptions : public Options { "acquire/release atomic memory operations") .addFeature(FeatureSet::CustomPageSizes, "custom page sizes") .addFeature(FeatureSet::WideArithmetic, "wide arithmetic") + .addFeature(FeatureSet::CompactImports, "compact import section") .add("--enable-typed-function-references", "", "Deprecated compatibility flag", diff --git a/src/wasm-binary.h b/src/wasm-binary.h index 51aa1fe352c..1dd4898a9ce 100644 --- a/src/wasm-binary.h +++ b/src/wasm-binary.h @@ -371,6 +371,10 @@ constexpr uint32_t HasMemoryIndexMask = 1 << 6; constexpr uint8_t HasTableInitializer = 0x40; constexpr uint8_t TableReservedByte = 0x00; +// TODO(sbc): Use upstream names for these schemes if/when they are decided. +constexpr uint8_t CompactImportsSharedModule = 0x7f; +constexpr uint8_t CompactImportsSharedAll = 0x7e; + enum EncodedType { // value types i32 = -0x1, // 0x7f @@ -475,6 +479,7 @@ extern const char* RelaxedAtomicsFeature; extern const char* MultibyteFeature; extern const char* CustomPageSizesFeature; extern const char* WideArithmeticFeature; +extern const char* CompactImportsFeature; enum Subsection { NameModule = 0, @@ -1693,6 +1698,9 @@ class WasmBinaryReader { std::unique_ptr readGlobalImport(Name module, Name base); std::unique_ptr readTagImport(Name module, Name base); + template + void readCompactImportsShared(Name module, ReadFunc readFunc); + // The signatures of each function, including imported functions, given in the // import and function sections. Store HeapTypes instead of Signatures because // reconstructing the HeapTypes from the Signatures is expensive. diff --git a/src/wasm-features.h b/src/wasm-features.h index 833281c0c11..2d64953631e 100644 --- a/src/wasm-features.h +++ b/src/wasm-features.h @@ -59,11 +59,12 @@ struct FeatureSet { CustomPageSizes = 1 << 23, Multibyte = 1 << 24, WideArithmetic = 1 << 25, + CompactImports = 1 << 26, MVP = None, // Keep in sync with llvm default features: // https://github.com/llvm/llvm-project/blob/c7576cb89d6c95f03968076e902d3adfd1996577/clang/lib/Basic/Targets/WebAssembly.cpp#L150-L153 Default = SignExt | MutableGlobals, - All = (1 << 26) - 1, + All = (1 << 27) - 1, }; static std::string toString(Feature f) { @@ -120,6 +121,8 @@ struct FeatureSet { return "multibyte"; case WideArithmetic: return "wide-arithmetic"; + case CompactImports: + return "compact-imports"; case MVP: case Default: case All: @@ -184,6 +187,7 @@ struct FeatureSet { bool hasCustomPageSizes() const { return (features & CustomPageSizes) != 0; } bool hasMultibyte() const { return (features & Multibyte) != 0; } bool hasWideArithmetic() const { return (features & WideArithmetic) != 0; } + bool hasCompactImports() const { return (features & CompactImports) != 0; } bool hasAll() const { return (features & All) != 0; } void set(FeatureSet f, bool v = true) { @@ -213,6 +217,7 @@ struct FeatureSet { void setRelaxedAtomics(bool v = true) { set(RelaxedAtomics, v); } void setMultibyte(bool v = true) { set(Multibyte, v); } void setWideArithmetic(bool v = true) { set(WideArithmetic, v); } + void setCompactImports(bool v = true) { set(CompactImports, v); } void setMVP() { features = MVP; } void setAll() { features = All; } diff --git a/src/wasm/wasm-binary.cpp b/src/wasm/wasm-binary.cpp index 91f8e9824dd..1e4e3f78b98 100644 --- a/src/wasm/wasm-binary.cpp +++ b/src/wasm/wasm-binary.cpp @@ -1489,6 +1489,8 @@ void WasmBinaryWriter::writeFeaturesSection() { return BinaryConsts::CustomSections::CustomPageSizesFeature; case FeatureSet::WideArithmetic: return BinaryConsts::CustomSections::WideArithmeticFeature; + case FeatureSet::CompactImports: + return BinaryConsts::CustomSections::CompactImportsFeature; case FeatureSet::None: case FeatureSet::Default: case FeatureSet::All: @@ -3156,6 +3158,18 @@ std::unique_ptr WasmBinaryReader::readTagImport(Name module, Name base) { return curr; } +template +void WasmBinaryReader::readCompactImportsShared(Name module, + ReadFunc readBaseDetails) { + std::unique_ptr baseDetails = readBaseDetails(Name()); + size_t numCompactImports = getU32LEB(); + while (numCompactImports--) { + auto details = std::make_unique(*baseDetails); + details->base = getInlineString(); + addImport(std::move(details)); + } +} + void WasmBinaryReader::readImport(Name module, Name base, uint32_t kind) { switch (kind & ~BinaryConsts::ExactImport) { case ExternalKind::Function: @@ -3183,8 +3197,52 @@ void WasmBinaryReader::readImports() { for (size_t i = 0; i < num; i++) { auto module = getInlineString(); auto base = getInlineString(); - auto kind = getU32LEB(); - readImport(module, base, kind); + auto kind = getInt8(); + if (base == "" && (kind == BinaryConsts::CompactImportsSharedModule || + kind == BinaryConsts::CompactImportsSharedAll)) { + if (!wasm.features.hasCompactImports()) { + throwError("compact imports not supported"); + } + if (kind == BinaryConsts::CompactImportsSharedModule) { + size_t numCompactImports = getU32LEB(); + while (numCompactImports--) { + base = getInlineString(); + kind = getInt8(); + readImport(module, base, kind); + } + } else { + kind = getInt8(); + switch (kind & ~BinaryConsts::ExactImport) { + case ExternalKind::Function: + readCompactImportsShared(module, [&](Name base) { + return readFunctionImport(module, base, kind); + }); + break; + case ExternalKind::Table: + readCompactImportsShared( + module, [&](Name base) { return readTableImport(module, base); }); + break; + case ExternalKind::Memory: + readCompactImportsShared(module, [&](Name base) { + return readMemoryImport(module, base); + }); + break; + case ExternalKind::Global: + readCompactImportsShared(module, [&](Name base) { + return readGlobalImport(module, base); + }); + break; + case ExternalKind::Tag: + readCompactImportsShared( + module, [&](Name base) { return readTagImport(module, base); }); + break; + default: + throwError("bad import kind"); + } + } + } else { + readImport(module, base, kind); + } } numFuncImports = wasm.functions.size(); } @@ -5519,6 +5577,8 @@ void WasmBinaryReader::readFeatures(size_t sectionPos, size_t payloadLen) { feature = FeatureSet::CustomPageSizes; } else if (name == BinaryConsts::CustomSections::WideArithmeticFeature) { feature = FeatureSet::WideArithmetic; + } else if (name == BinaryConsts::CustomSections::CompactImportsFeature) { + feature = FeatureSet::CompactImports; } else { // Silently ignore unknown features (this may be and old binaryen running // on a new wasm). diff --git a/src/wasm/wasm.cpp b/src/wasm/wasm.cpp index 15a1e3e6d86..6aa8373cb69 100644 --- a/src/wasm/wasm.cpp +++ b/src/wasm/wasm.cpp @@ -80,6 +80,7 @@ const char* RelaxedAtomicsFeature = "relaxed-atomics"; const char* MultibyteFeature = "multibyte"; const char* CustomPageSizesFeature = "custom-page-sizes"; const char* WideArithmeticFeature = "wide-arithmetic"; +const char* CompactImportsFeature = "compact-imports"; } // namespace BinaryConsts::CustomSections diff --git a/test/binaryen.js/kitchen-sink.js b/test/binaryen.js/kitchen-sink.js index 354668d0c12..4e76afd6970 100644 --- a/test/binaryen.js/kitchen-sink.js +++ b/test/binaryen.js/kitchen-sink.js @@ -103,6 +103,7 @@ function test_features() { console.log("Features.RelaxedAtomics: " + binaryen.Features.RelaxedAtomics); console.log("Features.CustomPageSizes: " + binaryen.Features.CustomPageSizes); console.log("Features.WideArithmetic: " + binaryen.Features.WideArithmetic); + console.log("Features.CompactImports: " + binaryen.Features.CompactImports); console.log("Features.All: " + binaryen.Features.All); } diff --git a/test/binaryen.js/kitchen-sink.js.txt b/test/binaryen.js/kitchen-sink.js.txt index b6f57fa8236..59aabef6ea6 100644 --- a/test/binaryen.js/kitchen-sink.js.txt +++ b/test/binaryen.js/kitchen-sink.js.txt @@ -36,7 +36,8 @@ Features.MultiMemory: 32768 Features.RelaxedAtomics: 4194304 Features.CustomPageSizes: 8388608 Features.WideArithmetic: 33554432 -Features.All: 67108863 +Features.CompactImports: 67108864 +Features.All: 134217727 InvalidId: 0 BlockId: 1 IfId: 2 diff --git a/test/example/c-api-kitchen-sink.c b/test/example/c-api-kitchen-sink.c index eeffd8fd35e..d749665aae1 100644 --- a/test/example/c-api-kitchen-sink.c +++ b/test/example/c-api-kitchen-sink.c @@ -381,6 +381,8 @@ void test_features() { printf("BinaryenFeatureMultibyte: %d\n", BinaryenFeatureMultibyte()); printf("BinaryenFeatureWideArithmetic: %d\n", BinaryenFeatureWideArithmetic()); + printf("BinaryenFeatureCompactImports: %d\n", + BinaryenFeatureCompactImports()); printf("BinaryenFeatureAll: %d\n", BinaryenFeatureAll()); } diff --git a/test/example/c-api-kitchen-sink.txt b/test/example/c-api-kitchen-sink.txt index 4907ac0cdd0..ce938059f18 100644 --- a/test/example/c-api-kitchen-sink.txt +++ b/test/example/c-api-kitchen-sink.txt @@ -51,7 +51,8 @@ BinaryenFeatureRelaxedAtomics: 4194304 BinaryenFeatureCustomPageSizes: 8388608 BinaryenFeatureMultibyte: 16777216 BinaryenFeatureWideArithmetic: 33554432 -BinaryenFeatureAll: 67108863 +BinaryenFeatureCompactImports: 67108864 +BinaryenFeatureAll: 134217727 (f32.neg (f32.const -33.61199951171875) ) diff --git a/test/lit/help/wasm-as.test b/test/lit/help/wasm-as.test index 35ea0de7868..fbb4f9c35e5 100644 --- a/test/lit/help/wasm-as.test +++ b/test/lit/help/wasm-as.test @@ -152,6 +152,10 @@ ;; CHECK-NEXT: ;; CHECK-NEXT: --disable-wide-arithmetic Disable wide arithmetic ;; CHECK-NEXT: +;; CHECK-NEXT: --enable-compact-imports Enable compact import section +;; CHECK-NEXT: +;; CHECK-NEXT: --disable-compact-imports Disable compact import section +;; CHECK-NEXT: ;; CHECK-NEXT: --enable-typed-function-references Deprecated compatibility flag ;; CHECK-NEXT: ;; CHECK-NEXT: --disable-typed-function-references Deprecated compatibility flag diff --git a/test/lit/help/wasm-ctor-eval.test b/test/lit/help/wasm-ctor-eval.test index e56f2b215bc..7807de5e1de 100644 --- a/test/lit/help/wasm-ctor-eval.test +++ b/test/lit/help/wasm-ctor-eval.test @@ -159,6 +159,10 @@ ;; CHECK-NEXT: ;; CHECK-NEXT: --disable-wide-arithmetic Disable wide arithmetic ;; CHECK-NEXT: +;; CHECK-NEXT: --enable-compact-imports Enable compact import section +;; CHECK-NEXT: +;; CHECK-NEXT: --disable-compact-imports Disable compact import section +;; CHECK-NEXT: ;; CHECK-NEXT: --enable-typed-function-references Deprecated compatibility flag ;; CHECK-NEXT: ;; CHECK-NEXT: --disable-typed-function-references Deprecated compatibility flag diff --git a/test/lit/help/wasm-dis.test b/test/lit/help/wasm-dis.test index 3c0fca5a0f4..2f95f7a448a 100644 --- a/test/lit/help/wasm-dis.test +++ b/test/lit/help/wasm-dis.test @@ -145,6 +145,10 @@ ;; CHECK-NEXT: ;; CHECK-NEXT: --disable-wide-arithmetic Disable wide arithmetic ;; CHECK-NEXT: +;; CHECK-NEXT: --enable-compact-imports Enable compact import section +;; CHECK-NEXT: +;; CHECK-NEXT: --disable-compact-imports Disable compact import section +;; CHECK-NEXT: ;; CHECK-NEXT: --enable-typed-function-references Deprecated compatibility flag ;; CHECK-NEXT: ;; CHECK-NEXT: --disable-typed-function-references Deprecated compatibility flag diff --git a/test/lit/help/wasm-emscripten-finalize.test b/test/lit/help/wasm-emscripten-finalize.test index 6ed8c98771f..5ce391f9548 100644 --- a/test/lit/help/wasm-emscripten-finalize.test +++ b/test/lit/help/wasm-emscripten-finalize.test @@ -187,6 +187,10 @@ ;; CHECK-NEXT: ;; CHECK-NEXT: --disable-wide-arithmetic Disable wide arithmetic ;; CHECK-NEXT: +;; CHECK-NEXT: --enable-compact-imports Enable compact import section +;; CHECK-NEXT: +;; CHECK-NEXT: --disable-compact-imports Disable compact import section +;; CHECK-NEXT: ;; CHECK-NEXT: --enable-typed-function-references Deprecated compatibility flag ;; CHECK-NEXT: ;; CHECK-NEXT: --disable-typed-function-references Deprecated compatibility flag diff --git a/test/lit/help/wasm-merge.test b/test/lit/help/wasm-merge.test index f1ff0631278..f235c12fe5e 100644 --- a/test/lit/help/wasm-merge.test +++ b/test/lit/help/wasm-merge.test @@ -182,6 +182,10 @@ ;; CHECK-NEXT: ;; CHECK-NEXT: --disable-wide-arithmetic Disable wide arithmetic ;; CHECK-NEXT: +;; CHECK-NEXT: --enable-compact-imports Enable compact import section +;; CHECK-NEXT: +;; CHECK-NEXT: --disable-compact-imports Disable compact import section +;; CHECK-NEXT: ;; CHECK-NEXT: --enable-typed-function-references Deprecated compatibility flag ;; CHECK-NEXT: ;; CHECK-NEXT: --disable-typed-function-references Deprecated compatibility flag diff --git a/test/lit/help/wasm-metadce.test b/test/lit/help/wasm-metadce.test index 5cd70538ba0..aadf987cf33 100644 --- a/test/lit/help/wasm-metadce.test +++ b/test/lit/help/wasm-metadce.test @@ -825,6 +825,10 @@ ;; CHECK-NEXT: ;; CHECK-NEXT: --disable-wide-arithmetic Disable wide arithmetic ;; CHECK-NEXT: +;; CHECK-NEXT: --enable-compact-imports Enable compact import section +;; CHECK-NEXT: +;; CHECK-NEXT: --disable-compact-imports Disable compact import section +;; CHECK-NEXT: ;; CHECK-NEXT: --enable-typed-function-references Deprecated compatibility flag ;; CHECK-NEXT: ;; CHECK-NEXT: --disable-typed-function-references Deprecated compatibility flag diff --git a/test/lit/help/wasm-opt.test b/test/lit/help/wasm-opt.test index 50aa71f196b..4dec96a4104 100644 --- a/test/lit/help/wasm-opt.test +++ b/test/lit/help/wasm-opt.test @@ -861,6 +861,10 @@ ;; CHECK-NEXT: ;; CHECK-NEXT: --disable-wide-arithmetic Disable wide arithmetic ;; CHECK-NEXT: +;; CHECK-NEXT: --enable-compact-imports Enable compact import section +;; CHECK-NEXT: +;; CHECK-NEXT: --disable-compact-imports Disable compact import section +;; CHECK-NEXT: ;; CHECK-NEXT: --enable-typed-function-references Deprecated compatibility flag ;; CHECK-NEXT: ;; CHECK-NEXT: --disable-typed-function-references Deprecated compatibility flag diff --git a/test/lit/help/wasm-reduce.test b/test/lit/help/wasm-reduce.test index 48da8b968f3..a85c42f13ec 100644 --- a/test/lit/help/wasm-reduce.test +++ b/test/lit/help/wasm-reduce.test @@ -235,6 +235,10 @@ ;; CHECK-NEXT: ;; CHECK-NEXT: --disable-wide-arithmetic Disable wide arithmetic ;; CHECK-NEXT: +;; CHECK-NEXT: --enable-compact-imports Enable compact import section +;; CHECK-NEXT: +;; CHECK-NEXT: --disable-compact-imports Disable compact import section +;; CHECK-NEXT: ;; CHECK-NEXT: --enable-typed-function-references Deprecated compatibility flag ;; CHECK-NEXT: ;; CHECK-NEXT: --disable-typed-function-references Deprecated compatibility flag diff --git a/test/lit/help/wasm-split.test b/test/lit/help/wasm-split.test index 3503a46675d..0bd68869a09 100644 --- a/test/lit/help/wasm-split.test +++ b/test/lit/help/wasm-split.test @@ -296,6 +296,10 @@ ;; CHECK-NEXT: ;; CHECK-NEXT: --disable-wide-arithmetic Disable wide arithmetic ;; CHECK-NEXT: +;; CHECK-NEXT: --enable-compact-imports Enable compact import section +;; CHECK-NEXT: +;; CHECK-NEXT: --disable-compact-imports Disable compact import section +;; CHECK-NEXT: ;; CHECK-NEXT: --enable-typed-function-references Deprecated compatibility flag ;; CHECK-NEXT: ;; CHECK-NEXT: --disable-typed-function-references Deprecated compatibility flag diff --git a/test/lit/help/wasm2js.test b/test/lit/help/wasm2js.test index 1f89eedb6d0..550677a376f 100644 --- a/test/lit/help/wasm2js.test +++ b/test/lit/help/wasm2js.test @@ -789,6 +789,10 @@ ;; CHECK-NEXT: ;; CHECK-NEXT: --disable-wide-arithmetic Disable wide arithmetic ;; CHECK-NEXT: +;; CHECK-NEXT: --enable-compact-imports Enable compact import section +;; CHECK-NEXT: +;; CHECK-NEXT: --disable-compact-imports Disable compact import section +;; CHECK-NEXT: ;; CHECK-NEXT: --enable-typed-function-references Deprecated compatibility flag ;; CHECK-NEXT: ;; CHECK-NEXT: --disable-typed-function-references Deprecated compatibility flag diff --git a/test/passes/strip-target-features_roundtrip_print-features_all-features.txt b/test/passes/strip-target-features_roundtrip_print-features_all-features.txt index 2272fb36ff1..b61f97053bd 100644 --- a/test/passes/strip-target-features_roundtrip_print-features_all-features.txt +++ b/test/passes/strip-target-features_roundtrip_print-features_all-features.txt @@ -24,6 +24,7 @@ --enable-custom-page-sizes --enable-multibyte --enable-wide-arithmetic +--enable-compact-imports (module (type $0 (func (result v128 externref))) (func $foo (type $0) (result v128 externref) diff --git a/test/spec/compact-import-section/binary-compact-imports.wast b/test/spec/compact-import-section/binary-compact-imports.wast new file mode 100644 index 00000000000..bf5d9e02130 --- /dev/null +++ b/test/spec/compact-import-section/binary-compact-imports.wast @@ -0,0 +1,174 @@ +;; Auxiliary modules to import + +(module + (func (export "b") (result i32) (i32.const 0x0f)) + (func (export "c") (result i32) (i32.const 0xf0)) +) +(register "a") +(module + (func (export "") (result i32) (i32.const 0xab)) +) +(register "") + + +;; Valid compact encodings + +(module binary + "\00asm" "\01\00\00\00" + "\01\05\01\60\00\01\7f" ;; Type section: (type (func (result i32))) + "\02\0e" ;; Import section + "\01" ;; 1 group + "\01a" ;; "a" + "\00" "\7f" ;; "" + 0x7f (compact encoding) + "\02" ;; 2 items + "\01b" "\00\00" ;; "b" (func (type 0)) + "\01c" "\00\00" ;; "c" (func (type 0)) + "\03\02" "\01" ;; Function section, 1 func + "\00" ;; func 2: type 0 + "\07\08" "\01" ;; Export section, 1 export + "\04test" "\00\02" ;; "test" func 2 + "\0a\09" "\01" ;; Code section, 1 func + "\07" "\00" ;; len, 0 locals + "\10\00" ;; call 0 + "\10\01" ;; call 1 + "\6a" ;; i32.add + "\0b" ;; end +) +(assert_return (invoke "test") (i32.const 0xff)) + +(module binary + "\00asm" "\01\00\00\00" + "\01\05\01\60\00\01\7f" ;; Type section: (type (func (result i32))) + "\02\0c" ;; Import section + "\01" ;; 1 group + "\01a" ;; "a" + "\00" "\7e" ;; "" + 0x7e (compact encoding) + "\00\00" ;; (func (type 0)) + "\02" ;; 2 items + "\01b" ;; "b" + "\01c" ;; "c" + "\03\02" "\01" ;; Function section, 1 func + "\00" ;; func 2: type 0 + "\07\08" "\01" ;; Export section, 1 export + "\04test" "\00\02" ;; "test" func 2 + "\0a\09" "\01" ;; Code section, 1 func + "\07" "\00" ;; len, 0 locals + "\10\00" ;; call 0 + "\10\01" ;; call 1 + "\6a" ;; i32.add + "\0b" ;; end +) +(assert_return (invoke "test") (i32.const 0xff)) + + +;; Overly-long empty name encodings are valid + +(module binary + "\00asm" "\01\00\00\00" + "\01\05\01\60\00\01\7f" ;; Type section: (type (func (result i32))) + "\02\11" ;; Import section + "\01" ;; 1 group + "\01a" ;; "a" + "\80\80\80\00" "\7f" ;; "" (long encoding) + 0x7f + "\02" ;; 2 items + "\01b" "\00\00" ;; "b" (func (type 0)) + "\01c" "\00\00" ;; "c" (func (type 0)) +) +(module binary + "\00asm" "\01\00\00\00" + "\01\05\01\60\00\01\7f" ;; Type section: (type (func (result i32))) + "\02\0f" ;; Import section + "\01" ;; 1 group + "\01a" ;; "a" + "\80\80\80\00" "\7e" ;; "" (long encoding) + 0x7e + "\00\00" ;; (func (type 0)) + "\02" ;; 2 items + "\01b" ;; "b" + "\01c" ;; "c" +) + + +;; Discriminator is not valid except after empty names + +(assert_malformed + (module binary + "\00asm" "\01\00\00\00" + "\01\05\01\60\00\01\7f" ;; Type section: (type (func (result i32))) + "\02\12" ;; Import section + "\01" ;; 1 group + "\01a" ;; "a" + "\01b" "\7f" ;; "b" + 0x7f + "\02" ;; 2 items + "\01b" "\00\00" ;; "b" (func (type 0)) + "\01c" "\00\00" ;; "c" (func (type 0)) + ) + "malformed import kind" +) +(assert_malformed + (module binary + "\00asm" "\01\00\00\00" + "\01\05\01\60\00\01\7f" ;; Type section: (type (func (result i32))) + "\02\10" ;; Import section + "\01" ;; 1 group + "\01a" ;; "a" + "\01b" "\7e" ;; "" + 0x7e (long encoding) + "\00\00" ;; (func (type 0)) + "\02" ;; 2 items + "\01b" ;; "b" + "\01c" ;; "c" + ) + "malformed import kind" +) + + +;; Discriminator is not to be interpreted as LEB128 + +(assert_malformed + (module binary + "\00asm" "\01\00\00\00" + "\01\05\01\60\00\01\7f" ;; Type section: (type (func (result i32))) + "\02\11" ;; Import section + "\01" ;; 1 group + "\01a" ;; "a" + "\00\ff\80\80\00" ;; "" + 0x7f (long encoding) + "\02" ;; 2 items + "\01b" "\00\00" ;; "b" (func (type 0)) + "\01c" "\00\00" ;; "c" (func (type 0)) + ) + "malformed import kind" +) +(assert_malformed + (module binary + "\00asm" "\01\00\00\00" + "\01\05\01\60\00\01\7f" ;; Type section: (type (func (result i32))) + "\02\0f" ;; Import section + "\01" ;; 1 group + "\01a" ;; "a" + "\00\fe\80\80\00" ;; "" + 0x7e (long encoding) + "\00\00" ;; (func (type 0)) + "\02" ;; 2 items + "\01b" ;; "b" + "\01c" ;; "c" + ) + "malformed import kind" +) + + +;; Empty names are still valid if not followed by a discriminator + +(module binary + "\00asm" "\01\00\00\00" + "\01\05\01\60\00\01\7f" ;; Type section: (type (func (result i32))) + "\02\05" ;; Import section + "\01" ;; 1 group + "\00\00\00\00" ;; "" "" (func (type 0)) + "\03\02" "\01" ;; Function section, 1 func + "\00" ;; func 1: type 0 + "\07\08" "\01" ;; Export section, 1 export + "\04test" "\00\01" ;; "test" func 1 + "\0a\06" "\01" ;; Code section, 1 func + "\04" "\00" ;; len, 0 locals + "\10\00" ;; call 0 + "\0b" ;; end +) +(assert_return (invoke "test") (i32.const 0xab)) diff --git a/test/unit/test_features.py b/test/unit/test_features.py index 2d693ded087..4e1dab185d0 100644 --- a/test/unit/test_features.py +++ b/test/unit/test_features.py @@ -459,4 +459,5 @@ def test_emit_all_features(self): '--enable-relaxed-atomics', '--enable-custom-page-sizes', '--enable-wide-arithmetic', + '--enable-compact-imports', ], p2.stdout.splitlines())