Skip to content

Commit 350a6e2

Browse files
authored
pulley: Fill out more bits and pieces of stack allocation (#9718)
* pulley: Fill out more bits and pieces of stack allocation * Use `push_frame` and `pop_frame` in the Cranelift backend. * Use dedicated instructions for modifying the stack pointer * decrementing the stack pointer is always checked * incrementing the stack pointer is checked in debug mode * Disregard stack probes and stack_limit checks as they're both unnecessary for Pulley (all stack allocations are checked). * Fix pulley fuzz * Fix some tests from a rebase * Fix more tests
1 parent 94da012 commit 350a6e2

File tree

20 files changed

+279
-666
lines changed

20 files changed

+279
-666
lines changed

cranelift/codegen/src/isa/pulley_shared/abi.rs

Lines changed: 26 additions & 85 deletions
Original file line numberDiff line numberDiff line change
@@ -220,18 +220,8 @@ where
220220
]
221221
}
222222

223-
fn gen_stack_lower_bound_trap(limit_reg: Reg) -> SmallInstVec<Self::I> {
224-
smallvec![Inst::TrapIf {
225-
cond: ir::condcodes::IntCC::UnsignedLessThan,
226-
size: match P::pointer_width() {
227-
super::PointerWidth::PointerWidth32 => OperandSize::Size32,
228-
super::PointerWidth::PointerWidth64 => OperandSize::Size64,
229-
},
230-
src1: limit_reg.try_into().unwrap(),
231-
src2: pulley_interpreter::regs::XReg::sp.into(),
232-
code: ir::TrapCode::STACK_OVERFLOW,
233-
}
234-
.into()]
223+
fn gen_stack_lower_bound_trap(_limit_reg: Reg) -> SmallInstVec<Self::I> {
224+
unimplemented!("pulley shouldn't need stack bound checks")
235225
}
236226

237227
fn gen_get_stack_addr(mem: StackAMode, dst: Writable<Reg>) -> Self::I {
@@ -258,29 +248,21 @@ where
258248
return smallvec![];
259249
}
260250

261-
let temp = WritableXReg::try_from(writable_spilltmp_reg()).unwrap();
262-
263-
let imm = if let Ok(x) = i8::try_from(amount) {
264-
Inst::Xconst8 { dst: temp, imm: x }.into()
265-
} else if let Ok(x) = i16::try_from(amount) {
266-
Inst::Xconst16 { dst: temp, imm: x }.into()
251+
let inst = if amount < 0 {
252+
let amount = amount.checked_neg().unwrap();
253+
if let Ok(amt) = u32::try_from(amount) {
254+
Inst::StackAlloc32 { amt }
255+
} else {
256+
unreachable!()
257+
}
267258
} else {
268-
Inst::Xconst32 {
269-
dst: temp,
270-
imm: amount,
259+
if let Ok(amt) = u32::try_from(amount) {
260+
Inst::StackFree32 { amt }
261+
} else {
262+
unreachable!()
271263
}
272-
.into()
273264
};
274-
275-
smallvec![
276-
imm,
277-
Inst::Xadd32 {
278-
dst: WritableXReg::try_from(writable_stack_reg()).unwrap(),
279-
src1: XReg::new(stack_reg()).unwrap(),
280-
src2: temp.to_reg(),
281-
}
282-
.into()
283-
]
265+
smallvec![inst.into()]
284266
}
285267

286268
fn gen_prologue_frame_setup(
@@ -292,29 +274,7 @@ where
292274
let mut insts = SmallVec::new();
293275

294276
if frame_layout.setup_area_size > 0 {
295-
// sp = sub sp, 16 ;; alloc stack space for frame pointer and return address.
296-
// store sp+8, lr ;; save return address.
297-
// store sp, fp ;; save old fp.
298-
// mov sp, fp ;; set fp to sp.
299-
insts.extend(Self::gen_sp_reg_adjust(-16));
300-
insts.push(
301-
Inst::gen_store(
302-
Amode::SpOffset { offset: 8 },
303-
lr_reg(),
304-
I64,
305-
MemFlags::trusted(),
306-
)
307-
.into(),
308-
);
309-
insts.push(
310-
Inst::gen_store(
311-
Amode::SpOffset { offset: 0 },
312-
fp_reg(),
313-
I64,
314-
MemFlags::trusted(),
315-
)
316-
.into(),
317-
);
277+
insts.push(Inst::PushFrame.into());
318278
if flags.unwind_info() {
319279
insts.push(
320280
Inst::Unwind {
@@ -325,13 +285,6 @@ where
325285
.into(),
326286
);
327287
}
328-
insts.push(
329-
Inst::Xmov {
330-
dst: Writable::from_reg(XReg::new(fp_reg()).unwrap()),
331-
src: XReg::new(stack_reg()).unwrap(),
332-
}
333-
.into(),
334-
);
335288
}
336289

337290
insts
@@ -347,25 +300,7 @@ where
347300
let mut insts = SmallVec::new();
348301

349302
if frame_layout.setup_area_size > 0 {
350-
insts.push(
351-
Inst::gen_load(
352-
writable_lr_reg(),
353-
Amode::SpOffset { offset: 8 },
354-
I64,
355-
MemFlags::trusted(),
356-
)
357-
.into(),
358-
);
359-
insts.push(
360-
Inst::gen_load(
361-
writable_fp_reg(),
362-
Amode::SpOffset { offset: 0 },
363-
I64,
364-
MemFlags::trusted(),
365-
)
366-
.into(),
367-
);
368-
insts.extend(Self::gen_sp_reg_adjust(16));
303+
insts.push(Inst::PopFrame.into());
369304
}
370305

371306
if frame_layout.tail_args_size > 0 {
@@ -386,7 +321,8 @@ where
386321
}
387322

388323
fn gen_probestack(_insts: &mut SmallInstVec<Self::I>, _frame_size: u32) {
389-
todo!()
324+
// Pulley doesn't implement stack probes since all stack pointer
325+
// decrements are checked already.
390326
}
391327

392328
fn gen_clobber_save(
@@ -582,11 +518,15 @@ where
582518
}
583519

584520
fn get_number_of_spillslots_for_value(
585-
_rc: RegClass,
521+
rc: RegClass,
586522
_target_vector_bytes: u32,
587523
_isa_flags: &PulleyFlags,
588524
) -> u32 {
589-
todo!()
525+
match rc {
526+
RegClass::Int => 1,
527+
RegClass::Float => todo!(),
528+
RegClass::Vector => unreachable!(),
529+
}
590530
}
591531

592532
fn get_machine_env(_flags: &settings::Flags, _call_conv: isa::CallConv) -> &MachineEnv {
@@ -651,7 +591,8 @@ where
651591
_frame_size: u32,
652592
_guard_size: u32,
653593
) {
654-
todo!()
594+
// Pulley doesn't need inline probestacks because it always checks stack
595+
// decrements.
655596
}
656597
}
657598

cranelift/codegen/src/isa/pulley_shared/inst.isle

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -120,6 +120,12 @@
120120
(BitcastIntFromFloat64 (dst WritableXReg) (src FReg))
121121
(BitcastFloatFromInt32 (dst WritableFReg) (src XReg))
122122
(BitcastFloatFromInt64 (dst WritableFReg) (src XReg))
123+
124+
;; Stack manipulations
125+
(PushFrame)
126+
(PopFrame)
127+
(StackAlloc32 (amt u32))
128+
(StackFree32 (amt u32))
123129
)
124130
)
125131

cranelift/codegen/src/isa/pulley_shared/inst/emit.rs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -548,6 +548,11 @@ fn pulley_emit<P>(
548548
// the assertion that we're always under worst-case-size.
549549
*start_offset = sink.cur_offset();
550550
}
551+
552+
Inst::PushFrame => enc::push_frame(sink),
553+
Inst::PopFrame => enc::pop_frame(sink),
554+
Inst::StackAlloc32 { amt } => enc::stack_alloc32(sink, *amt),
555+
Inst::StackFree32 { amt } => enc::stack_free32(sink, *amt),
551556
}
552557
}
553558

cranelift/codegen/src/isa/pulley_shared/inst/mod.rs

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -252,6 +252,9 @@ fn pulley_get_operands(inst: &mut Inst, collector: &mut impl OperandVisitor) {
252252
Inst::BrTable { idx, .. } => {
253253
collector.reg_use(idx);
254254
}
255+
256+
Inst::StackAlloc32 { .. } | Inst::StackFree32 { .. } | Inst::PushFrame | Inst::PopFrame => {
257+
}
255258
}
256259
}
257260

@@ -862,6 +865,15 @@ impl Inst {
862865
let idx = format_reg(**idx);
863866
format!("br_table {idx} {default:?} {targets:?}")
864867
}
868+
869+
Inst::StackAlloc32 { amt } => {
870+
format!("stack_alloc32 {amt:#x}")
871+
}
872+
Inst::StackFree32 { amt } => {
873+
format!("stack_free32 {amt:#x}")
874+
}
875+
Inst::PushFrame => format!("push_frame"),
876+
Inst::PopFrame => format!("pop_frame"),
865877
}
866878
}
867879
}

0 commit comments

Comments
 (0)