solar_codegen/mir/
module.rs1use super::{Function, FunctionId, MirType};
4use solar_data_structures::{
5 fmt::{self, FmtIteratorExt},
6 index::IndexVec,
7};
8use solar_interface::Ident;
9
10pub const IMMUTABLE_WORD_SIZE: usize = 32;
19
20#[derive(Clone, Debug)]
22pub struct Module {
23 pub name: Ident,
25 pub functions: IndexVec<FunctionId, Function>,
27 pub data_segments: Vec<DataSegment>,
29 pub storage_layout: Vec<StorageSlot>,
31 pub immutables: Vec<ImmutableSlot>,
33 pub is_interface: bool,
35}
36
37impl Module {
38 #[must_use]
40 pub fn new(name: Ident) -> Self {
41 Self {
42 name,
43 functions: IndexVec::new(),
44 data_segments: Vec::new(),
45 storage_layout: Vec::new(),
46 immutables: Vec::new(),
47 is_interface: false,
48 }
49 }
50
51 pub fn add_function(&mut self, function: Function) -> FunctionId {
53 self.functions.push(function)
54 }
55
56 #[must_use]
58 pub fn function(&self, id: FunctionId) -> &Function {
59 &self.functions[id]
60 }
61
62 pub fn function_mut(&mut self, id: FunctionId) -> &mut Function {
64 &mut self.functions[id]
65 }
66
67 pub fn add_data_segment(&mut self, data: Vec<u8>) -> usize {
69 let index = self.data_segments.len();
70 self.data_segments.push(DataSegment { data });
71 index
72 }
73
74 pub fn add_storage_slot(&mut self, slot: StorageSlot) -> usize {
76 let index = self.storage_layout.len();
77 self.storage_layout.push(slot);
78 index
79 }
80
81 pub fn add_immutable_slot(&mut self, slot: ImmutableSlot) -> usize {
83 let index = self.immutables.len();
84 self.immutables.push(slot);
85 index
86 }
87
88 #[must_use]
91 pub fn immutable_data_len(&self) -> usize {
92 self.immutables.len() * IMMUTABLE_WORD_SIZE
93 }
94
95 pub fn iter_functions(&self) -> impl Iterator<Item = (FunctionId, &Function)> {
97 self.functions.iter_enumerated()
98 }
99
100 pub fn to_text(&self) -> impl fmt::Display + '_ {
102 fmt::from_fn(move |f| {
103 writeln!(f, "; module @{}", self.name)?;
104 write!(
105 f,
106 "{}",
107 self.functions.iter().map(super::display::display_function_text).format("\n")
108 )
109 })
110 }
111
112 pub fn to_dot(&self) -> impl fmt::Display + '_ {
114 fmt::from_fn(move |f| {
115 write!(
116 f,
117 "{}",
118 self.functions.iter().map(super::display::display_function_dot).format("\n\n")
119 )
120 })
121 }
122}
123
124#[derive(Clone, Debug)]
126pub struct DataSegment {
127 pub data: Vec<u8>,
129}
130
131#[derive(Clone, Debug)]
133pub struct StorageSlot {
134 pub slot: u64,
136 pub offset: u8,
138 pub ty: MirType,
140 pub name: Option<Ident>,
142}
143
144#[derive(Clone, Debug)]
147pub struct ImmutableSlot {
148 pub offset: u32,
150 pub ty: MirType,
152 pub name: Option<Ident>,
154}
155
156impl StorageSlot {
157 #[must_use]
159 pub fn new(slot: u64, ty: MirType) -> Self {
160 Self { slot, offset: 0, ty, name: None }
161 }
162
163 #[must_use]
165 pub fn with_offset(slot: u64, offset: u8, ty: MirType) -> Self {
166 Self { slot, offset, ty, name: None }
167 }
168}
169
170impl fmt::Display for Module {
171 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
172 writeln!(f, "module {} {{", self.name)?;
173
174 if !self.storage_layout.is_empty() {
175 writeln!(f, " storage:")?;
176 for slot in &self.storage_layout {
177 writeln!(f, " slot {} @ {}: {}", slot.slot, slot.offset, slot.ty)?;
178 }
179 writeln!(f)?;
180 }
181
182 for (id, func) in self.functions.iter_enumerated() {
183 writeln!(f, " ; function {}", id.index())?;
184 writeln!(f, " {func}")?;
185 }
186
187 writeln!(f, "}}")
188 }
189}