Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
86 changes: 86 additions & 0 deletions cranelift/codegen/meta/src/gen_inst.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1439,6 +1439,90 @@ fn gen_imm_inst_builder(inst: &Instruction, fmt: &mut Formatter) {
});
}

/// Emit the `stack_load`, `stack_store`, `dynamic_stack_load`, and
/// `dynamic_stack_store` `InstBuilder` backwards-compat/convenience methods.
///
/// These are equivalent to a `[dynamic_]stack_addr` followed by a normal
/// `load`/`store`.
fn gen_stack_access_builders(fmt: &mut Formatter) {
// `stack_load` => `stack_addr` + `load`.
fmt.doc_comment(
"Load a value from a stack slot at the constant offset.\n\n\
This emits a `stack_addr` followed by a `load`.",
);
fmt.line("#[allow(non_snake_case, reason = \"generated code\")]");
fmt.add_block(
"fn stack_load<T1: Into<ir::immediates::Offset32>>(mut self, pointer_type: crate::ir::Type, Mem: crate::ir::Type, SS: ir::StackSlot, Offset: T1) -> Value",
|fmt| {
fmt.line("let Offset = Offset.into();");
fmt.line("let addr = self.build_aux_inst(InstructionData::StackAddr { opcode: Opcode::StackAddr, stack_slot: SS, offset: Offset }, pointer_type);");
fmt.line("let addr = self.data_flow_graph().first_result(addr);");
fmt.line("// Stack slots are required to be accessible, but we can't");
fmt.line("// currently ensure that they are aligned.");
fmt.line("let mut flags = ir::MemFlagsData::new();");
fmt.line("flags.set_notrap();");
fmt.line("self.load(Mem, flags, addr, 0)");
},
);
fmt.empty_line();

// `stack_store` => `stack_addr` + `store`.
fmt.doc_comment(
"Store a value to a stack slot at a constant offset.\n\n\
This emits a `stack_addr` followed by a `store`.",
);
fmt.line("#[allow(non_snake_case, reason = \"generated code\")]");
fmt.add_block(
"fn stack_store<T1: Into<ir::immediates::Offset32>>(mut self, pointer_type: crate::ir::Type, x: ir::Value, SS: ir::StackSlot, Offset: T1) -> Inst",
|fmt| {
fmt.line("let Offset = Offset.into();");
fmt.line("let addr = self.build_aux_inst(InstructionData::StackAddr { opcode: Opcode::StackAddr, stack_slot: SS, offset: Offset }, pointer_type);");
fmt.line("let addr = self.data_flow_graph().first_result(addr);");
fmt.line("// Stack slots are required to be accessible, but we can't");
fmt.line("// currently ensure that they are aligned.");
fmt.line("let mut flags = ir::MemFlagsData::new();");
fmt.line("flags.set_notrap();");
fmt.line("self.store(flags, x, addr, 0)");
},
);
fmt.empty_line();

// `dynamic_stack_load` => `dynamic_stack_addr` + `load`.
fmt.doc_comment(
"Load a value from a dynamic stack slot.\n\n\
This emits a `dynamic_stack_addr` followed by a `load`.",
);
fmt.line("#[allow(non_snake_case, reason = \"generated code\")]");
fmt.add_block(
"fn dynamic_stack_load(mut self, pointer_type: crate::ir::Type, Mem: crate::ir::Type, DSS: ir::DynamicStackSlot) -> Value",
|fmt| {
fmt.line("let addr = self.build_aux_inst(InstructionData::DynamicStackAddr { opcode: Opcode::DynamicStackAddr, dynamic_stack_slot: DSS }, pointer_type);");
fmt.line("let addr = self.data_flow_graph().first_result(addr);");
fmt.line("// Dynamic stack slots are required to be accessible and aligned.");
fmt.line("let flags = ir::MemFlagsData::trusted();");
fmt.line("self.load(Mem, flags, addr, 0)");
},
);
fmt.empty_line();

// `dynamic_stack_store` => `dynamic_stack_addr` + `store`.
fmt.doc_comment(
"Store a value to a dynamic stack slot.\n\n\
This emits a `dynamic_stack_addr` followed by a `store`.",
);
fmt.line("#[allow(non_snake_case, reason = \"generated code\")]");
fmt.add_block(
"fn dynamic_stack_store(mut self, pointer_type: crate::ir::Type, x: ir::Value, DSS: ir::DynamicStackSlot) -> Inst",
|fmt| {
fmt.line("let addr = self.build_aux_inst(InstructionData::DynamicStackAddr { opcode: Opcode::DynamicStackAddr, dynamic_stack_slot: DSS }, pointer_type);");
fmt.line("let addr = self.data_flow_graph().first_result(addr);");
fmt.line("// Dynamic stack slots are required to be accessible and aligned.");
fmt.line("let flags = ir::MemFlagsData::trusted();");
fmt.line("self.store(flags, x, addr, 0)");
},
);
}

/// Generate a Builder trait with methods for all instructions.
fn gen_builder(
instructions: &AllInstructions,
Expand Down Expand Up @@ -1474,6 +1558,8 @@ fn gen_builder(
fmt.empty_line();
}
}
gen_stack_access_builders(fmt);
fmt.empty_line();
for (i, format) in formats.iter().enumerate() {
gen_format_constructor(format, fmt);
if i + 1 != formats.len() {
Expand Down
21 changes: 4 additions & 17 deletions cranelift/codegen/meta/src/shared/formats.rs
Original file line number Diff line number Diff line change
Expand Up @@ -24,10 +24,8 @@ pub(crate) struct Formats {
pub(crate) multiary: Rc<InstructionFormat>,
pub(crate) nullary: Rc<InstructionFormat>,
pub(crate) shuffle: Rc<InstructionFormat>,
pub(crate) stack_load: Rc<InstructionFormat>,
pub(crate) stack_store: Rc<InstructionFormat>,
pub(crate) dynamic_stack_load: Rc<InstructionFormat>,
pub(crate) dynamic_stack_store: Rc<InstructionFormat>,
pub(crate) stack_addr: Rc<InstructionFormat>,
pub(crate) dynamic_stack_addr: Rc<InstructionFormat>,
pub(crate) store: Rc<InstructionFormat>,
pub(crate) store_no_offset: Rc<InstructionFormat>,
pub(crate) ternary: Rc<InstructionFormat>,
Expand Down Expand Up @@ -181,23 +179,12 @@ impl Formats {
.value()
.build(),

stack_load: Builder::new("StackLoad")
stack_addr: Builder::new("StackAddr")
.imm(&entities.stack_slot)
.imm(&imm.offset32)
.build(),

stack_store: Builder::new("StackStore")
.value()
.imm(&entities.stack_slot)
.imm(&imm.offset32)
.build(),

dynamic_stack_load: Builder::new("DynamicStackLoad")
.imm(&entities.dynamic_stack_slot)
.build(),

dynamic_stack_store: Builder::new("DynamicStackStore")
.value()
dynamic_stack_addr: Builder::new("DynamicStackAddr")
.imm(&entities.dynamic_stack_slot)
.build(),

Expand Down
84 changes: 2 additions & 82 deletions cranelift/codegen/meta/src/shared/instructions.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1187,52 +1187,6 @@ pub(crate) fn define(
.can_load(),
);

ig.push(
Inst::new(
"stack_load",
r#"
Load a value from a stack slot at the constant offset.
This is a polymorphic instruction that can load any value type which
has a memory representation.
The offset is an immediate constant, not an SSA value. The memory
access cannot go out of bounds, i.e.
`sizeof(a) + Offset <= sizeof(SS)`.
"#,
&formats.stack_load,
)
.operands_in(vec![
Operand::new("SS", &entities.stack_slot),
Operand::new("Offset", &imm.offset32).with_doc("In-bounds offset into stack slot"),
])
.operands_out(vec![Operand::new("a", Mem).with_doc("Value loaded")])
.can_load(),
);

ig.push(
Inst::new(
"stack_store",
r#"
Store a value to a stack slot at a constant offset.
This is a polymorphic instruction that can store any value type with a
memory representation.
The offset is an immediate constant, not an SSA value. The memory
access cannot go out of bounds, i.e.
`sizeof(a) + Offset <= sizeof(SS)`.
"#,
&formats.stack_store,
)
.operands_in(vec![
Operand::new("x", Mem).with_doc("Value to be stored"),
Operand::new("SS", &entities.stack_slot),
Operand::new("Offset", &imm.offset32).with_doc("In-bounds offset into stack slot"),
])
.can_store(),
);

ig.push(
Inst::new(
"stack_addr",
Expand All @@ -1243,7 +1197,7 @@ pub(crate) fn define(
refer to a byte inside the stack slot:
`0 <= Offset < sizeof(SS)`.
"#,
&formats.stack_load,
&formats.stack_addr,
)
.operands_in(vec![
Operand::new("SS", &entities.stack_slot),
Expand All @@ -1252,40 +1206,6 @@ pub(crate) fn define(
.operands_out(vec![Operand::new("addr", iAddr)]),
);

ig.push(
Inst::new(
"dynamic_stack_load",
r#"
Load a value from a dynamic stack slot.
This is a polymorphic instruction that can load any value type which
has a memory representation.
"#,
&formats.dynamic_stack_load,
)
.operands_in(vec![Operand::new("DSS", &entities.dynamic_stack_slot)])
.operands_out(vec![Operand::new("a", Mem).with_doc("Value loaded")])
.can_load(),
);

ig.push(
Inst::new(
"dynamic_stack_store",
r#"
Store a value to a dynamic stack slot.
This is a polymorphic instruction that can store any dynamic value type with a
memory representation.
"#,
&formats.dynamic_stack_store,
)
.operands_in(vec![
Operand::new("x", Mem).with_doc("Value to be stored"),
Operand::new("DSS", &entities.dynamic_stack_slot),
])
.can_store(),
);

ig.push(
Inst::new(
"dynamic_stack_addr",
Expand All @@ -1294,7 +1214,7 @@ pub(crate) fn define(
Compute the absolute address of the first byte of a dynamic stack slot.
"#,
&formats.dynamic_stack_load,
&formats.dynamic_stack_addr,
)
.operands_in(vec![Operand::new("DSS", &entities.dynamic_stack_slot)])
.operands_out(vec![Operand::new("addr", iAddr)]),
Expand Down
1 change: 0 additions & 1 deletion cranelift/codegen/src/inst_predicates.rs
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,6 @@ fn is_load_with_defined_trapping(
return false;
}
match *data {
InstructionData::StackLoad { .. } => false,
InstructionData::Load { flags, .. } => !dfg.mem_flags[flags].notrap(),
_ => true,
}
Expand Down
8 changes: 4 additions & 4 deletions cranelift/codegen/src/ir/function.rs
Original file line number Diff line number Diff line change
Expand Up @@ -235,14 +235,14 @@ impl FunctionStencil {
self.dfg.jump_tables.push(data)
}

/// Creates a sized stack slot in the function, to be used by `stack_load`, `stack_store`
/// and `stack_addr` instructions.
/// Creates a sized stack slot in the function, to be used by the `stack_addr`
/// instruction.
pub fn create_sized_stack_slot(&mut self, data: StackSlotData) -> StackSlot {
self.sized_stack_slots.push(data)
}

/// Creates a dynamic stack slot in the function, to be used by `dynamic_stack_load`,
/// `dynamic_stack_store` and `dynamic_stack_addr` instructions.
/// Creates a dynamic stack slot in the function, to be used by the
/// `dynamic_stack_addr` instruction.
pub fn create_dynamic_stack_slot(&mut self, data: DynamicStackSlotData) -> DynamicStackSlot {
self.dynamic_stack_slots.push(data)
}
Expand Down
24 changes: 11 additions & 13 deletions cranelift/codegen/src/ir/instructions.rs
Original file line number Diff line number Diff line change
Expand Up @@ -548,9 +548,8 @@ impl InstructionData {
pub fn load_store_offset(&self) -> Option<i32> {
match self {
&InstructionData::Load { offset, .. }
| &InstructionData::StackLoad { offset, .. }
| &InstructionData::Store { offset, .. }
| &InstructionData::StackStore { offset, .. } => Some(offset.into()),
| &InstructionData::StackAddr { offset, .. }
| &InstructionData::Store { offset, .. } => Some(offset.into()),
_ => None,
}
}
Expand All @@ -577,8 +576,7 @@ impl InstructionData {
/// If this instruction references a stack slot, return it
pub fn stack_slot(&self) -> Option<StackSlot> {
match self {
&InstructionData::StackStore { stack_slot, .. }
| &InstructionData::StackLoad { stack_slot, .. } => Some(stack_slot),
&InstructionData::StackAddr { stack_slot, .. } => Some(stack_slot),
_ => None,
}
}
Expand Down Expand Up @@ -1485,26 +1483,26 @@ mod tests {

// Mapping `StackSlot`s.
assert_eq!(
map(InstructionData::StackLoad {
opcode: Opcode::StackLoad,
map(InstructionData::StackAddr {
opcode: Opcode::StackAddr,
stack_slot: StackSlot::from_u32(0),
offset: 0.into()
}),
InstructionData::StackLoad {
opcode: Opcode::StackLoad,
InstructionData::StackAddr {
opcode: Opcode::StackAddr,
stack_slot: StackSlot::from_u32(1),
offset: 0.into()
},
);

// Mapping `DynamicStackSlot`s.
assert_eq!(
map(InstructionData::DynamicStackLoad {
opcode: Opcode::DynamicStackLoad,
map(InstructionData::DynamicStackAddr {
opcode: Opcode::DynamicStackAddr,
dynamic_stack_slot: DynamicStackSlot::from_u32(0),
}),
InstructionData::DynamicStackLoad {
opcode: Opcode::DynamicStackLoad,
InstructionData::DynamicStackAddr {
opcode: Opcode::DynamicStackAddr,
dynamic_stack_slot: DynamicStackSlot::from_u32(1),
},
);
Expand Down
8 changes: 4 additions & 4 deletions cranelift/codegen/src/ir/stackslot.rs
Original file line number Diff line number Diff line change
Expand Up @@ -23,11 +23,11 @@ pub type StackSize = u32;
#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
#[cfg_attr(feature = "enable-serde", derive(Serialize, Deserialize))]
pub enum StackSlotKind {
/// An explicit stack slot. This is a chunk of stack memory for use by the `stack_load`
/// and `stack_store` instructions.
/// An explicit stack slot. This is a chunk of stack memory for use by the
/// `stack_addr` instruction.
ExplicitSlot,
/// An explicit stack slot for dynamic vector types. This is a chunk of stack memory
/// for use by the `dynamic_stack_load` and `dynamic_stack_store` instructions.
/// An explicit stack slot for dynamic vector types. This is a chunk of
/// stack memory for use by the `dynamic_stack_addr` instruction.
ExplicitDynamicSlot,
}

Expand Down
Loading