Files
TransPyC/lib/core/Translator/BaseTranslator.py
T
TermiNexus fc5a6134ca feat(hotspot)!: 下线 --func-hotspot 并为 --hotspot-sites 增加每函数计时器
移除 --func-hotspot 全链路(CLI 解析与绑定、Config argparse 与注入、Translator 属性、LlvmGenerator 收口与透传、BaseGen 专属实现、Phase2Translator 透传、帮助文本);全仓已无 FuncHotspot/func-hotspot 残留引用。

通用截断逻辑保留并改名为 _InstallHotspotTruncate,供 --hotspot-sites 使用(分别清空 hotspot_sites.txt 与 hotspot_time.txt);ctor 注册改为直接新建并接收处理器列表(sites 与 time 两个处理器在同一 ctor 内注册)。

--hotspot-sites 现附带每函数计时:入口读一次 @llvm.readcyclecounter() 存起始 tick,在函数所有 ret 之前再读一次并累加差值到 internal i64 __fhs_ftime_N,同时 __fhs_ftime_enter_N 记录进入次数;单位为 tick(x86_64 即 CPU 周期),语义为 inclusive(包含内层调用)。

计时结果按耗时降序写入同目录 hotspot_time.txt(# time <module_sha1> 分段 + 函数名/累计 tick/进入次数),不改变 hotspot_sites.txt 的既有格式与字段。不传 --hotspot-sites 时零影响。
2026-09-14 13:10:06 +08:00

169 lines
8.0 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
from __future__ import annotations
import vast as ast
from typing import Any, Callable, Dict, TYPE_CHECKING
from lib.core.Exportable import Exportable
if TYPE_CHECKING:
import llvmlite.ir as ir
from lib.core.Handles import (
IfHandle, ForHandle, WhileHandle,
AnnAssignHandle,
HandlesTypeMerge, ExprHandle, BodyHandle,
ReturnHandle, AssignHandle, AugAssignHandle, DeleteHandle,
WithHandle, TryHandle, AssertHandle, RaiseHandle, MatchHandle,
ExprUtils, ExprOpsHandle, ExprAttrHandle, ExprBuiltinHandle,
ExprAsmHandle, ExprFormatHandle, ExprLambdaHandle, ExprCallHandle,
CSpecialCallHandle, TSpecialCallHandle,
ClassHandle,
FunctionHandle,
ImportHandle,
AsyncFunctionHandle
)
from lib.core.Handles.HandlesBase import CTypeInfo
from lib.core.SymbolTable import SymbolTable
from lib.core.SymbolNode import SymbolNode
from lib.constants.config import mode as _ConfigMode
from lib.core.VLogger import get_logger as _vlog
def _StrictLog(logger: Callable[[str], None], msg: str) -> None:
"""在 strict 模式下记录异常日志"""
if _ConfigMode == "strict":
logger(msg)
class BaseTranslatorMixin:
"""代码转换器基础 Mixin
提供 __init__、日志、调试输出与表达式处理等基础能力。
"""
def __init__(self) -> None:
self.VarScopes: list[Dict[str, SymbolNode]] = [{}] # 跟踪变量作用域,第一个是全局作用域
self.FunctionReturnTypes: Dict[str, CTypeInfo] = {} # 记录函数名和其返回类型
self.CurrentCReturnTypes: list[CTypeInfo] | None = None # 当前函数的 CReturn 类型列表
self._CurrentCpythonObjectClass: str | None = None # 当前正在处理的 CPython 对象类名
self.FunctionDefCache: dict = {} # 函数定义缓存
self.OriginalLines: list[str] = [] # 原始代码行
self.Content: str = ''
self.DebugFile: str | None = None # 调试输出文件路径
self.IsHeader: bool = False # 是否生成头文件(仅处理定义、宏、导入等,忽略函数体)
self.AnnotationModules: set[str] = set() # 注解模块集合,用于识别类型定义模块
self.Warnings: list[str] = [] # 警告日志
self._ErrorStack: list[tuple[str, str, str]] = [] # 错误栈,按顺序收集错误位置
self.Errors: list[dict[str, str | None]] = [] # 错误日志
self.SliceCount: int = 0 # 切片计数
self.SliceInfos: list = [] # 切片信息列表
self.SliceLevel: int = 3 # 切片优化级别
self.GeneratedTypes: set[str] = set() # 在当前代码中生成的类型(struct/typedef)
self.EmbeddedAssignments: dict[str, list] = {} # {ClassName: [var1, var2, ...]} 嵌入的实例化变量
self.TypedefAssignments: dict[str, list] = {} # {ClassName: [(var1, IsPtr), ...]} 嵌入的 typedef/指针变量
self.ChainAssignmentArrays: list = [] # 链式赋值数组形式 [(ClassName, VarName, ArraySize_node), ...]
self.tree: ast.AST | None = None # 保存解析后的 AST 树
self.LibraryPaths: list[str] = ['.'] # 库搜索路径列表,默认包含当前目录
self.InClass: bool = False # 是否正在处理 class 定义
self._UserTypeModules: dict = {}
self._source_module_sig_files: dict = {}
self._global_function_default_args: dict = {}
self._global_function_param_names: dict = {}
self.exception_registry: dict = {}
self.exception_parents: dict = {}
self._next_exception_code: int = 100
# 以下属性原先在外部懒注入,此处显式初始化以避免 hasattr/getattr 动态反射
self.config: Any = None
self._ImportedModules: set[str] | None = None
self._t_c_imported_names: dict = {}
# 调用点热点统计(--hotspot-sites):None=未启用(零影响),否则为调用点计数落盘文件路径
self.HotspotSitesFile: str | None = None
# 是否对全部直接 call 点插桩(忽略白名单;体积/开销大)
self.HotspotSitesAll: bool = False
# 白名单被调函数基名列表;None=使用默认内存/字符串族白名单
self.HotspotCallees: list[str] | None = None
# 注册策略:False=种子 CLI 单模块(在 main 入口注册);True=Projectrans
# 多模块(每模块 @llvm.global_ctors 自注册,见 BaseGen._InstallHotspotSitesModuleLocal)
self.HotspotSitesModuleLocal: bool = False
# 导出表
self.Exportable = Exportable(filename='')
self.SymbolTable = SymbolTable(self)
self.IfHandler = IfHandle(self)
self.ForHandler = ForHandle(self)
self.WhileHandler = WhileHandle(self)
self.AnnAssignHandler = AnnAssignHandle(self)
self.TypeMergeHandler = HandlesTypeMerge(self)
self.ExprHandler = ExprHandle(self)
self.ExprUtils = ExprUtils(self)
self.ExprOpsHandle = ExprOpsHandle(self)
self.ExprAttrHandle = ExprAttrHandle(self)
self.ExprBuiltinHandle = ExprBuiltinHandle(self)
self.ExprAsmHandle = ExprAsmHandle(self)
self.ExprFormatHandle = ExprFormatHandle(self)
self.ExprLambdaHandle = ExprLambdaHandle(self)
self.ExprCallHandle = ExprCallHandle(self)
self.CSpecialCallHandle = CSpecialCallHandle(self)
self.TSpecialCallHandle = TSpecialCallHandle(self)
self.ClassHandler = ClassHandle(self)
self.FunctionHandler = FunctionHandle(self)
self.ImportHandler = ImportHandle(self)
self.BodyHandler = BodyHandle(self)
self.ReturnHandler = ReturnHandle(self)
self.AssignHandler = AssignHandle(self)
self.AugAssignHandler = AugAssignHandle(self)
self.DeleteHandler = DeleteHandle(self)
self.WithHandler = WithHandle(self)
self.TryHandler = TryHandle(self)
self.AssertHandler = AssertHandle(self)
self.RaiseHandler = RaiseHandle(self)
self.MatchHandler = MatchHandle(self)
self.AsyncHandler = AsyncFunctionHandle(self)
def LogWarning(self, message: str, LineNum: int | None = None) -> None:
"""记录警告
Args:
message: 警告消息
LineNum: 行号(可选)
"""
warning = f"Warning: {message}"
if LineNum is not None:
warning += f" (line {LineNum})"
self.Warnings.append(warning)
def LogError(self, message: str, LineNum: int | None = None) -> None:
"""记录错误
Args:
message: 错误消息
LineNum: 行号
"""
_vlog().error(message)
entry: dict[str, str | int | None] = {'message': message, 'line': LineNum}
self.Errors.append(entry)
# 检查 config 中是否有 debug 文件
DebugFile: str | None = None
if hasattr(self, 'config') and self.config:
DebugFile = getattr(self.config, 'debug', None)
if DebugFile:
with open(DebugFile, 'a', encoding='utf-8') as f:
LineInfo: str = f' line {LineNum}' if LineNum else ''
f.write(f'[ERROR]{LineInfo}: {message}\n')
def SetDebugFile(self, FilePath: str) -> None:
"""设置调试输出文件"""
self.DebugFile = FilePath
def DebugPrint(self, *args: Any, **kwargs: Any) -> None:
"""输出调试信息到文件"""
if self.DebugFile:
with open(self.DebugFile, 'a', encoding='utf-8') as f:
print(*args, file=f, **kwargs)
def HandleExpr(self, Node: ast.AST, UseSingleQuote: bool = False, VarType: ir.Type | None = None) -> Any:
return self.ExprHandler.HandleExpr(Node, UseSingleQuote, VarType)