cranelift_codegen/ir/
stackslot.rs1use crate::entity::PrimaryMap;
7use crate::ir::StackSlot;
8use crate::ir::entities::{DynamicStackSlot, DynamicType};
9use core::fmt;
10use core::str::FromStr;
11
12#[cfg(feature = "enable-serde")]
13use serde_derive::{Deserialize, Serialize};
14
15pub type StackSize = u32;
21
22#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
24#[cfg_attr(feature = "enable-serde", derive(Serialize, Deserialize))]
25pub enum StackSlotKind {
26 ExplicitSlot,
29 ExplicitDynamicSlot,
32}
33
34impl FromStr for StackSlotKind {
35 type Err = ();
36
37 fn from_str(s: &str) -> Result<Self, ()> {
38 use self::StackSlotKind::*;
39 match s {
40 "explicit_slot" => Ok(ExplicitSlot),
41 "explicit_dynamic_slot" => Ok(ExplicitDynamicSlot),
42 _ => Err(()),
43 }
44 }
45}
46
47impl fmt::Display for StackSlotKind {
48 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
49 use self::StackSlotKind::*;
50 f.write_str(match *self {
51 ExplicitSlot => "explicit_slot",
52 ExplicitDynamicSlot => "explicit_dynamic_slot",
53 })
54 }
55}
56
57#[derive(Clone, Debug, PartialEq, Eq, Hash)]
59#[cfg_attr(feature = "enable-serde", derive(Serialize, Deserialize))]
60pub struct StackSlotData {
61 pub kind: StackSlotKind,
63
64 pub size: StackSize,
66
67 pub align_shift: u8,
72}
73
74impl StackSlotData {
75 pub fn new(kind: StackSlotKind, size: StackSize, align_shift: u8) -> Self {
77 Self {
78 kind,
79 size,
80 align_shift,
81 }
82 }
83}
84
85impl fmt::Display for StackSlotData {
86 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
87 if self.align_shift != 0 {
88 write!(
89 f,
90 "{} {}, align = {}",
91 self.kind,
92 self.size,
93 1u32 << self.align_shift
94 )
95 } else {
96 write!(f, "{} {}", self.kind, self.size)
97 }
98 }
99}
100
101#[derive(Clone, Debug, PartialEq, Eq, Hash)]
103#[cfg_attr(feature = "enable-serde", derive(Serialize, Deserialize))]
104pub struct DynamicStackSlotData {
105 pub kind: StackSlotKind,
107
108 pub dyn_ty: DynamicType,
110}
111
112impl DynamicStackSlotData {
113 pub fn new(kind: StackSlotKind, dyn_ty: DynamicType) -> Self {
115 assert!(kind == StackSlotKind::ExplicitDynamicSlot);
116 Self { kind, dyn_ty }
117 }
118
119 pub fn alignment(&self, max_align: StackSize) -> StackSize {
121 debug_assert!(max_align.is_power_of_two());
122 max_align
123 }
124}
125
126impl fmt::Display for DynamicStackSlotData {
127 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
128 write!(f, "{} {}", self.kind, self.dyn_ty)
129 }
130}
131
132pub type StackSlots = PrimaryMap<StackSlot, StackSlotData>;
134
135pub type DynamicStackSlots = PrimaryMap<DynamicStackSlot, DynamicStackSlotData>;
137
138#[cfg(test)]
139mod tests {
140 use super::*;
141 use crate::ir::Function;
142 use crate::ir::types::*;
143 use crate::ir::{DynamicTypeData, GlobalValueData};
144 use alloc::string::ToString;
145
146 #[test]
147 fn stack_slot() {
148 let mut func = Function::new();
149
150 let ss0 =
151 func.create_sized_stack_slot(StackSlotData::new(StackSlotKind::ExplicitSlot, 4, 0));
152 let ss1 =
153 func.create_sized_stack_slot(StackSlotData::new(StackSlotKind::ExplicitSlot, 8, 0));
154 assert_eq!(ss0.to_string(), "ss0");
155 assert_eq!(ss1.to_string(), "ss1");
156
157 assert_eq!(func.sized_stack_slots[ss0].size, 4);
158 assert_eq!(func.sized_stack_slots[ss1].size, 8);
159
160 assert_eq!(func.sized_stack_slots[ss0].to_string(), "explicit_slot 4");
161 assert_eq!(func.sized_stack_slots[ss1].to_string(), "explicit_slot 8");
162 }
163
164 #[test]
165 fn dynamic_stack_slot() {
166 let mut func = Function::new();
167
168 let int_vector_ty = I32X4;
169 let fp_vector_ty = F64X2;
170 let scale0 = GlobalValueData::DynScaleTargetConst {
171 vector_type: int_vector_ty,
172 };
173 let scale1 = GlobalValueData::DynScaleTargetConst {
174 vector_type: fp_vector_ty,
175 };
176 let gv0 = func.create_global_value(scale0);
177 let gv1 = func.create_global_value(scale1);
178 let dtd0 = DynamicTypeData::new(int_vector_ty, gv0);
179 let dtd1 = DynamicTypeData::new(fp_vector_ty, gv1);
180 let dt0 = func.dfg.make_dynamic_ty(dtd0);
181 let dt1 = func.dfg.make_dynamic_ty(dtd1);
182
183 let dss0 = func.create_dynamic_stack_slot(DynamicStackSlotData::new(
184 StackSlotKind::ExplicitDynamicSlot,
185 dt0,
186 ));
187 let dss1 = func.create_dynamic_stack_slot(DynamicStackSlotData::new(
188 StackSlotKind::ExplicitDynamicSlot,
189 dt1,
190 ));
191 assert_eq!(dss0.to_string(), "dss0");
192 assert_eq!(dss1.to_string(), "dss1");
193
194 assert_eq!(
195 func.dynamic_stack_slots[dss0].to_string(),
196 "explicit_dynamic_slot dt0"
197 );
198 assert_eq!(
199 func.dynamic_stack_slots[dss1].to_string(),
200 "explicit_dynamic_slot dt1"
201 );
202 }
203}