swamp_code_gen/
lib.rs

1/*
2 * Copyright (c) Peter Bjorklund. All rights reserved. https://github.com/swamp/swamp
3 * Licensed under the MIT License. See LICENSE in the project root for license information.
4 */
5pub 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}