diff --git a/cranelift/codegen/src/isa/pulley_shared/inst/emit.rs b/cranelift/codegen/src/isa/pulley_shared/inst/emit.rs index 3772c127955b..5bb7fcecc2d1 100644 --- a/cranelift/codegen/src/isa/pulley_shared/inst/emit.rs +++ b/cranelift/codegen/src/isa/pulley_shared/inst/emit.rs @@ -215,7 +215,19 @@ fn pulley_emit
(
state.adjust_virtual_sp_offset(-callee_pop_size);
}
- Inst::IndirectCall { .. } => todo!(),
+ Inst::IndirectCall { info } => {
+ enc::call_indirect(sink, info.dest);
+
+ if let Some(s) = state.take_stack_map() {
+ let offset = sink.cur_offset();
+ sink.push_user_stack_map(state, offset, s);
+ }
+
+ sink.add_call_site();
+
+ let callee_pop_size = i64::from(info.callee_pop_size);
+ state.adjust_virtual_sp_offset(-callee_pop_size);
+ }
Inst::Jump { label } => {
sink.use_label_at_offset(start_offset + 1, *label, LabelUse::Jump(1));
diff --git a/cranelift/filetests/filetests/isa/pulley32/call.clif b/cranelift/filetests/filetests/isa/pulley32/call.clif
index 2a1c1d07f29b..4dd26b42c745 100644
--- a/cranelift/filetests/filetests/isa/pulley32/call.clif
+++ b/cranelift/filetests/filetests/isa/pulley32/call.clif
@@ -408,3 +408,38 @@ block0:
; xadd32 sp, sp, spilltmp0
; ret
+function %call_indirect(i32) -> i64 {
+ sig0 = () -> i64 tail
+
+block0(v0: i32):
+ v1 = call_indirect sig0, v0()
+ return v1
+}
+
+; VCode:
+; x30 = xconst8 -16
+; x27 = xadd32 x27, x30
+; store64 sp+8, x28 // flags = notrap aligned
+; store64 sp+0, x29 // flags = notrap aligned
+; x29 = xmov x27
+; block0:
+; indirect_call x0, CallInfo { dest: XReg(p0i), uses: [], defs: [CallRetPair { vreg: Writable { reg: p0i }, preg: p0i }], clobbers: PRegSet { bits: [65534, 65279, 4294967295, 0] }, callee_conv: Tail, caller_conv: Fast, callee_pop_size: 0 }
+; x28 = load64_u sp+8 // flags = notrap aligned
+; x29 = load64_u sp+0 // flags = notrap aligned
+; x30 = xconst8 16
+; x27 = xadd32 x27, x30
+; ret
+;
+; Disassembled:
+; xconst8 spilltmp0, -16
+; xadd32 sp, sp, spilltmp0
+; store64_offset8 sp, 8, lr
+; store64 sp, fp
+; xmov fp, sp
+; call_indirect x0
+; load64_offset8 lr, sp, 8
+; load64 fp, sp
+; xconst8 spilltmp0, 16
+; xadd32 sp, sp, spilltmp0
+; ret
+
diff --git a/cranelift/filetests/filetests/isa/pulley64/call.clif b/cranelift/filetests/filetests/isa/pulley64/call.clif
index 559598418621..99a31a5f29ab 100644
--- a/cranelift/filetests/filetests/isa/pulley64/call.clif
+++ b/cranelift/filetests/filetests/isa/pulley64/call.clif
@@ -408,3 +408,38 @@ block0:
; xadd32 sp, sp, spilltmp0
; ret
+function %call_indirect(i64) -> i64 {
+ sig0 = () -> i64 tail
+
+block0(v0: i64):
+ v1 = call_indirect sig0, v0()
+ return v1
+}
+
+; VCode:
+; x30 = xconst8 -16
+; x27 = xadd32 x27, x30
+; store64 sp+8, x28 // flags = notrap aligned
+; store64 sp+0, x29 // flags = notrap aligned
+; x29 = xmov x27
+; block0:
+; indirect_call x0, CallInfo { dest: XReg(p0i), uses: [], defs: [CallRetPair { vreg: Writable { reg: p0i }, preg: p0i }], clobbers: PRegSet { bits: [65534, 65279, 4294967295, 0] }, callee_conv: Tail, caller_conv: Fast, callee_pop_size: 0 }
+; x28 = load64_u sp+8 // flags = notrap aligned
+; x29 = load64_u sp+0 // flags = notrap aligned
+; x30 = xconst8 16
+; x27 = xadd32 x27, x30
+; ret
+;
+; Disassembled:
+; xconst8 spilltmp0, -16
+; xadd32 sp, sp, spilltmp0
+; store64_offset8 sp, 8, lr
+; store64 sp, fp
+; xmov fp, sp
+; call_indirect x0
+; load64_offset8 lr, sp, 8
+; load64 fp, sp
+; xconst8 spilltmp0, 16
+; xadd32 sp, sp, spilltmp0
+; ret
+
diff --git a/pulley/fuzz/src/interp.rs b/pulley/fuzz/src/interp.rs
index 5fd70b082c16..c7a659ede488 100644
--- a/pulley/fuzz/src/interp.rs
+++ b/pulley/fuzz/src/interp.rs
@@ -97,6 +97,7 @@ fn op_is_safe_for_fuzzing(op: &Op) -> bool {
Op::BitcastFloatFromInt64(_) => true,
Op::ExtendedOp(op) => extended_op_is_safe_for_fuzzing(op),
Op::Call(_) => false,
+ Op::CallIndirect(_) => false,
Op::Xadd32(Xadd32 { operands, .. })
| Op::Xadd64(Xadd64 { operands, .. })
| Op::Xeq64(Xeq64 { operands, .. })
diff --git a/pulley/src/interp.rs b/pulley/src/interp.rs
index c0817f454144..470ea0dce0a5 100644
--- a/pulley/src/interp.rs
+++ b/pulley/src/interp.rs
@@ -642,6 +642,18 @@ impl OpVisitor for Interpreter<'_> {
ControlFlow::Continue(())
}
+ fn call_indirect(&mut self, dst: XReg) -> ControlFlow