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