Skip to content

Commit a9b2033

Browse files
authored
Merge pull request #16 from pythonbpf/sym
Use dataclass for local_sym_tab
2 parents 1a66887 + 7bc711c commit a9b2033

File tree

6 files changed

+88
-120
lines changed

6 files changed

+88
-120
lines changed

pythonbpf/binary_ops.py

Lines changed: 13 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ def handle_binary_op(rval, module, builder, var_name, local_sym_tab, map_sym_tab
2525
# Handle left operand
2626
if isinstance(left, ast.Name):
2727
if left.id in local_sym_tab:
28-
left = recursive_dereferencer(local_sym_tab[left.id][0], builder)
28+
left = recursive_dereferencer(local_sym_tab[left.id].var, builder)
2929
else:
3030
raise SyntaxError(f"Undefined variable: {left.id}")
3131
elif isinstance(left, ast.Constant):
@@ -35,7 +35,7 @@ def handle_binary_op(rval, module, builder, var_name, local_sym_tab, map_sym_tab
3535

3636
if isinstance(right, ast.Name):
3737
if right.id in local_sym_tab:
38-
right = recursive_dereferencer(local_sym_tab[right.id][0], builder)
38+
right = recursive_dereferencer(local_sym_tab[right.id].var, builder)
3939
else:
4040
raise SyntaxError(f"Undefined variable: {right.id}")
4141
elif isinstance(right, ast.Constant):
@@ -46,26 +46,26 @@ def handle_binary_op(rval, module, builder, var_name, local_sym_tab, map_sym_tab
4646
print(f"left is {left}, right is {right}, op is {op}")
4747

4848
if isinstance(op, ast.Add):
49-
builder.store(builder.add(left, right), local_sym_tab[var_name][0])
49+
builder.store(builder.add(left, right), local_sym_tab[var_name].var)
5050
elif isinstance(op, ast.Sub):
51-
builder.store(builder.sub(left, right), local_sym_tab[var_name][0])
51+
builder.store(builder.sub(left, right), local_sym_tab[var_name].var)
5252
elif isinstance(op, ast.Mult):
53-
builder.store(builder.mul(left, right), local_sym_tab[var_name][0])
53+
builder.store(builder.mul(left, right), local_sym_tab[var_name].var)
5454
elif isinstance(op, ast.Div):
55-
builder.store(builder.sdiv(left, right), local_sym_tab[var_name][0])
55+
builder.store(builder.sdiv(left, right), local_sym_tab[var_name].var)
5656
elif isinstance(op, ast.Mod):
57-
builder.store(builder.srem(left, right), local_sym_tab[var_name][0])
57+
builder.store(builder.srem(left, right), local_sym_tab[var_name].var)
5858
elif isinstance(op, ast.LShift):
59-
builder.store(builder.shl(left, right), local_sym_tab[var_name][0])
59+
builder.store(builder.shl(left, right), local_sym_tab[var_name].var)
6060
elif isinstance(op, ast.RShift):
61-
builder.store(builder.lshr(left, right), local_sym_tab[var_name][0])
61+
builder.store(builder.lshr(left, right), local_sym_tab[var_name].var)
6262
elif isinstance(op, ast.BitOr):
63-
builder.store(builder.or_(left, right), local_sym_tab[var_name][0])
63+
builder.store(builder.or_(left, right), local_sym_tab[var_name].var)
6464
elif isinstance(op, ast.BitXor):
65-
builder.store(builder.xor(left, right), local_sym_tab[var_name][0])
65+
builder.store(builder.xor(left, right), local_sym_tab[var_name].var)
6666
elif isinstance(op, ast.BitAnd):
67-
builder.store(builder.and_(left, right), local_sym_tab[var_name][0])
67+
builder.store(builder.and_(left, right), local_sym_tab[var_name].var)
6868
elif isinstance(op, ast.FloorDiv):
69-
builder.store(builder.udiv(left, right), local_sym_tab[var_name][0])
69+
builder.store(builder.udiv(left, right), local_sym_tab[var_name].var)
7070
else:
7171
raise SyntaxError("Unsupported binary operation")

pythonbpf/expr_pass.py

Lines changed: 12 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -10,15 +10,13 @@ def eval_expr(
1010
local_sym_tab,
1111
map_sym_tab,
1212
structs_sym_tab=None,
13-
local_var_metadata=None,
1413
):
1514
print(f"Evaluating expression: {ast.dump(expr)}")
16-
print(local_var_metadata)
1715
if isinstance(expr, ast.Name):
1816
if expr.id in local_sym_tab:
19-
var = local_sym_tab[expr.id][0]
17+
var = local_sym_tab[expr.id].var
2018
val = builder.load(var)
21-
return val, local_sym_tab[expr.id][1] # return value and type
19+
return val, local_sym_tab[expr.id].ir_type # return value and type
2220
else:
2321
print(f"Undefined variable {expr.id}")
2422
return None
@@ -51,7 +49,7 @@ def eval_expr(
5149
return None
5250
if isinstance(arg, ast.Name):
5351
if arg.id in local_sym_tab:
54-
arg = local_sym_tab[arg.id][0]
52+
arg = local_sym_tab[arg.id].var
5553
else:
5654
print(f"Undefined variable {arg.id}")
5755
return None
@@ -60,7 +58,7 @@ def eval_expr(
6058
return None
6159
# Since we are handling only name case, directly take type from sym tab
6260
val = builder.load(arg)
63-
return val, local_sym_tab[expr.args[0].id][1]
61+
return val, local_sym_tab[expr.args[0].id].ir_type
6462

6563
# check for helpers
6664
if HelperHandlerRegistry.has_handler(expr.func.id):
@@ -72,7 +70,6 @@ def eval_expr(
7270
local_sym_tab,
7371
map_sym_tab,
7472
structs_sym_tab,
75-
local_var_metadata,
7673
)
7774
elif isinstance(expr.func, ast.Attribute):
7875
print(f"Handling method call: {ast.dump(expr.func)}")
@@ -89,7 +86,6 @@ def eval_expr(
8986
local_sym_tab,
9087
map_sym_tab,
9188
structs_sym_tab,
92-
local_var_metadata,
9389
)
9490
elif isinstance(expr.func.value, ast.Name):
9591
obj_name = expr.func.value.id
@@ -104,24 +100,21 @@ def eval_expr(
104100
local_sym_tab,
105101
map_sym_tab,
106102
structs_sym_tab,
107-
local_var_metadata,
108103
)
109104
elif isinstance(expr, ast.Attribute):
110105
if isinstance(expr.value, ast.Name):
111106
var_name = expr.value.id
112107
attr_name = expr.attr
113108
if var_name in local_sym_tab:
114-
var_ptr, var_type = local_sym_tab[var_name]
115-
print(f"Loading attribute " f"{attr_name} from variable {var_name}")
109+
var_ptr, var_type, var_metadata = local_sym_tab[var_name]
110+
print(f"Loading attribute {attr_name} from variable {var_name}")
116111
print(f"Variable type: {var_type}, Variable ptr: {var_ptr}")
117-
print(local_var_metadata)
118-
if local_var_metadata and var_name in local_var_metadata:
119-
metadata = structs_sym_tab[local_var_metadata[var_name]]
120-
if attr_name in metadata.fields:
121-
gep = metadata.gep(builder, var_ptr, attr_name)
122-
val = builder.load(gep)
123-
field_type = metadata.field_type(attr_name)
124-
return val, field_type
112+
metadata = structs_sym_tab[var_metadata]
113+
if attr_name in metadata.fields:
114+
gep = metadata.gep(builder, var_ptr, attr_name)
115+
val = builder.load(gep)
116+
field_type = metadata.field_type(attr_name)
117+
return val, field_type
125118
print("Unsupported expression evaluation")
126119
return None
127120

@@ -134,11 +127,9 @@ def handle_expr(
134127
local_sym_tab,
135128
map_sym_tab,
136129
structs_sym_tab,
137-
local_var_metadata,
138130
):
139131
"""Handle expression statements in the function body."""
140132
print(f"Handling expression: {ast.dump(expr)}")
141-
print(local_var_metadata)
142133
call = expr.value
143134
if isinstance(call, ast.Call):
144135
eval_expr(
@@ -149,7 +140,6 @@ def handle_expr(
149140
local_sym_tab,
150141
map_sym_tab,
151142
structs_sym_tab,
152-
local_var_metadata,
153143
)
154144
else:
155145
print("Unsupported expression type")

pythonbpf/functions_pass.py

Lines changed: 41 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,27 @@
11
from llvmlite import ir
22
import ast
3+
import logging
34
from typing import Any
5+
from dataclasses import dataclass
46

57
from .helper import HelperHandlerRegistry, handle_helper_call
68
from .type_deducer import ctypes_to_ir
79
from .binary_ops import handle_binary_op
810
from .expr_pass import eval_expr, handle_expr
911

10-
local_var_metadata: dict[str | Any, Any] = {}
12+
logger = logging.getLogger(__name__)
13+
14+
15+
@dataclass
16+
class LocalSymbol:
17+
var: ir.AllocaInstr
18+
ir_type: ir.Type
19+
metadata: Any = None
20+
21+
def __iter__(self):
22+
yield self.var
23+
yield self.ir_type
24+
yield self.metadata
1125

1226

1327
def get_probe_string(func_node):
@@ -47,13 +61,12 @@ def handle_assign(
4761
if isinstance(target, ast.Attribute):
4862
# struct field assignment
4963
field_name = target.attr
50-
if var_name in local_sym_tab and var_name in local_var_metadata:
51-
struct_type = local_var_metadata[var_name]
64+
if var_name in local_sym_tab:
65+
struct_type = local_sym_tab[var_name].metadata
5266
struct_info = structs_sym_tab[struct_type]
53-
5467
if field_name in struct_info.fields:
5568
field_ptr = struct_info.gep(
56-
builder, local_sym_tab[var_name][0], field_name
69+
builder, local_sym_tab[var_name].var, field_name
5770
)
5871
val = eval_expr(
5972
func,
@@ -83,18 +96,21 @@ def handle_assign(
8396
elif isinstance(rval, ast.Constant):
8497
if isinstance(rval.value, bool):
8598
if rval.value:
86-
builder.store(ir.Constant(ir.IntType(1), 1), local_sym_tab[var_name][0])
99+
builder.store(
100+
ir.Constant(ir.IntType(1), 1), local_sym_tab[var_name].var
101+
)
87102
else:
88-
builder.store(ir.Constant(ir.IntType(1), 0), local_sym_tab[var_name][0])
103+
builder.store(
104+
ir.Constant(ir.IntType(1), 0), local_sym_tab[var_name].var
105+
)
89106
print(f"Assigned constant {rval.value} to {var_name}")
90107
elif isinstance(rval.value, int):
91108
# Assume c_int64 for now
92109
# var = builder.alloca(ir.IntType(64), name=var_name)
93110
# var.align = 8
94111
builder.store(
95-
ir.Constant(ir.IntType(64), rval.value), local_sym_tab[var_name][0]
112+
ir.Constant(ir.IntType(64), rval.value), local_sym_tab[var_name].var
96113
)
97-
# local_sym_tab[var_name] = var
98114
print(f"Assigned constant {rval.value} to {var_name}")
99115
elif isinstance(rval.value, str):
100116
str_val = rval.value.encode("utf-8") + b"\x00"
@@ -108,7 +124,7 @@ def handle_assign(
108124
global_str.global_constant = True
109125
global_str.initializer = str_const
110126
str_ptr = builder.bitcast(global_str, ir.PointerType(ir.IntType(8)))
111-
builder.store(str_ptr, local_sym_tab[var_name][0])
127+
builder.store(str_ptr, local_sym_tab[var_name].var)
112128
print(f"Assigned string constant '{rval.value}' to {var_name}")
113129
else:
114130
print("Unsupported constant type")
@@ -126,13 +142,13 @@ def handle_assign(
126142
# var = builder.alloca(ir_type, name=var_name)
127143
# var.align = ir_type.width // 8
128144
builder.store(
129-
ir.Constant(ir_type, rval.args[0].value), local_sym_tab[var_name][0]
145+
ir.Constant(ir_type, rval.args[0].value),
146+
local_sym_tab[var_name].var,
130147
)
131148
print(
132149
f"Assigned {call_type} constant "
133150
f"{rval.args[0].value} to {var_name}"
134151
)
135-
# local_sym_tab[var_name] = var
136152
elif HelperHandlerRegistry.has_handler(call_type):
137153
# var = builder.alloca(ir.IntType(64), name=var_name)
138154
# var.align = 8
@@ -144,10 +160,8 @@ def handle_assign(
144160
local_sym_tab,
145161
map_sym_tab,
146162
structs_sym_tab,
147-
local_var_metadata,
148163
)
149-
builder.store(val[0], local_sym_tab[var_name][0])
150-
# local_sym_tab[var_name] = var
164+
builder.store(val[0], local_sym_tab[var_name].var)
151165
print(f"Assigned constant {rval.func.id} to {var_name}")
152166
elif call_type == "deref" and len(rval.args) == 1:
153167
print(f"Handling deref assignment {ast.dump(rval)}")
@@ -164,18 +178,15 @@ def handle_assign(
164178
print("Failed to evaluate deref argument")
165179
return
166180
print(f"Dereferenced value: {val}, storing in {var_name}")
167-
builder.store(val[0], local_sym_tab[var_name][0])
168-
# local_sym_tab[var_name] = var
181+
builder.store(val[0], local_sym_tab[var_name].var)
169182
print(f"Dereferenced and assigned to {var_name}")
170183
elif call_type in structs_sym_tab and len(rval.args) == 0:
171184
struct_info = structs_sym_tab[call_type]
172185
ir_type = struct_info.ir_type
173186
# var = builder.alloca(ir_type, name=var_name)
174187
# Null init
175-
builder.store(ir.Constant(ir_type, None), local_sym_tab[var_name][0])
176-
local_var_metadata[var_name] = call_type
188+
builder.store(ir.Constant(ir_type, None), local_sym_tab[var_name].var)
177189
print(f"Assigned struct {call_type} to {var_name}")
178-
# local_sym_tab[var_name] = var
179190
else:
180191
print(f"Unsupported assignment call type: {call_type}")
181192
elif isinstance(rval.func, ast.Attribute):
@@ -198,12 +209,10 @@ def handle_assign(
198209
local_sym_tab,
199210
map_sym_tab,
200211
structs_sym_tab,
201-
local_var_metadata,
202212
)
203213
# var = builder.alloca(ir.IntType(64), name=var_name)
204214
# var.align = 8
205-
builder.store(val[0], local_sym_tab[var_name][0])
206-
# local_sym_tab[var_name] = var
215+
builder.store(val[0], local_sym_tab[var_name].var)
207216
else:
208217
print("Unsupported assignment call structure")
209218
else:
@@ -227,7 +236,7 @@ def handle_cond(func, module, builder, cond, local_sym_tab, map_sym_tab):
227236
return None
228237
elif isinstance(cond, ast.Name):
229238
if cond.id in local_sym_tab:
230-
var = local_sym_tab[cond.id][0]
239+
var = local_sym_tab[cond.id].var
231240
val = builder.load(var)
232241
if val.type != ir.IntType(1):
233242
# Convert nonzero values to true, zero to false
@@ -342,7 +351,6 @@ def process_stmt(
342351
):
343352
print(f"Processing statement: {ast.dump(stmt)}")
344353
if isinstance(stmt, ast.Expr):
345-
print(local_var_metadata)
346354
handle_expr(
347355
func,
348356
module,
@@ -351,7 +359,6 @@ def process_stmt(
351359
local_sym_tab,
352360
map_sym_tab,
353361
structs_sym_tab,
354-
local_var_metadata,
355362
)
356363
elif isinstance(stmt, ast.Assign):
357364
handle_assign(
@@ -401,6 +408,7 @@ def allocate_mem(
401408
module, builder, body, func, ret_type, map_sym_tab, local_sym_tab, structs_sym_tab
402409
):
403410
for stmt in body:
411+
has_metadata = False
404412
if isinstance(stmt, ast.If):
405413
if stmt.body:
406414
local_sym_tab = allocate_mem(
@@ -458,7 +466,7 @@ def allocate_mem(
458466
struct_info = structs_sym_tab[call_type]
459467
ir_type = struct_info.ir_type
460468
var = builder.alloca(ir_type, name=var_name)
461-
local_var_metadata[var_name] = call_type
469+
has_metadata = True
462470
print(
463471
f"Pre-allocated variable {var_name} "
464472
f"for struct {call_type}"
@@ -500,7 +508,11 @@ def allocate_mem(
500508
else:
501509
print("Unsupported assignment value type")
502510
continue
503-
local_sym_tab[var_name] = (var, ir_type)
511+
512+
if has_metadata:
513+
local_sym_tab[var_name] = LocalSymbol(var, ir_type, call_type)
514+
else:
515+
local_sym_tab[var_name] = LocalSymbol(var, ir_type)
504516
return local_sym_tab
505517

506518

@@ -662,7 +674,7 @@ def _expr_type(e):
662674
if found_type is None:
663675
found_type = t
664676
elif found_type != t:
665-
raise ValueError("Conflicting return types:" f"{found_type} vs {t}")
677+
raise ValueError(f"Conflicting return types: {found_type} vs {t}")
666678
return found_type or "None"
667679

668680

0 commit comments

Comments
 (0)