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