Make map val struct type allocation work by fixing pointer deref and debuginfogen: WIP

This commit is contained in:
Pragyansh Chaturvedi
2025-11-22 13:20:09 +05:30
parent e5b3b001ce
commit 9def969592
4 changed files with 97 additions and 3 deletions

View File

@ -61,6 +61,7 @@ def _handle_constant_expr(module, builder, expr: ast.Constant):
def _handle_attribute_expr(
func,
expr: ast.Attribute,
local_sym_tab: Dict,
structs_sym_tab: Dict,
@ -76,6 +77,89 @@ def _handle_attribute_expr(
logger.info(
f"Variable type: {var_type}, Variable ptr: {var_ptr}, Variable Metadata: {var_metadata}"
)
# Check if this is a pointer to a struct (from map lookup)
if (
isinstance(var_type, ir.PointerType)
and var_metadata
and isinstance(var_metadata, str)
):
if var_metadata in structs_sym_tab:
logger.info(
f"Handling pointer to struct {var_metadata} from map lookup"
)
if func is None:
raise ValueError(
f"func parameter required for null-safe pointer access to {var_name}.{attr_name}"
)
# Load the pointer value (ptr<struct>)
struct_ptr = builder.load(var_ptr)
# Create blocks for null check
null_check_block = builder.block
not_null_block = func.append_basic_block(
name=f"{var_name}_not_null"
)
merge_block = func.append_basic_block(name=f"{var_name}_merge")
# Check if pointer is null
null_ptr = ir.Constant(struct_ptr.type, None)
is_not_null = builder.icmp_signed("!=", struct_ptr, null_ptr)
logger.info(f"Inserted null check for pointer {var_name}")
builder.cbranch(is_not_null, not_null_block, merge_block)
# Not-null block: Access the field
builder.position_at_end(not_null_block)
# Get struct metadata
metadata = structs_sym_tab[var_metadata]
struct_ptr = builder.bitcast(
struct_ptr, metadata.ir_type.as_pointer()
)
if attr_name not in metadata.fields:
raise ValueError(
f"Field '{attr_name}' not found in struct '{var_metadata}'"
)
# GEP to field
field_gep = metadata.gep(builder, struct_ptr, attr_name)
# Load field value
field_val = builder.load(field_gep)
field_type = metadata.field_type(attr_name)
logger.info(
f"Loaded field {attr_name} from struct pointer, type: {field_type}"
)
# Branch to merge
not_null_after_load = builder.block
builder.branch(merge_block)
# Merge block: PHI node for the result
builder.position_at_end(merge_block)
phi = builder.phi(field_type, name=f"{var_name}_{attr_name}")
# If null, return zero/default value
if isinstance(field_type, ir.IntType):
zero_value = ir.Constant(field_type, 0)
elif isinstance(field_type, ir.PointerType):
zero_value = ir.Constant(field_type, None)
elif isinstance(field_type, ir.ArrayType):
# For arrays, we can't easily create a zero constant
# This case is tricky - for now, just use undef
zero_value = ir.Constant(field_type, ir.Undefined)
else:
zero_value = ir.Constant(field_type, ir.Undefined)
phi.add_incoming(zero_value, null_check_block)
phi.add_incoming(field_val, not_null_after_load)
logger.info(f"Created PHI node for {var_name}.{attr_name}")
return phi, field_type
if (
hasattr(var_metadata, "__module__")
and var_metadata.__module__ == "vmlinux"
@ -568,7 +652,9 @@ def eval_expr(
logger.warning(f"Unknown call: {ast.dump(expr)}")
return None
elif isinstance(expr, ast.Attribute):
return _handle_attribute_expr(expr, local_sym_tab, structs_sym_tab, builder)
return _handle_attribute_expr(
func, expr, local_sym_tab, structs_sym_tab, builder
)
elif isinstance(expr, ast.BinOp):
return _handle_binary_op(
func,