1use super::*;
2
3impl<'ctx, 'dw> EbpfContext<'ctx, 'dw> {
4 pub fn generate_print_variable_index(
6 &mut self,
7 var_name_index: u16,
8 type_encoding: TypeKind,
9 var_name: &str,
10 ) -> Result<()> {
11 info!(
12 "Generating PrintVariableIndex instruction: var_name_index={}, type={:?}, var_name={}",
13 var_name_index, type_encoding, var_name
14 );
15
16 let type_index = match self.query_dwarf_for_variable(var_name)? {
18 Some(var) => match var.dwarf_type {
19 Some(ref t) => self.trace_context.add_type(t.clone()),
20 None => self.add_synthesized_type_index_for_kind(type_encoding),
21 },
22 None => {
23 self.add_synthesized_type_index_for_kind(type_encoding)
25 }
26 };
27
28 self.generate_successful_variable_instruction(
29 var_name_index,
30 type_encoding,
31 type_index,
32 var_name,
33 )
34 }
35
36 pub(super) fn generate_successful_variable_instruction(
38 &mut self,
39 var_name_index: u16,
40 type_encoding: TypeKind,
41 type_index: u16,
42 var_name: &str,
43 ) -> Result<()> {
44 let data_size = match type_encoding {
46 TypeKind::U8 | TypeKind::I8 | TypeKind::Bool | TypeKind::Char => 1,
47 TypeKind::U16 | TypeKind::I16 => 2,
48 TypeKind::U32 | TypeKind::I32 | TypeKind::F32 => 4,
49 TypeKind::U64 | TypeKind::I64 | TypeKind::F64 | TypeKind::Pointer => 8,
50 _ => 8, };
52
53 let inst_buffer = self
55 .reserve_instruction_region_or_return_zero(
56 (std::mem::size_of::<InstructionHeader>()
57 + std::mem::size_of::<PrintVariableIndexData>()
58 + data_size as usize) as u64,
59 )?
60 .into_value_after_runtime_returns();
61
62 let inst_type_val = self
66 .context
67 .i8_type()
68 .const_int(InstructionType::PrintVariableIndex as u64, false);
69 self.builder
70 .build_store(inst_buffer, inst_type_val)
71 .map_err(|e| CodeGenError::LLVMError(format!("Failed to store inst_type: {e}")))?;
72
73 let data_length_ptr = unsafe {
77 self.builder
78 .build_gep(
79 self.context.i8_type(),
80 inst_buffer,
81 &[self.context.i32_type().const_int(
82 std::mem::offset_of!(InstructionHeader, data_length) as u64,
83 false,
84 )],
85 "data_length_ptr",
86 )
87 .map_err(|e| {
88 CodeGenError::LLVMError(format!("Failed to get data_length GEP: {e}"))
89 })?
90 };
91 let data_length_i16_ptr = self
92 .builder
93 .build_pointer_cast(
94 data_length_ptr,
95 self.context.ptr_type(AddressSpace::default()),
96 "data_length_i16_ptr",
97 )
98 .map_err(|e| CodeGenError::LLVMError(format!("Failed to cast data_length ptr: {e}")))?;
99 let total_data_length = std::mem::size_of::<PrintVariableIndexData>() + data_size as usize;
100 let data_length_val = self
101 .context
102 .i16_type()
103 .const_int(total_data_length as u64, false);
104 self.builder
105 .build_store(data_length_i16_ptr, data_length_val)
106 .map_err(|e| CodeGenError::LLVMError(format!("Failed to store data_length: {e}")))?;
107
108 let variable_data_start = unsafe {
112 self.builder
113 .build_gep(
114 self.context.i8_type(),
115 inst_buffer,
116 &[self
117 .context
118 .i32_type()
119 .const_int(std::mem::size_of::<InstructionHeader>() as u64, false)],
120 "variable_data_start",
121 )
122 .map_err(|e| {
123 CodeGenError::LLVMError(format!("Failed to get variable_data_start GEP: {e}"))
124 })?
125 };
126
127 let var_name_index_ptr = unsafe {
130 self.builder
131 .build_gep(
132 self.context.i8_type(),
133 variable_data_start,
134 &[self.context.i32_type().const_int(
135 std::mem::offset_of!(PrintVariableIndexData, var_name_index) as u64,
136 false,
137 )],
138 "var_name_index_ptr",
139 )
140 .map_err(|e| {
141 CodeGenError::LLVMError(format!("Failed to get var_name_index GEP: {e}"))
142 })?
143 };
144 let var_name_index_i16_ptr = self
145 .builder
146 .build_pointer_cast(
147 var_name_index_ptr,
148 self.context.ptr_type(AddressSpace::default()),
149 "var_name_index_i16_ptr",
150 )
151 .map_err(|e| {
152 CodeGenError::LLVMError(format!("Failed to cast var_name_index ptr: {e}"))
153 })?;
154 let var_name_index_val = self
155 .context
156 .i16_type()
157 .const_int(var_name_index as u64, false);
158 self.builder
159 .build_store(var_name_index_i16_ptr, var_name_index_val)
160 .map_err(|e| CodeGenError::LLVMError(format!("Failed to store var_name_index: {e}")))?;
161
162 let type_encoding_ptr = unsafe {
165 self.builder
166 .build_gep(
167 self.context.i8_type(),
168 variable_data_start,
169 &[self.context.i32_type().const_int(
170 std::mem::offset_of!(PrintVariableIndexData, type_encoding) as u64,
171 false,
172 )],
173 "type_encoding_ptr",
174 )
175 .map_err(|e| {
176 CodeGenError::LLVMError(format!("Failed to get type_encoding GEP: {e}"))
177 })?
178 };
179 let type_encoding_val = self
180 .context
181 .i8_type()
182 .const_int(type_encoding as u8 as u64, false);
183 self.builder
184 .build_store(type_encoding_ptr, type_encoding_val)
185 .map_err(|e| CodeGenError::LLVMError(format!("Failed to store type_encoding: {e}")))?;
186
187 let data_len_ptr = unsafe {
190 self.builder
191 .build_gep(
192 self.context.i8_type(),
193 variable_data_start,
194 &[self.context.i32_type().const_int(
195 std::mem::offset_of!(PrintVariableIndexData, data_len) as u64,
196 false,
197 )],
198 "data_len_ptr",
199 )
200 .map_err(|e| CodeGenError::LLVMError(format!("Failed to get data_len GEP: {e}")))?
201 };
202 let data_len_i16_ptr = self
203 .builder
204 .build_pointer_cast(
205 data_len_ptr,
206 self.context.ptr_type(AddressSpace::default()),
207 "data_len_i16_ptr",
208 )
209 .map_err(|e| CodeGenError::LLVMError(format!("Failed to cast data_len ptr: {e}")))?;
210 let data_len_val = self.context.i16_type().const_int(data_size as u64, false); self.builder
212 .build_store(data_len_i16_ptr, data_len_val)
213 .map_err(|e| CodeGenError::LLVMError(format!("Failed to store data_len: {e}")))?;
214
215 let type_index_ptr = unsafe {
218 self.builder
219 .build_gep(
220 self.context.i8_type(),
221 variable_data_start,
222 &[self.context.i32_type().const_int(
223 std::mem::offset_of!(PrintVariableIndexData, type_index) as u64,
224 false,
225 )],
226 "type_index_ptr",
227 )
228 .map_err(|e| {
229 CodeGenError::LLVMError(format!("Failed to get type_index GEP: {e}"))
230 })?
231 };
232 let type_index_i16_ptr = self
233 .builder
234 .build_pointer_cast(
235 type_index_ptr,
236 self.context.ptr_type(AddressSpace::default()),
237 "type_index_i16_ptr",
238 )
239 .map_err(|e| CodeGenError::LLVMError(format!("Failed to cast type_index ptr: {e}")))?;
240 let type_index_val = self.context.i16_type().const_int(type_index as u64, false);
241 self.builder
242 .build_store(type_index_i16_ptr, type_index_val)
243 .map_err(|e| CodeGenError::LLVMError(format!("Failed to store type_index: {e}")))?;
244
245 let status_ptr = unsafe {
248 self.builder
249 .build_gep(
250 self.context.i8_type(),
251 variable_data_start,
252 &[self.context.i32_type().const_int(
253 std::mem::offset_of!(PrintVariableIndexData, status) as u64,
254 false,
255 )],
256 "status_ptr",
257 )
258 .map_err(|e| CodeGenError::LLVMError(format!("Failed to get status GEP: {e}")))?
259 };
260 let status_val = self
261 .context
262 .i8_type()
263 .const_int(VariableStatus::Ok as u64, false);
264 self.builder
265 .build_store(status_ptr, status_val)
266 .map_err(|e| CodeGenError::LLVMError(format!("Failed to store status: {e}")))?;
267
268 let var_data = self.resolve_variable_value(var_name, type_encoding, Some(status_ptr))?;
269
270 let var_data_ptr = unsafe {
274 self.builder
275 .build_gep(
276 self.context.i8_type(),
277 variable_data_start,
278 &[self
279 .context
280 .i32_type()
281 .const_int(std::mem::size_of::<PrintVariableIndexData>() as u64, false)],
282 "var_data_ptr",
283 )
284 .map_err(|e| CodeGenError::LLVMError(format!("Failed to get var_data GEP: {e}")))?
285 };
286
287 match data_size {
290 1 => {
291 let truncated = match var_data {
293 BasicValueEnum::IntValue(int_val) => self
294 .builder
295 .build_int_truncate(int_val, self.context.i8_type(), "truncated_i8")
296 .map_err(|e| {
297 CodeGenError::LLVMError(format!("Failed to truncate to i8: {e}"))
298 })?,
299 _ => {
300 return Err(CodeGenError::LLVMError(
301 "Expected integer value for integer type".to_string(),
302 ));
303 }
304 };
305 self.builder
306 .build_store(var_data_ptr, truncated)
307 .map_err(|e| {
308 CodeGenError::LLVMError(format!("Failed to store i8 data: {e}"))
309 })?;
310 }
311 2 => {
312 let truncated = match var_data {
314 BasicValueEnum::IntValue(int_val) => self
315 .builder
316 .build_int_truncate(int_val, self.context.i16_type(), "truncated_i16")
317 .map_err(|e| {
318 CodeGenError::LLVMError(format!("Failed to truncate to i16: {e}"))
319 })?,
320 _ => {
321 return Err(CodeGenError::LLVMError(
322 "Expected integer value for integer type".to_string(),
323 ));
324 }
325 };
326 let i16_ptr = self
327 .builder
328 .build_pointer_cast(
329 var_data_ptr,
330 self.context.ptr_type(AddressSpace::default()),
331 "i16_ptr",
332 )
333 .map_err(|e| {
334 CodeGenError::LLVMError(format!("Failed to cast to i16 ptr: {e}"))
335 })?;
336 self.builder.build_store(i16_ptr, truncated).map_err(|e| {
337 CodeGenError::LLVMError(format!("Failed to store i16 data: {e}"))
338 })?;
339 }
340 4 => {
341 match var_data {
343 BasicValueEnum::IntValue(int_val) => {
344 let truncated = self
345 .builder
346 .build_int_truncate(int_val, self.context.i32_type(), "truncated_i32")
347 .map_err(|e| {
348 CodeGenError::LLVMError(format!("Failed to truncate to i32: {e}"))
349 })?;
350 let i32_ptr = self
351 .builder
352 .build_pointer_cast(
353 var_data_ptr,
354 self.context.ptr_type(AddressSpace::default()),
355 "i32_ptr",
356 )
357 .map_err(|e| {
358 CodeGenError::LLVMError(format!("Failed to cast to i32 ptr: {e}"))
359 })?;
360 self.builder.build_store(i32_ptr, truncated).map_err(|e| {
361 CodeGenError::LLVMError(format!("Failed to store i32 data: {e}"))
362 })?;
363 }
364 BasicValueEnum::FloatValue(float_val) => {
365 let f32_ptr = self
366 .builder
367 .build_pointer_cast(
368 var_data_ptr,
369 self.context.ptr_type(AddressSpace::default()),
370 "f32_ptr",
371 )
372 .map_err(|e| {
373 CodeGenError::LLVMError(format!("Failed to cast to f32 ptr: {e}"))
374 })?;
375 self.builder.build_store(f32_ptr, float_val).map_err(|e| {
376 CodeGenError::LLVMError(format!("Failed to store f32 data: {e}"))
377 })?;
378 }
379 _ => {
380 return Err(CodeGenError::LLVMError(
381 "Expected integer or float value for 4-byte type".to_string(),
382 ));
383 }
384 }
385 }
386 8 => {
387 match var_data {
389 BasicValueEnum::IntValue(int_val) => {
390 let i64_ptr = self
391 .builder
392 .build_pointer_cast(
393 var_data_ptr,
394 self.context.ptr_type(AddressSpace::default()),
395 "i64_ptr",
396 )
397 .map_err(|e| {
398 CodeGenError::LLVMError(format!("Failed to cast to i64 ptr: {e}"))
399 })?;
400 self.builder.build_store(i64_ptr, int_val).map_err(|e| {
401 CodeGenError::LLVMError(format!("Failed to store i64 data: {e}"))
402 })?;
403 }
404 BasicValueEnum::FloatValue(float_val) => {
405 let f64_ptr = self
406 .builder
407 .build_pointer_cast(
408 var_data_ptr,
409 self.context.ptr_type(AddressSpace::default()),
410 "f64_ptr",
411 )
412 .map_err(|e| {
413 CodeGenError::LLVMError(format!("Failed to cast to f64 ptr: {e}"))
414 })?;
415 self.builder.build_store(f64_ptr, float_val).map_err(|e| {
416 CodeGenError::LLVMError(format!("Failed to store f64 data: {e}"))
417 })?;
418 }
419 BasicValueEnum::PointerValue(ptr_val) => {
420 let ptr_int = self
422 .builder
423 .build_ptr_to_int(ptr_val, self.context.i64_type(), "ptr_as_int")
424 .map_err(|e| {
425 CodeGenError::LLVMError(format!(
426 "Failed to convert ptr to int: {e}"
427 ))
428 })?;
429 let i64_ptr = self
430 .builder
431 .build_pointer_cast(
432 var_data_ptr,
433 self.context.ptr_type(AddressSpace::default()),
434 "i64_ptr",
435 )
436 .map_err(|e| {
437 CodeGenError::LLVMError(format!("Failed to cast to i64 ptr: {e}"))
438 })?;
439 self.builder.build_store(i64_ptr, ptr_int).map_err(|e| {
440 CodeGenError::LLVMError(format!("Failed to store pointer data: {e}"))
441 })?;
442 }
443 _ => {
444 return Err(CodeGenError::LLVMError(
445 "Expected integer, float, or pointer value for 8-byte type".to_string(),
446 ));
447 }
448 }
449 }
450 _ => {
451 return Err(CodeGenError::LLVMError(format!(
452 "Unsupported data size: {data_size}"
453 )));
454 }
455 }
456
457 Ok(())
459 }
460 pub(super) fn resolve_variable_value(
462 &mut self,
463 var_name: &str,
464 type_encoding: TypeKind,
465 status_ptr: Option<inkwell::values::PointerValue<'ctx>>,
466 ) -> Result<BasicValueEnum<'ctx>> {
467 info!(
468 "Resolving variable value: {} ({:?})",
469 var_name, type_encoding
470 );
471
472 if self.variable_exists(var_name) {
474 info!("Found script variable for '{}', loading value", var_name);
475 return self.load_variable(var_name);
476 }
477
478 match self.query_dwarf_for_variable(var_name)? {
480 Some(var_info) => {
481 info!(
482 "Found DWARF variable read plan: {} availability={:?}",
483 var_name, var_info.availability
484 );
485
486 var_info.dwarf_type.as_ref().ok_or_else(|| {
488 CodeGenError::DwarfError(format!(
489 "Variable '{var_name}' has no type information in DWARF"
490 ))
491 })?;
492
493 let compile_context = self.get_compile_time_context()?;
494 self.variable_read_plan_to_llvm_value(
495 &var_info,
496 compile_context.pc_address,
497 status_ptr,
498 )
499 }
500 None => {
501 let compile_context = self.get_compile_time_context()?;
502 warn!(
503 "Variable '{}' not found in DWARF at address 0x{:x}",
504 var_name, compile_context.pc_address
505 );
506 Err(CodeGenError::VariableNotFound(var_name.to_string()))
507 }
508 }
509 }
510}