swamp_code_gen/
top_state.rs1use crate::code_bld::CodeBuilderOptions;
6use crate::state::CodeGenState;
7use crate::{ConstantInfo, FunctionInData, FunctionIps, GenFunctionInfo};
8use seq_map::SeqMap;
9use source_map_cache::SourceMapWrapper;
10use swamp_semantic::{ConstantId, ConstantRef, InternalFunctionId};
11
12use swamp_attributes::Attributes;
13use swamp_vm_debug_info::{DebugInfo, FunctionDebugInfo};
14use swamp_vm_instr_build::{InstructionBuilderState, PatchPosition};
15use swamp_vm_isa::{BinaryInstruction, InstructionPosition};
16use swamp_vm_types::types::FunctionInfoKind;
17use swamp_vm_types::{InstructionPositionOffset, InstructionRange, Meta};
18use tracing::error;
19
20pub struct TopLevelGenState {
22 pub builder_state: InstructionBuilderState,
23 pub codegen_state: CodeGenState,
24 pub code_builder_options: CodeBuilderOptions,
25}
26
27impl TopLevelGenState {
28 #[must_use]
29 pub fn new(code_builder_options: CodeBuilderOptions) -> Self {
30 Self {
31 builder_state: InstructionBuilderState::new(),
32 codegen_state: CodeGenState::new(),
33 code_builder_options,
34 }
35 }
36
37 #[must_use]
38 pub const fn debug_info(&self) -> &DebugInfo {
39 &self.codegen_state.debug_info
40 }
41 #[must_use]
42 pub const fn function_ips(&self) -> &FunctionIps {
43 &self.codegen_state.function_ips
44 }
45
46 pub fn reserve_space_for_constants(&mut self, constants: &[ConstantRef]) {
47 self.codegen_state.reserve_space_for_constants(constants);
48 }
49
50 #[must_use]
51 pub fn is_host_call(attributes: &Attributes) -> bool {
52 !attributes.get_attributes("host_call").is_empty()
53 }
54 #[must_use]
55 pub fn is_test_call(attributes: &Attributes) -> bool {
56 !attributes.get_attributes("test").is_empty()
57 }
58
59 pub fn finalize(&mut self) {
60 for function_fixup in &self.codegen_state.function_fixups {
61 if let Some(func) = self.codegen_state.function_infos.get(&function_fixup.fn_id) {
62 self.builder_state.patch_call(
63 PatchPosition(InstructionPosition(function_fixup.patch_position.0.0)),
64 &func.ip_range.start,
65 );
66 } else {
67 error!(?function_fixup.fn_id, name=function_fixup.internal_function_definition.assigned_name, path=?function_fixup.internal_function_definition.defined_in_module_path, "couldn't fixup function");
68 panic!(
69 "couldn't fixup function {}",
70 function_fixup.internal_function_definition.assigned_name
71 );
72 }
73 }
74
75 self.codegen_state.debug_info.info_for_each_instruction = self.builder_state.meta.clone();
76
77 self.codegen_state.function_fixups.clear();
78 }
79
80 pub fn emit_constants_expression_functions_in_order(
81 &mut self,
82 constants: &[ConstantRef],
83 source_map_wrapper: &SourceMapWrapper,
84 ) {
85 for constant in constants {
86 let target_region = self
87 .codegen_state
88 .constant_offsets
89 .get(&constant.id)
90 .unwrap()
91 .clone();
92
93 let in_data = FunctionInData {
94 function_name_node: constant.name.clone(),
95 kind: FunctionInfoKind::Constant(constant.id as usize),
96 assigned_name: constant.assigned_name.clone(),
97 function_variables: constant.function_scope_state.clone(),
98 return_type: constant.resolved_type.clone(),
99 expression: constant.expr.clone(),
100 };
101
102 let (start_ip, end_ip, function_info) =
103 self.emit_function_preamble(&in_data, source_map_wrapper, true);
104
105 let return_type_basic_type =
106 self.codegen_state.layout_cache.layout(&in_data.return_type);
107
108 let constant_info = ConstantInfo {
109 ip_range: InstructionRange {
110 count: InstructionPositionOffset(end_ip.0 - start_ip.0),
111 start: start_ip,
112 },
113 return_type: return_type_basic_type,
114 target_constant_memory: target_region,
115 constant_ref: constant.clone(),
116 };
117
118 self.codegen_state
119 .constant_functions_in_order
120 .insert(constant.id, constant_info)
121 .unwrap();
122
123 self.codegen_state
124 .debug_info
125 .function_table
126 .entries
127 .push(FunctionDebugInfo {
128 start_pc: start_ip.0,
129 function_id: constant.id as u16,
130 });
131
132 self.codegen_state
133 .debug_info
134 .function_infos
135 .insert(constant.id as u16, function_info)
136 .unwrap();
137 }
138 }
139
140 #[must_use]
141 pub fn take_instructions_and_constants(
142 self,
143 ) -> (
144 Vec<BinaryInstruction>,
145 SeqMap<ConstantId, ConstantInfo>,
146 SeqMap<InternalFunctionId, GenFunctionInfo>,
147 Vec<u8>,
148 DebugInfo,
149 ) {
150 (
151 self.builder_state.instructions,
152 self.codegen_state.constant_functions_in_order,
153 self.codegen_state.function_infos,
154 self.codegen_state.constants_manager.take_data(),
155 self.codegen_state.debug_info,
156 )
157 }
158
159 #[must_use]
160 pub fn instructions(&self) -> &[BinaryInstruction] {
161 &self.builder_state.instructions
162 }
163
164 #[must_use]
165 pub const fn ip(&self) -> InstructionPosition {
166 InstructionPosition(self.builder_state.instructions.len() as u32)
167 }
168 #[must_use]
169 pub fn meta(&self) -> &[Meta] {
170 &self.builder_state.meta
171 }
172}