Add remaining docstrings to complete documentation coverage

Co-authored-by: varun-r-mallya <100590632+varun-r-mallya@users.noreply.github.com>
This commit is contained in:
copilot-swe-agent[bot]
2025-10-08 17:25:29 +00:00
parent cdf4f3e885
commit d9dfb61000
10 changed files with 70 additions and 0 deletions

View File

@ -1,3 +1,5 @@
"""Debug information generation for BPF programs (DWARF/BTF)."""
from .dwarf_constants import * # noqa: F403 from .dwarf_constants import * # noqa: F403
from .dtypes import * # noqa: F403 from .dtypes import * # noqa: F403
from .debug_info_generator import DebugInfoGenerator from .debug_info_generator import DebugInfoGenerator

View File

@ -8,11 +8,31 @@ from typing import Any, List
class DebugInfoGenerator: class DebugInfoGenerator:
"""
Generator for DWARF/BTF debug information in LLVM IR modules.
This class provides methods to create debug metadata for BPF programs,
including types, structs, globals, and compilation units.
"""
def __init__(self, module): def __init__(self, module):
"""
Initialize the debug info generator.
Args:
module: LLVM IR module to attach debug info to
"""
self.module = module self.module = module
self._type_cache = {} # Cache for common debug types self._type_cache = {} # Cache for common debug types
def generate_file_metadata(self, filename, dirname): def generate_file_metadata(self, filename, dirname):
"""
Generate file metadata for debug info.
Args:
filename: Name of the source file
dirname: Directory containing the source file
"""
self.module._file_metadata = self.module.add_debug_info( self.module._file_metadata = self.module.add_debug_info(
"DIFile", "DIFile",
{ # type: ignore { # type: ignore
@ -24,6 +44,15 @@ class DebugInfoGenerator:
def generate_debug_cu( def generate_debug_cu(
self, language, producer: str, is_optimized: bool, is_distinct: bool self, language, producer: str, is_optimized: bool, is_distinct: bool
): ):
"""
Generate debug compile unit metadata.
Args:
language: DWARF language code (e.g., DW_LANG_C11)
producer: Compiler/producer string
is_optimized: Whether the code is optimized
is_distinct: Whether the compile unit should be distinct
"""
self.module._debug_compile_unit = self.module.add_debug_info( self.module._debug_compile_unit = self.module.add_debug_info(
"DICompileUnit", "DICompileUnit",
{ # type: ignore { # type: ignore
@ -83,6 +112,16 @@ class DebugInfoGenerator:
@staticmethod @staticmethod
def _compute_array_size(base_type: Any, count: int) -> int: def _compute_array_size(base_type: Any, count: int) -> int:
"""
Compute the size of an array in bits.
Args:
base_type: The base type of the array
count: Number of elements in the array
Returns:
Total size in bits
"""
# Extract size from base_type if possible # Extract size from base_type if possible
# For simplicity, assuming base_type has a size attribute # For simplicity, assuming base_type has a size attribute
return getattr(base_type, "size", 32) * count return getattr(base_type, "size", 32) * count

View File

@ -1,7 +1,10 @@
"""Debug information types and constants."""
import llvmlite.ir as ir import llvmlite.ir as ir
class DwarfBehaviorEnum: class DwarfBehaviorEnum:
"""DWARF module flag behavior constants for LLVM."""
ERROR_IF_MISMATCH = ir.Constant(ir.IntType(32), 1) ERROR_IF_MISMATCH = ir.Constant(ir.IntType(32), 1)
WARNING_IF_MISMATCH = ir.Constant(ir.IntType(32), 2) WARNING_IF_MISMATCH = ir.Constant(ir.IntType(32), 2)
OVERRIDE_USE_LARGEST = ir.Constant(ir.IntType(32), 7) OVERRIDE_USE_LARGEST = ir.Constant(ir.IntType(32), 7)

View File

@ -41,6 +41,7 @@ def section(name: str):
A decorator function that marks the function with the section name A decorator function that marks the function with the section name
""" """
def wrapper(fn): def wrapper(fn):
"""Decorator that sets the section name on the function."""
fn._section = name fn._section = name
return fn return fn

View File

@ -1,3 +1,5 @@
"""Registry for statement handler functions."""
from typing import Dict from typing import Dict
@ -11,6 +13,7 @@ class StatementHandlerRegistry:
"""Register a handler for a specific statement type.""" """Register a handler for a specific statement type."""
def decorator(handler): def decorator(handler):
"""Decorator that registers the handler."""
cls._handlers[stmt_type] = handler cls._handlers[stmt_type] = handler
return handler return handler

View File

@ -25,11 +25,20 @@ logger = logging.getLogger(__name__)
@dataclass @dataclass
class LocalSymbol: class LocalSymbol:
"""
Represents a local variable in a BPF function.
Attributes:
var: LLVM IR alloca instruction for the variable
ir_type: LLVM IR type of the variable
metadata: Optional metadata (e.g., struct type name)
"""
var: ir.AllocaInstr var: ir.AllocaInstr
ir_type: ir.Type ir_type: ir.Type
metadata: Any = None metadata: Any = None
def __iter__(self): def __iter__(self):
"""Support tuple unpacking of LocalSymbol."""
yield self.var yield self.var
yield self.ir_type yield self.ir_type
yield self.metadata yield self.metadata
@ -692,6 +701,7 @@ def infer_return_type(func_node: ast.FunctionDef):
found_type = None found_type = None
def _expr_type(e): def _expr_type(e):
"""Helper function to extract type from an expression."""
if e is None: if e is None:
return "None" return "None"
if isinstance(e, ast.Constant): if isinstance(e, ast.Constant):

View File

@ -24,6 +24,7 @@ logger: Logger = logging.getLogger(__name__)
class BPFHelperID(Enum): class BPFHelperID(Enum):
"""Enumeration of BPF helper function IDs."""
BPF_MAP_LOOKUP_ELEM = 1 BPF_MAP_LOOKUP_ELEM = 1
BPF_MAP_UPDATE_ELEM = 2 BPF_MAP_UPDATE_ELEM = 2
BPF_MAP_DELETE_ELEM = 3 BPF_MAP_DELETE_ELEM = 3
@ -260,6 +261,11 @@ def bpf_perf_event_output_handler(
local_sym_tab=None, local_sym_tab=None,
struct_sym_tab=None, struct_sym_tab=None,
): ):
"""
Emit LLVM IR for bpf_perf_event_output helper function call.
This allows sending data to userspace via a perf event array.
"""
if len(call.args) != 1: if len(call.args) != 1:
raise ValueError( raise ValueError(
f"Perf event output expects exactly one argument, got {len(call.args)}" f"Perf event output expects exactly one argument, got {len(call.args)}"
@ -310,6 +316,7 @@ def handle_helper_call(
# Helper function to get map pointer and invoke handler # Helper function to get map pointer and invoke handler
def invoke_helper(method_name, map_ptr=None): def invoke_helper(method_name, map_ptr=None):
"""Helper function to look up and invoke a registered handler."""
handler = HelperHandlerRegistry.get_handler(method_name) handler = HelperHandlerRegistry.get_handler(method_name)
if not handler: if not handler:
raise NotImplementedError( raise NotImplementedError(

View File

@ -26,6 +26,7 @@ class HelperHandlerRegistry:
"""Decorator to register a handler function for a helper""" """Decorator to register a handler function for a helper"""
def decorator(func): def decorator(func):
"""Decorator that registers the handler function."""
cls._handlers[helper_name] = func cls._handlers[helper_name] = func
return func return func

View File

@ -43,6 +43,7 @@ def is_map(func_node):
class BPFMapType(Enum): class BPFMapType(Enum):
"""Enumeration of BPF map types."""
UNSPEC = 0 UNSPEC = 0
HASH = 1 HASH = 1
ARRAY = 2 ARRAY = 2

View File

@ -1,3 +1,5 @@
"""Registry for BPF map processor functions."""
from collections.abc import Callable from collections.abc import Callable
from typing import Any from typing import Any
@ -12,6 +14,7 @@ class MapProcessorRegistry:
"""Decorator to register a processor function for a map type""" """Decorator to register a processor function for a map type"""
def decorator(func): def decorator(func):
"""Decorator that registers the processor function."""
cls._processors[map_type_name] = func cls._processors[map_type_name] = func
return func return func