swamp_code_gen/
variable.rs1use crate::code_bld::CodeBuilder;
6use crate::ctx::Context;
7use swamp_semantic::{Expression, ExpressionKind, VariableRef};
8use swamp_vm_isa::MemoryOffset;
9use swamp_vm_types::MemoryLocation;
10use swamp_vm_types::types::VmTypeOrigin;
11
12impl CodeBuilder<'_> {
13 pub fn initialize_variable_the_first_time(&mut self, variable: &VariableRef) {
14 let target_register = self
15 .variable_registers
16 .get(&variable.unique_id_within_function)
17 .unwrap_or_else(|| {
18 panic!(
19 "could not find variable id {} {}",
20 variable.unique_id_within_function, variable.assigned_name
21 )
22 })
23 .clone();
24 if let VmTypeOrigin::Frame(frame_region) = target_register.ty.origin {
27 self.builder.add_lea_from_frame_region(
28 &target_register,
29 frame_region,
30 &variable.name,
31 &format!(
32 "initialize frame-placed variable {}",
33 variable.assigned_name
34 ),
35 );
36
37 self.builder.add_frame_memory_clear(
39 frame_region,
40 &variable.name,
41 &format!("clear memory for variable {}", variable.assigned_name),
42 );
43
44 if target_register.ty.basic_type.is_aggregate() {
46 let target_reg_clone = target_register;
48 let memory_location =
49 MemoryLocation::new_copy_over_whole_type_with_zero_offset(target_reg_clone);
50
51 self.emit_initialize_memory_for_any_type(
53 &memory_location,
54 &variable.name,
55 &format!(
56 "initialize collections for variable {}",
57 variable.assigned_name
58 ),
59 );
60 }
61 }
62 }
63
64 pub(crate) fn emit_variable_definition(
65 &mut self,
66 variable: &VariableRef,
67 expression: &Expression,
68 ctx: &Context,
69 ) {
70 self.initialize_variable_the_first_time(variable);
71
72 self.emit_variable_assignment_with_init_flag(variable, expression, ctx, true);
74 }
75
76 pub(crate) fn emit_variable_assignment(
77 &mut self,
78 variable: &VariableRef,
79 expression: &Expression,
80 ctx: &Context,
81 ) {
82 self.emit_variable_assignment_with_init_flag(variable, expression, ctx, false);
83 }
84
85 fn emit_variable_assignment_with_init_flag(
86 &mut self,
87 variable: &VariableRef,
88 expression: &Expression,
89 ctx: &Context,
90 already_initialized: bool,
91 ) {
92 let target_register = self
93 .variable_registers
94 .get(&variable.unique_id_within_function)
95 .unwrap_or_else(|| {
96 panic!(
97 "could not find variable id {} {}",
98 variable.unique_id_within_function, variable.assigned_name
99 )
100 })
101 .clone();
102
103 if target_register.ty.basic_type.is_reg_copy() {
105 self.emit_expression_into_register(
106 &target_register,
107 expression,
108 "variable scalar",
109 ctx,
110 );
111 } else {
112 let memory_location = MemoryLocation {
113 base_ptr_reg: target_register.clone(),
114 offset: MemoryOffset(0),
115 ty: target_register.ty,
116 };
117
118 let is_function_call_returning_aggregate =
121 matches!(
122 &expression.kind,
123 ExpressionKind::InternalCall(_, _)
124 | ExpressionKind::HostCall(_, _)
125 | ExpressionKind::PostfixChain(_, _)
126 ) && !self.state.layout_cache.layout(&expression.ty).is_scalar();
127
128 let is_parameter = matches!(
130 variable.variable_type,
131 swamp_semantic::VariableType::Parameter
132 );
133
134 if is_function_call_returning_aggregate || is_parameter {
135 self.emit_expression_into_target_memory(
138 &memory_location,
139 expression,
140 "variable assignment (direct function call or parameter)",
141 ctx,
142 );
143 } else {
144 if !already_initialized {
146 self.emit_initialize_memory_for_any_type(
147 &memory_location,
148 &variable.name,
149 "initialize variable for the first time",
150 );
151 }
152
153 self.emit_expression_into_target_memory(
154 &memory_location,
155 expression,
156 "variable assignment",
157 ctx,
158 );
159 }
160 }
161 }
162
163 pub(crate) fn emit_variable_reassignment(
164 &mut self,
165 variable: &VariableRef,
166 expression: &Expression,
167 ctx: &Context,
168 ) {
169 self.emit_variable_assignment(variable, expression, ctx);
170 }
171}