11from llvmlite import ir
22import ast
33
4- from llvmlite import ir
5- import ast
64from logging import Logger
75import logging
86from .type_deducer import ctypes_to_ir
119
1210
1311def emit_global (module : ir .Module , node , name ):
14- print ("global" , node .returns .id )
12+ logger .info (f"global identifier { name } processing" )
13+ # TODO: below part is LLM generated check logic.
14+ # deduce LLVM type from the annotated return
15+ if not isinstance (node .returns , ast .Name ):
16+ raise ValueError (f"Unsupported return annotation { ast .dump (node .returns )} " )
1517 ty = ctypes_to_ir (node .returns .id )
1618
19+ # extract the return expression
20+ ret_stmt = node .body [0 ]
21+ if not isinstance (ret_stmt , ast .Return ) or ret_stmt .value is None :
22+ raise ValueError (f"Global '{ name } ' has no valid return" )
23+
24+ init_val = ret_stmt .value
25+
26+ # simple constant like "return 0"
27+ if isinstance (init_val , ast .Constant ):
28+ llvm_init = ir .Constant (ty , init_val .value )
29+
30+ # variable reference like "return SOME_CONST"
31+ elif isinstance (init_val , ast .Name ):
32+ # you may need symbol resolution here, stub as 0 for now
33+ raise ValueError (f"Name reference { init_val .id } not yet supported" )
34+
35+ # constructor call like "return c_int64(0)" or dataclass(...)
36+ elif isinstance (init_val , ast .Call ):
37+ if len (init_val .args ) == 1 and isinstance (init_val .args [0 ], ast .Constant ):
38+ llvm_init = ir .Constant (ty , init_val .args [0 ].value )
39+ else :
40+ raise ValueError (f"Complex constructor not supported: { ast .dump (init_val )} " )
41+
42+ else :
43+ raise ValueError (f"Unsupported return expr { ast .dump (init_val )} " )
44+
1745 gvar = ir .GlobalVariable (module , ty , name = name )
18- gvar .initializer = ir . Constant ( ty , initial_value )
46+ gvar .initializer = llvm_init
1947 gvar .align = 8
2048 gvar .linkage = "dso_local"
2149 gvar .global_constant = False
@@ -24,11 +52,11 @@ def emit_global(module: ir.Module, node, name):
2452
2553def globals_processing (tree , module ):
2654 """Process stuff decorated with @bpf and @bpfglobal except license and return the section name"""
27- global_sym_tab = []
55+ globals_sym_tab = []
2856
2957 for node in tree .body :
3058 # Skip non-assignment and non-function nodes
31- if not (isinstance (node , ( ast .FunctionDef , ast . AnnAssign , ast . Assign ) )):
59+ if not (isinstance (node , ast .FunctionDef )):
3260 continue
3361
3462 # Get the name based on node type
@@ -38,33 +66,31 @@ def globals_processing(tree, module):
3866 continue
3967
4068 # Check for duplicate names
41- if name in global_sym_tab :
69+ if name in globals_sym_tab :
4270 raise SyntaxError (f"ERROR: Global name '{ name } ' previously defined" )
4371 else :
44- global_sym_tab .append (name )
72+ globals_sym_tab .append (name )
4573
46- # Process decorated functions
4774 if isinstance (node , ast .FunctionDef ) and node .name != "LICENSE" :
48- # Check decorators
4975 decorators = [
5076 dec .id for dec in node .decorator_list if isinstance (dec , ast .Name )
5177 ]
52-
5378 if "bpf" in decorators and "bpfglobal" in decorators :
5479 if (
55- len (node .body ) == 1
56- and isinstance (node .body [0 ], ast .Return )
57- and node .body [0 ].value is not None
58- and isinstance (node .body [0 ].value , (ast .Constant , ast .Name ))
80+ len (node .body ) == 1
81+ and isinstance (node .body [0 ], ast .Return )
82+ and node .body [0 ].value is not None
83+ and isinstance (
84+ node .body [0 ].value , (ast .Constant , ast .Name , ast .Call )
85+ )
5986 ):
6087 emit_global (module , node , name )
61- return node .name
6288 else :
63- logger .info (f"Invalid global expression for '{ node .name } '" )
64- return None
89+ raise SyntaxError (f"ERROR: Invalid syntax for { name } global" )
6590
6691 return None
6792
93+
6894def emit_llvm_compiler_used (module : ir .Module , names : list [str ]):
6995 """
7096 Emit the @llvm.compiler.used global given a list of function/global names.
@@ -94,12 +120,12 @@ def globals_list_creation(tree, module: ir.Module):
94120 if isinstance (node , ast .FunctionDef ):
95121 for dec in node .decorator_list :
96122 if (
97- isinstance (dec , ast .Call )
98- and isinstance (dec .func , ast .Name )
99- and dec .func .id == "section"
100- and len (dec .args ) == 1
101- and isinstance (dec .args [0 ], ast .Constant )
102- and isinstance (dec .args [0 ].value , str )
123+ isinstance (dec , ast .Call )
124+ and isinstance (dec .func , ast .Name )
125+ and dec .func .id == "section"
126+ and len (dec .args ) == 1
127+ and isinstance (dec .args [0 ], ast .Constant )
128+ and isinstance (dec .args [0 ].value , str )
103129 ):
104130 collected .append (node .name )
105131
0 commit comments