Assign stack slots to incoming function arguments.
Function arguments that don't fit in registers are passed on the stack. Create "incoming_arg" stack slots representing the stack arguments, and assign them to the value arguments during spilling.
This commit is contained in:
@@ -253,19 +253,8 @@ impl<'a> Context<'a> {
|
||||
}
|
||||
|
||||
}
|
||||
Affinity::Stack => {
|
||||
if let ArgumentLoc::Stack(_offset) = abi.location {
|
||||
// TODO: Allocate a stack slot at incoming offset and assign it.
|
||||
panic!("Unimplemented {}: {} stack allocation",
|
||||
lv.value,
|
||||
abi.display(&self.reginfo));
|
||||
} else {
|
||||
// This should have been fixed by the reload pass.
|
||||
panic!("Entry arg {} has stack affinity, but ABI {}",
|
||||
lv.value,
|
||||
abi.display(&self.reginfo));
|
||||
}
|
||||
}
|
||||
// The spiller will have assigned an incoming stack slot already.
|
||||
Affinity::Stack => assert!(abi.location.is_stack()),
|
||||
// This is a ghost value, unused in the function. Don't assign it to a location
|
||||
// either.
|
||||
Affinity::None => {}
|
||||
|
||||
@@ -17,7 +17,7 @@
|
||||
|
||||
use dominator_tree::DominatorTree;
|
||||
use ir::{DataFlowGraph, Layout, Cursor, InstBuilder};
|
||||
use ir::{Function, Ebb, Inst, Value, ValueLoc, SigRef};
|
||||
use ir::{Function, Ebb, Inst, Value, ValueLoc, ArgumentLoc, Signature, SigRef};
|
||||
use ir::{InstEncodings, StackSlots, ValueLocations};
|
||||
use isa::registers::{RegClass, RegClassMask};
|
||||
use isa::{TargetIsa, RegInfo, EncInfo, RecipeConstraints, ConstraintKind};
|
||||
@@ -45,6 +45,7 @@ struct Context<'a> {
|
||||
encodings: &'a mut InstEncodings,
|
||||
stack_slots: &'a mut StackSlots,
|
||||
locations: &'a mut ValueLocations,
|
||||
func_signature: &'a Signature,
|
||||
|
||||
// References to contextual data structures we need.
|
||||
domtree: &'a DominatorTree,
|
||||
@@ -92,6 +93,7 @@ impl Spilling {
|
||||
encodings: &mut func.encodings,
|
||||
stack_slots: &mut func.stack_slots,
|
||||
locations: &mut func.locations,
|
||||
func_signature: &func.signature,
|
||||
domtree,
|
||||
liveness,
|
||||
virtregs,
|
||||
@@ -109,12 +111,37 @@ impl<'a> Context<'a> {
|
||||
layout: &mut Layout,
|
||||
dfg: &mut DataFlowGraph,
|
||||
tracker: &mut LiveValueTracker) {
|
||||
if let Some(entry) = layout.entry_block() {
|
||||
self.spill_entry_arguments(entry, dfg);
|
||||
}
|
||||
|
||||
self.topo.reset(layout.ebbs());
|
||||
while let Some(ebb) = self.topo.next(layout, self.domtree) {
|
||||
self.visit_ebb(ebb, layout, dfg, tracker);
|
||||
}
|
||||
}
|
||||
|
||||
/// Assign stack slots to incoming function arguments on the stack.
|
||||
fn spill_entry_arguments(&mut self, entry: Ebb, dfg: &DataFlowGraph) {
|
||||
for (abi, &arg) in self.func_signature
|
||||
.argument_types
|
||||
.iter()
|
||||
.zip(dfg.ebb_args(entry)) {
|
||||
if let ArgumentLoc::Stack(offset) = abi.location {
|
||||
// Function arguments passed on the stack can't be part of a virtual register. We
|
||||
// would need to write other values to the stack slot, but it belongs to the
|
||||
// caller. (Not that the caller would care, nobody depends on stack arguments being
|
||||
// preserved across calls).
|
||||
assert_eq!(self.virtregs.get(arg),
|
||||
None,
|
||||
"Stack argument {} can't be part of a virtual register",
|
||||
arg);
|
||||
let ss = self.stack_slots.make_incoming_arg(abi.value_type, offset);
|
||||
*self.locations.ensure(arg) = ValueLoc::Stack(ss);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn visit_ebb(&mut self,
|
||||
ebb: Ebb,
|
||||
layout: &mut Layout,
|
||||
|
||||
Reference in New Issue
Block a user