Implement stack_addr, stack_load, stack_store for x86-64. (#370)
This commit is contained in:
@@ -80,6 +80,10 @@ expand.custom_legalize(insts.select, 'expand_select')
|
||||
expand.custom_legalize(insts.f32const, 'expand_fconst')
|
||||
expand.custom_legalize(insts.f64const, 'expand_fconst')
|
||||
|
||||
# Custom expansions for stack memory accesses.
|
||||
expand.custom_legalize(insts.stack_load, 'expand_stack_load')
|
||||
expand.custom_legalize(insts.stack_store, 'expand_stack_store')
|
||||
|
||||
x = Var('x')
|
||||
y = Var('y')
|
||||
a = Var('a')
|
||||
|
||||
@@ -436,6 +436,15 @@ X86_64.enc(base.globalsym_addr.i64, *r.pcrel_gvaddr8.rex(0x8d, w=1),
|
||||
X86_64.enc(base.globalsym_addr.i64, *r.got_gvaddr8.rex(0x8b, w=1),
|
||||
isap=is_pic)
|
||||
|
||||
#
|
||||
# Stack addresses.
|
||||
#
|
||||
# TODO: Add encoding rules for stack_load and stack_store, so that they
|
||||
# don't get legalized to stack_addr + load/store.
|
||||
#
|
||||
X86_32.enc(base.stack_addr.i32, *r.spaddr4_id(0x8d))
|
||||
X86_64.enc(base.stack_addr.i64, *r.spaddr8_id.rex(0x8d, w=1))
|
||||
|
||||
#
|
||||
# Call/return
|
||||
#
|
||||
|
||||
@@ -17,6 +17,7 @@ from base.formats import Jump, Branch, BranchInt, BranchFloat
|
||||
from base.formats import Ternary, FuncAddr, UnaryGlobalValue
|
||||
from base.formats import RegMove, RegSpill, RegFill, CopySpecial
|
||||
from base.formats import LoadComplex, StoreComplex
|
||||
from base.formats import StackLoad
|
||||
from .registers import GPR, ABCD, FPR, GPR_DEREF_SAFE, GPR_ZERO_DEREF_SAFE
|
||||
from .registers import GPR8, FPR8, GPR8_DEREF_SAFE, GPR8_ZERO_DEREF_SAFE, FLAG
|
||||
from .registers import StackGPR32, StackFPR32
|
||||
@@ -751,6 +752,36 @@ got_gvaddr8 = TailRecipe(
|
||||
sink.put4(0);
|
||||
''')
|
||||
|
||||
#
|
||||
# Stack addresses.
|
||||
#
|
||||
# TODO: Alternative forms for 8-bit immediates, when applicable.
|
||||
#
|
||||
|
||||
spaddr4_id = TailRecipe(
|
||||
'spaddr4_id', StackLoad, size=6, ins=(), outs=GPR,
|
||||
emit='''
|
||||
let sp = StackRef::sp(stack_slot, &func.stack_slots);
|
||||
let base = stk_base(sp.base);
|
||||
PUT_OP(bits, rex2(out_reg0, base), sink);
|
||||
modrm_sib_disp8(out_reg0, sink);
|
||||
sib_noindex(base, sink);
|
||||
let imm : i32 = offset.into();
|
||||
sink.put4(sp.offset.checked_add(imm).unwrap() as u32);
|
||||
''')
|
||||
|
||||
spaddr8_id = TailRecipe(
|
||||
'spaddr8_id', StackLoad, size=6, ins=(), outs=GPR,
|
||||
emit='''
|
||||
let sp = StackRef::sp(stack_slot, &func.stack_slots);
|
||||
let base = stk_base(sp.base);
|
||||
PUT_OP(bits, rex2(base, out_reg0), sink);
|
||||
modrm_sib_disp32(out_reg0, sink);
|
||||
sib_noindex(base, sink);
|
||||
let imm : i32 = offset.into();
|
||||
sink.put4(sp.offset.checked_add(imm).unwrap() as u32);
|
||||
''')
|
||||
|
||||
|
||||
#
|
||||
# Store recipes.
|
||||
|
||||
@@ -16,7 +16,7 @@
|
||||
use bitset::BitSet;
|
||||
use cursor::{Cursor, FuncCursor};
|
||||
use flowgraph::ControlFlowGraph;
|
||||
use ir::{self, InstBuilder};
|
||||
use ir::{self, InstBuilder, MemFlags};
|
||||
use isa::TargetIsa;
|
||||
use timing;
|
||||
|
||||
@@ -269,3 +269,71 @@ fn expand_fconst(
|
||||
};
|
||||
pos.func.dfg.replace(inst).bitcast(ty, ival);
|
||||
}
|
||||
|
||||
/// Expand illegal `stack_load` instructions.
|
||||
fn expand_stack_load(
|
||||
inst: ir::Inst,
|
||||
func: &mut ir::Function,
|
||||
_cfg: &mut ControlFlowGraph,
|
||||
isa: &TargetIsa,
|
||||
) {
|
||||
let ty = func.dfg.value_type(func.dfg.first_result(inst));
|
||||
let addr_ty = isa.pointer_type();
|
||||
|
||||
let mut pos = FuncCursor::new(func).at_inst(inst);
|
||||
pos.use_srcloc(inst);
|
||||
|
||||
let (stack_slot, offset) = match pos.func.dfg[inst] {
|
||||
ir::InstructionData::StackLoad {
|
||||
opcode: _opcode,
|
||||
stack_slot,
|
||||
offset,
|
||||
} => (stack_slot, offset),
|
||||
_ => panic!(
|
||||
"Expected stack_load: {}",
|
||||
pos.func.dfg.display_inst(inst, None)
|
||||
),
|
||||
};
|
||||
|
||||
let addr = pos.ins().stack_addr(addr_ty, stack_slot, offset);
|
||||
|
||||
let mut mflags = MemFlags::new();
|
||||
// Stack slots are required to be accessible and aligned.
|
||||
mflags.set_notrap();
|
||||
mflags.set_aligned();
|
||||
pos.func.dfg.replace(inst).load(ty, mflags, addr, 0);
|
||||
}
|
||||
|
||||
/// Expand illegal `stack_store` instructions.
|
||||
fn expand_stack_store(
|
||||
inst: ir::Inst,
|
||||
func: &mut ir::Function,
|
||||
_cfg: &mut ControlFlowGraph,
|
||||
isa: &TargetIsa,
|
||||
) {
|
||||
let addr_ty = isa.pointer_type();
|
||||
|
||||
let mut pos = FuncCursor::new(func).at_inst(inst);
|
||||
pos.use_srcloc(inst);
|
||||
|
||||
let (val, stack_slot, offset) = match pos.func.dfg[inst] {
|
||||
ir::InstructionData::StackStore {
|
||||
opcode: _opcode,
|
||||
arg,
|
||||
stack_slot,
|
||||
offset,
|
||||
} => (arg, stack_slot, offset),
|
||||
_ => panic!(
|
||||
"Expected stack_store: {}",
|
||||
pos.func.dfg.display_inst(inst, None)
|
||||
),
|
||||
};
|
||||
|
||||
let addr = pos.ins().stack_addr(addr_ty, stack_slot, offset);
|
||||
|
||||
let mut mflags = MemFlags::new();
|
||||
// Stack slots are required to be accessible and aligned.
|
||||
mflags.set_notrap();
|
||||
mflags.set_aligned();
|
||||
pos.func.dfg.replace(inst).store(mflags, val, addr, 0);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user