mirror of
https://github.com/varun-r-mallya/pylibbpf.git
synced 2026-02-11 23:51:08 +00:00
Add IR Types to CTypes struct convertor
This commit is contained in:
84
ir_to_ctypes.py
Normal file
84
ir_to_ctypes.py
Normal file
@ -0,0 +1,84 @@
|
||||
import ctypes
|
||||
from typing import Dict, Type
|
||||
from llvmlite import ir
|
||||
import logging
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
|
||||
def ir_type_to_ctypes(ir_type):
|
||||
"""Convert LLVM IR type to ctypes type."""
|
||||
if isinstance(ir_type, ir.IntType):
|
||||
width = ir_type.width
|
||||
type_map = {
|
||||
8: ctypes.c_uint8,
|
||||
16: ctypes.c_uint16,
|
||||
32: ctypes.c_uint32,
|
||||
64: ctypes.c_uint64,
|
||||
}
|
||||
if width not in type_map:
|
||||
raise ValueError(f"Unsupported integer width: {width}")
|
||||
return type_map[width]
|
||||
|
||||
elif isinstance(ir_type, ir.ArrayType):
|
||||
count = ir_type.count
|
||||
element_type = ir_type_to_ctypes(ir_type.element)
|
||||
return element_type * count
|
||||
|
||||
elif isinstance(ir_type, ir.PointerType):
|
||||
return ctypes.c_void_p
|
||||
|
||||
else:
|
||||
raise TypeError(f"Unsupported IR type: {ir_type}")
|
||||
|
||||
|
||||
def convert_structs_to_ctypes(structs_sym_tab) -> Dict[str, Type[ctypes.Structure]]:
|
||||
"""Convert PythonBPF's structs_sym_tab to ctypes.Structure classes."""
|
||||
if not structs_sym_tab:
|
||||
return {}
|
||||
|
||||
ctypes_structs = {}
|
||||
|
||||
for struct_name, struct_type_obj in structs_sym_tab.items():
|
||||
try:
|
||||
fields = []
|
||||
for field_name, field_ir_type in struct_type_obj.fields.items():
|
||||
field_ctypes = ir_type_to_ctypes(field_ir_type)
|
||||
fields.append((field_name, field_ctypes))
|
||||
|
||||
struct_class = type(
|
||||
struct_name,
|
||||
(ctypes.Structure,),
|
||||
{'_fields_': fields, '__module__': 'pylibbpf.ir_to_ctypes', '__doc__': f'Auto-generated ctypes structure for {struct_name}',
|
||||
'__repr__': lambda self: (
|
||||
f"<{struct_name} " +
|
||||
" ".join(f"{name}={getattr(self, name)}" for name, _ in fields) +
|
||||
">"
|
||||
)}
|
||||
)
|
||||
|
||||
ctypes_structs[struct_name] = struct_class
|
||||
# Pretty print field info
|
||||
field_info = ", ".join(f"{name}: {typ.__name__}" for name, typ in fields)
|
||||
logger.debug(f" {struct_name}({field_info})")
|
||||
except Exception as e:
|
||||
logger.error(f"Failed to convert struct '{struct_name}': {e}")
|
||||
raise
|
||||
logger.info(f"Converted struct '{struct_name}' to ctypes")
|
||||
return ctypes_structs
|
||||
|
||||
|
||||
def is_pythonbpf_structs(structs) -> bool:
|
||||
"""Check if structs dict is from PythonBPF."""
|
||||
if not isinstance(structs, dict) or not structs:
|
||||
return False
|
||||
|
||||
first_value = next(iter(structs.values()))
|
||||
return (
|
||||
hasattr(first_value, 'ir_type') and
|
||||
hasattr(first_value, 'fields') and
|
||||
hasattr(first_value, 'size')
|
||||
)
|
||||
|
||||
|
||||
__all__ = ["convert_structs_to_ctypes", "is_pythonbpf_structs"]
|
||||
Reference in New Issue
Block a user