From 9febadffd34f9bd183fae41421c0c6a4db38fa2a Mon Sep 17 00:00:00 2001 From: Pragyansh Chaturvedi Date: Fri, 10 Oct 2025 15:01:15 +0530 Subject: [PATCH] Add pointer handling to helper_utils, finish pointer assignment --- pythonbpf/expr/__init__.py | 10 +++++-- pythonbpf/expr/expr_pass.py | 2 +- pythonbpf/expr/type_normalization.py | 6 ++-- pythonbpf/helper/helper_utils.py | 42 ++++++++++++++++++++++++---- 4 files changed, 48 insertions(+), 12 deletions(-) diff --git a/pythonbpf/expr/__init__.py b/pythonbpf/expr/__init__.py index 577ee3c..dd5b480 100644 --- a/pythonbpf/expr/__init__.py +++ b/pythonbpf/expr/__init__.py @@ -1,4 +1,10 @@ from .expr_pass import eval_expr, handle_expr -from .type_normalization import convert_to_bool, get_base_type_and_depth +from .type_normalization import convert_to_bool, get_base_type_and_depth, deref_to_depth -__all__ = ["eval_expr", "handle_expr", "convert_to_bool", "get_base_type_and_depth"] +__all__ = [ + "eval_expr", + "handle_expr", + "convert_to_bool", + "get_base_type_and_depth", + "deref_to_depth", +] diff --git a/pythonbpf/expr/expr_pass.py b/pythonbpf/expr/expr_pass.py index 21be196..d4fc940 100644 --- a/pythonbpf/expr/expr_pass.py +++ b/pythonbpf/expr/expr_pass.py @@ -26,7 +26,7 @@ def _handle_constant_expr(expr: ast.Constant): if isinstance(expr.value, int) or isinstance(expr.value, bool): return ir.Constant(ir.IntType(64), int(expr.value)), ir.IntType(64) else: - logger.error("Unsupported constant type") + logger.error(f"Unsupported constant type {ast.dump(expr)}") return None diff --git a/pythonbpf/expr/type_normalization.py b/pythonbpf/expr/type_normalization.py index 34b4fb7..fec53a4 100644 --- a/pythonbpf/expr/type_normalization.py +++ b/pythonbpf/expr/type_normalization.py @@ -26,7 +26,7 @@ def get_base_type_and_depth(ir_type): return cur_type, depth -def _deref_to_depth(func, builder, val, target_depth): +def deref_to_depth(func, builder, val, target_depth): """Dereference a pointer to a certain depth.""" cur_val = val @@ -92,9 +92,9 @@ def _normalize_types(func, builder, lhs, rhs): rhs_base, rhs_depth = get_base_type_and_depth(rhs.type) if lhs_base == rhs_base: if lhs_depth < rhs_depth: - rhs = _deref_to_depth(func, builder, rhs, rhs_depth - lhs_depth) + rhs = deref_to_depth(func, builder, rhs, rhs_depth - lhs_depth) elif rhs_depth < lhs_depth: - lhs = _deref_to_depth(func, builder, lhs, lhs_depth - rhs_depth) + lhs = deref_to_depth(func, builder, lhs, lhs_depth - rhs_depth) return _normalize_types(func, builder, lhs, rhs) diff --git a/pythonbpf/helper/helper_utils.py b/pythonbpf/helper/helper_utils.py index 68ab52c..7b46a40 100644 --- a/pythonbpf/helper/helper_utils.py +++ b/pythonbpf/helper/helper_utils.py @@ -3,7 +3,7 @@ import logging from collections.abc import Callable from llvmlite import ir -from pythonbpf.expr import eval_expr +from pythonbpf.expr import eval_expr, get_base_type_and_depth, deref_to_depth logger = logging.getLogger(__name__) @@ -224,10 +224,27 @@ def _populate_fval(ftype, node, fmt_parts, exprs): raise NotImplementedError( f"Unsupported integer width in f-string: {ftype.width}" ) - elif ftype == ir.PointerType(ir.IntType(8)): - # NOTE: We assume i8* is a string - fmt_parts.append("%s") - exprs.append(node) + elif isinstance(ftype, ir.PointerType): + target, depth = get_base_type_and_depth(ftype) + if isinstance(target, ir.IntType): + if target.width == 64: + fmt_parts.append("%lld") + exprs.append(node) + elif target.width == 32: + fmt_parts.append("%d") + exprs.append(node) + elif target.width == 8 and depth == 1: + # NOTE: Assume i8* is a string + fmt_parts.append("%s") + exprs.append(node) + else: + raise NotImplementedError( + f"Unsupported pointer target type in f-string: {target}" + ) + else: + raise NotImplementedError( + f"Unsupported pointer target type in f-string: {target}" + ) else: raise NotImplementedError(f"Unsupported field type in f-string: {ftype}") @@ -264,7 +281,20 @@ def _prepare_expr_args(expr, func, module, builder, local_sym_tab, struct_sym_ta if val: if isinstance(val.type, ir.PointerType): - val = builder.ptrtoint(val, ir.IntType(64)) + target, depth = get_base_type_and_depth(val.type) + if isinstance(target, ir.IntType): + if target.width >= 32: + val = deref_to_depth(func, builder, val, depth) + val = builder.sext(val, ir.IntType(64)) + elif target.width == 8 and depth == 1: + # NOTE: i8* is string, no need to deref + pass + + else: + logger.warning( + "Only int and ptr supported in bpf_printk args. Others default to 0." + ) + val = ir.Constant(ir.IntType(64), 0) elif isinstance(val.type, ir.IntType): if val.type.width < 64: val = builder.sext(val, ir.IntType(64))