Skip to content
Merged
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
3 changes: 3 additions & 0 deletions src/tools/wasm-ctor-eval.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -368,6 +368,9 @@ struct CtorEvalExternalInterface : EvallingModuleRunner::ExternalInterface {
if (!Properties::isConstantExpression(value)) {
throw FailToEvalException("tableLoad of non-literal");
}
if (auto* r = value->dynCast<RefFunc>()) {
return instance->makeFuncData(r->func, r->type.getHeapType());
}
return Properties::getLiteral(value);
}

Expand Down
7 changes: 4 additions & 3 deletions src/wasm-interpreter.h
Original file line number Diff line number Diff line change
Expand Up @@ -3561,15 +3561,16 @@ class ModuleRunnerBase : public ExpressionRunner<SubType> {
trap("non-function target in call_indirect");
}

auto* func = self()->getModule()->getFunction(funcref.getFunc());
if (!HeapType::isSubType(func->type, curr->heapType)) {
// TODO: Throw a non-constant exception if the reference is to an imported
// function that has a supertype of the expected type.
if (!HeapType::isSubType(funcref.type.getHeapType(), curr->heapType)) {
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Let's add a TODO about throwing a non-constant exception here if the reference is to an imported function that has a supertype of the expected type.

trap("callIndirect: non-subtype");
}

#if WASM_INTERPRETER_DEBUG
std::cout << self()->indent() << "(calling table)\n";
#endif
Flow ret = callFunction(funcref.getFunc(), arguments);
Flow ret = funcref.getFuncData()->doCall(arguments);
#if WASM_INTERPRETER_DEBUG
std::cout << self()->indent() << "(returned to " << scope->function->name
<< ")\n";
Expand Down
55 changes: 55 additions & 0 deletions test/spec/call_indirect_cross_module.wast
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@

;; Test for confusion regarding internal function names when using
;; call_indirect.

(module $primary
(import "spectest" "print_i32" (func $log (param i32)))

(func $run (export "run") (result funcref)
(call $log (i32.const -1))
(ref.func $run)
)
)

(register "primary")

(module $secondary
(type $func (func (result funcref)))

(import "spectest" "print_i32" (func $log (param i32)))

(import "primary" "run" (func $primary_run (result funcref)))

(table $table 10 20 funcref)

(global $sum (mut i32) (i32.const 0))

(func $run (export "secondary_run") (result funcref)
(global.set $sum
(i32.add
(global.get $sum)
(i32.const 1)
)
)
(call $log (i32.const 10))
(table.set $table
(i32.const 0)
(call $primary_run)
)
(call $log (i32.const 20))
;; This should call primary's $run, not ours. The overlap in internal name
;; should not confuse us. If we do get confused, we'd recurse here and keep
;; incrementing $sum.
(call_indirect (type $func)
(i32.const 0)
)
)

(func $sum (export "secondary_sum") (result i32)
(global.get $sum)
)
)

(invoke "secondary_run")
(assert_return (invoke "secondary_sum") (i32.const 1))

Loading