support referencing other variables inside binops

This commit is contained in:
2025-09-12 23:05:52 +05:30
parent a09e4e1bb6
commit ca203a1fdd
6 changed files with 61 additions and 47 deletions

View File

@ -1,5 +1,5 @@
BPF_CLANG := clang BPF_CLANG := clang
CFLAGS := -O2 -emit-llvm -target bpf -c CFLAGS := -O0 -emit-llvm -target bpf -c
SRC := $(wildcard *.bpf.c) SRC := $(wildcard *.bpf.c)
LL := $(SRC:.bpf.c=.bpf.ll) LL := $(SRC:.bpf.c=.bpf.ll)

View File

@ -13,6 +13,9 @@ struct {
SEC("tracepoint/syscalls/sys_enter_execve") SEC("tracepoint/syscalls/sys_enter_execve")
int hello(struct pt_regs *ctx) { int hello(struct pt_regs *ctx) {
bpf_printk("Hello, World!\n"); bpf_printk("Hello, World!\n");
u64 b;
u64 a = 3 * b;
bpf_printk("%d", a);
return 0; return 0;
} }

View File

@ -1,5 +1,5 @@
from pythonbpf import bpf, map, section, bpfglobal, compile from pythonbpf import bpf, map, section, bpfglobal, compile
from pythonbpf.helpers import ktime from pythonbpf.helpers import ktime, deref
from pythonbpf.maps import HashMap from pythonbpf.maps import HashMap
from ctypes import c_void_p, c_int64, c_int32, c_uint64 from ctypes import c_void_p, c_int64, c_int32, c_uint64
@ -34,36 +34,13 @@ def hello_again(ctx: c_void_p) -> c_int64:
last().delete(key) last().delete(key)
ts = ktime() ts = ktime()
last().update(key, ts) last().update(key, ts)
keema = 8
keeda = keema * keema
print(f"this is a variable {keeda}")
# st = "st" # st = "st"
# last().update(key, ts) # last().update(key, ts)
keena = 2 + 1
# below breaks
# keela = keena + 1
# TODO: binops evaluate but into a random register and dont get assigned.
keema = 8 * 9
keesa = 10 - 11
keeda = 10 / 5
# x = 3
# y = False
# if x > 0:
# if x < 5:
# print(f"we prevailed {x}")
# else:
# print(f"we did not prevail {x}")
# ts = ktime()
# last().update(key, ts)
#
# st = "st"
# last().update(key, ts)
#
# keena = 2 + 1
# # below breaks
# # keela = keena + 1
# keema = 8 * 9
# keesa = 10 - 11
# keeda = 10 / 5
return c_int64(0) return c_int64(0)

View File

@ -1,41 +1,64 @@
import ast import ast
from llvmlite import ir from llvmlite import ir
def handle_binary_op(rval, module, builder, var_name, local_sym_tab, map_sym_tab):
def handle_binary_op(rval, module, builder, func, local_sym_tab, map_sym_tab):
print(module) print(module)
left = rval.left left = rval.left
right = rval.right right = rval.right
op = rval.op op = rval.op
# In case of pointers, we'll deref once. # Handle left operand
if isinstance(left, ast.Name): if isinstance(left, ast.Name):
left = local_sym_tab[left.id] if left.id in local_sym_tab:
left = builder.load(local_sym_tab[left.id])
else:
raise SyntaxError(f"Undefined variable: {left.id}")
elif isinstance(left, ast.Constant): elif isinstance(left, ast.Constant):
left = ir.Constant(ir.IntType(64), left.value) left = ir.Constant(ir.IntType(64), left.value)
else: else:
print("Unsupported left operand type") raise SyntaxError("Unsupported left operand type")
if isinstance(right, ast.Name): if isinstance(right, ast.Name):
right = local_sym_tab[right.id] if right.id in local_sym_tab:
right = builder.load(local_sym_tab[right.id]) # Dereference the pre-assigned value
else:
raise SyntaxError(f"Undefined variable: {right.id}")
elif isinstance(right, ast.Constant): elif isinstance(right, ast.Constant):
right = ir.Constant(ir.IntType(64), right.value) right = ir.Constant(ir.IntType(64), right.value)
else: else:
SyntaxError("Unsupported right operand type") raise SyntaxError("Unsupported right operand type")
print(f"left is {left}, right is {right}, op is {op}") print(f"left is {left}, right is {right}, op is {op}")
if isinstance(op, ast.Add): if isinstance(op, ast.Add):
result = builder.add(left, right) builder.store(builder.add(left, right),
local_sym_tab[var_name])
elif isinstance(op, ast.Sub): elif isinstance(op, ast.Sub):
result = builder.sub(left, right) builder.store(builder.sub(left, right),
local_sym_tab[var_name])
elif isinstance(op, ast.Mult): elif isinstance(op, ast.Mult):
result = builder.mul(left, right) builder.store(builder.mul(left, right),
local_sym_tab[var_name])
elif isinstance(op, ast.Div): elif isinstance(op, ast.Div):
result = builder.sdiv(left, right) builder.store(builder.sdiv(left, right),
local_sym_tab[var_name])
elif isinstance(op, ast.Mod):
builder.store(builder.srem(left, right),
local_sym_tab[var_name])
elif isinstance(op, ast.LShift):
builder.store(builder.shl(left, right),
local_sym_tab[var_name])
elif isinstance(op, ast.RShift):
builder.store(builder.lshr(left, right),
local_sym_tab[var_name])
elif isinstance(op, ast.BitOr):
builder.store(builder.or_(left, right),
local_sym_tab[var_name])
elif isinstance(op, ast.BitXor):
builder.store(builder.xor(left, right),
local_sym_tab[var_name])
elif isinstance(op, ast.BitAnd):
builder.store(builder.and_(left, right),
local_sym_tab[var_name])
else: else:
result = "fuck type errors" raise SyntaxError("Unsupported binary operation")
SyntaxError("Unsupported binary operation")
return result

View File

@ -110,7 +110,7 @@ def handle_assign(func, module, builder, stmt, map_sym_tab, local_sym_tab):
else: else:
print("Unsupported assignment call function type") print("Unsupported assignment call function type")
elif isinstance(rval, ast.BinOp): elif isinstance(rval, ast.BinOp):
handle_binary_op(rval, module, builder, func, handle_binary_op(rval, module, builder, var_name,
local_sym_tab, map_sym_tab) local_sym_tab, map_sym_tab)
else: else:
print("Unsupported assignment value type") print("Unsupported assignment value type")
@ -306,6 +306,13 @@ def allocate_mem(module, builder, body, func, ret_type, map_sym_tab, local_sym_t
else: else:
print("Unsupported constant type") print("Unsupported constant type")
continue continue
elif isinstance(rval, ast.BinOp):
# Assume c_int64 for now
ir_type = ir.IntType(64)
var = builder.alloca(ir_type, name=var_name)
var.align = ir_type.width // 8
print(
f"Pre-allocated variable {var_name} of type c_int64")
else: else:
print("Unsupported assignment value type") print("Unsupported assignment value type")
continue continue

View File

@ -1,5 +1,9 @@
import ctypes import ctypes
def ktime(): def ktime():
return ctypes.c_int64(0) return ctypes.c_int64(0)
def deref(ptr):
"dereference a pointer"
result = ctypes.cast(ptr, ctypes.POINTER(ctypes.c_void_p)).contents.value
return result if result is not None else 0