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