Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,11 @@ full changeset diff at the end of each section.
Current Trunk
-------------

- Add a new flag to Directize, `--pass-arg=directize-skip-type-mismatch`
which leaves type-mismatched indirect calls unchanged instead of turning them
into traps. This is useful when fpcast-emu will run later to fix up those
mismatches.

v128
----

Expand Down
23 changes: 20 additions & 3 deletions src/passes/Directize.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,14 @@
// then the initial tables' contents are assumed to be immutable (see
// TableUtils::TableInfo).
//
// If called with
//
// --pass-arg=directize-skip-type-mismatch
//
// then type-mismatched call_indirect with constant table indices will be
// left as Unknown (not turned into traps). This is useful when fpcast-emu
// will run later and fix up those mismatches.
//

#include <unordered_map>

Expand All @@ -47,10 +55,12 @@ struct FunctionDirectizer : public WalkerPass<PostWalker<FunctionDirectizer>> {
bool isFunctionParallel() override { return true; }

std::unique_ptr<Pass> create() override {
return std::make_unique<FunctionDirectizer>(tables);
return std::make_unique<FunctionDirectizer>(tables, skipTypeMismatch);
}

FunctionDirectizer(const TableUtils::TableInfoMap& tables) : tables(tables) {}
FunctionDirectizer(const TableUtils::TableInfoMap& tables,
bool skipTypeMismatch = false)
: tables(tables), skipTypeMismatch(skipTypeMismatch) {}

void visitCallIndirect(CallIndirect* curr) {
auto& table = tables.at(curr->table);
Expand Down Expand Up @@ -91,6 +101,8 @@ struct FunctionDirectizer : public WalkerPass<PostWalker<FunctionDirectizer>> {
private:
const TableUtils::TableInfoMap& tables;

bool skipTypeMismatch = false;

bool changedTypes = false;

// Given an expression that we will use as the target of an indirect call,
Expand Down Expand Up @@ -129,6 +141,9 @@ struct FunctionDirectizer : public WalkerPass<PostWalker<FunctionDirectizer>> {
}
auto* func = getModule()->getFunction(name);
if (!HeapType::isSubType(func->type.getHeapType(), original->heapType)) {
if (skipTypeMismatch) {
return CallUtils::Unknown{};
}
return CallUtils::Trap{};
}
return CallUtils::Known{name};
Expand Down Expand Up @@ -201,8 +216,10 @@ struct Directize : public Pass {
return;
}

auto skipTypeMismatch = hasArgument("directize-skip-type-mismatch");

// We can optimize!
FunctionDirectizer(tables).run(getPassRunner(), module);
FunctionDirectizer(tables, skipTypeMismatch).run(getPassRunner(), module);
}
};

Expand Down
60 changes: 60 additions & 0 deletions test/lit/passes/directize-gc.wast
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
;; NOTE: This test was ported using port_passes_tests_to_lit.py and could be cleaned up.

;; RUN: foreach %s %t wasm-opt --directize -all -S -o - | filecheck %s
;; RUN: foreach %s %t wasm-opt --directize --pass-arg=directize-skip-type-mismatch -all -S -o - | filecheck %s --check-prefix=SKIPTM

;; Call a subtype with the supertype. This call should succeed.
(module
Expand All @@ -10,22 +11,34 @@

;; CHECK: (rec
;; CHECK-NEXT: (type $super (sub (func)))
;; SKIPTM: (type $0 (func))

;; SKIPTM: (rec
;; SKIPTM-NEXT: (type $super (sub (func)))
(type $super (sub (func)))
;; CHECK: (type $sub (sub final $super (func)))
;; SKIPTM: (type $sub (sub final $super (func)))
(type $sub (sub final $super (func)))
)

;; CHECK: (table $table 93 funcref)
;; SKIPTM: (table $table 93 funcref)
(table $table 93 funcref)

;; CHECK: (elem $elem (i32.const 0) $target)
;; SKIPTM: (elem $elem (i32.const 0) $target)
(elem $elem (i32.const 0) $target)

;; CHECK: (export "caller" (func $caller))

;; CHECK: (func $caller (type $0)
;; CHECK-NEXT: (call $target)
;; CHECK-NEXT: )
;; SKIPTM: (export "caller" (func $caller))

;; SKIPTM: (func $caller (type $0)
;; SKIPTM-NEXT: (call $target)
;; SKIPTM-NEXT: )
(func $caller (export "caller")
;; This turns into a direct call.
(call_indirect (type $super)
Expand All @@ -35,6 +48,8 @@

;; CHECK: (func $target (type $sub)
;; CHECK-NEXT: )
;; SKIPTM: (func $target (type $sub)
;; SKIPTM-NEXT: )
(func $target (type $sub)
)
)
Expand All @@ -46,22 +61,36 @@

;; CHECK: (rec
;; CHECK-NEXT: (type $super (sub (func)))
;; SKIPTM: (type $0 (func))

;; SKIPTM: (rec
;; SKIPTM-NEXT: (type $super (sub (func)))
(type $super (sub (func)))
;; CHECK: (type $other (sub (func)))
;; SKIPTM: (type $other (sub (func)))
(type $other (sub (func)))
)

;; CHECK: (table $table 93 funcref)
;; SKIPTM: (table $table 93 funcref)
(table $table 93 funcref)

;; CHECK: (elem $elem (i32.const 0) $target)
;; SKIPTM: (elem $elem (i32.const 0) $target)
(elem $elem (i32.const 0) $target)

;; CHECK: (export "caller" (func $caller))

;; CHECK: (func $caller (type $0)
;; CHECK-NEXT: (unreachable)
;; CHECK-NEXT: )
;; SKIPTM: (export "caller" (func $caller))

;; SKIPTM: (func $caller (type $0)
;; SKIPTM-NEXT: (call_indirect $table (type $super)
;; SKIPTM-NEXT: (i32.const 0)
;; SKIPTM-NEXT: )
;; SKIPTM-NEXT: )
(func $caller (export "caller")
;; This turns into an unreachable.
(call_indirect (type $super)
Expand All @@ -71,6 +100,8 @@

;; CHECK: (func $target (type $other)
;; CHECK-NEXT: )
;; SKIPTM: (func $target (type $other)
;; SKIPTM-NEXT: )
(func $target (type $other)
)
)
Expand All @@ -83,22 +114,36 @@

;; CHECK: (rec
;; CHECK-NEXT: (type $super (sub (func)))
;; SKIPTM: (rec
;; SKIPTM-NEXT: (type $super (sub (func)))
(type $super (sub (func)))
;; CHECK: (type $sub (sub final $super (func)))
;; SKIPTM: (type $sub (sub final $super (func)))
(type $sub (sub final $super (func)))
)

;; CHECK: (table $table 93 funcref)
;; SKIPTM: (type $2 (func))

;; SKIPTM: (table $table 93 funcref)
(table $table 93 funcref)

;; CHECK: (elem $elem (i32.const 0) $target)
;; SKIPTM: (elem $elem (i32.const 0) $target)
(elem $elem (i32.const 0) $target)

;; CHECK: (export "caller" (func $caller))

;; CHECK: (func $caller (type $0)
;; CHECK-NEXT: (unreachable)
;; CHECK-NEXT: )
;; SKIPTM: (export "caller" (func $caller))

;; SKIPTM: (func $caller (type $2)
;; SKIPTM-NEXT: (call_indirect $table (type $sub)
;; SKIPTM-NEXT: (i32.const 0)
;; SKIPTM-NEXT: )
;; SKIPTM-NEXT: )
(func $caller (export "caller")
;; This turns into a direct call.
(call_indirect (type $sub)
Expand All @@ -108,6 +153,8 @@

;; CHECK: (func $target (type $super)
;; CHECK-NEXT: )
;; SKIPTM: (func $target (type $super)
;; SKIPTM-NEXT: )
(func $target (type $super)
)
)
Expand All @@ -118,21 +165,31 @@
(rec
;; CHECK: (rec
;; CHECK-NEXT: (type $super (sub (func (result (ref any)))))
;; SKIPTM: (rec
;; SKIPTM-NEXT: (type $super (sub (func (result (ref any)))))
(type $super (sub (func (result (ref any)))))
;; CHECK: (type $sub (sub $super (func (result (ref none)))))
;; SKIPTM: (type $sub (sub $super (func (result (ref none)))))
(type $sub (sub $super (func (result (ref none)))))
)

;; CHECK: (table $table 42 funcref)
;; SKIPTM: (table $table 42 funcref)
(table $table 42 funcref)
;; CHECK: (elem $elem (i32.const 0) $sub)
;; SKIPTM: (elem $elem (i32.const 0) $sub)
(elem $elem (i32.const 0) $sub)

;; CHECK: (func $super (type $super) (result (ref any))
;; CHECK-NEXT: (block $show-type (result (ref none))
;; CHECK-NEXT: (call $sub)
;; CHECK-NEXT: )
;; CHECK-NEXT: )
;; SKIPTM: (func $super (type $super) (result (ref any))
;; SKIPTM-NEXT: (block $show-type (result (ref none))
;; SKIPTM-NEXT: (call $sub)
;; SKIPTM-NEXT: )
;; SKIPTM-NEXT: )
(func $super (type $super) (result (ref any))
(block $show-type (result (ref any))
(call_indirect $table (type $super)
Expand All @@ -144,6 +201,9 @@
;; CHECK: (func $sub (type $sub) (result (ref none))
;; CHECK-NEXT: (unreachable)
;; CHECK-NEXT: )
;; SKIPTM: (func $sub (type $sub) (result (ref none))
;; SKIPTM-NEXT: (unreachable)
;; SKIPTM-NEXT: )
(func $sub (type $sub) (result (ref none))
(unreachable)
)
Expand Down
Loading