ghostscope_compiler/ebpf/
variables.rs1use super::context::{CodeGenError, EbpfContext, Result};
6use crate::script::VarType;
7use inkwell::types::BasicTypeEnum;
8use inkwell::values::BasicValueEnum;
9use inkwell::AddressSpace;
10use tracing::{debug, info};
11
12impl<'ctx> EbpfContext<'ctx> {
13 pub fn set_alias_variable(&mut self, name: &str, expr: crate::script::Expr) {
15 self.alias_vars.insert(name.to_string(), expr);
16 self.variables.remove(name);
18 self.var_types.remove(name);
19 self.optimized_out_vars.remove(name);
20 self.var_pc_addresses.remove(name);
21 self.string_vars.remove(name);
22 }
23
24 pub fn alias_variable_exists(&self, name: &str) -> bool {
26 self.alias_vars.contains_key(name)
27 }
28
29 pub fn get_alias_variable(&self, name: &str) -> Option<crate::script::Expr> {
31 self.alias_vars.get(name).cloned()
32 }
33 pub fn store_variable(&mut self, name: &str, value: BasicValueEnum<'ctx>) -> Result<()> {
35 let var_type = match value {
37 BasicValueEnum::IntValue(_) => VarType::Int,
38 BasicValueEnum::FloatValue(_) => VarType::Float,
39 BasicValueEnum::PointerValue(_) => VarType::String,
40 _ => {
41 return Err(CodeGenError::TypeError(
42 "Unsupported variable type".to_string(),
43 ))
44 }
45 };
46
47 let global_name = format!("_var_{name}");
57 let global_var = match value {
58 BasicValueEnum::IntValue(_) => {
59 let i64_type = self.context.i64_type();
60 let global =
61 self.module
62 .add_global(i64_type, Some(AddressSpace::default()), &global_name);
63 global.set_initializer(&i64_type.const_zero());
64 global.as_pointer_value()
65 }
66 BasicValueEnum::FloatValue(_) => {
67 let f64_type = self.context.f64_type();
68 let global =
69 self.module
70 .add_global(f64_type, Some(AddressSpace::default()), &global_name);
71 global.set_initializer(&f64_type.const_zero());
72 global.as_pointer_value()
73 }
74 BasicValueEnum::PointerValue(_) => {
75 let ptr_type = self.context.ptr_type(AddressSpace::default());
76 let global =
77 self.module
78 .add_global(ptr_type, Some(AddressSpace::default()), &global_name);
79 global.set_initializer(&ptr_type.const_null());
80 global.as_pointer_value()
81 }
82 _ => {
83 return Err(CodeGenError::TypeError(
84 "Unsupported variable type".to_string(),
85 ))
86 }
87 };
88
89 self.builder
91 .build_store(global_var, value)
92 .map_err(|e| CodeGenError::Builder(e.to_string()))?;
93
94 self.variables.insert(name.to_string(), global_var);
96 self.var_types.insert(name.to_string(), var_type.clone());
97
98 info!(
99 "store_variable: Stored variable '{}' with type {:?}",
100 name, var_type
101 );
102 debug!("store_variable: Value type stored: {:?}", value.get_type());
103 match &value {
104 BasicValueEnum::IntValue(iv) => debug!(
105 "store_variable: Stored IntValue with bit width {}",
106 iv.get_type().get_bit_width()
107 ),
108 BasicValueEnum::FloatValue(_) => debug!("store_variable: Stored FloatValue"),
109 BasicValueEnum::PointerValue(_) => debug!("store_variable: Stored PointerValue"),
110 _ => debug!("store_variable: Stored other type"),
111 }
112 Ok(())
113 }
114
115 pub fn load_variable(&mut self, name: &str) -> Result<BasicValueEnum<'ctx>> {
117 if let Some(alloca) = self.variables.get(name) {
118 let var_type = self
119 .var_types
120 .get(name)
121 .ok_or_else(|| CodeGenError::VariableNotFound(name.to_string()))?;
122
123 debug!(
124 "load_variable: Loading variable '{}' with stored type {:?}",
125 name, var_type
126 );
127
128 let pointed_type: BasicTypeEnum = match var_type {
130 VarType::Int => self.context.i64_type().into(),
131 VarType::Float => self.context.f64_type().into(),
132 VarType::String => self.context.ptr_type(AddressSpace::default()).into(),
133 VarType::Bool => self.context.bool_type().into(),
134 };
135
136 let loaded_value = self
137 .builder
138 .build_load(pointed_type, *alloca, name)
139 .map_err(|e| CodeGenError::Builder(e.to_string()))?;
140
141 debug!(
142 "load_variable: Loaded variable '{}' with actual type: {:?}",
143 name,
144 loaded_value.get_type()
145 );
146 match &loaded_value {
147 BasicValueEnum::IntValue(iv) => debug!(
148 "load_variable: Loaded IntValue with bit width {}",
149 iv.get_type().get_bit_width()
150 ),
151 BasicValueEnum::FloatValue(_) => debug!("load_variable: Loaded FloatValue"),
152 BasicValueEnum::PointerValue(_) => debug!("load_variable: Loaded PointerValue"),
153 _ => debug!("load_variable: Loaded other type"),
154 }
155
156 Ok(loaded_value)
157 } else {
158 Err(CodeGenError::VariableNotFound(name.to_string()))
159 }
160 }
161
162 pub fn variable_exists(&self, name: &str) -> bool {
164 self.variables.contains_key(name)
165 }
166
167 pub fn get_variable_type(&self, name: &str) -> Option<&VarType> {
169 self.var_types.get(name)
170 }
171
172 pub fn clear_variables(&mut self) {
174 debug!("Clearing all variables from scope");
175 self.variables.clear();
176 self.var_types.clear();
177 self.optimized_out_vars.clear();
178 self.var_pc_addresses.clear();
179 self.alias_vars.clear();
180 self.string_vars.clear();
181 }
182
183 pub fn set_string_variable_bytes(&mut self, name: &str, bytes: Vec<u8>) {
185 self.string_vars.insert(name.to_string(), bytes);
186 self.alias_vars.remove(name);
188 }
189
190 pub fn get_string_variable_bytes(&self, name: &str) -> Option<&Vec<u8>> {
192 self.string_vars.get(name)
193 }
194}