diff --git a/cranelift/codegen/src/isa/s390x/inst.isle b/cranelift/codegen/src/isa/s390x/inst.isle index 0880ac23c8..6f0a4605b7 100644 --- a/cranelift/codegen/src/isa/s390x/inst.isle +++ b/cranelift/codegen/src/isa/s390x/inst.isle @@ -3511,6 +3511,9 @@ (decl abi_sig (SigRef) Sig) (extern constructor abi_sig abi_sig) +(decl abi_first_ret (SigRef Sig) usize) +(extern constructor abi_first_ret abi_first_ret) + (decl abi_call_info (Sig ExternalName CallArgList CallRetList Opcode) BoxCallInfo) (extern constructor abi_call_info abi_call_info) diff --git a/cranelift/codegen/src/isa/s390x/lower.isle b/cranelift/codegen/src/isa/s390x/lower.isle index f5ca29cdbd..1140658acd 100644 --- a/cranelift/codegen/src/isa/s390x/lower.isle +++ b/cranelift/codegen/src/isa/s390x/lower.isle @@ -3892,7 +3892,8 @@ (uses CallArgList (lower_call_args abi (range 0 (abi_num_args abi)) args)) (defs CallRetList (defs_init abi)) (_ InstOutput (side_effect (abi_call abi name uses defs (Opcode.Call))))) - (lower_call_rets abi defs (range 0 (abi_num_rets abi)) (output_builder_new)))) + (lower_call_rets abi defs (range (abi_first_ret sig_ref abi) + (abi_num_rets abi)) (output_builder_new)))) ;; Direct call to an out-of-range function (implicitly via pointer). (rule (lower (call (func_ref_data sig_ref name _) args)) @@ -3902,7 +3903,8 @@ (defs CallRetList (defs_init abi)) (target Reg (load_symbol_reloc (SymbolReloc.Absolute name 0))) (_ InstOutput (side_effect (abi_call_ind abi target uses defs (Opcode.Call))))) - (lower_call_rets abi defs (range 0 (abi_num_rets abi)) (output_builder_new)))) + (lower_call_rets abi defs (range (abi_first_ret sig_ref abi) + (abi_num_rets abi)) (output_builder_new)))) ;; Indirect call. (rule (lower (call_indirect sig_ref ptr args)) @@ -3912,7 +3914,8 @@ (uses CallArgList (lower_call_args abi (range 0 (abi_num_args abi)) args)) (defs CallRetList (defs_init abi)) (_ InstOutput (side_effect (abi_call_ind abi target uses defs (Opcode.CallIndirect))))) - (lower_call_rets abi defs (range 0 (abi_num_rets abi)) (output_builder_new)))) + (lower_call_rets abi defs (range (abi_first_ret sig_ref abi) + (abi_num_rets abi)) (output_builder_new)))) ;; Lower function arguments. (decl lower_call_args (Sig Range ValueSlice) CallArgList) diff --git a/cranelift/codegen/src/isa/s390x/lower/isle.rs b/cranelift/codegen/src/isa/s390x/lower/isle.rs index 1e6b3da5aa..c956410227 100644 --- a/cranelift/codegen/src/isa/s390x/lower/isle.rs +++ b/cranelift/codegen/src/isa/s390x/lower/isle.rs @@ -165,6 +165,13 @@ impl generated_code::Context for IsleContext<'_, '_, MInst, Flags, IsaFlags, 6> self.lower_ctx.sigs().abi_sig_for_sig_ref(sig_ref) } + fn abi_first_ret(&mut self, sig_ref: SigRef, abi: &Sig) -> usize { + // Return the index of the first actual return value, excluding + // any StructReturn that might have been added to Sig. + let sig = &self.lower_ctx.dfg().signatures[sig_ref]; + self.lower_ctx.sigs()[*abi].num_rets() - sig.returns.len() + } + fn abi_lane_order(&mut self, abi: &Sig) -> LaneOrder { lane_order_for_call_conv(self.lower_ctx.sigs()[*abi].call_conv()) } diff --git a/cranelift/filetests/filetests/isa/s390x/call.clif b/cranelift/filetests/filetests/isa/s390x/call.clif index 53bc100ca2..f07479ee83 100644 --- a/cranelift/filetests/filetests/isa/s390x/call.clif +++ b/cranelift/filetests/filetests/isa/s390x/call.clif @@ -220,3 +220,21 @@ block0(v0: i128, v1: i128, v2: i128, v3: i128, v4: i128, v5: i128, v6: i128, v7: ; vst %v17, 0(%r2) ; br %r14 + +function %call_sret() -> i64 { + fn0 = colocated %g(i64 sret) + +block0: + v1 = iconst.i64 0 + call fn0(v1) + trap user0 +} + +; stmg %r14, %r15, 112(%r15) +; aghi %r15, -160 +; virtual_sp_offset_adjust 160 +; block0: +; lghi %r2, 0 +; brasl %r14, %g +; trap +