Skip to content

Commit 1e665a1

Browse files
r41k0uclaude
andcommitted
Core: Fold a negated integer literal into a constant
-2 parses as USub(Constant 2), so u32 / -2 reached the divider as a mul-by-minus-one instruction rather than the constant clang folds it to. Fold it at the unary operator; the result is a literal like any other, with a literal's C rank, so the usual arithmetic conversions still make u32 / -2 an unsigned division by 0xFFFFFFFE. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01BSDVsZH5NtoASyxB8FCtGU
1 parent e9a4806 commit 1e665a1

1 file changed

Lines changed: 12 additions & 2 deletions

File tree

‎pythonbpf/expr/expr_pass.py‎

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -51,14 +51,20 @@ def _handle_name_expr(
5151
raise SyntaxError(f"Undefined variable {expr.id}")
5252

5353

54+
def _int_literal(v: int):
55+
"""An integer literal: a 64-bit constant with C's literal rank as its
56+
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
59+
60+
5461
def _handle_constant_expr(compilation_context, builder, expr: ast.Constant):
5562
"""Handle ast.Constant expressions."""
5663
if isinstance(expr.value, int) or isinstance(expr.value, bool):
5764
# C gives a literal the type int if it fits, otherwise long long. That
5865
# rank is what makes `u32 / -2` an unsigned 32-bit division as in C.
5966
v = int(expr.value)
60-
lit_ty = IntTy(32, True) if -(1 << 31) <= v < (1 << 31) else IntTy(64, True)
61-
return ir.Constant(ir.IntType(64), v), lit_ty
67+
return _int_literal(v)
6268
elif isinstance(expr.value, str):
6369
str_name = f".str.{id(expr)}"
6470
str_bytes = expr.value.encode("utf-8") + b"\x00"
@@ -417,6 +423,10 @@ def _handle_unary_op(
417423
result = builder.xor(convert_to_bool(builder, operand), true_const)
418424
return result, ir.IntType(1)
419425
elif isinstance(expr.op, ast.USub):
426+
if isinstance(operand, ir.Constant) and isinstance(operand.constant, int):
427+
# -2 parses as USub(Constant 2); fold it so it is a literal like
428+
# any other, with a literal's C rank.
429+
return _int_literal(-operand.constant)
420430
# Negation happens in the operand's promoted type; for an unsigned
421431
# operand that is C's 2^N - x, which the narrowing produces.
422432
result_ty = usual_arithmetic_conversions(operand_ty, operand_ty)

0 commit comments

Comments
 (0)