Merge pull request #1570 from cfallin/fix-long-range-aarch64-call

Fix long-range (non-colocated) aarch64 calls to not use Arm64Call reloc, and fix simplejit to use new long-distance call.
This commit is contained in:
Chris Fallin
2020-05-05 10:45:55 -07:00
committed by GitHub
10 changed files with 114 additions and 23 deletions

View File

@@ -1061,7 +1061,7 @@ impl ABIBody for AArch64ABIBody {
}
enum CallDest {
ExtName(ir::ExternalName),
ExtName(ir::ExternalName, RelocDistance),
Reg(Reg),
}
@@ -1102,6 +1102,7 @@ impl AArch64ABICall {
pub fn from_func(
sig: &ir::Signature,
extname: &ir::ExternalName,
dist: RelocDistance,
loc: ir::SourceLoc,
) -> AArch64ABICall {
let sig = ABISig::from_func_sig(sig);
@@ -1110,7 +1111,7 @@ impl AArch64ABICall {
sig,
uses,
defs,
dest: CallDest::ExtName(extname.clone()),
dest: CallDest::ExtName(extname.clone(), dist),
loc,
opcode: ir::Opcode::Call,
}
@@ -1207,13 +1208,28 @@ impl ABICall for AArch64ABICall {
fn gen_call(&self) -> Vec<Inst> {
let (uses, defs) = (self.uses.clone(), self.defs.clone());
match &self.dest {
&CallDest::ExtName(ref name) => vec![Inst::Call {
&CallDest::ExtName(ref name, RelocDistance::Near) => vec![Inst::Call {
dest: name.clone(),
uses,
defs,
loc: self.loc,
opcode: self.opcode,
}],
&CallDest::ExtName(ref name, RelocDistance::Far) => vec![
Inst::LoadExtName {
rd: writable_spilltmp_reg(),
name: name.clone(),
offset: 0,
srcloc: self.loc,
},
Inst::CallInd {
rn: spilltmp_reg(),
uses,
defs,
loc: self.loc,
opcode: self.opcode,
},
],
&CallDest::Reg(reg) => vec![Inst::CallInd {
rn: reg,
uses,

View File

@@ -612,7 +612,10 @@ pub enum Inst {
cond: Cond,
},
/// A machine call instruction.
/// A machine call instruction. N.B.: this allows only a +/- 128MB offset (it uses a relocation
/// of type `Reloc::Arm64Call`); if the destination distance is not `RelocDistance::Near`, the
/// code should use a `LoadExtName` / `CallInd` sequence instead, allowing an arbitrary 64-bit
/// target.
Call {
dest: ExternalName,
uses: Set<Reg>,

View File

@@ -1233,7 +1233,8 @@ pub(crate) fn lower_insn_to_regs<C: LowerCtx<I = Inst>>(ctx: &mut C, insn: IRIns
Opcode::FuncAddr => {
let rd = output_to_reg(ctx, outputs[0]);
let extname = ctx.call_target(insn).unwrap().clone();
let (extname, _) = ctx.call_target(insn).unwrap();
let extname = extname.clone();
let loc = ctx.srcloc(insn);
ctx.emit(Inst::LoadExtName {
rd,
@@ -1249,7 +1250,7 @@ pub(crate) fn lower_insn_to_regs<C: LowerCtx<I = Inst>>(ctx: &mut C, insn: IRIns
Opcode::SymbolValue => {
let rd = output_to_reg(ctx, outputs[0]);
let (extname, offset) = ctx.symbol_value(insn).unwrap();
let (extname, _, offset) = ctx.symbol_value(insn).unwrap();
let extname = extname.clone();
let loc = ctx.srcloc(insn);
ctx.emit(Inst::LoadExtName {
@@ -1264,12 +1265,15 @@ pub(crate) fn lower_insn_to_regs<C: LowerCtx<I = Inst>>(ctx: &mut C, insn: IRIns
let loc = ctx.srcloc(insn);
let (abi, inputs) = match op {
Opcode::Call => {
let extname = ctx.call_target(insn).unwrap();
let (extname, dist) = ctx.call_target(insn).unwrap();
let extname = extname.clone();
let sig = ctx.call_sig(insn).unwrap();
assert!(inputs.len() == sig.params.len());
assert!(outputs.len() == sig.returns.len());
(AArch64ABICall::from_func(sig, &extname, loc), &inputs[..])
(
AArch64ABICall::from_func(sig, &extname, dist, loc),
&inputs[..],
)
}
Opcode::CallIndirect => {
let ptr = input_to_reg(ctx, inputs[0], NarrowValueMode::ZeroExtend64);