Skip to content

Commit c9363e6

Browse files
move field name generation to assignments dict
1 parent a20643f commit c9363e6

File tree

2 files changed

+85
-10
lines changed

2 files changed

+85
-10
lines changed

pythonbpf/vmlinux_parser/dependency_node.py

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,44 @@ class Field:
1818
value: Any = None
1919
ready: bool = False
2020

21+
def __hash__(self):
22+
"""
23+
Create a hash based on the immutable attributes that define this field's identity.
24+
This allows Field objects to be used as dictionary keys.
25+
"""
26+
# Use a tuple of the fields that uniquely identify this field
27+
identity = (
28+
self.name,
29+
id(self.type), # Use id for non-hashable types
30+
id(self.ctype_complex_type) if self.ctype_complex_type else None,
31+
id(self.containing_type) if self.containing_type else None,
32+
self.type_size,
33+
self.bitfield_size,
34+
self.offset,
35+
self.value if self.value else None,
36+
)
37+
return hash(identity)
38+
39+
def __eq__(self, other):
40+
"""
41+
Define equality consistent with the hash function.
42+
Two fields are equal if they have the same name, type, and offset.
43+
"""
44+
# DO ther change here
45+
if not isinstance(other, Field):
46+
return False
47+
48+
return (
49+
self.name == other.name
50+
and self.type is other.type
51+
and self.ctype_complex_type is other.ctype_complex_type
52+
and self.containing_type is other.containing_type
53+
and self.type_size == other.type_size
54+
and self.bitfield_size == other.bitfield_size
55+
and self.offset == other.offset
56+
and self.value == other.value
57+
)
58+
2159
def set_ready(self, is_ready: bool = True) -> None:
2260
"""Set the readiness state of this field."""
2361
self.ready = is_ready

pythonbpf/vmlinux_parser/ir_gen/ir_generation.py

Lines changed: 47 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
import ctypes
22
import logging
33

4-
from ..dependency_node import Field
54
from ..assignment_info import AssignmentInfo, AssignmentType
65
from ..dependency_handler import DependencyHandler
76
from .debug_info_gen import debug_info_generation
@@ -18,7 +17,8 @@ def __init__(self, llvm_module, handler: DependencyHandler, assignments):
1817
self.handler: DependencyHandler = handler
1918
self.generated: list[str] = []
2019
self.generated_debug_info: list = []
21-
self.generated_field_names: dict[Field, str] = {}
20+
# Use struct_name and field_name as key instead of Field object
21+
self.generated_field_names: dict[str, dict[str, str]] = {}
2222
self.assignments: dict[str, AssignmentInfo] = assignments
2323
if not handler.is_ready:
2424
raise ImportError(
@@ -72,12 +72,30 @@ def struct_processor(self, struct, processing_stack=None):
7272
f"Warning: Dependency {dependency} not found in handler"
7373
)
7474

75+
# Generate IR first to populate field names
76+
self.generated_debug_info.append(
77+
(struct, self.gen_ir(struct, self.generated_debug_info))
78+
)
79+
7580
# Fill the assignments dictionary with struct information
7681
if struct.name not in self.assignments:
7782
# Create a members dictionary for AssignmentInfo
7883
members_dict = {}
7984
for field_name, field in struct.fields.items():
80-
members_dict[field_name] = (self.generated_field_names[field], field)
85+
# Get the generated field name from our dictionary, or use field_name if not found
86+
if (
87+
struct.name in self.generated_field_names
88+
and field_name in self.generated_field_names[struct.name]
89+
):
90+
field_co_re_name = self.generated_field_names[struct.name][
91+
field_name
92+
]
93+
members_dict[field_name] = (field_co_re_name, field)
94+
else:
95+
raise ValueError(
96+
f"llvm global name not found for struct field {field_name}"
97+
)
98+
# members_dict[field_name] = (field_name, field)
8199

82100
# Add struct to assignments dictionary
83101
self.assignments[struct.name] = AssignmentInfo(
@@ -90,10 +108,6 @@ def struct_processor(self, struct, processing_stack=None):
90108
)
91109
logger.info(f"Added struct assignment info for {struct.name}")
92110

93-
# Actual processor logic here after dependencies are resolved
94-
self.generated_debug_info.append(
95-
(struct, self.gen_ir(struct, self.generated_debug_info))
96-
)
97111
self.generated.append(struct.name)
98112

99113
finally:
@@ -108,6 +122,11 @@ def gen_ir(self, struct, generated_debug_info):
108122
struct, self.llvm_module, generated_debug_info
109123
)
110124
field_index = 0
125+
126+
# Make sure the struct has an entry in our field names dictionary
127+
if struct.name not in self.generated_field_names:
128+
self.generated_field_names[struct.name] = {}
129+
111130
for field_name, field in struct.fields.items():
112131
# does not take arrays and similar types into consideration yet.
113132
if field.ctype_complex_type is not None and issubclass(
@@ -117,11 +136,27 @@ def gen_ir(self, struct, generated_debug_info):
117136
containing_type = field.containing_type
118137
if containing_type.__module__ == ctypes.__name__:
119138
containing_type_size = ctypes.sizeof(containing_type)
139+
if array_size == 0:
140+
field_co_re_name = self._struct_name_generator(
141+
struct, field, field_index, True, 0, containing_type_size
142+
)
143+
self.generated_field_names[struct.name][field_name] = (
144+
field_co_re_name
145+
)
146+
globvar = ir.GlobalVariable(
147+
self.llvm_module, ir.IntType(64), name=field_co_re_name
148+
)
149+
globvar.linkage = "external"
150+
globvar.set_metadata("llvm.preserve.access.index", debug_info)
151+
field_index += 1
152+
continue
120153
for i in range(0, array_size):
121154
field_co_re_name = self._struct_name_generator(
122155
struct, field, field_index, True, i, containing_type_size
123156
)
124-
self.generated_field_names[field] = field_co_re_name
157+
self.generated_field_names[struct.name][field_name] = (
158+
field_co_re_name
159+
)
125160
globvar = ir.GlobalVariable(
126161
self.llvm_module, ir.IntType(64), name=field_co_re_name
127162
)
@@ -139,7 +174,9 @@ def gen_ir(self, struct, generated_debug_info):
139174
field_co_re_name = self._struct_name_generator(
140175
struct, field, field_index, True, i, containing_type_size
141176
)
142-
self.generated_field_names[field] = field_co_re_name
177+
self.generated_field_names[struct.name][field_name] = (
178+
field_co_re_name
179+
)
143180
globvar = ir.GlobalVariable(
144181
self.llvm_module, ir.IntType(64), name=field_co_re_name
145182
)
@@ -150,7 +187,7 @@ def gen_ir(self, struct, generated_debug_info):
150187
field_co_re_name = self._struct_name_generator(
151188
struct, field, field_index
152189
)
153-
self.generated_field_names[field] = field_co_re_name
190+
self.generated_field_names[struct.name][field_name] = field_co_re_name
154191
field_index += 1
155192
globvar = ir.GlobalVariable(
156193
self.llvm_module, ir.IntType(64), name=field_co_re_name

0 commit comments

Comments
 (0)