Skip to content

Commit 8450030

Browse files
committed
Move structs_pass under structs, create StructType
1 parent 0d21f84 commit 8450030

2 files changed

Lines changed: 40 additions & 11 deletions

File tree

pythonbpf/structs/struct_type.py

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
from llvmlite import ir
2+
3+
4+
class StructType:
5+
def __init__(self, ir_type, fields, size):
6+
self.ir_type = ir_type
7+
self.fields = fields
8+
self.size = size
9+
10+
def field_idx(self, field_name):
11+
return self.fields.keys().index(field_name)
12+
13+
def field_type(self, field_name):
14+
return self.fields[field_name]
15+
16+
def gep(self, builder, ptr, field_name):
17+
idx = self.field_idx(field_name)
18+
return builder.gep(ptr, [ir.Constant(ir.IntType(32), 0),
19+
ir.Constant(ir.IntType(32), idx)],
20+
inbounds=True)
21+
22+
def field_size(self, field_name):
23+
fld = self.fields[field_name]
24+
if isinstance(fld, ir.ArrayType):
25+
return fld.element.count * (fld.element.width // 8)
26+
elif isinstance(fld, ir.IntType):
27+
return fld.width // 8
28+
elif isinstance(fld, ir.PointerType):
29+
return 8
Lines changed: 11 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -34,43 +34,42 @@ def is_bpf_struct(cls_node):
3434
def process_bpf_struct(cls_node, module):
3535
""" Process a single BPF struct definition """
3636

37-
field_names, field_types = parse_struct_fields(cls_node)
38-
total_size = calc_struct_size(field_types)
39-
struct_type = ir.LiteralStructType(field_types)
40-
logger.info(f"Created struct {cls_node.name} with fields {field_names}")
37+
fields = parse_struct_fields(cls_node)
38+
total_size = calc_struct_size(fields.values())
39+
struct_type = ir.LiteralStructType(fields.values())
40+
logger.info(f"Created struct {cls_node.name} with fields {fields.keys()}")
4141
return {
4242
"type": struct_type,
43-
"fields": {name: idx for idx, name in enumerate(field_names)},
43+
"fields": fields,
4444
"size": total_size,
45-
"field_types": field_types,
4645
}
4746

4847

4948
def parse_struct_fields(cls_node):
5049
""" Parse fields of a struct class node """
51-
field_names = []
52-
field_types = []
50+
fields = {}
5351

5452
for item in cls_node.body:
5553
if isinstance(item, ast.AnnAssign) and \
5654
isinstance(item.target, ast.Name):
57-
field_names.append(item.target.id)
58-
field_types.append(get_type_from_ann(item.annotation))
55+
fields[item.target.id] = get_type_from_ann(item.annotation)
5956
else:
6057
logger.error(f"Unsupported struct field: {ast.dump(item)}")
6158
raise TypeError(f"Unsupported field in {ast.dump(cls_node)}")
62-
return field_names, field_types
59+
return fields
6360

6461

6562
def get_type_from_ann(annotation):
6663
""" Convert an AST annotation node to an LLVM IR type for struct fields"""
6764
if isinstance(annotation, ast.Call) and \
6865
isinstance(annotation.func, ast.Name):
6966
if annotation.func.id == "str":
67+
# Char array
7068
# Assumes constant integer argument
7169
length = annotation.args[0].value
7270
return ir.ArrayType(ir.IntType(8), length)
7371
elif isinstance(annotation, ast.Name):
72+
# Int type, written as c_int64, c_uint32, etc.
7473
return ctypes_to_ir(annotation.id)
7574

7675
raise TypeError(f"Unsupported annotation type: {ast.dump(annotation)}")
@@ -87,6 +86,7 @@ def calc_struct_size(field_types):
8786
fsize = ftype.count * (ftype.element.width // 8)
8887
alignment = ftype.element.width // 8
8988
elif isinstance(ftype, ir.PointerType):
89+
# We won't encounter this rn, but for the future
9090
fsize = 8
9191
alignment = 8
9292
else:

0 commit comments

Comments
 (0)