Skip to content

Commit ca92f2a

Browse files
r41k0uclaude
andcommitted
Core: Rank an enum constant as C's int, not as i64
An enum constant has type int in C whatever the enum's underlying type is; clang emits `sub nsw i32` + sext for `XDP_PASS - k` and reserves the enum's u32 for variables of the enum type. The vmlinux handler was typing constants as i64, which made `XDP_PASS - k` with an unsigned k a signed 64-bit operation instead of C's u32 one. The constant's C rank is now decided once, in type_deducer.int_literal_type, shared by literals and enum constants, and the handler returns it as the descriptor so both operand typing and local inference read it from the source. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
1 parent 8e802e8 commit ca92f2a

4 files changed

Lines changed: 22 additions & 9 deletions

File tree

‎pythonbpf/expr/expr_pass.py‎

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,13 @@
44
import logging
55
from typing import Dict
66

7-
from pythonbpf.type_deducer import ctypes_to_ir, is_ctypes, IntTy, signedness
7+
from pythonbpf.type_deducer import (
8+
ctypes_to_ir,
9+
is_ctypes,
10+
IntTy,
11+
int_literal_type,
12+
signedness,
13+
)
814
from .call_registry import CallHandlerRegistry
915
from .ir_ops import deref_to_depth, access_struct_field
1016
from .operators import apply_binop, usual_arithmetic_conversions, UNARY_OPS, BOOL_OPS
@@ -54,8 +60,7 @@ def _handle_name_expr(
5460
def _int_literal(v: int):
5561
"""An integer literal: a 64-bit constant with C's literal rank as its
5662
descriptor, `int` if the value fits and `long long` otherwise."""
57-
lit_ty = IntTy(32, True) if -(1 << 31) <= v < (1 << 31) else IntTy(64, True)
58-
return ir.Constant(ir.IntType(64), v), lit_ty
63+
return ir.Constant(ir.IntType(64), v), int_literal_type(v)
5964

6065

6166
def _handle_constant_expr(compilation_context, builder, expr: ast.Constant):
@@ -221,8 +226,7 @@ def get_typed_operand(func, compilation_context, operand, builder, local_sym_tab
221226
else:
222227
vmlinux_result = VmlinuxHandlerRegistry.handle_name(operand.id)
223228
if vmlinux_result is not None:
224-
val, _ = vmlinux_result
225-
return val, IntTy(64, True)
229+
return vmlinux_result # (i64 constant, its C rank)
226230
elif isinstance(operand, ast.Constant):
227231
if isinstance(operand.value, (int, bool)):
228232
v = int(operand.value)

‎pythonbpf/expr/type_inference.py‎

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -40,8 +40,9 @@ def infer_int_type(expr, local_sym_tab, compilation_context):
4040
return _as_intty(local_sym_tab[expr.id].ir_type)
4141
if expr.id in compilation_context.bpf_globals:
4242
return _as_intty(compilation_context.bpf_globals[expr.id].ir_type)
43-
if VmlinuxHandlerRegistry.handle_name(expr.id) is not None:
44-
return IntTy(64, True) # enum constants are emitted as i64
43+
enum = VmlinuxHandlerRegistry.handle_name(expr.id)
44+
if enum is not None:
45+
return _as_intty(enum[1])
4546
return None
4647

4748
if isinstance(expr, ast.BinOp):

‎pythonbpf/type_deducer.py‎

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,14 @@ def describe(self) -> str:
4141
return f"{'i' if self.signed else 'u'}{self.width}"
4242

4343

44+
def int_literal_type(value: int) -> IntTy:
45+
"""C's type for an integer constant: `int` if the value fits, else
46+
`long long`. Literals and enum constants alike; an enum constant is an
47+
`int` whatever the enum's underlying type is (that type belongs to
48+
variables of the enum type, such as struct fields)."""
49+
return IntTy(32, True) if -(1 << 31) <= value < (1 << 31) else IntTy(64, True)
50+
51+
4452
def signedness(ty) -> bool:
4553
"""Sign of an integer type descriptor.
4654

‎pythonbpf/vmlinux_parser/vmlinux_exports_handler.py‎

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
from llvmlite import ir
55

66
from pythonbpf.symbols import LocalSymbol
7-
from pythonbpf.type_deducer import is_signed_ctype
7+
from pythonbpf.type_deducer import int_literal_type, is_signed_ctype
88
from pythonbpf.vmlinux_parser.assignment_info import AssignmentType
99

1010
logger = logging.getLogger(__name__)
@@ -74,7 +74,7 @@ def handle_vmlinux_enum(self, name):
7474
if self.is_vmlinux_enum(name):
7575
value = self.vmlinux_symtab[name].value
7676
logger.info(f"Resolving vmlinux enum {name} = {value}")
77-
return ir.Constant(ir.IntType(64), value), ir.IntType(64)
77+
return ir.Constant(ir.IntType(64), value), int_literal_type(value)
7878
return None
7979

8080
def get_vmlinux_enum_value(self, name):

0 commit comments

Comments
 (0)