Skip to content

Commit a230b44

Browse files
r41k0uclaude
andcommitted
Core: Give bools C's rules: widen to 0 or 1, narrow by comparing with zero
A bool is ir.IntType(1), so convert() handled it as a 1-bit integer: a bool slot's plain descriptor read as signed and True sign-extended to -1 on the way out, and an integer narrowed to a bool by truncation, so 2 became false. Both predate this branch. C widens a bool to 0 or 1 and narrows to it with != 0, and Python's truthiness agrees on the second. signedness() now answers unsigned for any 1-bit integer whatever it is wrapped in, convert() narrows to width 1 with icmp ne 0, and a bool constant's slot carries the unsigned descriptor like the comparison results already do. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
1 parent eaaa12e commit a230b44

3 files changed

Lines changed: 10 additions & 1 deletion

File tree

‎pythonbpf/allocation_pass.py‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -263,7 +263,7 @@ def _allocate_for_constant(builder, var_name, rval, local_sym_tab):
263263
"""Allocate memory for variable assigned from a constant."""
264264

265265
if isinstance(rval.value, bool):
266-
ir_type = ir.IntType(1)
266+
ir_type = IntTy(1, False) # a bool widens to 0 or 1, never sign-extends
267267
var = builder.alloca(ir_type, name=var_name)
268268
var.align = 1
269269
local_sym_tab[var_name] = LocalSymbol(var, ir_type)

‎pythonbpf/expr/type_normalization.py‎

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,10 @@ def convert(builder, val, from_ty, to_ty):
6060
f"integer conversion requested for a {val.type} value to {to_ty}"
6161
)
6262
if val.type.width > to_ty.width:
63+
if to_ty.width == 1:
64+
# C's rule for bool: nonzero is true. Truncation would keep the
65+
# low bit and turn 2 into false.
66+
return builder.icmp_unsigned("!=", val, ir.Constant(val.type, 0))
6367
return builder.trunc(val, to_ty)
6468
if val.type.width < to_ty.width:
6569
ext = builder.zext if not signedness(from_ty) else builder.sext

‎pythonbpf/type_deducer.py‎

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,11 @@ def int_literal_type(value: int) -> IntTy:
5050

5151

5252
def signedness(ty) -> bool:
53+
"""Sign of a descriptor: an IntTy says; a vmlinux Field says through its
54+
ctype; a 1-bit integer is a bool and never negative, whatever it is
55+
wrapped in; anything else is signed, the pre-signedness default."""
56+
if isinstance(ty, ir.IntType) and ty.width == 1:
57+
return False
5358
"""Sign of an integer type descriptor.
5459
5560
IntTy carries it directly. A vmlinux Field carries a ctypes class in .type,

0 commit comments

Comments
 (0)