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