diff --git a/pythonbpf/allocation_pass.py b/pythonbpf/allocation_pass.py index 289d30f..36b0a75 100644 --- a/pythonbpf/allocation_pass.py +++ b/pythonbpf/allocation_pass.py @@ -248,13 +248,25 @@ def _allocate_for_attribute(builder, var_name, rval, local_sym_tab, structs_sym_ logger.error(f"Field '{field_name}' not found in struct '{struct_type}'") return - # Allocate with field's type and alignment + # Get field type field_type = struct_info.field_type(field_name) - var = _allocate_with_type(builder, var_name, field_type) - local_sym_tab[var_name] = LocalSymbol(var, field_type) + + # Special case: char array -> allocate as i8* pointer instead + if ( + isinstance(field_type, ir.ArrayType) + and isinstance(field_type.element, ir.IntType) + and field_type.element.width == 8 + ): + alloc_type = ir.PointerType(ir.IntType(8)) + logger.info(f"Allocating {var_name} as i8* (pointer to char array)") + else: + alloc_type = field_type + + var = _allocate_with_type(builder, var_name, alloc_type) + local_sym_tab[var_name] = LocalSymbol(var, alloc_type) logger.info( - f"Pre-allocated {var_name} from {struct_var}.{field_name} with type {field_type}" + f"Pre-allocated {var_name} from {struct_var}.{field_name} with type {alloc_type}" ) diff --git a/pythonbpf/assign_pass.py b/pythonbpf/assign_pass.py index ab09141..a7cd52b 100644 --- a/pythonbpf/assign_pass.py +++ b/pythonbpf/assign_pass.py @@ -71,6 +71,17 @@ def handle_variable_assignment( logger.info(f"Initialized struct {struct_name} for variable {var_name}") return True + # Special case: struct field char array -> pointer + # Handle this before eval_expr to get the pointer, not the value + if isinstance(rval, ast.Attribute) and isinstance(rval.value, ast.Name): + converted_val = _try_convert_char_array_to_ptr( + rval, var_type, builder, local_sym_tab, structs_sym_tab + ) + if converted_val is not None: + builder.store(converted_val, var_ptr) + logger.info(f"Assigned char array pointer to {var_name}") + return True + val_result = eval_expr( func, module, builder, rval, local_sym_tab, map_sym_tab, structs_sym_tab ) @@ -106,3 +117,52 @@ def handle_variable_assignment( builder.store(val, var_ptr) logger.info(f"Assigned value to variable {var_name}") return True + + +def _try_convert_char_array_to_ptr( + rval, var_type, builder, local_sym_tab, structs_sym_tab +): + """Try to convert char array field to i8* pointer""" + # Only convert if target is i8* + if not ( + isinstance(var_type, ir.PointerType) + and isinstance(var_type.pointee, ir.IntType) + and var_type.pointee.width == 8 + ): + return None + + struct_var = rval.value.id + field_name = rval.attr + + # Validate struct + if struct_var not in local_sym_tab: + return None + + struct_type = local_sym_tab[struct_var].metadata + if not struct_type or struct_type not in structs_sym_tab: + return None + + struct_info = structs_sym_tab[struct_type] + if field_name not in struct_info.fields: + return None + + field_type = struct_info.field_type(field_name) + + # Check if it's a char array + if not ( + isinstance(field_type, ir.ArrayType) + and isinstance(field_type.element, ir.IntType) + and field_type.element.width == 8 + ): + return None + + # Get pointer to struct field + struct_ptr = local_sym_tab[struct_var].var + field_ptr = struct_info.gep(builder, struct_ptr, field_name) + + # GEP to first element: [N x i8]* -> i8* + return builder.gep( + field_ptr, + [ir.Constant(ir.IntType(32), 0), ir.Constant(ir.IntType(32), 0)], + inbounds=True, + )