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;
49mod err;
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_layout::LayoutCache;
64use swamp_vm_types::types::{
65    BasicTypeRef, FrameMemoryInfo, FramePlacedType, FunctionInfoKind, HeapPlacedType,
66    TypedRegister, VmType,
67};
68use swamp_vm_types::{
69    CountU16, FrameMemoryRegion, InstructionPosition, InstructionRange, MemorySize,
70    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 target_constant_memory: HeapPlacedType,
233}
234
235pub struct FunctionIps {
236    ranges: Vec<FunctionIp>,
237}
238
239impl Default for FunctionIps {
240    fn default() -> Self {
241        Self::new()
242    }
243}
244
245impl FunctionIps {
246    #[must_use]
247    pub const fn new() -> Self {
248        Self { ranges: Vec::new() }
249    }
250
251    #[must_use]
252    pub fn get_function_end_from_start(&self, ip: InstructionPosition) -> Option<FunctionIp> {
253        for range in &self.ranges {
254            if range.ip_range.start.0 == ip.0 {
255                return Some(range.clone());
256            }
257        }
258
259        None
260    }
261}
262
263pub fn reserve(
264    ty: &TypeRef,
265    layout_cache: &mut LayoutCache,
266    allocator: &mut StackFrameAllocator,
267) -> FramePlacedType {
268    allocator.reserve(layout_cache, ty)
269}
270
271pub struct FrameAndVariableInfo {
272    pub frame_memory: FrameMemoryInfo,
273    pub return_type: VmType,
274    parameter_and_variable_offsets: SeqMap<usize, TypedRegister>,
275    local_frame_allocator: StackFrameAllocator,
276}
277
278#[derive(Debug)]
279pub struct FunctionInData {
280    pub function_name_node: Node,
281    pub kind: FunctionInfoKind,
282    pub assigned_name: String,
283    pub function_variables: VariableScopes,
284    pub return_type: TypeRef,
285    pub expression: Expression,
286}
287
288fn single_intrinsic_fn(
289    body: &Expression,
290) -> Option<(&IntrinsicFunction, &Vec<ArgumentExpression>)> {
291    let ExpressionKind::Block(block_expressions) = &body.kind else {
292        return None;
293    };
294
295    if block_expressions.is_empty() {
296        return None;
297    }
298    if let ExpressionKind::IntrinsicCallEx(found_intrinsic_fn, arguments) =
299        &block_expressions[0].kind
300    {
301        Some((found_intrinsic_fn, arguments))
302    } else {
303        None
304    }
305}