Skip to content

Commit 2f4785b

Browse files
add int type conversion for all vmlinux struct field int types.
1 parent c5fdd3b commit 2f4785b

File tree

2 files changed

+39
-8
lines changed

2 files changed

+39
-8
lines changed

pythonbpf/expr/expr_pass.py

Lines changed: 37 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
get_base_type_and_depth,
1313
deref_to_depth,
1414
)
15+
from pythonbpf.vmlinux_parser.assignment_info import Field
1516
from .vmlinux_registry import VmlinuxHandlerRegistry
1617

1718
logger: Logger = logging.getLogger(__name__)
@@ -279,16 +280,45 @@ def _handle_ctypes_call(
279280
call_type = expr.func.id
280281
expected_type = ctypes_to_ir(call_type)
281282

282-
if val[1] != expected_type:
283+
# Extract the actual IR value and type
284+
# val could be (value, ir_type) or (value, Field)
285+
value, val_type = val
286+
287+
# If val_type is a Field object (from vmlinux struct), get the actual IR type of the value
288+
if isinstance(val_type, Field):
289+
# The value is already the correct IR value (potentially zero-extended)
290+
# Get the IR type from the value itself
291+
actual_ir_type = value.type
292+
logger.info(
293+
f"Converting vmlinux field {val_type.name} (IR type: {actual_ir_type}) to {call_type}"
294+
)
295+
else:
296+
actual_ir_type = val_type
297+
298+
if actual_ir_type != expected_type:
283299
# NOTE: We are only considering casting to and from int types for now
284-
if isinstance(val[1], ir.IntType) and isinstance(expected_type, ir.IntType):
285-
if val[1].width < expected_type.width:
286-
val = (builder.sext(val[0], expected_type), expected_type)
300+
if isinstance(actual_ir_type, ir.IntType) and isinstance(
301+
expected_type, ir.IntType
302+
):
303+
if actual_ir_type.width < expected_type.width:
304+
value = builder.sext(value, expected_type)
305+
logger.info(
306+
f"Sign-extended from i{actual_ir_type.width} to i{expected_type.width}"
307+
)
308+
elif actual_ir_type.width > expected_type.width:
309+
value = builder.trunc(value, expected_type)
310+
logger.info(
311+
f"Truncated from i{actual_ir_type.width} to i{expected_type.width}"
312+
)
287313
else:
288-
val = (builder.trunc(val[0], expected_type), expected_type)
314+
# Same width, just use as-is (e.g., both i64)
315+
pass
289316
else:
290-
raise ValueError(f"Type mismatch: expected {expected_type}, got {val[1]}")
291-
return val
317+
raise ValueError(
318+
f"Type mismatch: expected {expected_type}, got {actual_ir_type} (original type: {val_type})"
319+
)
320+
321+
return value, expected_type
292322

293323

294324
def _handle_compare(

tests/failing_tests/vmlinux/i32_test_fail_2.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
from ctypes import c_int64
2-
from pythonbpf import bpf, section, bpfglobal, compile
2+
from pythonbpf import bpf, section, bpfglobal, compile, compile_to_ir
33
from vmlinux import struct_xdp_md
44
from vmlinux import XDP_PASS
55
import logging
@@ -20,4 +20,5 @@ def LICENSE() -> str:
2020
return "GPL"
2121

2222

23+
compile_to_ir("i32_test_fail_2.py", "i32_test_fail_2.ll")
2324
compile(logging.INFO)

0 commit comments

Comments
 (0)