55
66logger = logging .getLogger (__name__ )
77
8+ # TODO: Shall we allow the following syntax:
9+ # struct MyStruct:
10+ # field1: int
11+ # field2: str(32)
12+ # Where int is mapped to c_uint64?
13+ # Shall we just int64, int32 and uint32 similarly?
14+
815
916def structs_proc (tree , module , chunks ):
1017 """ Process all class definitions to find BPF structs """
@@ -27,62 +34,16 @@ def is_bpf_struct(cls_node):
2734def process_bpf_struct (cls_node , module ):
2835 """ Process a single BPF struct definition """
2936
30- field_names = []
31- field_types = []
32-
33- for item in cls_node .body :
34- #
35- # field syntax:
36- # class struct_example:
37- # num: c_uint64
38- #
39- if isinstance (item , ast .AnnAssign ):
40- if isinstance (item .target , ast .Name ):
41- print (f"Field: { item .target .id } , Type: "
42- f"{ ast .dump (item .annotation )} " )
43- field_names .append (item .target .id )
44- if isinstance (item .annotation , ast .Call ):
45- if isinstance (item .annotation .func , ast .Name ):
46- if item .annotation .func .id == "str" :
47- # This is a char array with fixed length
48- # TODO: For now assume str is always with constant
49- field_types .append (ir .ArrayType (
50- ir .IntType (8 ), item .annotation .args [0 ].value ))
51- else :
52- field_types .append (
53- ctypes_to_ir (item .annotation .id ))
54- else :
55- print (f"Unsupported struct field: { ast .dump (item )} " )
56- return
57-
58- curr_offset = 0
59- for ftype in field_types :
60- if isinstance (ftype , ir .IntType ):
61- fsize = ftype .width // 8
62- alignment = fsize
63- elif isinstance (ftype , ir .ArrayType ):
64- fsize = ftype .count * (ftype .element .width // 8 )
65- alignment = ftype .element .width // 8
66- elif isinstance (ftype , ir .PointerType ):
67- fsize = 8
68- alignment = 8
69- else :
70- print (f"Unsupported field type in struct { cls_node .name } " )
71- return
72- padding = (alignment - (curr_offset % alignment )) % alignment
73- curr_offset += padding
74- curr_offset += fsize
75- final_padding = (8 - (curr_offset % 8 )) % 8
76- total_size = curr_offset + final_padding
77-
37+ field_names , field_types = parse_struct_fields (cls_node )
38+ total_size = calc_struct_size (field_types )
7839 struct_type = ir .LiteralStructType (field_types )
79- structs_sym_tab [cls_node .name ] = {
40+ logger .info (f"Created struct { cls_node .name } with fields { field_names } " )
41+ return {
8042 "type" : struct_type ,
8143 "fields" : {name : idx for idx , name in enumerate (field_names )},
8244 "size" : total_size ,
8345 "field_types" : field_types ,
8446 }
85- print (f"Created struct { cls_node .name } with fields { field_names } " )
8647
8748
8849def parse_struct_fields (cls_node ):
@@ -91,7 +52,8 @@ def parse_struct_fields(cls_node):
9152 field_types = []
9253
9354 for item in cls_node .body :
94- if isinstance (item , ast .AnnAssign ) and isinstance (item .target , ast .Name ):
55+ if isinstance (item , ast .AnnAssign ) and \
56+ isinstance (item .target , ast .Name ):
9557 field_names .append (item .target .id )
9658 field_types .append (get_type_from_ann (item .annotation ))
9759 else :
@@ -112,3 +74,26 @@ def get_type_from_ann(annotation):
11274 return ctypes_to_ir (annotation .id )
11375
11476 raise TypeError (f"Unsupported annotation type: { ast .dump (annotation )} " )
77+
78+
79+ def calc_struct_size (field_types ):
80+ """ Calculate total size of the struct with alignment and padding """
81+ curr_offset = 0
82+ for ftype in field_types :
83+ if isinstance (ftype , ir .IntType ):
84+ fsize = ftype .width // 8
85+ alignment = fsize
86+ elif isinstance (ftype , ir .ArrayType ):
87+ fsize = ftype .count * (ftype .element .width // 8 )
88+ alignment = ftype .element .width // 8
89+ elif isinstance (ftype , ir .PointerType ):
90+ fsize = 8
91+ alignment = 8
92+ else :
93+ raise TypeError (f"Unsupported field type: { ftype } " )
94+
95+ padding = (alignment - (curr_offset % alignment )) % alignment
96+ curr_offset += padding + fsize
97+
98+ final_padding = (8 - (curr_offset % 8 )) % 8
99+ return curr_offset + final_padding
0 commit comments