643 lines
36 KiB
Python
643 lines
36 KiB
Python
from __future__ import annotations
|
||
|
||
import 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
|
||
|
||
|
||
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_call_const_val(node: ast.AST) -> int | str | float | None:
|
||
if isinstance(node, ast.Call):
|
||
if isinstance(node.func, ast.Attribute):
|
||
if getattr(node.func.value, 'id', None) == 't':
|
||
if node.args and isinstance(node.args[0], ast.Constant):
|
||
return node.args[0].value
|
||
elif isinstance(node.func, ast.Name):
|
||
if node.args and isinstance(node.args[0], ast.Constant):
|
||
return node.args[0].value
|
||
return None
|
||
|
||
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)
|
||
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 = None
|
||
if isinstance(Node.value, ast.Constant):
|
||
val = Node.value.value
|
||
else:
|
||
val = _extract_call_const_val(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[Node.target.id] = val
|
||
existing = self.SymbolTable.lookup(Node.target.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(Node.target.id, sym_info)
|
||
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 = None
|
||
if isinstance(Node.value, ast.Constant):
|
||
val = Node.value.value
|
||
else:
|
||
val = _extract_call_const_val(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
|
||
|
||
# 首先处理所有导入语句,确保模块在类型解析前被加载
|
||
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:
|
||
lineno: int = getattr(Node, 'lineno', 0)
|
||
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))
|
||
|
||
# 前向声明所有顶层函数,确保全局变量初始化时能引用函数指针
|
||
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.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)
|
||
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)
|
||
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 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 = '<stdin>'
|
||
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 = '<stdin>'
|
||
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 = '<stdin>'
|
||
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 = '<stdin>'
|
||
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 = '<stdin>'
|
||
self.SymbolTable.insert(VarName, TypedefNode)
|
||
else:
|
||
TypedefNode = CTypeInfo()
|
||
TypedefNode.Name = VarName
|
||
TypedefNode.IsTypedef = True
|
||
TypedefNode.OriginalType = f'struct {OriginalType}'
|
||
TypedefNode.file = '<stdin>'
|
||
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 = '<stdin>'
|
||
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 = '<stdin>'
|
||
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 = '<stdin>'
|
||
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 = '<stdin>'
|
||
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 = '<stdin>'
|
||
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
|
||
self.LlvmGen.setup_from_symbol_table(self.SymbolTable)
|
||
if hasattr(self, 'CurrentFile') and self.CurrentFile:
|
||
self.LlvmGen._set_source_info(self.CurrentFile)
|
||
|
||
# --- 修复:共享 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)
|