1pub mod alloc;
6mod anon_struct;
7mod assignment;
8mod bin_op;
9mod block;
10mod call;
11pub mod code_bld;
12pub mod constants;
13pub mod ctx;
14pub mod disasm;
15mod enum_variants;
16mod equal;
17mod err;
18mod expr;
19mod func;
20mod guard;
21mod host;
22mod init;
23mod initializer_list;
24mod initializer_pair_list;
25pub mod intr;
26mod iter;
27pub mod layout;
28mod literal;
29mod location;
30mod logical;
31mod lvalue;
32mod map;
33mod match_expr;
34mod postfix;
35pub mod prelude;
36pub mod reg_pool;
37mod relational;
38mod rvalue;
39mod sparse;
40pub mod state;
41mod statement;
42pub mod top_state;
43mod transfer;
44mod transfer_instr;
45mod transformer;
46mod tuple;
47mod variable;
48mod vec;
49mod when;
50
51pub const MAX_REGISTER_INDEX_FOR_PARAMETERS: u8 = 6;
52
53use crate::alloc::StackFrameAllocator;
54use crate::reg_pool::TempRegister;
55use seq_map::SeqMap;
56use source_map_node::Node;
57use swamp_semantic::intr::IntrinsicFunction;
58use swamp_semantic::{
59 ArgumentExpression, ConstantId, ConstantRef, Expression, ExpressionKind,
60 InternalFunctionDefinitionRef, InternalFunctionId, VariableScopes,
61};
62use swamp_types::TypeRef;
63use swamp_vm_isa::{InstructionPosition, MemorySize};
64use swamp_vm_layout::LayoutCache;
65use swamp_vm_types::types::{
66 BasicTypeRef, FrameMemoryInfo, FramePlacedType, FunctionInfoKind, HeapPlacedType,
67 TypedRegister, VmType,
68};
69use swamp_vm_types::{
70 CountU16, FrameMemoryRegion, InstructionRange, TempFrameMemoryAddress, ZFlagPolarity,
71};
72
73#[derive(Clone)]
74pub struct SpilledRegister {
75 pub register: TypedRegister,
76 pub frame_memory_region: FrameMemoryRegion,
77}
78
79#[derive(Clone)]
80pub enum RepresentationOfRegisters {
81 Individual(Vec<TypedRegister>),
82 Range { start_reg: u8, count: u8 },
83 Mask(u8),
84}
85
86#[derive(Clone)]
87pub struct SpilledRegisterRegion {
88 pub registers: RepresentationOfRegisters,
89 pub frame_memory_region: FrameMemoryRegion,
90}
91
92#[derive(Clone)]
93pub struct SpilledRegisterScope {
94 pub regions: Vec<SpilledRegisterRegion>,
95}
96
97pub struct ArgumentAndTempScope {
98 pub argument_registers: SpilledRegisterRegion,
99 pub scratch_registers: Option<SpilledRegisterRegion>,
100}
101
102pub struct SpilledRegisterScopes {
103 pub stack: Vec<SpilledRegisterScope>,
104}
105
106impl Default for SpilledRegisterScopes {
107 fn default() -> Self {
108 Self::new()
109 }
110}
111
112impl SpilledRegisterScopes {
113 #[must_use]
114 pub const fn new() -> Self {
115 Self { stack: Vec::new() }
116 }
117 pub fn push(&mut self, scope: SpilledRegisterScope) {
118 self.stack.push(scope);
119 }
120
121 pub fn pop(&mut self) -> SpilledRegisterScope {
122 self.stack.pop().unwrap()
123 }
124}
125
126pub enum DetailedLocationResolved {
127 Register(TypedRegister),
128 TempRegister(TempRegister),
129}
130
131impl DetailedLocationResolved {
132 #[must_use]
133 pub const fn register(&self) -> &TypedRegister {
134 match self {
135 Self::Register(reg) => reg,
136 Self::TempRegister(reg) => reg.register(),
137 }
138 }
139}
140
141#[derive(Clone)]
142pub enum FunctionIpKind {
143 Normal(InternalFunctionId),
144 Constant(ConstantId),
145}
146
147#[derive(Clone)]
148pub struct FunctionIp {
149 ip_range: InstructionRange,
150 pub kind: FunctionIpKind,
151}
152
153#[derive(PartialEq, Eq, Debug)]
154pub enum FlagStateKind {
155 TFlagIsIndeterminate,
156 TFlagIsTrueWhenSet,
157 TFlagIsTrueWhenClear,
158}
159
160pub struct FlagState {
161 pub kind: FlagStateKind,
162}
163
164impl FlagState {
165 pub(crate) fn invert_polarity(&self) -> Self {
166 Self {
167 kind: self.kind.invert_polarity(),
168 }
169 }
170}
171
172impl FlagStateKind {
173 pub(crate) fn invert_polarity(&self) -> Self {
174 match self {
175 Self::TFlagIsIndeterminate => {
176 panic!("can not invert polarity. status is unknown")
177 }
178 Self::TFlagIsTrueWhenSet => Self::TFlagIsTrueWhenClear,
179 Self::TFlagIsTrueWhenClear => Self::TFlagIsTrueWhenSet,
180 }
181 }
182
183 pub(crate) fn polarity(&self) -> ZFlagPolarity {
184 match self {
185 Self::TFlagIsIndeterminate => panic!("polarity is undefined"),
186 Self::TFlagIsTrueWhenSet => ZFlagPolarity::TrueWhenSet,
187 Self::TFlagIsTrueWhenClear => ZFlagPolarity::TrueWhenClear,
188 }
189 }
190}
191
192impl FlagState {
193 pub(crate) fn polarity(&self) -> ZFlagPolarity {
194 self.kind.polarity()
195 }
196}
197
198impl Default for FlagState {
199 fn default() -> Self {
200 Self {
201 kind: FlagStateKind::TFlagIsIndeterminate,
202 }
203 }
204}
205
206pub struct SlicePairInfo {
207 pub addr: TempFrameMemoryAddress,
208 pub key_size: MemorySize,
209 pub value_size: MemorySize,
210 pub element_count: CountU16,
211 pub element_size: MemorySize,
212}
213
214#[derive(Clone, Debug)]
215pub struct GenFunctionInfo {
216 pub ip_range: InstructionRange,
217 pub return_type: BasicTypeRef,
218 pub params: Vec<BasicTypeRef>,
219 pub internal_function_definition: InternalFunctionDefinitionRef,
220}
221
222impl GenFunctionInfo {
223 #[must_use]
224 pub fn return_type(&self) -> &TypeRef {
225 &self.internal_function_definition.signature.return_type
226 }
227}
228
229pub struct ConstantInfo {
230 pub ip_range: InstructionRange,
231 pub constant_ref: ConstantRef,
232 pub return_type: BasicTypeRef,
233 pub target_constant_memory: HeapPlacedType,
234}
235
236pub struct FunctionIps {
237 ranges: Vec<FunctionIp>,
238}
239
240impl Default for FunctionIps {
241 fn default() -> Self {
242 Self::new()
243 }
244}
245
246impl FunctionIps {
247 #[must_use]
248 pub const fn new() -> Self {
249 Self { ranges: Vec::new() }
250 }
251
252 #[must_use]
253 pub fn get_function_end_from_start(&self, ip: InstructionPosition) -> Option<FunctionIp> {
254 for range in &self.ranges {
255 if range.ip_range.start.0 == ip.0 {
256 return Some(range.clone());
257 }
258 }
259
260 None
261 }
262}
263
264pub fn reserve(
265 ty: &TypeRef,
266 layout_cache: &mut LayoutCache,
267 allocator: &mut StackFrameAllocator,
268) -> FramePlacedType {
269 allocator.reserve(layout_cache, ty)
270}
271
272pub struct FrameAndVariableInfo {
273 pub frame_memory: FrameMemoryInfo,
274 pub return_type: VmType,
275 parameter_and_variable_offsets: SeqMap<usize, TypedRegister>,
276 local_frame_allocator: StackFrameAllocator,
277}
278
279#[derive(Debug)]
280pub struct FunctionInData {
281 pub function_name_node: Node,
282 pub kind: FunctionInfoKind,
283 pub assigned_name: String,
284 pub function_variables: VariableScopes,
285 pub return_type: TypeRef,
286 pub expression: Expression,
287}
288
289fn single_intrinsic_fn(
290 body: &Expression,
291) -> Option<(&IntrinsicFunction, &Vec<ArgumentExpression>)> {
292 let ExpressionKind::Block(block_expressions) = &body.kind else {
293 return None;
294 };
295
296 if block_expressions.is_empty() {
297 return None;
298 }
299 if let ExpressionKind::IntrinsicCallEx(found_intrinsic_fn, arguments) =
300 &block_expressions[0].kind
301 {
302 Some((found_intrinsic_fn, arguments))
303 } else {
304 None
305 }
306}