Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

s390x: Hard code the link register in all call and return instructions #9361

Open
wants to merge 2 commits into
base: main
Choose a base branch
from
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
1 change: 0 additions & 1 deletion cranelift/bforest/src/node.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,6 @@ use core::fmt;
///
/// An inner node contains at least M/2 node references unless it is the right-most node at its
/// level. A leaf node contains at least N/2 keys unless it is the right-most leaf.
#[allow(dead_code)] // workaround for https://github.com/rust-lang/rust/issues/64362
pub(super) enum NodeData<F: Forest> {
Inner {
/// The number of keys in this node.
Expand Down
1 change: 0 additions & 1 deletion cranelift/codegen/src/isa/riscv64/inst/imms.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@

// Some variants are never constructed, but we still want them as options in the future.
use super::Inst;
#[allow(dead_code)]
use std::fmt::{Debug, Display, Formatter, Result};

#[derive(Copy, Clone, Debug, Default)]
Expand Down
2 changes: 1 addition & 1 deletion cranelift/codegen/src/isa/s390x/abi.rs
Original file line number Diff line number Diff line change
Expand Up @@ -638,7 +638,7 @@ impl ABIMachineSpec for S390xMachineDeps {
_isa_flags: &s390x_settings::Flags,
_frame_layout: &FrameLayout,
) -> SmallInstVec<Inst> {
smallvec![Inst::Ret { link: gpr(14) }]
smallvec![Inst::Ret]
}

fn gen_probestack(_insts: &mut SmallInstVec<Self::I>, _: u32) {
Expand Down
27 changes: 10 additions & 17 deletions cranelift/codegen/src/isa/s390x/inst.isle
Original file line number Diff line number Diff line change
Expand Up @@ -893,12 +893,10 @@

;; A machine call instruction.
(Call
(link WritableReg)
(info BoxCallInfo))

;; A machine indirect-call instruction.
(CallInd
(link WritableReg)
(info BoxCallIndInfo))

;; A machine tail call instruction.
Expand All @@ -920,8 +918,7 @@
;; ---- branches (exactly one must appear at end of BB) ----

;; A machine return instruction.
(Ret
(link Reg))
(Ret)

;; An unconditional branch.
(Jump
Expand Down Expand Up @@ -1021,7 +1018,6 @@
(tls_offset WritableReg)
(got Reg)
(got_offset Reg)
(link WritableReg)
(symbol BoxSymbolReloc))
))

Expand Down Expand Up @@ -2699,14 +2695,14 @@
dst))

;; Helper for emitting `MInst.Call` instructions.
(decl call_impl (WritableReg BoxCallInfo) SideEffectNoResult)
(rule (call_impl reg info)
(SideEffectNoResult.Inst (MInst.Call reg info)))
(decl call_impl (BoxCallInfo) SideEffectNoResult)
(rule (call_impl info)
(SideEffectNoResult.Inst (MInst.Call info)))

;; Helper for emitting `MInst.CallInd` instructions.
(decl call_ind_impl (WritableReg BoxCallIndInfo) SideEffectNoResult)
(rule (call_ind_impl reg info)
(SideEffectNoResult.Inst (MInst.CallInd reg info)))
(decl call_ind_impl (BoxCallIndInfo) SideEffectNoResult)
(rule (call_ind_impl info)
(SideEffectNoResult.Inst (MInst.CallInd info)))

;; Helper for emitting `MInst.ReturnCall` instructions.
(decl return_call_impl (BoxReturnCallInfo) SideEffectNoResult)
Expand Down Expand Up @@ -3581,16 +3577,13 @@
(decl abi_return_call_stack_args (Sig) MemArg)
(extern constructor abi_return_call_stack_args abi_return_call_stack_args)

(decl writable_link_reg () WritableReg)
(rule (writable_link_reg) (writable_gpr 14))

(decl abi_call (Sig ExternalName CallArgList CallRetList) SideEffectNoResult)
(rule (abi_call abi name uses defs)
(call_impl (writable_link_reg) (abi_call_info abi name uses defs)))
(call_impl (abi_call_info abi name uses defs)))

(decl abi_call_ind (Sig Reg CallArgList CallRetList) SideEffectNoResult)
(rule (abi_call_ind abi target uses defs)
(call_ind_impl (writable_link_reg) (abi_call_ind_info abi target uses defs)))
(call_ind_impl (abi_call_ind_info abi target uses defs)))

(decl abi_return_call (Sig ExternalName CallArgList) SideEffectNoResult)
(rule (abi_return_call abi name uses)
Expand All @@ -3613,7 +3606,7 @@

(decl lib_call (BoxCallInfo) SideEffectNoResult)
(rule (lib_call info)
(call_impl (writable_link_reg) info))
(call_impl info))


;; Helpers for generating vector pack and unpack instructions ;;;;;;;;;;;;;;;;;;
Expand Down
23 changes: 7 additions & 16 deletions cranelift/codegen/src/isa/s390x/inst/emit.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3257,9 +3257,7 @@ impl Inst {
inst.emit(sink, emit_info, state);
state.nominal_sp_offset += size;
}
&Inst::Call { link, ref info } => {
debug_assert_eq!(link.to_reg(), gpr(14));

&Inst::Call { ref info } => {
let opcode = 0xc05; // BRASL

// Add relocation for target function. This has to be done *before*
Expand All @@ -3272,21 +3270,19 @@ impl Inst {
sink.push_user_stack_map(state, offset, s);
}

put(sink, &enc_ril_b(opcode, link.to_reg(), 0));
put(sink, &enc_ril_b(opcode, link_reg(), 0));
sink.add_call_site();

state.nominal_sp_offset -= info.callee_pop_size;
}
&Inst::CallInd { link, ref info } => {
debug_assert_eq!(link.to_reg(), gpr(14));

&Inst::CallInd { ref info } => {
if let Some(s) = state.take_stack_map() {
let offset = sink.cur_offset() + 2;
sink.push_user_stack_map(state, offset, s);
}

let opcode = 0x0d; // BASR
put(sink, &enc_rr(opcode, link.to_reg(), info.dest));
put(sink, &enc_rr(opcode, link_reg(), info.dest));
sink.add_call_site();

state.nominal_sp_offset -= info.callee_pop_size;
Expand Down Expand Up @@ -3319,11 +3315,7 @@ impl Inst {
put(sink, &enc_rr(opcode, gpr(15), rn));
sink.add_call_site();
}
&Inst::ElfTlsGetOffset {
ref symbol, link, ..
} => {
debug_assert_eq!(link.to_reg(), gpr(14));

&Inst::ElfTlsGetOffset { ref symbol, .. } => {
let opcode = 0xc05; // BRASL

// Add relocation for target function. This has to be done
Expand All @@ -3341,10 +3333,9 @@ impl Inst {
}
&Inst::Args { .. } => {}
&Inst::Rets { .. } => {}
&Inst::Ret { link } => {
debug_assert_eq!(link, gpr(14));
&Inst::Ret => {
let opcode = 0x07; // BCR
put(sink, &enc_rr(opcode, gpr(15), link));
put(sink, &enc_rr(opcode, gpr(15), link_reg()));
}
&Inst::Jump { dest } => {
let off = sink.cur_offset();
Expand Down
4 changes: 1 addition & 3 deletions cranelift/codegen/src/isa/s390x/inst/emit_tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6982,7 +6982,6 @@ fn test_s390x_binemit() {

insns.push((
Inst::Call {
link: writable_gpr(14),
info: Box::new(CallInfo::empty(
ExternalName::testcase("test0"),
CallConv::SystemV,
Expand All @@ -6994,14 +6993,13 @@ fn test_s390x_binemit() {

insns.push((
Inst::CallInd {
link: writable_gpr(14),
info: Box::new(CallInfo::empty(gpr(1), CallConv::SystemV)),
},
"0DE1",
"basr %r14, %r1",
));

insns.push((Inst::Ret { link: gpr(14) }, "07FE", "br %r14"));
insns.push((Inst::Ret, "07FE", "br %r14"));

insns.push((Inst::Debugtrap, "0001", ".word 0x0001 # debugtrap"));

Expand Down
42 changes: 15 additions & 27 deletions cranelift/codegen/src/isa/s390x/inst/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -873,7 +873,7 @@ fn s390x_get_operands(inst: &mut Inst, collector: &mut DenyReuseVisitor<impl Ope
collector.reg_use(rn);
}
Inst::AllocateArgs { .. } => {}
Inst::Call { link, info, .. } => {
Inst::Call { info } => {
let CallInfo {
uses,
defs,
Expand All @@ -884,14 +884,14 @@ fn s390x_get_operands(inst: &mut Inst, collector: &mut DenyReuseVisitor<impl Ope
collector.reg_fixed_use(vreg, *preg);
}
let mut clobbers = *clobbers;
clobbers.add(link.to_reg().to_real_reg().unwrap().into());
clobbers.add(link_reg().to_real_reg().unwrap().into());
for CallRetPair { vreg, preg } in defs {
clobbers.remove(PReg::from(preg.to_real_reg().unwrap()));
collector.reg_fixed_def(vreg, *preg);
}
collector.reg_clobbers(clobbers);
}
Inst::CallInd { link, info } => {
Inst::CallInd { info } => {
let CallInfo {
dest,
uses,
Expand All @@ -904,7 +904,7 @@ fn s390x_get_operands(inst: &mut Inst, collector: &mut DenyReuseVisitor<impl Ope
collector.reg_fixed_use(vreg, *preg);
}
let mut clobbers = *clobbers;
clobbers.add(link.to_reg().to_real_reg().unwrap().into());
clobbers.add(link_reg().to_real_reg().unwrap().into());
for CallRetPair { vreg, preg } in defs {
clobbers.remove(PReg::from(preg.to_real_reg().unwrap()));
collector.reg_fixed_def(vreg, *preg);
Expand All @@ -928,15 +928,14 @@ fn s390x_get_operands(inst: &mut Inst, collector: &mut DenyReuseVisitor<impl Ope
tls_offset,
got,
got_offset,
link,
..
} => {
collector.reg_fixed_use(got, gpr(12));
collector.reg_fixed_use(got_offset, gpr(2));
collector.reg_fixed_def(tls_offset, gpr(2));

let mut clobbers = S390xMachineDeps::get_regs_clobbered_by_call(CallConv::SystemV);
clobbers.add(link.to_reg().to_real_reg().unwrap().into());
clobbers.add(link_reg().to_real_reg().unwrap().into());
clobbers.remove(gpr_preg(2));
collector.reg_clobbers(clobbers);
}
Expand Down Expand Up @@ -1063,8 +1062,8 @@ impl MachInst for Inst {
// registers.
match self {
&Inst::Args { .. } => false,
&Inst::Call { ref info, .. } => info.caller_conv != info.callee_conv,
&Inst::CallInd { ref info, .. } => info.caller_conv != info.callee_conv,
&Inst::Call { ref info } => info.caller_conv != info.callee_conv,
&Inst::CallInd { ref info } => info.caller_conv != info.callee_conv,
&Inst::ElfTlsGetOffset { .. } => false,
_ => true,
}
Expand Down Expand Up @@ -3141,31 +3140,27 @@ impl Inst {
format!("slgfi {}, {}", show_reg(stack_reg()), size)
}
}
&Inst::Call { link, ref info } => {
let link = link.to_reg();
&Inst::Call { ref info } => {
let callee_pop_size = if info.callee_pop_size > 0 {
format!(" ; callee_pop_size {}", info.callee_pop_size)
} else {
"".to_string()
};
debug_assert_eq!(link, gpr(14));
format!(
"brasl {}, {}{}",
show_reg(link),
show_reg(link_reg()),
info.dest.display(None),
callee_pop_size
)
}
&Inst::CallInd { link, ref info, .. } => {
let link = link.to_reg();
&Inst::CallInd { ref info, .. } => {
let rn = pretty_print_reg(info.dest);
let callee_pop_size = if info.callee_pop_size > 0 {
format!(" ; callee_pop_size {}", info.callee_pop_size)
} else {
"".to_string()
};
debug_assert_eq!(link, gpr(14));
format!("basr {}, {}{}", show_reg(link), rn, callee_pop_size)
format!("basr {}, {}{}", show_reg(link_reg()), rn, callee_pop_size)
}
&Inst::ReturnCall { ref info } => {
let callee_pop_size = if info.callee_pop_size > 0 {
Expand All @@ -3184,20 +3179,14 @@ impl Inst {
};
format!("return_call_ind {rn}{callee_pop_size}")
}
&Inst::ElfTlsGetOffset {
ref symbol,
ref link,
..
} => {
let link = link.to_reg();
&Inst::ElfTlsGetOffset { ref symbol, .. } => {
let dest = match &**symbol {
SymbolReloc::TlsGd { name } => {
format!("tls_gdcall:{}", name.display(None))
}
_ => unreachable!(),
};
debug_assert_eq!(link, gpr(14));
format!("brasl {}, {}", show_reg(link), dest)
format!("brasl {}, {}", show_reg(link_reg()), dest)
}
&Inst::Args { ref args } => {
let mut s = "args".to_string();
Expand All @@ -3217,9 +3206,8 @@ impl Inst {
}
s
}
&Inst::Ret { link } => {
debug_assert_eq!(link, gpr(14));
let link = show_reg(link);
&Inst::Ret => {
let link = show_reg(link_reg());
format!("br {link}")
}
&Inst::Jump { dest } => {
Expand Down
4 changes: 4 additions & 0 deletions cranelift/codegen/src/isa/s390x/inst/regs.rs
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,10 @@ pub fn zero_reg() -> Reg {
gpr(0)
}

pub fn link_reg() -> Reg {
gpr(14)
}

pub fn show_reg(reg: Reg) -> String {
if let Some(rreg) = reg.to_real_reg() {
match rreg.class() {
Expand Down
2 changes: 1 addition & 1 deletion cranelift/codegen/src/isa/s390x/lower.isle
Original file line number Diff line number Diff line change
Expand Up @@ -2279,7 +2279,7 @@
(rule (lib_call_tls_get_offset got got_offset symbol)
(let ((tls_offset WritableReg (temp_writable_reg $I64))
(_ Unit (abi_for_elf_tls_get_offset))
(_ Unit (emit (MInst.ElfTlsGetOffset tls_offset got got_offset (writable_link_reg) symbol))))
(_ Unit (emit (MInst.ElfTlsGetOffset tls_offset got got_offset symbol))))
tls_offset))

(decl abi_for_elf_tls_get_offset () Unit)
Expand Down