mirror of
https://github.com/varun-r-mallya/Python-BPF.git
synced 2025-12-31 21:06:25 +00:00
Move structs_pass under structs, create StructType
This commit is contained in:
29
pythonbpf/structs/struct_type.py
Normal file
29
pythonbpf/structs/struct_type.py
Normal file
@ -0,0 +1,29 @@
|
|||||||
|
from llvmlite import ir
|
||||||
|
|
||||||
|
|
||||||
|
class StructType:
|
||||||
|
def __init__(self, ir_type, fields, size):
|
||||||
|
self.ir_type = ir_type
|
||||||
|
self.fields = fields
|
||||||
|
self.size = size
|
||||||
|
|
||||||
|
def field_idx(self, field_name):
|
||||||
|
return self.fields.keys().index(field_name)
|
||||||
|
|
||||||
|
def field_type(self, field_name):
|
||||||
|
return self.fields[field_name]
|
||||||
|
|
||||||
|
def gep(self, builder, ptr, field_name):
|
||||||
|
idx = self.field_idx(field_name)
|
||||||
|
return builder.gep(ptr, [ir.Constant(ir.IntType(32), 0),
|
||||||
|
ir.Constant(ir.IntType(32), idx)],
|
||||||
|
inbounds=True)
|
||||||
|
|
||||||
|
def field_size(self, field_name):
|
||||||
|
fld = self.fields[field_name]
|
||||||
|
if isinstance(fld, ir.ArrayType):
|
||||||
|
return fld.element.count * (fld.element.width // 8)
|
||||||
|
elif isinstance(fld, ir.IntType):
|
||||||
|
return fld.width // 8
|
||||||
|
elif isinstance(fld, ir.PointerType):
|
||||||
|
return 8
|
||||||
@ -34,32 +34,29 @@ def is_bpf_struct(cls_node):
|
|||||||
def process_bpf_struct(cls_node, module):
|
def process_bpf_struct(cls_node, module):
|
||||||
""" Process a single BPF struct definition """
|
""" Process a single BPF struct definition """
|
||||||
|
|
||||||
field_names, field_types = parse_struct_fields(cls_node)
|
fields = parse_struct_fields(cls_node)
|
||||||
total_size = calc_struct_size(field_types)
|
total_size = calc_struct_size(fields.values())
|
||||||
struct_type = ir.LiteralStructType(field_types)
|
struct_type = ir.LiteralStructType(fields.values())
|
||||||
logger.info(f"Created struct {cls_node.name} with fields {field_names}")
|
logger.info(f"Created struct {cls_node.name} with fields {fields.keys()}")
|
||||||
return {
|
return {
|
||||||
"type": struct_type,
|
"type": struct_type,
|
||||||
"fields": {name: idx for idx, name in enumerate(field_names)},
|
"fields": fields,
|
||||||
"size": total_size,
|
"size": total_size,
|
||||||
"field_types": field_types,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
def parse_struct_fields(cls_node):
|
def parse_struct_fields(cls_node):
|
||||||
""" Parse fields of a struct class node """
|
""" Parse fields of a struct class node """
|
||||||
field_names = []
|
fields = {}
|
||||||
field_types = []
|
|
||||||
|
|
||||||
for item in cls_node.body:
|
for item in cls_node.body:
|
||||||
if isinstance(item, ast.AnnAssign) and \
|
if isinstance(item, ast.AnnAssign) and \
|
||||||
isinstance(item.target, ast.Name):
|
isinstance(item.target, ast.Name):
|
||||||
field_names.append(item.target.id)
|
fields[item.target.id] = get_type_from_ann(item.annotation)
|
||||||
field_types.append(get_type_from_ann(item.annotation))
|
|
||||||
else:
|
else:
|
||||||
logger.error(f"Unsupported struct field: {ast.dump(item)}")
|
logger.error(f"Unsupported struct field: {ast.dump(item)}")
|
||||||
raise TypeError(f"Unsupported field in {ast.dump(cls_node)}")
|
raise TypeError(f"Unsupported field in {ast.dump(cls_node)}")
|
||||||
return field_names, field_types
|
return fields
|
||||||
|
|
||||||
|
|
||||||
def get_type_from_ann(annotation):
|
def get_type_from_ann(annotation):
|
||||||
@ -67,10 +64,12 @@ def get_type_from_ann(annotation):
|
|||||||
if isinstance(annotation, ast.Call) and \
|
if isinstance(annotation, ast.Call) and \
|
||||||
isinstance(annotation.func, ast.Name):
|
isinstance(annotation.func, ast.Name):
|
||||||
if annotation.func.id == "str":
|
if annotation.func.id == "str":
|
||||||
|
# Char array
|
||||||
# Assumes constant integer argument
|
# Assumes constant integer argument
|
||||||
length = annotation.args[0].value
|
length = annotation.args[0].value
|
||||||
return ir.ArrayType(ir.IntType(8), length)
|
return ir.ArrayType(ir.IntType(8), length)
|
||||||
elif isinstance(annotation, ast.Name):
|
elif isinstance(annotation, ast.Name):
|
||||||
|
# Int type, written as c_int64, c_uint32, etc.
|
||||||
return ctypes_to_ir(annotation.id)
|
return ctypes_to_ir(annotation.id)
|
||||||
|
|
||||||
raise TypeError(f"Unsupported annotation type: {ast.dump(annotation)}")
|
raise TypeError(f"Unsupported annotation type: {ast.dump(annotation)}")
|
||||||
@ -87,6 +86,7 @@ def calc_struct_size(field_types):
|
|||||||
fsize = ftype.count * (ftype.element.width // 8)
|
fsize = ftype.count * (ftype.element.width // 8)
|
||||||
alignment = ftype.element.width // 8
|
alignment = ftype.element.width // 8
|
||||||
elif isinstance(ftype, ir.PointerType):
|
elif isinstance(ftype, ir.PointerType):
|
||||||
|
# We won't encounter this rn, but for the future
|
||||||
fsize = 8
|
fsize = 8
|
||||||
alignment = 8
|
alignment = 8
|
||||||
else:
|
else:
|
||||||
Reference in New Issue
Block a user