Skip to content

Commit 3d8a211

Browse files
r41k0uclaude
andcommitted
Core: Register @bpfglobal variables in a symbol table
globals_processing emitted each global and forgot it, which is why nothing could ever read one back. Each integer-scalar global now lands in CompilationContext.bpf_globals as a BpfGlobalSymbol; non-scalar globals get a clear NotImplementedError instead of emitting something unusable. LICENSE stays special-cased and unaffected. Alignment becomes natural (width/8) instead of a blanket 8, matching what clang emits for the same declarations in tests/c-form/global_vars.bpf.c -- llc derives the BTF DATASEC layout from these symbols. Also adds current_func_globals to the context for the upcoming write support. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01L1PX8EuP9C3o3veWGA84RF
1 parent cd1f2be commit 3d8a211

2 files changed

Lines changed: 40 additions & 2 deletions

File tree

pythonbpf/context.py

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
if TYPE_CHECKING:
66
from pythonbpf.structs.struct_type import StructType
77
from pythonbpf.maps.maps_utils import MapSymbol
8+
from pythonbpf.globals_pass import BpfGlobalSymbol
89

910
logger = logging.getLogger(__name__)
1011

@@ -66,6 +67,11 @@ def __init__(self, module: ir.Module):
6667
self.global_sym_tab: list[ir.GlobalVariable] = []
6768
self.structs_sym_tab: dict[str, "StructType"] = {}
6869
self.map_sym_tab: dict[str, "MapSymbol"] = {}
70+
self.bpf_globals: dict[str, "BpfGlobalSymbol"] = {}
71+
72+
# Names a `global` statement declared writable in the function whose
73+
# body is currently being emitted; managed by process_func_body.
74+
self.current_func_globals: set[str] = set()
6975

7076
# Helper management
7177
self.scratch_pool = ScratchPoolManager()
@@ -80,3 +86,4 @@ def reset(self):
8086
"""Reset state between functions if necessary, though new context per compile is preferred."""
8187
self.scratch_pool.reset()
8288
self.current_func = None
89+
self.current_func_globals = set()

pythonbpf/globals_pass.py

Lines changed: 33 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,28 @@
11
from llvmlite import ir
22
import ast
33

4+
from dataclasses import dataclass
45
from logging import Logger
56
import logging
67
from .type_deducer import ctypes_to_ir
78

89
logger: Logger = logging.getLogger(__name__)
910

1011

12+
@dataclass
13+
class BpfGlobalSymbol:
14+
"""A mutable BPF global variable declared with @bpfglobal.
15+
16+
Lands in .bss (zero initializer) or .data (non-zero) and is read with a
17+
plain load / written with a plain store; libbpf exposes the sections to
18+
userspace as global-data maps.
19+
"""
20+
21+
var: ir.GlobalVariable
22+
ir_type: ir.Type
23+
ctype_name: str
24+
25+
1126
def populate_global_symbol_table(tree, compilation_context):
1227
"""
1328
compilation_context: CompilationContext
@@ -68,7 +83,11 @@ def _emit_global(module: ir.Module, node, name):
6883

6984
gvar = ir.GlobalVariable(module, ty, name=name)
7085
gvar.initializer = llvm_init
71-
gvar.align = 8
86+
# Natural alignment, matching what clang emits for the same declaration
87+
# (align 4 for i32, align 8 for i64). llc derives the BTF DATASEC layout
88+
# from these symbols, so the alignment should mirror the C reference in
89+
# tests/c-form/global_vars.bpf.c.
90+
gvar.align = ty.width // 8 if isinstance(ty, ir.IntType) else 8
7291
gvar.linkage = "dso_local"
7392
gvar.global_constant = False
7493
return gvar
@@ -111,7 +130,19 @@ def globals_processing(tree, compilation_context):
111130
node.body[0].value, (ast.Constant, ast.Name, ast.Call)
112131
)
113132
):
114-
_emit_global(compilation_context.module, node, name)
133+
gvar = _emit_global(compilation_context.module, node, name)
134+
if isinstance(gvar.value_type, ir.IntType):
135+
compilation_context.bpf_globals[name] = BpfGlobalSymbol(
136+
var=gvar,
137+
ir_type=gvar.value_type,
138+
ctype_name=node.returns.id,
139+
)
140+
else:
141+
raise NotImplementedError(
142+
f"Global '{name}': only integer scalar globals are "
143+
f"supported so far; '{node.returns.id}' globals are "
144+
f"planned for a later milestone"
145+
)
115146
else:
116147
raise SyntaxError(f"ERROR: Invalid syntax for {name} global")
117148

0 commit comments

Comments
 (0)