Skip to content

Commit 9fc3c85

Browse files
committed
Add struct-field to named-var assignment of char arrays
1 parent fd63029 commit 9fc3c85

File tree

2 files changed

+76
-4
lines changed

2 files changed

+76
-4
lines changed

pythonbpf/allocation_pass.py

Lines changed: 16 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -248,13 +248,25 @@ def _allocate_for_attribute(builder, var_name, rval, local_sym_tab, structs_sym_
248248
logger.error(f"Field '{field_name}' not found in struct '{struct_type}'")
249249
return
250250

251-
# Allocate with field's type and alignment
251+
# Get field type
252252
field_type = struct_info.field_type(field_name)
253-
var = _allocate_with_type(builder, var_name, field_type)
254-
local_sym_tab[var_name] = LocalSymbol(var, field_type)
253+
254+
# Special case: char array -> allocate as i8* pointer instead
255+
if (
256+
isinstance(field_type, ir.ArrayType)
257+
and isinstance(field_type.element, ir.IntType)
258+
and field_type.element.width == 8
259+
):
260+
alloc_type = ir.PointerType(ir.IntType(8))
261+
logger.info(f"Allocating {var_name} as i8* (pointer to char array)")
262+
else:
263+
alloc_type = field_type
264+
265+
var = _allocate_with_type(builder, var_name, alloc_type)
266+
local_sym_tab[var_name] = LocalSymbol(var, alloc_type)
255267

256268
logger.info(
257-
f"Pre-allocated {var_name} from {struct_var}.{field_name} with type {field_type}"
269+
f"Pre-allocated {var_name} from {struct_var}.{field_name} with type {alloc_type}"
258270
)
259271

260272

pythonbpf/assign_pass.py

Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -71,6 +71,17 @@ def handle_variable_assignment(
7171
logger.info(f"Initialized struct {struct_name} for variable {var_name}")
7272
return True
7373

74+
# Special case: struct field char array -> pointer
75+
# Handle this before eval_expr to get the pointer, not the value
76+
if isinstance(rval, ast.Attribute) and isinstance(rval.value, ast.Name):
77+
converted_val = _try_convert_char_array_to_ptr(
78+
rval, var_type, builder, local_sym_tab, structs_sym_tab
79+
)
80+
if converted_val is not None:
81+
builder.store(converted_val, var_ptr)
82+
logger.info(f"Assigned char array pointer to {var_name}")
83+
return True
84+
7485
val_result = eval_expr(
7586
func, module, builder, rval, local_sym_tab, map_sym_tab, structs_sym_tab
7687
)
@@ -106,3 +117,52 @@ def handle_variable_assignment(
106117
builder.store(val, var_ptr)
107118
logger.info(f"Assigned value to variable {var_name}")
108119
return True
120+
121+
122+
def _try_convert_char_array_to_ptr(
123+
rval, var_type, builder, local_sym_tab, structs_sym_tab
124+
):
125+
"""Try to convert char array field to i8* pointer"""
126+
# Only convert if target is i8*
127+
if not (
128+
isinstance(var_type, ir.PointerType)
129+
and isinstance(var_type.pointee, ir.IntType)
130+
and var_type.pointee.width == 8
131+
):
132+
return None
133+
134+
struct_var = rval.value.id
135+
field_name = rval.attr
136+
137+
# Validate struct
138+
if struct_var not in local_sym_tab:
139+
return None
140+
141+
struct_type = local_sym_tab[struct_var].metadata
142+
if not struct_type or struct_type not in structs_sym_tab:
143+
return None
144+
145+
struct_info = structs_sym_tab[struct_type]
146+
if field_name not in struct_info.fields:
147+
return None
148+
149+
field_type = struct_info.field_type(field_name)
150+
151+
# Check if it's a char array
152+
if not (
153+
isinstance(field_type, ir.ArrayType)
154+
and isinstance(field_type.element, ir.IntType)
155+
and field_type.element.width == 8
156+
):
157+
return None
158+
159+
# Get pointer to struct field
160+
struct_ptr = local_sym_tab[struct_var].var
161+
field_ptr = struct_info.gep(builder, struct_ptr, field_name)
162+
163+
# GEP to first element: [N x i8]* -> i8*
164+
return builder.gep(
165+
field_ptr,
166+
[ir.Constant(ir.IntType(32), 0), ir.Constant(ir.IntType(32), 0)],
167+
inbounds=True,
168+
)

0 commit comments

Comments
 (0)