from __future__ import annotations import vast as ast import re import llvmlite.ir as ir from lib.core.LlvmCodeGenerator import LlvmCodeGenerator from lib.core.Handles.HandlesBase import CTypeInfo from lib.core.Handles.HandlesBase import CTypeInfo as _CTypeInfo, CTypeHelper from lib.includes import t from lib.constants.config import mode as _config_mode from lib.core.VLogger import get_logger as _vlog from lib.core.DecoratorPass import run as _run_decorator_pass from lib.core.SymbolUtils import ( IsTModule, AnnotationContainsName, RequireDefineConstStorable, ) # 治本修复:导入 ConstEvaluator 用于预扫描 CDefine 常量的复杂表达式求值 from lib.core.ConstEvaluator import ConstEvaluator class LlvmGeneratorMixin: """LLVM IR 生成 Mixin 提供 LLVM IR 直接生成、模块级 LLVM IR 处理与 C 代码生成入口能力。 """ def GenerateLlvmDirect(self, Tree: ast.Module) -> str: Gen: LlvmCodeGenerator = self.LlvmGen # === 新增:轻量 AST 遍历,收集类图信息,解决前向引用 === Gen._class_graph: dict[str, dict[str, bool | list[str]]] = {} for Node in ast.iter_child_nodes(Tree): if isinstance(Node, ast.ClassDef): bases: list[str] = [] for base in Node.bases: if hasattr(base, 'id'): bases.append(base.id) elif hasattr(base, 'attr'): bases.append(base.attr) has_methods: bool = any(isinstance(item, ast.FunctionDef) for item in Node.body) # 检测 @t.NoVTable 装饰器(非多态继承基类标记) has_novtable: bool = False if hasattr(Node, 'decorator_list') and Node.decorator_list: for decorator in Node.decorator_list: if isinstance(decorator, ast.Attribute): if getattr(decorator.value, 'id', None) == 't' and decorator.attr == 'NoVTable': has_novtable = True elif isinstance(decorator, ast.Name): if decorator.id == 'NoVTable': has_novtable = True Gen._class_graph[Node.name] = { 'bases': bases, 'has_methods': has_methods, 'has_novtable': has_novtable, } # === 结束新增 === # 预扫描:为所有 -> str 注解的函数注册正确的返回类型 i8* # 这样在类方法中调用这些函数时,前向声明会使用正确的类型 for Node in ast.iter_child_nodes(Tree): if isinstance(Node, ast.FunctionDef): if Node.returns and isinstance(Node.returns, ast.Name) and Node.returns.id == 'str': Gen.known_return_types[Node.name] = ir.PointerType(ir.IntType(8)) # 首先收集所有 CDefine 常量,确保类定义中可以引用 def _extract_const_value(node: ast.AST) -> int | str | float | None: """求值 CDefine 常量表达式,支持 Constant、BinOp、UnaryOp、Name(引用其他 define)、Call(类型构造)。 治本修复:原 _extract_call_const_val 只支持 t.XxxType(Constant) 形式, 无法处理 FOREGROUND_WHITE = FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE 等引用其他 CDefine 的 BinOp 表达式,导致依赖常量无法被预扫描。 现使用 ConstEvaluator.eval_with_symtab 统一求值。 """ if isinstance(node, ast.Constant): return node.value # 使用 ConstEvaluator 处理 BinOp/UnaryOp/Name/Attribute/Call return ConstEvaluator.eval_with_symtab(node, self.SymbolTable) def _is_cdefine_type(TypeInfo: CTypeInfo | None) -> bool: """判断 CTypeInfo 是否对应 t.CDefine 注解""" return bool(TypeInfo and TypeInfo.BaseType and ((isinstance(TypeInfo.BaseType, type) and issubclass(TypeInfo.BaseType, t.CDefine)) or isinstance(TypeInfo.BaseType, t.CDefine) or TypeInfo.IsDefine)) def _register_cdefine_constant(NameNode: ast.Name, Annotation: ast.expr, Value: ast.expr) -> None: """注册 CDefine 编译期常量(_define_constants + SymbolTable)""" TypeInfo: CTypeInfo | None = self.TypeMergeHandler.GetCTypeInfo(Annotation) if not _is_cdefine_type(TypeInfo): return val: int | str | float | None = _extract_const_value(Value) if val is not None: # fail-fast:常量值必须能落进声明类型(define 带类型形态)/ 64 位存储 # (自动推导形态,本语言无 64 位以上整数类型)——此前超大值会被静默 # 截断/生成非法 IR 文本。唯一判据见 SymbolUtils.RequireDefineIntStorable。 RequireDefineConstStorable(Gen, self, NameNode, TypeInfo.BaseType, Annotation, val, NameNode.id) if not hasattr(Gen, '_define_constants'): Gen._define_constants: dict[str, int | str | float | bool] = {} Gen._define_constants[NameNode.id] = val existing = self.SymbolTable.lookup(NameNode.id) if not (existing and existing.IsTypedef and existing.OriginalType): sym_info: _CTypeInfo = _CTypeInfo() sym_info.IsDefine = True sym_info.DefineValue = val self.SymbolTable.insert(NameNode.id, sym_info) for Node in ast.iter_child_nodes(Tree): if isinstance(Node, ast.AnnAssign) and isinstance(Node.target, ast.Name) and Node.value: TypeInfo: CTypeInfo | None = self.TypeMergeHandler.GetCTypeInfo(Node.annotation) # 治本修复:检查 BaseType 是否为 t.CDefine 实例/子类,或 IsDefine 标志 # IsDefine 由 GetCTypeInfo 对 t.CDefine 注解自动设置 if _is_cdefine_type(TypeInfo): _register_cdefine_constant(Node.target, Node.annotation, Node.value) elif isinstance(Node, ast.ClassDef): # 类体 CDefine 常量(2026-08-10):供方法内裸名(如 Mixin 的 # ISINSTANCE_CLASS_MAX/MRO_MAX: t.CDefine = N)编译期解析为常量值。 # 原预扫描只用 iter_child_nodes 扫顶层,类体常量不注册 → 方法内 # 裸名解析为 0 → pool.alloc(8*0) 失败(TPV 编译测试 SUBS-NONE)。 for _citem in Node.body: if isinstance(_citem, ast.AnnAssign) and isinstance(_citem.target, ast.Name) and _citem.value: _register_cdefine_constant(_citem.target, _citem.annotation, _citem.value) elif isinstance(Node, ast.Assign): for target in Node.targets: if isinstance(target, ast.Name): TypeInfo: CTypeInfo | None = None if Node.type_comment: try: tc_ast: ast.Expression = ast.parse(Node.type_comment, '', mode='eval') TypeInfo = self.TypeMergeHandler.GetCTypeInfo(tc_ast.body) except Exception as _e: if _config_mode == "strict": raise _vlog().warning(f"解析类型注释失败: {_e}", "Exception") if TypeInfo and TypeInfo.BaseType and ((isinstance(TypeInfo.BaseType, type) and issubclass(TypeInfo.BaseType, t.CDefine)) or isinstance(TypeInfo.BaseType, t.CDefine)): val: int | str | float | None = _extract_const_value(Node.value) if val is not None: if not hasattr(Gen, '_define_constants'): Gen._define_constants: dict[str, int | str | float | bool] = {} Gen._define_constants[target.id] = val sym_info: _CTypeInfo = _CTypeInfo() sym_info.IsDefine = True sym_info.DefineValue = val self.SymbolTable.insert(target.id, sym_info) # 预扫描所有顶层函数定义,填充 FunctionDefCache(不创建 LLVM 声明) # 这样类方法编译时遇到未声明的函数可以按需前向声明 for Node in ast.iter_child_nodes(Tree): if isinstance(Node, ast.FunctionDef): FuncName: str = Node.name if FuncName not in self.FunctionDefCache: self.FunctionDefCache[FuncName] = Node elif isinstance(Node, ast.AsyncFunctionDef): # 协程:注册到 AsyncHandler(生成 create_/resume_,不进 FunctionDefCache, # 避免被当作普通函数前向声明) self.AsyncHandler._RegisterAsyncFunc(Node.name, Node) # 首先处理所有导入语句,确保模块在类型解析前被加载 for Node in ast.iter_child_nodes(Tree): Gen._set_node_info(Node) try: if isinstance(Node, ast.Import): self.ImportHandler._EmitImportDeclarationsLlvm(Node, Gen) elif isinstance(Node, ast.ImportFrom): self.ImportHandler._EmitImportFromDeclarationsLlvm(Node, Gen) except Exception as e: # fail-fast:import 模块不存在(ImportError)必须立即终止编译, # 不能吞进 _ErrorStack(该栈无消费点,静默容忍导致 import 路径 # 错误延迟到链接期才暴露,如 ClassGenGeneric 漏改 import 路径)。 if isinstance(e, ImportError): raise lineno: int = getattr(Node, 'lineno', 0) # 注入行偏移还原:AST 行号含 _inject_auto_imports 在文件头注入的 N 行, # 先按精确偏移减回磁盘真实行号(N 由 Phase2Translator 计算并挂到 translator); # 报文行号与源码行必须同用还原后的 lineno,二者一致(否则会显示下一行源码)。 _line_offset: int = int(getattr(self, '_line_offset', 0) or 0) if _line_offset > 0 and lineno > _line_offset: lineno -= _line_offset source_line: str | None = Gen._get_source_line(lineno) src_file: str = getattr(Gen, '_current_source_file', '') src_path: str = src_file if src_file else 'unknown' line_info: str = "源代码 (%s, line %d)" % (src_path, lineno) if source_line: line_info += ":\n %d | %s" % (lineno, source_line) self._ErrorStack.append((type(e).__name__, str(e), line_info)) # 本模块泛型类模板必须在前置声明之前注册(与 includes 侧注册判据同源, # 见 HandlesClassDef.PrescanModuleGenericClassTemplates):前置声明要解析 # 参数/返回注解里的泛型类下标(`def f(b: Box[Node])`),而类处理阶段 # (下方 _EmitClassLlvm)才注册模板 → 注解解析为空 → VoidType → # "无法识别的参数类型注解"。放在 import 扫描之后,保证本地类覆盖同名 # 导入类(与 _EmitClassLlvm 的覆盖顺序一致)。 self.ClassHandler.PrescanModuleGenericClassTemplates(ast.iter_child_nodes(Tree)) # 前向声明所有顶层函数,确保全局变量初始化时能引用函数指针 for Node in ast.iter_child_nodes(Tree): if isinstance(Node, ast.FunctionDef): Gen._set_node_info(Node) self.FunctionHandler._EmitFunctionForwardDeclLlvm(Node, Gen) # 预创建全局变量(带初始化器),确保类方法编译时能引用全局数组等 Gen._current_tree: ast.Module = Tree for Node in ast.iter_child_nodes(Tree): Gen._set_node_info(Node) if isinstance(Node, ast.AnnAssign): self.AssignHandler._EmitGlobalAnnAssignLlvm(Node, Gen) elif isinstance(Node, ast.Assign): self.AssignHandler._EmitGlobalAssignLlvm(Node, Gen) # 首先处理所有类定义(包括 CUnion),确保类型定义在使用前完成 for Node in ast.iter_child_nodes(Tree): if isinstance(Node, ast.ClassDef): Gen._set_node_info(Node) self.ClassHandler._EmitClassLlvm(Node, Gen) Gen._generate_structs() Gen._create_Vtable_globals() for Node in ast.iter_child_nodes(Tree): Gen._set_node_info(Node) try: if isinstance(Node, ast.Import): continue elif isinstance(Node, ast.ImportFrom): continue elif isinstance(Node, ast.ClassDef): continue elif isinstance(Node, ast.FunctionDef): self.FunctionHandler._EmitFunctionLlvm(Node, Gen) elif isinstance(Node, ast.AsyncFunctionDef): self.AsyncHandler._EmitAsyncFunctionLlvm(Node, Gen) elif isinstance(Node, ast.AnnAssign): self.AssignHandler._EmitGlobalAnnAssignLlvm(Node, Gen) elif isinstance(Node, ast.Assign): self.AssignHandler._EmitGlobalAssignLlvm(Node, Gen) elif isinstance(Node, ast.If): pass elif isinstance(Node, ast.Expr): self._HandleModuleLevelExprLlvm(Node, Gen) except Exception as e: lineno: int = getattr(Node, 'lineno', 0) # 注入行偏移还原:AST 行号含 _inject_auto_imports 在文件头注入的 N 行, # 先按精确偏移减回磁盘真实行号(N 由 Phase2Translator 计算并挂到 translator); # 报文行号与源码行必须同用还原后的 lineno,二者一致(否则会显示下一行源码)。 _line_offset: int = int(getattr(self, '_line_offset', 0) or 0) if _line_offset > 0 and lineno > _line_offset: lineno -= _line_offset source_line: str | None = Gen._get_source_line(lineno) src_file: str = getattr(Gen, '_current_source_file', '') src_path: str = src_file if src_file else 'unknown' line_info: str = "源代码 (%s, line %d)" % (src_path, lineno) if source_line: line_info += ":\n %d | %s" % (lineno, source_line) self._ErrorStack.append((type(e).__name__, str(e), line_info)) raise Gen._set_Vtable_initializers() # 执行 DecoratorPass:为带自定义装饰器的函数生成 wrapper _run_decorator_pass(Gen) # 调用点热点统计与每函数计时(--hotspot-sites):在装饰器 wrapper 生成之后 # 统一收口;未启用时不执行(零影响)。hotspot_sites_module_local=True 走 # Projectrans 多模块路径(每模块 @llvm.global_ctors 自注册),否则走种子 # CLI 单模块路径(在 main 入口注册)。 if Gen.hotspot_sites_file: if Gen.hotspot_sites_module_local: Gen._InstallHotspotSitesModuleLocal() else: Gen._InstallHotspotSites() ir_code: str = Gen.finalize() return ir_code def _HandleModuleLevelExprLlvm(self, Node: ast.Expr, Gen: LlvmCodeGenerator) -> None: if not isinstance(Node.value, ast.Call): return call: ast.Call = Node.value if isinstance(call.func, ast.Name): # 模块级裸名 __llvmir__(...) 等价 c.LLVMIR(...) if call.func.id == '__llvmir__': self._HandleModuleLevelLLVMIR(call, Gen) return if not isinstance(call.func, ast.Attribute): return if not isinstance(call.func.value, ast.Name) or call.func.value.id != 'c': return func_name: str = call.func.attr if func_name == 'LLVMIR': self._HandleModuleLevelLLVMIR(call, Gen) def _HandleModuleLevelLLVMIR(self, Node: ast.Call, Gen: LlvmCodeGenerator) -> None: if not Node.args: return first_arg: ast.expr = Node.args[0] if isinstance(first_arg, ast.Constant) and isinstance(first_arg.value, str): ir_text: str = first_arg.value elif isinstance(first_arg, ast.JoinedStr): parts: list[str] = [] for value in first_arg.values: if isinstance(value, ast.Constant) and isinstance(value.value, str): parts.append(value.value) elif isinstance(value, ast.FormattedValue): parts.append('') ir_text = ''.join(parts) else: return self._InsertModuleLevelLLVMIR(Gen, ir_text) def _InsertModuleLevelLLVMIR(self, Gen: LlvmCodeGenerator, ir_text: str) -> None: for line in ir_text.strip().split('\n'): line = line.strip() if not line: continue module_flags_match: re.Match[str] | None = re.match(r'!llvm\.module\.flags\s*=\s*!\{(!\d+)\}', line) if module_flags_match: ref: str = module_flags_match.group(1) if not hasattr(Gen, '_pending_module_flags'): Gen._pending_module_flags: list = [] Gen._pending_module_flags_refs: str = ref continue metadata_match: re.Match[str] | None = re.match(r'(!\d+)\s*=\s*!\{(.+)\}', line) if metadata_match: md_id: str = metadata_match.group(1) md_body: str = metadata_match.group(2) fields: list[ir.Constant | ir.MetaDataString | str] = [] for field_str in re.split(r',\s*', md_body): field_str = field_str.strip() if not field_str: continue int_m: re.Match[str] | None = re.match(r'^i32\s+(\d+)$', field_str) if int_m: fields.append(ir.Constant(ir.IntType(32), int(int_m.group(1)))) continue str_m: re.Match[str] | None = re.match(r'^"([^"]*)"$', field_str) if str_m: fields.append(ir.MetaDataString(Gen.module, str_m.group(1))) continue mdstr_m: re.Match[str] | None = re.match(r'^!"([^"]*)"$', field_str) if mdstr_m: fields.append(ir.MetaDataString(Gen.module, mdstr_m.group(1))) continue int_m2: re.Match[str] | None = re.match(r'^(\d+)$', field_str) if int_m2: fields.append(ir.Constant(ir.IntType(32), int(int_m2.group(1)))) continue ref_m: re.Match[str] | None = re.match(r'^(!\d+)$', field_str) if ref_m: fields.append(ref_m.group(1)) continue if fields: if not hasattr(Gen, '_pending_metadata'): Gen._pending_metadata: list[tuple[str, list]] = [] Gen._pending_metadata.append((md_id, fields)) continue self._FlushModuleMetadata(Gen) def _FlushModuleMetadata(self, Gen: LlvmCodeGenerator) -> None: if not hasattr(Gen, '_pending_metadata') or not Gen._pending_metadata: return md_map: dict[str, ir.MetaDataString] = {} for md_id, fields in Gen._pending_metadata: resolved: list[ir.Constant | ir.MetaDataString] = [] for f in fields: if isinstance(f, str) and f.startswith('!'): ref: ir.MetaDataString | None = md_map.get(f) if ref: resolved.append(ref) else: resolved.append(f) md_value: ir.MetaDataString = Gen.module.add_metadata(resolved) md_map[md_id] = md_value if hasattr(Gen, '_pending_module_flags_refs'): ref: str = Gen._pending_module_flags_refs md_node: ir.MetaDataString | None = md_map.get(ref) if md_node: Gen.module.add_named_metadata('llvm.module.flags', md_node) Gen._pending_metadata = [] Gen._pending_module_flags_refs = None def GenerateCCode(self, Tree: ast.Module, target: str = 'llvm') -> str: """生成代码 Args: Tree: Python AST 树 target: 目标代码类型,仅支持 'llvm' Returns: 生成的代码字符串 """ self._generated_vars: set[str] = set() self.VarScopes = [{}] # 全局作用域 # 预扫描 import 语句,注册别名,确保类型解析时能正确解析模块别名 if not getattr(self, '_ImportedModules', None): self._ImportedModules: set[str] = set() for Node in ast.iter_child_nodes(Tree): if isinstance(Node, ast.Import): for alias in Node.names: name: str = alias.name if name in ('c', 't'): continue self._ImportedModules.add(name) if alias.asname: self.SymbolTable.import_aliases[alias.asname] = name elif isinstance(Node, ast.ImportFrom): module_name: str | None = Node.module if module_name and module_name not in ('c', 't'): self._ImportedModules.add(module_name) for alias in Node.names: if alias.asname: self.SymbolTable.import_aliases[alias.asname] = f"{module_name}.{alias.name}" for Node in ast.iter_child_nodes(Tree): if isinstance(Node, ast.ClassDef): ClassName: str = Node.name # 检查是否是特殊类型(枚举或联合体) IsSpecialType: bool = False if Node.bases: for base in Node.bases: if hasattr(base, 'attr'): if base.attr in ['CEnum', 'Enum', 'CUnion', 'REnum']: IsSpecialType = True break elif hasattr(base, 'id'): if base.id in ['CEnum', 'Enum', 'CUnion', 'REnum']: IsSpecialType = True break # 如果是特殊类型,跳过这里的处理(由 HandleClassDef 处理) if IsSpecialType: continue members: dict[str, CTypeInfo] = {} IsTypedef: bool = False TypedefName: str | None = None if hasattr(Node, 'annotation') and Node.annotation: try: if AnnotationContainsName(Node.annotation, 'CTypedef'): IsTypedef = True if isinstance(Node.annotation, ast.Call): if Node.annotation.args: if isinstance(Node.annotation.args[0], ast.Constant): TypedefName = Node.annotation.args[0].value except Exception as _e: if _config_mode == "strict": raise _vlog().warning(f"解析 typedef 注解失败: {_e}", "Exception") if not IsTypedef: for item in Node.body: if isinstance(item, ast.Assign): for target in item.targets: if isinstance(target, ast.Name) and target.id == '__annotations__': if isinstance(item.value, ast.Dict): for key, value in zip(item.value.keys, item.value.values): if isinstance(key, ast.Constant) and key.value == '__type__': if AnnotationContainsName(value, 'CTypedef'): IsTypedef = True if IsTypedef: TypedefKey: str = TypedefName if TypedefName else ClassName TypedefNode: CTypeInfo = CTypeInfo() TypedefNode.Name = TypedefKey TypedefNode.IsTypedef = True TypedefNode.OriginalType = f'struct {ClassName}' TypedefNode.set('IsComplete', True) TypedefNode.file = '' self.SymbolTable.insert(TypedefKey, TypedefNode) for item in Node.body: if isinstance(item, ast.AnnAssign) and isinstance(item.target, ast.Name): VarName: str = item.target.id try: TypeInfo: CTypeInfo | None = self.TypeMergeHandler.GetCTypeInfo(item.annotation) if TypeInfo is None: TypeInfo = CTypeInfo() TypeInfo.BaseType = t.CInt() IsPtr: bool = TypeInfo.IsPtr if not IsPtr: if isinstance(item.annotation, ast.BinOp) and isinstance(item.annotation.op, ast.BitOr): if AnnotationContainsName(item.annotation, 'CPtr'): IsPtr = True dims: list[int] = [] if hasattr(item.annotation, 'slice') and isinstance(item.annotation.slice, ast.Constant): if isinstance(item.annotation.value, ast.Name): if IsTModule(item.annotation.value.id, self.SymbolTable): if hasattr(item.annotation, 'slice'): try: dims.append(int(item.annotation.slice.value)) except Exception as _e: if _config_mode == "strict": self.LogWarning(f"异常被忽略: {_e}") MemberInfo: CTypeInfo = TypeInfo.Copy() if dims: MemberInfo.ArrayDims = [str(d) for d in dims] members[VarName] = MemberInfo except Exception as _e: if _config_mode == "strict": self.LogWarning(f"异常被忽略: {_e}") if not IsTypedef: StructNode: CTypeInfo = CTypeInfo() StructNode.Name = ClassName StructNode.IsStruct = True StructNode.Members = members or {} StructNode.file = '' existing: CTypeInfo | None = self.SymbolTable.lookup(ClassName) if existing: if hasattr(existing, 'IsCpythonObject') and existing.IsCpythonObject: StructNode.IsCpythonObject = True self.SymbolTable.insert(ClassName, StructNode) elif isinstance(Node, ast.FunctionDef): FuncName: str = Node.name if not self.SymbolTable.has(FuncName): FuncNode: CTypeInfo = CTypeInfo() FuncNode.Name = FuncName FuncNode.IsFunction = True FuncNode.file = '' self.SymbolTable.insert(FuncName, FuncNode) elif isinstance(Node, ast.AsyncFunctionDef): FuncName = Node.name if not self.SymbolTable.has(FuncName): FuncNode = CTypeInfo() FuncNode.Name = FuncName FuncNode.IsFunction = True FuncNode.file = '' self.SymbolTable.insert(FuncName, FuncNode) elif isinstance(Node, ast.AnnAssign): if isinstance(Node.target, ast.Name): VarName: str = Node.target.id VarType: str = 'unknown' IsPtr: bool = False IsTypedef_assignment: bool = False if Node.annotation: try: if AnnotationContainsName(Node.annotation, 'CTypedef'): IsTypedef_assignment = True except Exception as _e: if _config_mode == "strict": self.LogWarning(f"异常被忽略: {_e}") if IsTypedef_assignment and Node.value: if isinstance(Node.value, ast.Name): OriginalType: str = Node.value.id if OriginalType in self.GeneratedTypes: OriginalInfo: CTypeInfo | None = self.SymbolTable.lookup(OriginalType) if OriginalInfo: if isinstance(OriginalInfo, dict): actual_type: str = OriginalInfo.get('type', 'struct') elif isinstance(OriginalInfo, CTypeInfo): if OriginalInfo.IsEnum: actual_type = 'enum' elif OriginalInfo.IsTypedef: actual_type = 'typedef' elif OriginalInfo.IsStruct: actual_type = 'struct' else: actual_type = 'struct' else: actual_type = 'struct' if actual_type == 'enum': TypedefNode: CTypeInfo = CTypeInfo() TypedefNode.Name = VarName TypedefNode.IsTypedef = True TypedefNode.OriginalType = f'enum {OriginalType}' TypedefNode.file = '' self.SymbolTable.insert(VarName, TypedefNode) elif actual_type == 'typedef': TypedefNode = CTypeInfo() TypedefNode.Name = VarName TypedefNode.IsTypedef = True if isinstance(OriginalInfo, dict): TypedefNode.OriginalType = OriginalInfo.get('OriginalType', f'struct {OriginalType}') elif isinstance(OriginalInfo, CTypeInfo) and OriginalInfo.OriginalType: TypedefNode.OriginalType = OriginalInfo.OriginalType else: TypedefNode.OriginalType = f'struct {OriginalType}' TypedefNode.file = '' self.SymbolTable.insert(VarName, TypedefNode) else: TypedefNode = CTypeInfo() TypedefNode.Name = VarName TypedefNode.IsTypedef = True TypedefNode.OriginalType = f'struct {OriginalType}' TypedefNode.file = '' self.SymbolTable.insert(VarName, TypedefNode) self.GeneratedTypes.add(VarName) continue else: OriginalInfo: CTypeInfo | None = self.SymbolTable.lookup(OriginalType) if OriginalInfo: if isinstance(OriginalInfo, dict): actual_type: str = OriginalInfo.get('type', 'struct') elif isinstance(OriginalInfo, CTypeInfo): if OriginalInfo.IsEnum: actual_type = 'enum' elif OriginalInfo.IsTypedef: actual_type = 'typedef' elif OriginalInfo.IsStruct: actual_type = 'struct' else: actual_type = 'struct' else: actual_type = 'struct' if actual_type == 'typedef': TypedefNode: CTypeInfo = CTypeInfo() TypedefNode.Name = VarName TypedefNode.IsTypedef = True if isinstance(OriginalInfo, dict): TypedefNode.OriginalType = OriginalInfo.get('OriginalType', f'struct {OriginalType}') elif isinstance(OriginalInfo, CTypeInfo) and OriginalInfo.OriginalType: TypedefNode.OriginalType = OriginalInfo.OriginalType else: TypedefNode.OriginalType = f'struct {OriginalType}' TypedefNode.file = '' self.SymbolTable.insert(VarName, TypedefNode) self.GeneratedTypes.add(VarName) if isinstance(OriginalInfo, dict): OriginalInfo['skip_generation'] = True continue elif actual_type == 'struct': TypedefNode = CTypeInfo() TypedefNode.Name = VarName TypedefNode.IsTypedef = True TypedefNode.OriginalType = f'struct {OriginalType}' TypedefNode.file = '' self.SymbolTable.insert(VarName, TypedefNode) self.GeneratedTypes.add(VarName) if isinstance(OriginalInfo, dict): OriginalInfo['skip_generation'] = True continue elif actual_type == 'enum': TypedefNode = CTypeInfo() TypedefNode.Name = VarName TypedefNode.IsTypedef = True TypedefNode.OriginalType = f'enum {OriginalType}' TypedefNode.file = '' self.SymbolTable.insert(VarName, TypedefNode) self.GeneratedTypes.add(VarName) if isinstance(OriginalInfo, dict): OriginalInfo['skip_generation'] = True continue elif isinstance(Node.value, ast.Attribute): CName: str | None = CTypeHelper.GetCName(Node.value.attr) if CName: TypedefNode: CTypeInfo = CTypeInfo() TypedefNode.Name = VarName TypedefNode.IsTypedef = True TypedefNode.OriginalType = CName TypedefNode.file = '' self.SymbolTable.insert(VarName, TypedefNode) self.GeneratedTypes.add(VarName) continue if Node.annotation: try: TypeInfo: CTypeInfo | None = self.TypeMergeHandler.GetCTypeInfo(Node.annotation) IsPtr = TypeInfo.IsPtr if TypeInfo else False except Exception as _e: if _config_mode == "strict": self.LogWarning(f"异常被忽略: {_e}") # 如果符号已经存在且是 typedef,不要覆盖它 existing = self.SymbolTable.lookup(VarName) if existing and existing.IsTypedef and existing.OriginalType: # typedef 已正确插入,保持现有条目不覆盖 pass else: var_node: CTypeInfo = CTypeInfo() var_node.Name = VarName var_node.IsVariable = True var_node.PtrCount = 1 if IsPtr else 0 var_node.file = '' self.SymbolTable.insert(VarName, var_node) self.LlvmGen: LlvmCodeGenerator = LlvmCodeGenerator( triple=getattr(self, 'triple', None), datalayout=getattr(self, 'datalayout', None), ) self.LlvmGen._Trans = self self.LlvmGen._import_handler_ref = self.ImportHandler if hasattr(self, '_module_sha1'): self.LlvmGen.module_sha1 = self._module_sha1 if hasattr(self, '_ModuleSha1Map'): self.LlvmGen.ModuleSha1Map = self._ModuleSha1Map if hasattr(self, '_struct_sha1_map'): self.LlvmGen._struct_sha1_map = self._struct_sha1_map if hasattr(self, '_temp_dir'): self.LlvmGen._temp_dir = self._temp_dir if hasattr(self, '_export_extern_funcs'): self.LlvmGen._export_extern_funcs = self._export_extern_funcs # 调用点热点统计与每函数计时(--hotspot-sites):透传落盘路径与注册策略; # 未启用时不产生任何 IR 改动 self.LlvmGen.hotspot_sites_file = getattr(self, 'HotspotSitesFile', None) self.LlvmGen.hotspot_sites_all = getattr(self, 'HotspotSitesAll', False) self.LlvmGen.hotspot_callees = getattr(self, 'HotspotCallees', None) self.LlvmGen.hotspot_sites_module_local = getattr(self, 'HotspotSitesModuleLocal', False) # 【本模块声明的类:SHA1 前缀钉死为本模块(2026-09-30)】 # 必须**先于** setup_from_symbol_table —— 其内部 _generate_structs 会为符号表里的 # 每个类建 struct,IR 名前缀取自 `class_sha1_map`(空)→ `_struct_sha1_map` # (Phase2 扫描各 .vpi 得到的"裸类名 → 定义模块 SHA1")。两张表都按**裸类名** # 索引,两个模块各定义同名类时只能留一个:现场 includes/ast/astaux.vp 的 # `class Keyword(AST)` 与 includes/ast/tokens.vp 的 `class Keyword(t.CEnum)` # 同名,`_build_struct_sha1_map` 的"每类只登记一次"判据误用了 sha1 键(恒假、 # 实为后扫到的覆盖先扫到的)⇒ astaux 自己那份被命名成 # `%"fef783da4d24330d.Keyword"`(= tokens 的 sha1)。于是同一类在本模块里出现 # 两个 struct 实例:`__new__`/`__init__` 用按本模块前缀另建的那份 # `%"8312ce86a2fd82c0.Keyword"*`,而 `HandlesClassDef._EmitNewFunctionLlvm` # 生成的 `__before_init__` 用 `Gen.structs['Keyword']`(错名前缀那份)⇒ 声明与 # 调用点分叉,llvmlite 报 # "Type of #1 arg mismatch: %"fef783da4d24330d.Keyword"* != %"8312ce86a2fd82c0.Keyword"*" # (报文是 `形参 != 实参`,下标 1-based ⇒ 指的其实是第 0 个形参 self)。 # "本文件顶层 ClassDef 名单"是**正向事实**(就在本次要翻译的 AST 里,且 # class_sha1_map 是 Gen 实例级、每模块重建)⇒ 命中即钉死为本模块 SHA1; # 非本模块声明的类不受影响,仍走原来的全局映射。 _DefSha1: str | None = getattr(self, '_module_sha1', None) if _DefSha1: for _Nd in ast.iter_child_nodes(Tree): if isinstance(_Nd, ast.ClassDef) and getattr(_Nd, 'name', None): self.LlvmGen.class_sha1_map[_Nd.name] = _DefSha1 self.LlvmGen.setup_from_symbol_table(self.SymbolTable) if hasattr(self, 'CurrentFile') and self.CurrentFile: self.LlvmGen._set_source_info(self.CurrentFile) # 函数级 DWARF 调试元数据(--dwarf / --asan):透传开关给本模块的 # LlvmCodeGenerator;未启用时 dwarf_enabled=False → 不构造 DI、不挂 !dbg, # 生成的 .ll 与改动前逐字节一致(零影响) self.LlvmGen.dwarf_enabled = bool(getattr(self, 'DwarfEnabled', False)) # Ctrl+C 调用栈(--traceback):透传"本模块需注入 Install() 启动期构造器" # 标记(仅 includes/traceback.vp 的翻译上下文为 True);未启用时为 False # → finalize() 不做任何事,生成的 .ll 与改动前逐字节一致(零影响) self.LlvmGen.traceback_ctor = bool(getattr(self, 'TracebackCtor', False)) # --- 修复:共享 vtable 状态跨模块 --- # 根因:LlvmGen 每模块重新创建,class_vtable/class_methods 等是实例级属性, # 不跨模块共享。导致模块 B 编译时 _specialize_generic_class 触发的 # pool.alloc(48) 找不到 MemManager 的虚表状态,直接调用 stub 返回 NULL → 段错误。 # 修复:将 vtable 状态存储在 Translator 对象上并赋值给每个新 Gen。 if not hasattr(self, '_shared_class_vtable'): self._shared_class_vtable: set[str] = set() self._shared_cross_module_vtable: set[str] = set() self._shared_class_methods: dict[str, list[str]] = {} self._shared_cross_module_novtable: set[str] = set() # 合并 setup_from_symbol_table 创建的实例级 class_methods 到共享 dict # (仅添加新类,不覆盖已有方法列表) for _cls_name, _methods in self.LlvmGen.class_methods.items(): if _cls_name not in self._shared_class_methods: self._shared_class_methods[_cls_name] = _methods else: for _m in _methods: if _m not in self._shared_class_methods[_cls_name]: self._shared_class_methods[_cls_name].append(_m) # 替换为共享状态 self.LlvmGen.class_vtable = self._shared_class_vtable self.LlvmGen._cross_module_vtable_classes = self._shared_cross_module_vtable self.LlvmGen.class_methods = self._shared_class_methods self.LlvmGen._cross_module_novtable = self._shared_cross_module_novtable # --- 修复结束 --- return self.GenerateLlvmDirect(Tree)