Implement stack_addr for AArch64

This commit is contained in:
bjorn3
2020-04-15 18:28:31 +02:00
parent d2eb56c607
commit 1bee1af755
6 changed files with 95 additions and 3 deletions

View File

@@ -497,6 +497,16 @@ impl ABIBody for AArch64ABIBody {
store_stack(fp_off, from_reg, ty)
}
fn stackslot_addr(&self, slot: StackSlot, offset: u32, into_reg: Writable<Reg>) -> Inst {
// Offset from beginning of stackslot area, which is at FP - stackslots_size.
let stack_off = self.stackslots[slot.as_u32() as usize] as i64;
let fp_off: i64 = -(self.stackslots_size as i64) + stack_off + (offset as i64);
Inst::LoadAddr {
rd: into_reg,
mem: MemArg::FPOffset(fp_off),
}
}
// Load from a spillslot.
fn load_spillslot(&self, slot: SpillSlot, ty: Type, into_reg: Writable<Reg>) -> Inst {
// Note that when spills/fills are generated, we don't yet know how many

View File

@@ -6,11 +6,10 @@ use crate::ir::types::*;
use crate::ir::TrapCode;
use crate::isa::aarch64::inst::*;
use core::convert::TryFrom;
use regalloc::{Reg, RegClass, Writable};
use alloc::vec::Vec;
use core::convert::TryFrom;
/// Memory label/reference finalization: convert a MemLabel to a PC-relative
/// offset, possibly emitting relocation(s) as necessary.
@@ -1275,6 +1274,40 @@ impl<O: MachSectionOutput> MachInstEmit<O> for Inst {
sink.add_reloc(srcloc, Reloc::Abs8, name, offset);
sink.put8(0);
}
&Inst::LoadAddr { rd, ref mem } => match *mem {
MemArg::FPOffset(fp_off) => {
let alu_op = if fp_off < 0 {
ALUOp::Sub64
} else {
ALUOp::Add64
};
if let Some(imm12) = Imm12::maybe_from_u64(u64::try_from(fp_off.abs()).unwrap())
{
let inst = Inst::AluRRImm12 {
alu_op,
rd,
imm12,
rn: fp_reg(),
};
inst.emit(sink);
} else {
let tmp = writable_spilltmp_reg();
let const_insts =
Inst::load_constant(tmp, u64::try_from(fp_off.abs()).unwrap());
for inst in const_insts {
inst.emit(sink);
}
let inst = Inst::AluRRR {
alu_op,
rd,
rn: fp_reg(),
rm: tmp.to_reg(),
};
inst.emit(sink);
}
}
_ => unimplemented!("{:?}", mem),
},
}
}
}

View File

@@ -707,6 +707,12 @@ pub enum Inst {
srcloc: SourceLoc,
offset: i64,
},
/// Load address referenced by `mem` into `rd`.
LoadAddr {
rd: Writable<Reg>,
mem: MemArg,
},
}
fn count_zero_half_words(mut value: u64) -> usize {
@@ -1089,6 +1095,9 @@ fn aarch64_get_regs(inst: &Inst, collector: &mut RegUsageCollector) {
&Inst::LoadConst64 { rd, .. } | &Inst::LoadExtName { rd, .. } => {
collector.add_def(rd);
}
&Inst::LoadAddr { rd, mem: _ } => {
collector.add_def(rd);
}
}
}
@@ -1643,6 +1652,13 @@ fn aarch64_map_regs(
&mut Inst::LoadExtName { ref mut rd, .. } => {
map_wr(d, rd);
}
&mut Inst::LoadAddr {
ref mut rd,
ref mut mem,
} => {
map_wr(d, rd);
map_mem(u, mem);
}
}
}
@@ -2536,6 +2552,12 @@ impl ShowWithRRU for Inst {
let rd = rd.show_rru(mb_rru);
format!("ldr {}, 8 ; b 12 ; data {:?} + {}", rd, name, offset)
}
&Inst::LoadAddr { rd, ref mem } => {
let rd = rd.show_rru(mb_rru);
let (mem_str, mem) = mem_finalize_for_show(mem, mb_rru);
let mem = mem.show_rru(mb_rru);
format!("{}load_addr {}, {}", mem_str, rd, mem)
}
}
}
}

View File

@@ -22,6 +22,7 @@ use crate::isa::aarch64::AArch64Backend;
use regalloc::{Reg, RegClass, Writable};
use alloc::vec::Vec;
use core::convert::TryFrom;
use smallvec::SmallVec;
//============================================================================
@@ -1546,7 +1547,24 @@ fn lower_insn_to_regs<C: LowerCtx<I = Inst>>(ctx: &mut C, insn: IRInst) {
});
}
Opcode::StackLoad | Opcode::StackStore | Opcode::StackAddr => {
Opcode::StackAddr => {
let (stack_slot, offset) = match *ctx.data(insn) {
InstructionData::StackLoad {
opcode: Opcode::StackAddr,
stack_slot,
offset,
} => (stack_slot, offset),
_ => unreachable!(),
};
let rd = output_to_reg(ctx, outputs[0]);
let offset: i32 = offset.into();
let inst = ctx
.abi()
.stackslot_addr(stack_slot, u32::try_from(offset).unwrap(), rd);
ctx.emit(inst);
}
Opcode::StackLoad | Opcode::StackStore => {
panic!("Direct stack memory access not supported; should not be used by Wasm");
}

View File

@@ -56,6 +56,9 @@ pub trait ABIBody {
/// Update with the clobbered registers, post-regalloc.
fn set_clobbered(&mut self, clobbered: Set<Writable<RealReg>>);
/// Get the address of a stackslot.
fn stackslot_addr(&self, slot: StackSlot, offset: u32, into_reg: Writable<Reg>) -> Self::I;
/// Load from a stackslot.
fn load_stackslot(
&self,

View File

@@ -31,6 +31,8 @@ pub trait LowerCtx {
fn data(&self, ir_inst: Inst) -> &InstructionData;
/// Get the controlling type for a polymorphic IR instruction.
fn ty(&self, ir_inst: Inst) -> Type;
/// Get the `ABIBody`.
fn abi(&mut self) -> &dyn ABIBody<I = Self::I>;
/// Emit a machine instruction.
fn emit(&mut self, mach_inst: Self::I);
/// Indicate that an IR instruction has been merged, and so one of its
@@ -527,6 +529,10 @@ impl<'a, I: VCodeInst> LowerCtx for Lower<'a, I> {
self.f.dfg.ctrl_typevar(ir_inst)
}
fn abi(&mut self) -> &dyn ABIBody<I = I> {
self.vcode.abi()
}
/// Emit a machine instruction.
fn emit(&mut self, mach_inst: I) {
self.vcode.push(mach_inst);