summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/interp/binary-reader-interp.cc7
-rw-r--r--test/interp/return-call-set-local.txt20
2 files changed, 25 insertions, 2 deletions
diff --git a/src/interp/binary-reader-interp.cc b/src/interp/binary-reader-interp.cc
index 7a1bc26e..699fdd20 100644
--- a/src/interp/binary-reader-interp.cc
+++ b/src/interp/binary-reader-interp.cc
@@ -576,7 +576,7 @@ Result BinaryReaderInterp::OnFunctionCount(Index count) {
Result BinaryReaderInterp::OnFunction(Index index, Index sig_index) {
CHECK_RESULT(validator_.OnFunction(GetLocation(), Var(sig_index)));
FuncType& func_type = module_.func_types[sig_index];
- module_.funcs.push_back(FuncDesc{func_type, {}, 0, {}});
+ module_.funcs.push_back(FuncDesc{func_type, {}, Istream::kInvalidOffset, {}});
func_types_.push_back(func_type);
return Result::Ok;
}
@@ -1132,7 +1132,10 @@ Result BinaryReaderInterp::OnReturnCallExpr(Index func_index) {
if (func_index >= num_func_imports()) {
istream_.Emit(Opcode::InterpAdjustFrameForReturnCall, func_index);
- istream_.Emit(Opcode::Br, GetFuncOffset(func_index));
+ istream_.Emit(Opcode::Br);
+ // We emit this separately to ensure that the fixup generated by
+ // GetFuncOffset comes after the Br opcode.
+ istream_.Emit(GetFuncOffset(func_index));
} else {
istream_.Emit(Opcode::InterpCallImport, func_index);
istream_.Emit(Opcode::Return);
diff --git a/test/interp/return-call-set-local.txt b/test/interp/return-call-set-local.txt
new file mode 100644
index 00000000..5b566361
--- /dev/null
+++ b/test/interp/return-call-set-local.txt
@@ -0,0 +1,20 @@
+;;; TOOL: run-interp
+;;; ARGS*: --enable-tail-call
+(module
+ (func (export "f") (result i32)
+ (i64.const 1)
+ (return_call $g))
+
+ (func $g (param i64) (result i32)
+ (i32.const 3)
+ (return_call $h))
+
+ (func $h (param i32) (result i32)
+ (i32.const 2)
+ (local.set 0)
+ (local.get 0)
+ return)
+)
+(;; STDOUT ;;;
+f() => i32:2
+;;; STDOUT ;;)