diff --git a/src/ir/module-splitting.cpp b/src/ir/module-splitting.cpp index 5a7bd538343..b97269acaee 100644 --- a/src/ir/module-splitting.cpp +++ b/src/ir/module-splitting.cpp @@ -89,7 +89,7 @@ template void forEachElement(Module& module, F f) { Name base = ""; Index offset = 0; if (auto* c = segment->offset->dynCast()) { - offset = c->value.geti32(); + offset = c->value.getInteger(); } else if (auto* g = segment->offset->dynCast()) { base = g->name; } @@ -129,11 +129,15 @@ struct TableSlotManager { Expression* TableSlotManager::Slot::makeExpr(Module& module) { Builder builder(module); - auto makeIndex = [&]() { return builder.makeConst(int32_t(index)); }; + auto* table = module.getTable(tableName); + auto makeIndex = [&]() { + return builder.makeConst(Literal::makeFromInt32(index, table->addressType)); + }; if (global.size()) { - Expression* getBase = builder.makeGlobalGet(global, Type::i32); + Expression* getBase = builder.makeGlobalGet(global, table->addressType); + auto addOp = table->is64() ? AddInt64 : AddInt32; return index == 0 ? getBase - : builder.makeBinary(AddInt32, getBase, makeIndex()); + : builder.makeBinary(addOp, getBase, makeIndex()); } else { return makeIndex(); } @@ -209,7 +213,7 @@ TableSlotManager::TableSlotManager(Module& module) : module(module) { for (auto& segment : activeTableSegments) { assert(segment->offset->is() && "Unexpected non-const segment offset with multiple segments"); - Index segmentBase = segment->offset->cast()->value.geti32(); + Index segmentBase = segment->offset->cast()->value.getInteger(); if (segmentBase + segment->data.size() >= maxIndex) { maxIndex = segmentBase + segment->data.size(); activeSegment = segment; @@ -233,10 +237,13 @@ Table* TableSlotManager::makeTable() { } ElementSegment* TableSlotManager::makeElementSegment() { + Builder builder(module); + Expression* offset = + builder.makeConst(Literal::makeFromInt32(0, activeTable->addressType)); return module.addElementSegment(Builder::makeElementSegment( Names::getValidElementSegmentName(module, Name::fromInt(0)), activeTable->name, - Builder(module).makeConst(int32_t(0)))); + offset)); } TableSlotManager::Slot TableSlotManager::getSlot(Name func, HeapType type) { @@ -801,7 +808,8 @@ void ModuleSplitter::setupTablePatching() { Index currBase = replacedElems.begin()->first; std::vector currData; auto finishSegment = [&]() { - auto* offset = Builder(secondary).makeConst(int32_t(currBase)); + auto* offset = Builder(secondary).makeConst( + Literal::makeFromInt32(currBase, secondaryTable->addressType)); auto secondarySeg = std::make_unique( secondaryTable->name, offset, secondaryTable->type, currData); Name name = Names::getValidElementSegmentName( diff --git a/test/lit/wasm-split/table64-const-offset.wast b/test/lit/wasm-split/table64-const-offset.wast new file mode 100644 index 00000000000..58bb33d6139 --- /dev/null +++ b/test/lit/wasm-split/table64-const-offset.wast @@ -0,0 +1,86 @@ +;; When reference types is disabled, we reuse the existing i64 table +;; RUN: wasm-split %s -g -o1 %t.1.wasm -o2 %t.2.wasm --export-prefix='%' --keep-funcs=foo --enable-memory64 -v 2>&1 | filecheck %s --check-prefix CHECK +;; RUN: wasm-dis %t.1.wasm | filecheck %s --check-prefix PRIMARY-NOREF +;; RUN: wasm-dis %t.2.wasm | filecheck %s --check-prefix SECONDARY-NOREF +;; Check whether the split files conform to memory64 +;; RUN: wasm-opt --enable-memory64 %t.1.wasm +;; RUN: wasm-opt --enable-memory64 %t.2.wasm + +;; When reference types is enabled, we create a new table +;; RUN: wasm-split %s -g -o1 %t.1.wasm -o2 %t.2.wasm --export-prefix='%' --keep-funcs=foo --enable-memory64 --enable-reference-types -v 2>&1 | filecheck %s --check-prefix CHECK +;; RUN: wasm-dis %t.1.wasm | filecheck %s --check-prefix PRIMARY-REF +;; RUN: wasm-dis %t.2.wasm | filecheck %s --check-prefix SECONDARY-REF +;; Check whether the split files conform to memory64 +;; RUN: wasm-opt --enable-memory64 --enable-reference-types %t.1.wasm +;; RUN: wasm-opt --enable-memory64 --enable-reference-types %t.2.wasm + +;; CHECK: Keeping functions: foo{{$}} +;; CHECK: Splitting out functions: bar{{$}} + +;; PRIMARY-NOREF: (module +;; PRIMARY-NOREF-NEXT: (type $0 (func (param i32) (result i32))) +;; PRIMARY-NOREF-NEXT: (import "placeholder" "1" (func $placeholder_1 (param i32) (result i32))) +;; PRIMARY-NOREF-NEXT: (table $table i64 2 2 funcref) +;; PRIMARY-NOREF-NEXT: (elem $0 (i64.const 0) $foo $placeholder_1) +;; PRIMARY-NOREF-NEXT: (export "%foo" (func $foo)) +;; PRIMARY-NOREF-NEXT: (export "%table" (table $table)) +;; PRIMARY-NOREF-NEXT: (func $foo (param $0 i32) (result i32) +;; PRIMARY-NOREF-NEXT: (call_indirect (type $0) +;; PRIMARY-NOREF-NEXT: (i32.const 0) +;; PRIMARY-NOREF-NEXT: (i64.const 1) +;; PRIMARY-NOREF-NEXT: ) +;; PRIMARY-NOREF-NEXT: ) +;; PRIMARY-NOREF-NEXT: ) + +;; SECONDARY-NOREF: (module +;; SECONDARY-NOREF-NEXT: (type $0 (func (param i32) (result i32))) +;; SECONDARY-NOREF-NEXT: (import "primary" "%table" (table $table i64 2 2 funcref)) +;; SECONDARY-NOREF-NEXT: (import "primary" "%foo" (func $foo (param i32) (result i32))) +;; SECONDARY-NOREF-NEXT: (elem $0 (i64.const 1) $bar) +;; SECONDARY-NOREF-NEXT: (func $bar (param $0 i32) (result i32) +;; SECONDARY-NOREF-NEXT: (call $foo +;; SECONDARY-NOREF-NEXT: (i32.const 1) +;; SECONDARY-NOREF-NEXT: ) +;; SECONDARY-NOREF-NEXT: ) +;; SECONDARY-NOREF-NEXT: ) + +;; PRIMARY-REF: (module +;; PRIMARY-REF-NEXT: (type $0 (func (param i32) (result i32))) +;; PRIMARY-REF-NEXT: (import "placeholder" "0" (func $placeholder_0 (param i32) (result i32))) +;; PRIMARY-REF-NEXT: (table $table i64 1 1 funcref) +;; PRIMARY-REF-NEXT: (table $1 1 funcref) +;; PRIMARY-REF-NEXT: (elem $0 (table $table) (i64.const 0) func $foo) +;; PRIMARY-REF-NEXT: (elem $1 (table $1) (i32.const 0) func $placeholder_0) +;; PRIMARY-REF-NEXT: (export "%foo" (func $foo)) +;; PRIMARY-REF-NEXT: (export "%table" (table $table)) +;; PRIMARY-REF-NEXT: (export "%table_2" (table $1)) +;; PRIMARY-REF-NEXT: (func $foo (param $0 i32) (result i32) +;; PRIMARY-REF-NEXT: (call_indirect $1 (type $0) +;; PRIMARY-REF-NEXT: (i32.const 0) +;; PRIMARY-REF-NEXT: (i32.const 0) +;; PRIMARY-REF-NEXT: ) +;; PRIMARY-REF-NEXT: ) +;; PRIMARY-REF-NEXT: ) + +;; SECONDARY-REF: (module +;; SECONDARY-REF-NEXT: (type $0 (func (param i32) (result i32))) +;; SECONDARY-REF-NEXT: (import "primary" "%table_2" (table $timport$0 1 funcref)) +;; SECONDARY-REF-NEXT: (import "primary" "%foo" (func $foo (param i32) (result i32))) +;; SECONDARY-REF-NEXT: (elem $0 (i32.const 0) $bar) +;; SECONDARY-REF-NEXT: (func $bar (param $0 i32) (result i32) +;; SECONDARY-REF-NEXT: (call $foo +;; SECONDARY-REF-NEXT: (i32.const 1) +;; SECONDARY-REF-NEXT: ) +;; SECONDARY-REF-NEXT: ) +;; SECONDARY-REF-NEXT: ) + +(module + (table $table i64 1 1 funcref) + (elem (i64.const 0) $foo) + (func $foo (param i32) (result i32) + (call $bar (i32.const 0)) + ) + (func $bar (param i32) (result i32) + (call $foo (i32.const 1)) + ) +) diff --git a/test/lit/wasm-split/table64-global-offset.wast b/test/lit/wasm-split/table64-global-offset.wast new file mode 100644 index 00000000000..7cacbe7de61 --- /dev/null +++ b/test/lit/wasm-split/table64-global-offset.wast @@ -0,0 +1,95 @@ +;; When reference types is disabled, we reuse the existing i64 table +;; RUN: wasm-split %s -g -o1 %t.1.wasm -o2 %t.2.wasm --export-prefix='%' --keep-funcs=foo --enable-memory64 -v 2>&1 | filecheck %s --check-prefix CHECK +;; RUN: wasm-dis %t.1.wasm | filecheck %s --check-prefix PRIMARY-NOREF +;; RUN: wasm-dis %t.2.wasm | filecheck %s --check-prefix SECONDARY-NOREF +;; Check whether the split files conform to memory64 +;; RUN: wasm-opt --enable-memory64 %t.1.wasm +;; RUN: wasm-opt --enable-memory64 %t.2.wasm + +;; When reference types is enabled, we create a new table +;; RUN: wasm-split %s -g -o1 %t.1.wasm -o2 %t.2.wasm --export-prefix='%' --keep-funcs=foo --enable-memory64 --enable-reference-types -v 2>&1 | filecheck %s --check-prefix CHECK +;; RUN: wasm-dis %t.1.wasm | filecheck %s --check-prefix PRIMARY-REF +;; RUN: wasm-dis %t.2.wasm | filecheck %s --check-prefix SECONDARY-REF +;; Check whether the split files conform to memory64 +;; RUN: wasm-opt --enable-memory64 --enable-reference-types %t.1.wasm +;; RUN: wasm-opt --enable-memory64 --enable-reference-types %t.2.wasm + +;; CHECK: Keeping functions: foo{{$}} +;; CHECK: Splitting out functions: bar{{$}} + +;; PRIMARY-NOREF: (module +;; PRIMARY-NOREF-NEXT: (type $0 (func (param i32) (result i32))) +;; PRIMARY-NOREF-NEXT: (import "env" "g" (global $g i64)) +;; PRIMARY-NOREF-NEXT: (import "placeholder" "1" (func $placeholder_1 (param i32) (result i32))) +;; PRIMARY-NOREF-NEXT: (table $table i64 2 2 funcref) +;; PRIMARY-NOREF-NEXT: (elem $0 (global.get $g) $foo $placeholder_1) +;; PRIMARY-NOREF-NEXT: (export "%foo" (func $foo)) +;; PRIMARY-NOREF-NEXT: (export "%table" (table $table)) +;; PRIMARY-NOREF-NEXT: (export "%global" (global $g)) +;; PRIMARY-NOREF-NEXT: (func $foo (param $0 i32) (result i32) +;; PRIMARY-NOREF-NEXT: (call_indirect (type $0) +;; PRIMARY-NOREF-NEXT: (i32.const 0) +;; PRIMARY-NOREF-NEXT: (i64.add +;; PRIMARY-NOREF-NEXT: (global.get $g) +;; PRIMARY-NOREF-NEXT: (i64.const 1) +;; PRIMARY-NOREF-NEXT: ) +;; PRIMARY-NOREF-NEXT: ) +;; PRIMARY-NOREF-NEXT: ) +;; PRIMARY-NOREF-NEXT: ) + +;; SECONDARY-NOREF: (module +;; SECONDARY-NOREF-NEXT: (type $0 (func (param i32) (result i32))) +;; SECONDARY-NOREF-NEXT: (import "primary" "%table" (table $table i64 2 2 funcref)) +;; SECONDARY-NOREF-NEXT: (import "primary" "%global" (global $g i64)) +;; SECONDARY-NOREF-NEXT: (import "primary" "%foo" (func $foo (param i32) (result i32))) +;; SECONDARY-NOREF-NEXT: (elem $0 (global.get $g) $foo $bar) +;; SECONDARY-NOREF-NEXT: (func $bar (param $0 i32) (result i32) +;; SECONDARY-NOREF-NEXT: (call $foo +;; SECONDARY-NOREF-NEXT: (i32.const 1) +;; SECONDARY-NOREF-NEXT: ) +;; SECONDARY-NOREF-NEXT: ) +;; SECONDARY-NOREF-NEXT: ) + +;; PRIMARY-REF: (module +;; PRIMARY-REF-NEXT: (type $0 (func (param i32) (result i32))) +;; PRIMARY-REF-NEXT: (import "env" "g" (global $g i64)) +;; PRIMARY-REF-NEXT: (import "placeholder" "0" (func $placeholder_0 (param i32) (result i32))) +;; PRIMARY-REF-NEXT: (table $table i64 1 1 funcref) +;; PRIMARY-REF-NEXT: (table $1 1 funcref) +;; PRIMARY-REF-NEXT: (elem $0 (table $table) (global.get $g) func $foo) +;; PRIMARY-REF-NEXT: (elem $1 (table $1) (i32.const 0) func $placeholder_0) +;; PRIMARY-REF-NEXT: (export "%foo" (func $foo)) +;; PRIMARY-REF-NEXT: (export "%table" (table $table)) +;; PRIMARY-REF-NEXT: (export "%table_2" (table $1)) +;; PRIMARY-REF-NEXT: (export "%global" (global $g)) +;; PRIMARY-REF-NEXT: (func $foo (param $0 i32) (result i32) +;; PRIMARY-REF-NEXT: (call_indirect $1 (type $0) +;; PRIMARY-REF-NEXT: (i32.const 0) +;; PRIMARY-REF-NEXT: (i32.const 0) +;; PRIMARY-REF-NEXT: ) +;; PRIMARY-REF-NEXT: ) +;; PRIMARY-REF-NEXT: ) + +;; SECONDARY-REF: (module +;; SECONDARY-REF-NEXT: (type $0 (func (param i32) (result i32))) +;; SECONDARY-REF-NEXT: (import "primary" "%table_2" (table $timport$0 1 funcref)) +;; SECONDARY-REF-NEXT: (import "primary" "%foo" (func $foo (param i32) (result i32))) +;; SECONDARY-REF-NEXT: (elem $0 (i32.const 0) $bar) +;; SECONDARY-REF-NEXT: (func $bar (param $0 i32) (result i32) +;; SECONDARY-REF-NEXT: (call $foo +;; SECONDARY-REF-NEXT: (i32.const 1) +;; SECONDARY-REF-NEXT: ) +;; SECONDARY-REF-NEXT: ) +;; SECONDARY-REF-NEXT: ) + +(module + (global $g (import "env" "g") i64) + (table $table i64 1 1 funcref) + (elem (global.get $g) $foo) + (func $foo (param i32) (result i32) + (call $bar (i32.const 0)) + ) + (func $bar (param i32) (result i32) + (call $foo (i32.const 1)) + ) +)