swamp_code_gen/
state.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 */
5use crate::constants::ConstantsManager;
6use crate::{ConstantInfo, FunctionIps, GenFunctionInfo};
7use seq_map::SeqMap;
8use source_map_node::Node;
9use swamp_semantic::{ConstantId, ConstantRef, InternalFunctionDefinitionRef, InternalFunctionId};
10use swamp_vm_debug_info::DebugInfo;
11use swamp_vm_isa::InstructionPosition;
12use swamp_vm_layout::LayoutCache;
13use swamp_vm_types::types::{CompleteFunctionInfo, FunctionInfo, FunctionInfoKind, HeapPlacedType};
14use swamp_vm_types::{InstructionPositionOffset, PatchPosition};
15use tracing::info;
16
17pub struct GenOptions {
18    pub is_halt_function: bool,
19}
20
21pub struct FunctionFixup {
22    pub patch_position: PatchPosition,
23    pub fn_id: InternalFunctionId,
24    pub internal_function_definition: InternalFunctionDefinitionRef,
25}
26
27pub struct CodeGenState {
28    pub(crate) constants_manager: ConstantsManager,
29    pub(crate) constant_offsets: SeqMap<ConstantId, HeapPlacedType>,
30    pub(crate) constant_functions_in_order: SeqMap<ConstantId, ConstantInfo>,
31    pub function_infos: SeqMap<InternalFunctionId, GenFunctionInfo>,
32    pub function_ips: FunctionIps,
33    pub function_fixups: Vec<FunctionFixup>,
34    pub functions: SeqMap<usize, CompleteFunctionInfo>,
35    pub constants: SeqMap<usize, CompleteFunctionInfo>,
36    pub layout_cache: LayoutCache,
37
38    pub debug_info: DebugInfo,
39}
40
41impl CodeGenState {}
42
43impl Default for CodeGenState {
44    fn default() -> Self {
45        Self::new()
46    }
47}
48
49impl CodeGenState {
50    #[must_use]
51    pub fn new() -> Self {
52        Self {
53            constants_manager: ConstantsManager::new(32 * 1024 * 1024),
54            constant_offsets: SeqMap::default(),
55            function_infos: SeqMap::default(),
56            constant_functions_in_order: SeqMap::default(),
57            function_ips: FunctionIps::default(),
58            function_fixups: Vec::new(),
59            functions: SeqMap::default(),
60            constants: SeqMap::default(),
61            debug_info: DebugInfo::default(),
62            layout_cache: LayoutCache::new(),
63        }
64    }
65
66    pub fn add_function(
67        &mut self,
68        function_info: FunctionInfo,
69        node: &Node,
70        comment: &str,
71    ) -> CompleteFunctionInfo {
72        self.add_function_helper(function_info, node, comment)
73    }
74
75    /// # Panics
76    ///
77    pub fn add_function_helper(
78        &mut self,
79        function_info: FunctionInfo,
80        node: &Node,
81        comment: &str,
82    ) -> CompleteFunctionInfo {
83        let complete_info = CompleteFunctionInfo {
84            ip: function_info.ip_range.start,
85            size: InstructionPositionOffset(0),
86            info: function_info.clone(),
87        };
88        if let FunctionInfoKind::Constant(constant_id) = function_info.kind {
89            self.constants
90                .insert(constant_id, complete_info.clone())
91                .unwrap();
92        } else if let FunctionInfoKind::Normal(normal_id) = function_info.kind {
93            if self.functions.contains_key(&normal_id) {
94                // TODO: improve monomorph
95                info!("skipping");
96            } else {
97                self.functions
98                    .insert(normal_id, complete_info.clone())
99                    .unwrap();
100            }
101        }
102
103        complete_info
104    }
105
106    /// # Panics
107    /// If function info is not a constant
108    pub fn add_constant_function(
109        &mut self,
110        constant_info: FunctionInfo,
111        node: &Node,
112        comment: &str,
113    ) -> CompleteFunctionInfo {
114        let FunctionInfoKind::Constant(_id) = constant_info.kind else {
115            panic!("must be constant")
116        };
117
118        self.add_function_helper(constant_info, node, comment)
119    }
120
121    #[must_use]
122    pub const fn constant_functions(&self) -> &SeqMap<ConstantId, ConstantInfo> {
123        &self.constant_functions_in_order
124    }
125
126    #[must_use]
127    pub fn create_function_sections(&self) -> SeqMap<InstructionPosition, String> {
128        let mut lookups = SeqMap::new();
129        for (_func_id, function_info) in &self.function_infos {
130            let description = function_info
131                .internal_function_definition
132                .assigned_name
133                .clone();
134            lookups
135                .insert(function_info.ip_range.start, description)
136                .unwrap();
137        }
138
139        for (_func_id, function_info) in &self.constant_functions_in_order {
140            let description = format!("constant {}", function_info.constant_ref.assigned_name);
141            lookups
142                .insert(function_info.ip_range.start, description)
143                .unwrap();
144        }
145
146        lookups
147    }
148
149    pub fn reserve_space_for_constants(&mut self, constants: &[ConstantRef]) {
150        for constant in constants {
151            let heap_placed_type = self
152                .constants_manager
153                .allocator
154                .allocate(&mut self.layout_cache, &constant.resolved_type);
155
156            self.constant_offsets
157                .insert(constant.id, heap_placed_type)
158                .unwrap();
159        }
160    }
161}