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