1361 lines
76 KiB
Python
1361 lines
76 KiB
Python
from __future__ import annotations
|
||
from typing import TYPE_CHECKING
|
||
if TYPE_CHECKING:
|
||
from lib.core.translator import Translator
|
||
from lib.core.Translator.LlvmGenerator import LlvmGeneratorMixin
|
||
import ast
|
||
import copy
|
||
import llvmlite.ir as ir
|
||
from lib.core.Exportable import EnumMember as ExportEnumMember
|
||
from lib.core.Handles.HandlesBase import BaseHandle, CTypeInfo, FuncMeta
|
||
from lib.core.SymbolUtils import IsTModule, FindStructNameInAnnotation
|
||
from lib.core.VLogger import get_logger as _vlog
|
||
from lib.constants.config import mode as _config_mode
|
||
from lib.includes import t
|
||
from lib.includes.t import CTypeRegistry
|
||
|
||
|
||
class ClassHandle(BaseHandle):
|
||
def _is_exception_class(self, Node: ast.ClassDef) -> bool:
|
||
if not Node.bases:
|
||
return False
|
||
for base in Node.bases:
|
||
if hasattr(base, 'id'):
|
||
if base.id == 'Exception':
|
||
return True
|
||
if base.id in self.Trans.exception_registry:
|
||
return True
|
||
elif hasattr(base, 'attr'):
|
||
if base.attr == 'Exception':
|
||
return True
|
||
if base.attr in self.Trans.exception_registry:
|
||
return True
|
||
return False
|
||
|
||
def _get_exception_parent(self, Node: ast.ClassDef) -> str | None:
|
||
if not Node.bases:
|
||
return None
|
||
for base in Node.bases:
|
||
if hasattr(base, 'id'):
|
||
if base.id != 'Exception' and base.id in self.Trans.exception_registry:
|
||
return base.id
|
||
elif hasattr(base, 'attr'):
|
||
if base.attr != 'Exception' and base.attr in self.Trans.exception_registry:
|
||
return base.attr
|
||
return None
|
||
|
||
def _RegisterExceptionClass(self, Node: ast.ClassDef) -> None:
|
||
ClassName: str = Node.name
|
||
if ClassName in self.Trans.exception_registry:
|
||
return
|
||
code: int = self.Trans._next_exception_code
|
||
self.Trans._next_exception_code += 1
|
||
self.Trans.exception_registry[ClassName] = code
|
||
parent: str | None = self._get_exception_parent(Node)
|
||
if parent:
|
||
self.Trans.exception_parents[ClassName] = parent
|
||
ExcTypeInfo: CTypeInfo = CTypeInfo()
|
||
ExcTypeInfo.Name = ClassName
|
||
ExcTypeInfo.IsExceptionClass = True
|
||
ExcTypeInfo.value = code
|
||
self.Trans.SymbolTable.insert(ClassName, ExcTypeInfo)
|
||
|
||
def _is_generic_class(self, Node: ast.ClassDef) -> bool:
|
||
if hasattr(Node, 'type_params') and Node.type_params:
|
||
return True
|
||
return False
|
||
|
||
def _mangle_generic_class_name(self, class_name: str, type_args: list[str]) -> str:
|
||
mangled_args: list[str] = []
|
||
for ta in type_args:
|
||
llvm_str: str | None = CTypeRegistry.NameToLLVM(ta)
|
||
if llvm_str:
|
||
if llvm_str in ('float', 'double', 'half', 'fp128'):
|
||
mangled: str = 'f' + str(CTypeRegistry.GetClassByName(ta)().Size)
|
||
else:
|
||
mangled = llvm_str
|
||
else:
|
||
mangled = ta
|
||
mangled_args.append(mangled)
|
||
return class_name + '[' + ']['.join(mangled_args) + ']'
|
||
|
||
def _specialize_generic_class(self, ClassName: str, type_args: list[str], Gen: LlvmGeneratorMixin, type_names: list[str] | None = None, declare_only: bool = False) -> str | None:
|
||
if not hasattr(self, '_generic_class_templates') or ClassName not in self._generic_class_templates:
|
||
return None
|
||
# 防御:共享符号表构建阶段 Gen 可能为 None,此时无法发射特化 IR
|
||
if Gen is None:
|
||
return None
|
||
template: dict = self._generic_class_templates[ClassName]
|
||
Node: ast.ClassDef = template['node']
|
||
type_param_names: list[str] = template['type_params']
|
||
if len(type_args) != len(type_param_names):
|
||
return None
|
||
spec_key: str = ClassName + '<' + ','.join(type_args) + '>'
|
||
# 缓存必须在 Gen 上(每个模块独立),不能在 ClassHandler 上跨模块共享,
|
||
# 否则临时 Gen(如共享符号表构建阶段)的特化会污染正式翻译阶段的缓存
|
||
if not hasattr(Gen, '_generic_class_specializations'):
|
||
Gen._generic_class_specializations = {}
|
||
if spec_key in Gen._generic_class_specializations:
|
||
cached: object = Gen._generic_class_specializations[spec_key]
|
||
# 缓存格式: (spec_name, was_declare_only)
|
||
if isinstance(cached, tuple):
|
||
cached_name: str = cached[0]
|
||
cached_declare_only: bool = cached[1]
|
||
# 完整特化请求但缓存只有 declare_only 版本 → 需要补发方法体
|
||
if not declare_only and cached_declare_only:
|
||
spec_name = cached_name
|
||
# 标记为正在完整特化,防止递归
|
||
Gen._generic_class_specializations[spec_key] = (spec_name, False)
|
||
else:
|
||
return cached_name
|
||
else:
|
||
# 旧格式(纯字符串):直接返回
|
||
return cached
|
||
else:
|
||
spec_name: str = self._mangle_generic_class_name(ClassName, type_args)
|
||
# 预注册到缓存,防止特化过程中方法体引用自身类型导致无限递归
|
||
Gen._generic_class_specializations[spec_key] = (spec_name, declare_only)
|
||
type_map: dict[str, str] = {}
|
||
for i, tp_name in enumerate(type_param_names):
|
||
if type_names and i < len(type_names):
|
||
type_map[tp_name] = type_names[i]
|
||
else:
|
||
type_map[tp_name] = type_args[i]
|
||
# 内建类型名集合(必须在 cptr_params 检测之前定义)
|
||
_BUILTIN_TYPE_NAMES: set = {
|
||
'CInt', 'CUInt', 'CInt8T', 'CUInt8T', 'CInt16T', 'CUInt16T',
|
||
'CInt32T', 'CUInt32T', 'CInt64T', 'CUInt64T', 'CChar', 'CShort',
|
||
'CLong', 'CDouble', 'CFloat', 'CFloat32T', 'CFloat64T', 'CBool',
|
||
'CVoid', 'CSizeT', 'CSSizeT', 'CPtr', 'CArray', 'CEnum', 'CUnion',
|
||
'CStruct', 'CDefine',
|
||
'int', 'double', 'float', 'i8', 'i16', 'i32', 'i64', 'void',
|
||
'half', 'fp128', 'char', 'bool',
|
||
}
|
||
# 检测哪些类型参数在原始类型实参中带有 | t.CPtr
|
||
# 当 type_arg 以 'ptr' 结尾(_resolve_type_arg_str 将 t.CPtr 规范化为 'ptr')
|
||
# 且对应的 type_name 不是内建类型名时,说明调用方写了 list[AST | t.CPtr]
|
||
cptr_params: set[str] = set()
|
||
for i, tp_name in enumerate(type_param_names):
|
||
type_arg: str = type_args[i]
|
||
if type_arg.endswith('ptr'):
|
||
tn: str = type_names[i] if type_names and i < len(type_names) else type_args[i]
|
||
if tn not in _BUILTIN_TYPE_NAMES:
|
||
cptr_params.add(tp_name)
|
||
# Bug 2 修复:识别特化为 class 类型的类型参数
|
||
# 这类参数在方法签名中是裸 T(无 | t.CPtr),特化后为裸 ClassName(值类型)
|
||
# 需要加 | t.CPtr 使其成为指针类型(class 实例应按指针传递)
|
||
class_type_names: set[str] = set()
|
||
for i, tp_name in enumerate(type_param_names):
|
||
tn: str = type_names[i] if type_names and i < len(type_names) else type_args[i]
|
||
if tn not in _BUILTIN_TYPE_NAMES:
|
||
class_type_names.add(tn)
|
||
# 仅对 t 模块内建类型名注册 _t_c_imported_names(如 CInt -> ('t','CInt'))
|
||
# 类名(如 AST)不应注册为 t.AST,否则会污染名称解析
|
||
if type_names:
|
||
if not hasattr(self.Trans, '_t_c_imported_names'):
|
||
self.Trans._t_c_imported_names = {}
|
||
for tn in type_names:
|
||
if tn in _BUILTIN_TYPE_NAMES and tn not in self.Trans._t_c_imported_names:
|
||
self.Trans._t_c_imported_names[tn] = ('t', tn)
|
||
SpecNode: ast.ClassDef = copy.deepcopy(Node)
|
||
SpecNode.type_params = []
|
||
SpecNode.name = spec_name
|
||
for item in SpecNode.body:
|
||
if isinstance(item, ast.AnnAssign) and isinstance(item.target, ast.Name):
|
||
if item.annotation:
|
||
item.annotation = self.Trans.FunctionHandler._replace_type_in_annotation(item.annotation, type_map, cptr_params)
|
||
elif isinstance(item, ast.FunctionDef):
|
||
for arg in item.args.args:
|
||
if arg.annotation:
|
||
arg.annotation = self.Trans.FunctionHandler._replace_type_in_annotation(arg.annotation, type_map, cptr_params)
|
||
# class 类型参数加指针语义:T -> GNode -> GNode | t.CPtr
|
||
# 去除 SHA1 前缀后检查(如 fc06023a9bcfc93a.AST -> AST)
|
||
if isinstance(arg.annotation, ast.Name):
|
||
raw_name: str = arg.annotation.id
|
||
if '.' in raw_name:
|
||
raw_name = raw_name.split('.')[-1]
|
||
if raw_name in class_type_names:
|
||
arg.annotation = ast.BinOp(
|
||
left=ast.Name(id=arg.annotation.id, ctx=ast.Load()),
|
||
op=ast.BitOr(),
|
||
right=ast.Attribute(value=ast.Name(id='t', ctx=ast.Load()), attr='CPtr', ctx=ast.Load())
|
||
)
|
||
if item.returns:
|
||
item.returns = self.Trans.FunctionHandler._replace_type_in_annotation(item.returns, type_map, cptr_params)
|
||
# 返回类型也加指针语义
|
||
if isinstance(item.returns, ast.Name):
|
||
raw_name: str = item.returns.id
|
||
if '.' in raw_name:
|
||
raw_name = raw_name.split('.')[-1]
|
||
if raw_name in class_type_names:
|
||
item.returns = ast.BinOp(
|
||
left=ast.Name(id=item.returns.id, ctx=ast.Load()),
|
||
op=ast.BitOr(),
|
||
right=ast.Attribute(value=ast.Name(id='t', ctx=ast.Load()), attr='CPtr', ctx=ast.Load())
|
||
)
|
||
self.Trans.FunctionHandler._apply_type_map_to_body(item.body, type_map, cptr_params)
|
||
saved_builder: ir.IRBuilder = Gen.builder
|
||
saved_func: ir.Function = Gen.func
|
||
saved_variables: dict = dict(Gen.variables) if Gen.variables else {}
|
||
saved_direct_values: dict = dict(Gen._direct_values) if Gen._direct_values else {}
|
||
saved_var_type_info: dict = dict(Gen.var_type_info) if Gen.var_type_info else {}
|
||
saved_var_signedness: dict = dict(Gen.var_signedness) if Gen.var_signedness else {}
|
||
saved_global_vars: set = set(Gen.global_vars) if Gen.global_vars else set()
|
||
saved_var_scopes: list = [dict(s) for s in self.Trans.VarScopes] if self.Trans.VarScopes else []
|
||
saved_block: ir.Block | None = None
|
||
if Gen.builder and Gen.builder.block and not Gen.builder.block.is_terminated:
|
||
saved_block = Gen.builder.block
|
||
try:
|
||
self._EmitClassLlvm(SpecNode, Gen, declare_only=declare_only)
|
||
finally:
|
||
# 确保 Gen 状态恢复,即使 _EmitClassLlvm 抛出异常
|
||
Gen.builder = saved_builder
|
||
if saved_block is not None and Gen.builder is not None:
|
||
Gen.builder.position_at_end(saved_block)
|
||
Gen.func = saved_func
|
||
Gen.variables = saved_variables
|
||
Gen._direct_values = saved_direct_values
|
||
Gen.var_type_info = saved_var_type_info
|
||
Gen.var_signedness = saved_var_signedness
|
||
Gen.global_vars = saved_global_vars
|
||
self.Trans.VarScopes = saved_var_scopes
|
||
Gen._generic_class_specializations[spec_key] = (spec_name, declare_only)
|
||
# 缓存 type_args/type_names,供后续 declare_only=False 完整特化补发方法体使用
|
||
# (如 _HandleMethodCallLlvm 中发现方法未定义时触发)
|
||
if not hasattr(Gen, '_generic_class_spec_type_info'):
|
||
Gen._generic_class_spec_type_info = {}
|
||
Gen._generic_class_spec_type_info[spec_key] = (list(type_args), list(type_names) if type_names else None)
|
||
if not hasattr(self.Trans, '_generic_class_specializations'):
|
||
self.Trans._generic_class_specializations = {}
|
||
self.Trans._generic_class_specializations[spec_key] = spec_name
|
||
if hasattr(self.Trans, '_module_sha1') and self.Trans._module_sha1:
|
||
Gen._struct_sha1_map[spec_name] = self.Trans._module_sha1
|
||
return spec_name
|
||
|
||
def _resolve_base_kind(self, base_name: str, Gen: LlvmGeneratorMixin) -> str | None:
|
||
"""解析基类名称的类型种类
|
||
|
||
查询顺序:
|
||
1. _t_type_symbols(from t import CEnum as en)
|
||
2. t 模块属性(t.CEnum / t.CUnion / t.CStruct / t.REnum)
|
||
3. 返回 None 表示不是已知标记基类
|
||
|
||
Returns:
|
||
'enum' | 'union' | 'renum' | 'struct' | None
|
||
"""
|
||
# 1) 查 _t_type_symbols(别名导入)
|
||
symtab: object = self.Trans.SymbolTable
|
||
cls: type | None = symtab._t_type_symbols.get(base_name)
|
||
if cls is not None:
|
||
if issubclass(cls, (t.CEnum, t.REnum)):
|
||
return 'renum' if issubclass(cls, t.REnum) else 'enum'
|
||
if issubclass(cls, t.CUnion):
|
||
return 'union'
|
||
if issubclass(cls, t.CStruct):
|
||
return 'struct'
|
||
# CType 及其子类(CChar/CInt/CVoid/CPtr 等)是"类型强转"标记,
|
||
# 不应被编译为真实结构体。
|
||
if issubclass(cls, t.CType):
|
||
return 'ctype_marker'
|
||
|
||
# 2) 查 t 模块属性(直接引用 t.CEnum 等)
|
||
t_cls: type | None = getattr(t, base_name, None)
|
||
if isinstance(t_cls, type) and issubclass(t_cls, t.CType):
|
||
if issubclass(t_cls, (t.CEnum, t.REnum)):
|
||
return 'renum' if issubclass(t_cls, t.REnum) else 'enum'
|
||
if issubclass(t_cls, t.CUnion):
|
||
return 'union'
|
||
if issubclass(t_cls, t.CStruct):
|
||
return 'struct'
|
||
# CType 及其子类是"类型强转"标记,不编译为结构体。
|
||
return 'ctype_marker'
|
||
|
||
return None
|
||
|
||
@staticmethod
|
||
def _is_classname_ctype_marker(class_name: str) -> bool:
|
||
"""检查类名是否是 t.CType 的"类型强转"标记子类。
|
||
|
||
只有 position 不含 BASE 的纯修饰符/标记类型(CPtr/CVolatile/CConst/
|
||
CInline/CStatic/CExtern/CExport/CRegister/CAuto/_CTypedef/CTypeDefault 等)
|
||
才应跳过编译。有 BASE position 的基本类型(CInt/CChar/CSizeT/CLong 等)
|
||
有具体大小,应被正常编译。CType 基类本身无 bases,base 检测无法触发,
|
||
需要直接按类名检查。
|
||
|
||
注意:CTypeRegistry.GetClassByName 会跳过 CType 本身和 CTypeDefault,
|
||
所以这里直接用 getattr(t, name) 检查 t 模块属性。
|
||
|
||
Returns:
|
||
True 如果 class_name 是 CType 标记子类名(应跳过编译)
|
||
"""
|
||
if not class_name:
|
||
return False
|
||
# 直接查 t 模块属性(CTypeRegistry._build 会跳过 CType/CTypeDefault/BigEndian/LittleEndian)
|
||
t_cls: type | None = getattr(t, class_name, None)
|
||
if not isinstance(t_cls, type) or not issubclass(t_cls, t.CType):
|
||
return False
|
||
if issubclass(t_cls, (t.CStruct, t.CEnum, t.REnum, t.CUnion)):
|
||
return False
|
||
# 基本类型(position 含 BASE 且 Size > 0)有具体大小,不应跳过
|
||
# CVoid 虽含 BASE 但 Size=0,CType Size=None,仍需跳过
|
||
if t.CType.BASE in t_cls.position:
|
||
try:
|
||
inst = t_cls()
|
||
size_val = getattr(inst, 'Size', None)
|
||
if size_val is not None and size_val > 0:
|
||
return False
|
||
except Exception:
|
||
pass
|
||
return True
|
||
|
||
def _resolve_decorator_kind(self, Node: ast.ClassDef, Gen: LlvmGeneratorMixin) -> str | None:
|
||
"""从装饰器列表中解析结构体类型种类
|
||
|
||
支持 @t.CStruct, @t.CUnion, @t.CEnum, @t.REnum
|
||
也支持 from t import CStruct 等别名形式
|
||
|
||
Returns:
|
||
'enum' | 'union' | 'renum' | 'struct' | None
|
||
"""
|
||
if not hasattr(Node, 'decorator_list') or not Node.decorator_list:
|
||
return None
|
||
symtab: object = self.Trans.SymbolTable
|
||
for decorator in Node.decorator_list:
|
||
attr_name: str | None = None
|
||
# @t.CStruct 形式
|
||
if isinstance(decorator, ast.Attribute) and isinstance(decorator.value, ast.Name):
|
||
if IsTModule(decorator.value.id, symtab):
|
||
attr_name = decorator.attr
|
||
# @CStruct 形式 (from t import CStruct)
|
||
elif isinstance(decorator, ast.Name):
|
||
cls: type | None = getattr(t, decorator.id, None)
|
||
if cls is None and hasattr(symtab, '_t_type_symbols'):
|
||
cls = symtab._t_type_symbols.get(decorator.id)
|
||
if cls is not None and isinstance(cls, type) and issubclass(cls, t.CType):
|
||
attr_name = cls.__name__
|
||
if attr_name:
|
||
# 查 _t_type_symbols 和 t 模块属性以确定种类
|
||
resolved_cls: type | None = None
|
||
if hasattr(symtab, '_t_type_symbols'):
|
||
resolved_cls = symtab._t_type_symbols.get(attr_name)
|
||
if resolved_cls is None:
|
||
resolved_cls = getattr(t, attr_name, None)
|
||
if resolved_cls is not None and isinstance(resolved_cls, type):
|
||
if issubclass(resolved_cls, t.REnum):
|
||
return 'renum'
|
||
if issubclass(resolved_cls, t.CEnum):
|
||
return 'enum'
|
||
if issubclass(resolved_cls, t.CUnion):
|
||
return 'union'
|
||
if issubclass(resolved_cls, t.CStruct):
|
||
return 'struct'
|
||
return None
|
||
|
||
def _resolve_class_flags(self, Node: ast.ClassDef, Gen: LlvmGeneratorMixin) -> tuple[bool, bool, str | None, bool]:
|
||
"""解析类的 Object/CVTable 标志和父类信息
|
||
|
||
Returns:
|
||
tuple: (IsCpythonObject, IsCVTable, ParentClassName, IsNoVTable)
|
||
"""
|
||
ClassName: str = Node.name
|
||
IsCpythonObject: bool = False
|
||
IsCVTable: bool = False
|
||
IsNoVTable: bool = False
|
||
if hasattr(Node, 'decorator_list') and Node.decorator_list:
|
||
for decorator in Node.decorator_list:
|
||
if isinstance(decorator, ast.Attribute):
|
||
if hasattr(decorator.value, 'id') and IsTModule(decorator.value.id, self.Trans.SymbolTable):
|
||
if decorator.attr == 'Object':
|
||
IsCpythonObject = True
|
||
elif decorator.attr == 'CVTable':
|
||
IsCVTable = True
|
||
elif decorator.attr == 'NoVTable':
|
||
IsNoVTable = True
|
||
elif isinstance(decorator, ast.Name):
|
||
if decorator.id == 'Object':
|
||
IsCpythonObject = True
|
||
elif decorator.id == 'CVTable':
|
||
IsCVTable = True
|
||
elif decorator.id == 'NoVTable':
|
||
IsNoVTable = True
|
||
elif isinstance(decorator, ast.Call):
|
||
# 检测 @c.Attribute(t.attr.packed)
|
||
if isinstance(decorator.func, ast.Attribute):
|
||
if getattr(decorator.func.value, 'id', None) == 'c' and decorator.func.attr == 'Attribute':
|
||
for arg in decorator.args:
|
||
if isinstance(arg, ast.Attribute):
|
||
if isinstance(arg.value, ast.Attribute):
|
||
if IsTModule(getattr(arg.value.value, 'id', ''), self.Trans.SymbolTable) and arg.value.attr == 'attr' and arg.attr == 'packed':
|
||
Gen.class_packed.add(ClassName)
|
||
class_graph: dict = Gen._class_graph
|
||
if class_graph.get(ClassName, {}).get('has_methods', False) and not IsNoVTable:
|
||
if not IsCpythonObject:
|
||
IsCpythonObject = True
|
||
# 仅当该类作为其他类的基类时,才启用 CVTable
|
||
# 检查 _class_graph 中是否有任何类将此类作为基类
|
||
is_base_of_any: bool = False
|
||
for other_cls, info in class_graph.items():
|
||
if ClassName in info.get('bases', []):
|
||
is_base_of_any = True
|
||
break
|
||
if is_base_of_any:
|
||
IsCVTable = True
|
||
HasParentClass: bool = False
|
||
ParentClassName: str | None = None
|
||
ParentIsNoVTable: bool = False
|
||
if Node.bases:
|
||
for base in Node.bases:
|
||
base_name: str | None = None
|
||
if hasattr(base, 'id'):
|
||
base_name = base.id
|
||
elif hasattr(base, 'attr'):
|
||
base_name = base.attr
|
||
if base_name:
|
||
kind: str | None = self._resolve_base_kind(base_name, Gen)
|
||
if kind is not None or base_name in t._MARKER_BASES:
|
||
continue # 标记基类,跳过
|
||
if base_name in class_graph or base_name in Gen.class_members or base_name in Gen.structs:
|
||
HasParentClass = True
|
||
ParentClassName = base_name
|
||
# 检测父类是否有 @t.NoVTable 标记(非多态继承)
|
||
if class_graph.get(base_name, {}).get('has_novtable', False):
|
||
ParentIsNoVTable = True
|
||
# 跨模块父类:检查 _cross_module_novtable 集合
|
||
if base_name in Gen._cross_module_novtable:
|
||
ParentIsNoVTable = True
|
||
break
|
||
if HasParentClass and not IsCVTable and not IsNoVTable and not ParentIsNoVTable:
|
||
IsCVTable = True
|
||
if IsCVTable:
|
||
Gen.class_vtable.add(ClassName)
|
||
# 沿继承链向上传播,将所有祖先类加入 vtable
|
||
visited: set[str] = {ClassName}
|
||
ancestor: str | None = ParentClassName
|
||
while ancestor and ancestor not in visited:
|
||
visited.add(ancestor)
|
||
Gen.class_vtable.add(ancestor)
|
||
# 查询祖先类的父类
|
||
ancestor_info: dict | None = class_graph.get(ancestor)
|
||
if ancestor_info:
|
||
ancestor_bases: list = ancestor_info.get('bases', [])
|
||
next_ancestor: str | None = None
|
||
for ab in ancestor_bases:
|
||
if ab not in t._MARKER_BASES and ab not in visited:
|
||
next_ancestor = ab
|
||
break
|
||
ancestor = next_ancestor
|
||
else:
|
||
# 类图中没有,尝试从 class_parent 查询
|
||
ancestor = Gen.class_parent.get(ancestor)
|
||
return IsCpythonObject, IsCVTable, ParentClassName, IsNoVTable
|
||
|
||
def _EmitClassLlvm(self, Node: ast.ClassDef, Gen: LlvmGeneratorMixin, declare_only: bool = False) -> None:
|
||
ClassName: str = Node.name
|
||
# t.CType 及其子类(CChar/CInt/CVoid/CPtr/CTypeDefault 等)是"类型强转"标记,
|
||
# 不应被编译为真实结构体。CType 基类本身无 bases,base 检测无法触发,
|
||
# 此处在方法入口直接按类名跳过。
|
||
if self._is_classname_ctype_marker(ClassName):
|
||
return
|
||
if self._is_generic_class(Node):
|
||
if not hasattr(self, '_generic_class_templates'):
|
||
self._generic_class_templates = {}
|
||
type_params: list[str] = [tp.name for tp in Node.type_params]
|
||
self._generic_class_templates[ClassName] = {
|
||
'node': Node,
|
||
'type_params': type_params,
|
||
}
|
||
return
|
||
if self._is_exception_class(Node):
|
||
self._RegisterExceptionClass(Node)
|
||
return
|
||
IsCenum: bool = False
|
||
IsCunion: bool = False
|
||
IsRenum: bool = False
|
||
# 先检查装饰器形式(@t.CStruct / @t.CEnum / @t.CUnion / @t.REnum)
|
||
deco_kind: str | None = self._resolve_decorator_kind(Node, Gen)
|
||
if deco_kind == 'enum':
|
||
IsCenum = True
|
||
elif deco_kind == 'union':
|
||
IsCunion = True
|
||
elif deco_kind == 'renum':
|
||
IsRenum = True
|
||
# 再检查基类继承形式(class X(t.CStruct):),与装饰器合并
|
||
if not IsCenum and not IsCunion and not IsRenum and Node.bases:
|
||
for base in Node.bases:
|
||
base_name: str | None = None
|
||
if hasattr(base, 'attr'):
|
||
base_name = base.attr
|
||
elif hasattr(base, 'id'):
|
||
base_name = base.id
|
||
if base_name:
|
||
kind: str | None = self._resolve_base_kind(base_name, Gen)
|
||
if kind == 'enum':
|
||
IsCenum = True
|
||
break
|
||
elif kind == 'union':
|
||
IsCunion = True
|
||
elif kind == 'renum':
|
||
IsRenum = True
|
||
elif kind == 'ctype_marker':
|
||
# CType 及其子类(CChar/CInt/CVoid/CPtr/CTypeDefault 等)是
|
||
# "类型强转"标记,不应被编译为真实结构体。直接 return 跳过编译。
|
||
return
|
||
if IsCenum:
|
||
self._RegisterEnumMembers(Node)
|
||
return
|
||
if IsCunion:
|
||
self._EmitUnionLlvm(Node, Gen)
|
||
return
|
||
if IsRenum:
|
||
self._EmitREnumLlvm(Node, Gen)
|
||
return
|
||
IsCpythonObject: bool
|
||
IsCVTable: bool
|
||
ParentClassName: str | None
|
||
IsNoVTable: bool
|
||
IsCpythonObject, IsCVTable, ParentClassName, IsNoVTable = self._resolve_class_flags(Node, Gen)
|
||
# 跟踪正在发射的类,防止递归特化时 _generate_structs 过早为空成员类设置 body
|
||
Gen._classes_in_progress.add(ClassName)
|
||
# 标记正在收集字段,阻止继承处理(_ResolveGenericSlice → _specialize_generic_class)
|
||
# 和 CollectAnnAssignMember 触发的嵌套 _generate_structs 用不完整 class_members 调用 set_body
|
||
Gen._collecting_members_set.add(ClassName)
|
||
if ClassName not in Gen.class_methods:
|
||
Gen.class_methods[ClassName] = []
|
||
else:
|
||
# 防御性清除:移除导入阶段可能添加的构造函数(__new__/__init__/__before_init__)。
|
||
# 构造函数不参与虚分派,放入 vtable 会导致子类与基类 vtable 大小不一致,
|
||
# 索引偏移破坏多态分派(如 Module 有 __new__/__init__ 使 vtable=7,而 AST 无它们 vtable=5,
|
||
# 调用方按 AST 布局取 append@idx4 实际取到 Module.dump@idx4)。
|
||
Gen.class_methods[ClassName] = [
|
||
m for m in Gen.class_methods[ClassName]
|
||
if m.split('.')[-1] not in ('__new__', '__init__', '__before_init__')
|
||
]
|
||
# 当前文件定义的类是权威定义,覆盖之前导入阶段可能添加的外部声明。
|
||
# 关键:如果本地类是 @t.NoVTable 但同名导入类有 vtable(名称冲突),
|
||
# 必须清除 vtable 状态,否则 _generate_structs 会错误添加 vtable 指针。
|
||
if IsNoVTable:
|
||
Gen.class_vtable.discard(ClassName)
|
||
Gen._cross_module_vtable_classes.discard(ClassName)
|
||
Gen._cross_module_novtable.add(ClassName)
|
||
# 清除可能从导入 stub 加载的旧 struct body(含错误 vtable 指针),
|
||
# 让 _generate_structs 用本地 class_members 重新生成
|
||
_old_st = Gen.structs.get(ClassName)
|
||
if isinstance(_old_st, ir.IdentifiedStructType) and _old_st.elements is not None:
|
||
_old_st._elements = None
|
||
_ih = getattr(Gen, '_import_handler_ref', None)
|
||
if _ih is not None:
|
||
_ck = (id(Gen), ClassName)
|
||
if _ck in _ih._struct_Load_cache:
|
||
del _ih._struct_Load_cache[_ck]
|
||
Gen.class_members[ClassName] = []
|
||
Gen.class_member_defaults[ClassName] = {}
|
||
Gen.class_member_signeds[ClassName] = {}
|
||
Gen.class_member_bitfields[ClassName] = {}
|
||
Gen.class_member_byteorders[ClassName] = {}
|
||
Gen.class_member_bitoffsets[ClassName] = {}
|
||
ParentClass: str | None = None
|
||
if Node.bases:
|
||
class_graph: dict = Gen._class_graph
|
||
for base in Node.bases:
|
||
if hasattr(base, 'id'):
|
||
base_name = base.id
|
||
elif hasattr(base, 'attr'):
|
||
base_name = base.attr
|
||
elif isinstance(base, ast.Subscript):
|
||
# 泛型特化基类:GSListNode[GNode]
|
||
# 特化泛型类,用特化名作为父类名
|
||
spec_name: str | None = self.Trans.ExprCallHandle._ResolveGenericSlice(base)
|
||
if spec_name:
|
||
base_name = spec_name
|
||
else:
|
||
continue
|
||
else:
|
||
continue
|
||
if base_name == ClassName:
|
||
continue
|
||
if base_name in ('Object', 'CVTable', 'NoVTable', 'CStruct', 'CUnion', 'CEnum', 'REnum', 'Exception', 'Enum'):
|
||
continue
|
||
# 总是记录父类名,即使父类 class_members 未加载。
|
||
# _get_member_offset 会沿 class_parent 链回退查找继承字段。
|
||
ParentClass = base_name
|
||
Gen.class_parent[ClassName] = ParentClass
|
||
break
|
||
if ParentClass and (ParentClass in class_graph or ParentClass in Gen.class_members):
|
||
parent_members: list = list(Gen.class_members[ParentClass])
|
||
parent_defaults: dict = dict(Gen.class_member_defaults.get(ParentClass, {}))
|
||
existing_names: set = {m[0] for m in Gen.class_members[ClassName]}
|
||
inherited: list[tuple] = []
|
||
for pm_name, pm_type in parent_members:
|
||
if pm_name not in existing_names:
|
||
inherited.append((pm_name, pm_type))
|
||
if pm_name in parent_defaults:
|
||
Gen.class_member_defaults[ClassName][pm_name] = parent_defaults[pm_name]
|
||
Gen.class_members[ClassName] = inherited + Gen.class_members[ClassName]
|
||
if ParentClass in Gen.class_methods:
|
||
parent_methods: list = list(Gen.class_methods[ParentClass])
|
||
# 构建子类已有方法映射(方法短名 -> 方法全名)
|
||
child_method_map: dict[str, str] = {}
|
||
for m in Gen.class_methods[ClassName]:
|
||
method_name: str = m.split('.')[-1] if '.' in m else m
|
||
child_method_map[method_name] = m
|
||
# 父类方法在前(保证 vtable 布局一致性,子类多态分派索引正确),
|
||
# 子类新增方法在后。子类覆盖的方法放在父类方法的位置(用子类实现)。
|
||
new_methods: list = []
|
||
covered_names: set[str] = set()
|
||
for pm in parent_methods:
|
||
method_name: str = pm.split('.')[-1] if '.' in pm else pm
|
||
if method_name in child_method_map:
|
||
# 子类覆盖了父类方法 — 用子类的实现,放在父类的位置
|
||
new_methods.append(child_method_map[method_name])
|
||
covered_names.add(method_name)
|
||
else:
|
||
# 父类独有方法 — 子类未覆盖,注册子类包装器
|
||
child_method: str = f"{ClassName}.{method_name}"
|
||
new_methods.append(child_method)
|
||
Gen.register_method(ClassName, child_method)
|
||
# 添加子类新增方法(不在父类中的)
|
||
for m in Gen.class_methods[ClassName]:
|
||
method_name: str = m.split('.')[-1] if '.' in m else m
|
||
if method_name not in covered_names:
|
||
new_methods.append(m)
|
||
Gen.class_methods[ClassName] = new_methods
|
||
# 提取首个裸字符串字面量作为结构体 __doc__ docstring
|
||
if (Node.body and isinstance(Node.body[0], ast.Expr)
|
||
and isinstance(Node.body[0].value, ast.Constant)
|
||
and isinstance(Node.body[0].value.value, str)):
|
||
Gen._create_doc_global(ClassName, Node.body[0].value.value)
|
||
else:
|
||
Gen._create_doc_global(ClassName, None)
|
||
# 解析 __provides__/__requires__/__require_must__ 编译期元数据
|
||
for item in Node.body:
|
||
if isinstance(item, ast.AnnAssign) and isinstance(item.target, ast.Name):
|
||
field_name: str = item.target.id
|
||
if field_name in ('__provides__', '__requires__', '__require_must__') and item.value:
|
||
values: list[str] = []
|
||
if isinstance(item.value, ast.List):
|
||
for elt in item.value.elts:
|
||
if isinstance(elt, ast.Constant) and isinstance(elt.value, str):
|
||
values.append(elt.value)
|
||
if field_name == '__provides__':
|
||
Gen.class_provides[ClassName] = values
|
||
elif field_name == '__requires__':
|
||
Gen.class_requires[ClassName] = values
|
||
elif field_name == '__require_must__':
|
||
Gen.class_require_must[ClassName] = values
|
||
for item in Node.body:
|
||
# 跳过编译期元数据字段(__provides__/__requires__/__require_must__)
|
||
if isinstance(item, ast.AnnAssign) and isinstance(item.target, ast.Name):
|
||
if item.target.id in ('__provides__', '__requires__', '__require_must__'):
|
||
continue
|
||
parsed = self.CollectAnnAssignMember(item, Gen)
|
||
if parsed:
|
||
VarName, MemberType, TypeInfo = parsed
|
||
Gen.class_members[ClassName].append((VarName, MemberType))
|
||
if TypeInfo:
|
||
if isinstance(MemberType, ir.PointerType) and isinstance(MemberType.pointee, ir.IntType) and MemberType.pointee.width == 8:
|
||
if isinstance(item.annotation, ast.BinOp) and isinstance(item.annotation.op, ast.BitOr):
|
||
element_class: str | None = FindStructNameInAnnotation(item.annotation, Gen.structs)
|
||
# Fallback: FindStructNameInAnnotation 不处理 Subscript slice 为 BinOp 的情况
|
||
# (如 list[AST | t.CPtr] | t.CPtr),使用 TypeInfo.Name 作为回退。
|
||
# TypeInfo.Name 由 _HandleSubscript 设置为特化名(如 'list[sha1.ASTptr]'),
|
||
# 经 _MergeCTypeInfoInto 传播后保留。
|
||
if not element_class and TypeInfo.IsStruct and TypeInfo.Name and TypeInfo.Name in Gen.structs:
|
||
element_class = TypeInfo.Name
|
||
if element_class:
|
||
if ClassName not in Gen.class_member_element_class:
|
||
Gen.class_member_element_class[ClassName] = {}
|
||
Gen.class_member_element_class[ClassName][VarName] = element_class
|
||
# 泛型特化结构体指针字段(如 GSList[BasicBlock] | t.CPtr):
|
||
# 记录特化名,供后续 _try_access_opaque_generic_member 在所有候选特化版本
|
||
# 都有目标字段(如 Head/Tail/Count)时选择正确特化版本。
|
||
# 现有 i8* 分支不覆盖结构体指针字段,这里补充。
|
||
elif (isinstance(MemberType, ir.PointerType)
|
||
and isinstance(MemberType.pointee, ir.IdentifiedStructType)
|
||
and isinstance(item.annotation, ast.BinOp)
|
||
and isinstance(item.annotation.op, ast.BitOr)):
|
||
spec_in_anno: str | None = FindStructNameInAnnotation(item.annotation, Gen.structs)
|
||
if spec_in_anno and '[' in spec_in_anno:
|
||
if ClassName not in Gen.class_member_element_class:
|
||
Gen.class_member_element_class[ClassName] = {}
|
||
Gen.class_member_element_class[ClassName][VarName] = spec_in_anno
|
||
if hasattr(TypeInfo.BaseType, 'IsSigned'):
|
||
Gen.class_member_signeds[ClassName][VarName] = TypeInfo.BaseType.IsSigned
|
||
else:
|
||
Gen.class_member_signeds[ClassName][VarName] = None
|
||
if TypeInfo.IsBitField:
|
||
Gen.class_member_bitfields[ClassName][VarName] = TypeInfo.BitWidth
|
||
else:
|
||
Gen.class_member_bitfields[ClassName][VarName] = 0
|
||
if TypeInfo.ByteOrder:
|
||
Gen.class_member_byteorders[ClassName][VarName] = TypeInfo.ByteOrder
|
||
else:
|
||
Gen.class_member_byteorders[ClassName][VarName] = ""
|
||
if item.value:
|
||
const: ir.Constant | None = self._BuildScalarConstant(item.value, MemberType, Gen)
|
||
if const:
|
||
Gen.class_member_defaults[ClassName][VarName] = const
|
||
else:
|
||
Gen.class_member_signeds[ClassName][VarName] = None
|
||
Gen.class_member_bitfields[ClassName][VarName] = 0
|
||
# 字段收集完成,清除标志,允许后续 _generate_structs 正常设置 body
|
||
Gen._collecting_members_set.discard(ClassName)
|
||
existing_members: set[str] = {m[0] for m in Gen.class_members[ClassName]}
|
||
for item in Node.body:
|
||
if isinstance(item, ast.FunctionDef):
|
||
self._current_method_args = {}
|
||
for arg in item.args.args:
|
||
if arg.arg != 'self' and arg.annotation:
|
||
self._current_method_args[arg.arg] = arg.annotation
|
||
self._scan_method_body_for_self_members(item.body, ClassName, existing_members, Gen)
|
||
self._current_method_args = {}
|
||
for item in Node.body:
|
||
if isinstance(item, ast.FunctionDef):
|
||
MethodName: str = item.name
|
||
FullMethodName: str = f"{ClassName}.{MethodName}"
|
||
# property setter/deleter 使用不同的函数名后缀
|
||
item_meta: FuncMeta = self.Trans.FunctionHandler._ExtractFuncMeta(item.decorator_list)
|
||
if FuncMeta.PROPERTY_SETTER in item_meta:
|
||
FullMethodName = FullMethodName + '$set'
|
||
elif FuncMeta.PROPERTY_DELETER in item_meta:
|
||
FullMethodName = FullMethodName + '$del'
|
||
# 构造函数(__new__/__init__)不放入 vtable,避免子类与基类
|
||
# vtable 大小不一致导致虚分派索引偏移。__before_init__ 由 TPC
|
||
# 自动生成,不会出现在 FunctionDef 中,此处一并防御。
|
||
if MethodName not in ('__new__', '__init__', '__before_init__'):
|
||
if FullMethodName not in Gen.class_methods[ClassName]:
|
||
Gen.class_methods[ClassName].append(FullMethodName)
|
||
Gen.register_method(ClassName, FullMethodName)
|
||
if IsCVTable:
|
||
Gen.class_vtable.add(ClassName)
|
||
Gen._generate_structs()
|
||
Gen._create_Vtable_globals()
|
||
# _create_Vtable_globals 会跳过正在发射中的类(方法列表可能不完整),
|
||
# 当前类的方法已全部注册(L559-571),此处显式创建其 vtable
|
||
if IsCVTable:
|
||
Gen._create_vtable_for_class(ClassName)
|
||
if ClassName in Gen.structs:
|
||
self._EmitNewFunctionLlvm(ClassName, Gen, IsCVTable=IsCVTable, IsCpythonObject=IsCpythonObject)
|
||
for item in Node.body:
|
||
if isinstance(item, ast.FunctionDef):
|
||
self.Trans.FunctionHandler._EmitFunctionForwardDeclLlvm(item, Gen, ClassName=ClassName)
|
||
if not declare_only:
|
||
for item in Node.body:
|
||
if isinstance(item, ast.FunctionDef):
|
||
self.Trans.FunctionHandler._EmitFunctionLlvm(item, Gen, ClassName=ClassName)
|
||
if IsCVTable and ClassName in Gen.Vtables:
|
||
self._fill_vtable_with_methods(ClassName, Gen)
|
||
# Generate wrapper functions for inherited methods that are not overridden
|
||
if ParentClass:
|
||
self._generate_inherited_method_wrappers(ClassName, Gen)
|
||
Gen._classes_in_progress.discard(ClassName)
|
||
|
||
def _generate_inherited_method_wrappers(self, ClassName: str, Gen: LlvmGeneratorMixin) -> None:
|
||
"""为子类继承但未覆写的方法生成包装函数,使跨模块调用能正确链接。
|
||
|
||
例如 Label 继承 Widget.place,生成 Label.place 函数,
|
||
内部将 self 从 Label* bitcast 为 Widget*,然后调用 Widget.place。
|
||
"""
|
||
# 收集本类方法 + 沿继承链收集父类方法名
|
||
# 原代码只遍历 class_methods[ClassName],遗漏父类独有方法(如 __enter__),
|
||
# 导致子类调用继承的方法时链接失败(undefined reference)
|
||
methods: list = list(Gen.class_methods.get(ClassName, []))
|
||
p: str | None = Gen.class_parent.get(ClassName) if hasattr(Gen, 'class_parent') else None
|
||
while p:
|
||
parent_methods: list = Gen.class_methods.get(p, [])
|
||
for pm in parent_methods:
|
||
pm_short: str = pm.split('.')[-1] if '.' in pm else pm
|
||
# 避免重复:如果子类已覆写同名方法,不添加
|
||
if not any(m.split('.')[-1] == pm_short for m in methods):
|
||
methods.append(pm)
|
||
p = Gen.class_parent.get(p)
|
||
if not methods:
|
||
return
|
||
if ClassName not in Gen.structs:
|
||
return
|
||
|
||
for method_name in methods:
|
||
method_short: str = method_name.split('.')[-1] if '.' in method_name else method_name
|
||
child_full: str = f"{ClassName}.{method_short}"
|
||
|
||
# 如果子类已经有该方法的实现,跳过
|
||
if Gen._find_function(child_full):
|
||
continue
|
||
|
||
# 沿继承链查找父类实现
|
||
parent_func: ir.Function | None = None
|
||
parent_class: str | None = None
|
||
p: str | None = Gen.class_parent.get(ClassName)
|
||
while p:
|
||
parent_full: str = f"{p}.{method_short}"
|
||
parent_func = Gen._find_function(parent_full)
|
||
if parent_func:
|
||
parent_class = p
|
||
break
|
||
p = Gen.class_parent.get(p)
|
||
|
||
if not parent_func or not parent_class:
|
||
continue
|
||
|
||
# 父类和子类都需要有 struct 定义
|
||
if parent_class not in Gen.structs:
|
||
continue
|
||
|
||
# 构造子类包装函数签名:与父类函数相同,但 self 参数类型为子类指针
|
||
parent_ftype: ir.FunctionType = parent_func.function_type
|
||
parent_ret_type: ir.Type = parent_ftype.return_type
|
||
parent_param_types: list[ir.Type] = list(parent_ftype.args)
|
||
is_vararg: bool = parent_ftype.var_arg
|
||
|
||
# 判断父类方法是否是静态方法:
|
||
# 如果第一个参数类型是父类指针,说明是实例方法;否则是静态方法
|
||
parent_struct_ptr_type: ir.PointerType | None = ir.PointerType(Gen.structs[parent_class]) if parent_class in Gen.structs else None
|
||
is_static: bool = True
|
||
if parent_param_types and parent_struct_ptr_type:
|
||
first_param: ir.Type = parent_param_types[0]
|
||
# 检查第一个参数是否是父类指针(或可以 bitcast 为父类指针的指针类型)
|
||
if isinstance(first_param, ir.PointerType):
|
||
if isinstance(first_param.pointee, ir.IdentifiedStructType):
|
||
if first_param.pointee.name == Gen.structs[parent_class].name:
|
||
is_static = False
|
||
elif first_param == ir.IntType(8):
|
||
# i8* 可能是前向声明时的 self 类型,视为实例方法
|
||
is_static = False
|
||
|
||
if is_static:
|
||
# 静态方法:签名与父类完全一致,不需要 self 参数
|
||
child_param_types: list[ir.Type] = list(parent_param_types)
|
||
child_struct_ptr: ir.PointerType | None = None
|
||
else:
|
||
# 实例方法:替换第一个参数(self)的类型为子类指针
|
||
child_struct_ptr = ir.PointerType(Gen.structs[ClassName])
|
||
if parent_param_types:
|
||
child_param_types = [child_struct_ptr] + parent_param_types[1:]
|
||
else:
|
||
child_param_types = [child_struct_ptr]
|
||
|
||
child_func_type: ir.FunctionType = ir.FunctionType(parent_ret_type, child_param_types, var_arg=is_vararg)
|
||
child_mangled: str = Gen._mangle_func_name(child_full)
|
||
child_func: ir.Function = Gen._get_or_declare_function(child_mangled, child_func_type)
|
||
Gen.functions[child_full] = child_func
|
||
|
||
# 生成函数体
|
||
entry_block: ir.Block = child_func.append_basic_block(name="entry")
|
||
saved_builder: ir.IRBuilder = Gen.builder
|
||
saved_func: ir.Function = Gen.func
|
||
Gen.builder = ir.IRBuilder(entry_block)
|
||
Gen.func = child_func
|
||
|
||
# 准备参数
|
||
call_args: list[ir.Value] = []
|
||
if is_static:
|
||
# 静态方法:参数直接传递,不做 bitcast
|
||
for arg in child_func.args:
|
||
call_args.append(arg)
|
||
else:
|
||
# 实例方法:bitcast self,其余参数直接传递
|
||
for i, arg in enumerate(child_func.args):
|
||
if i == 0 and parent_param_types:
|
||
actual_self_type: ir.Type = parent_param_types[0]
|
||
casted_self: ir.Value = Gen.builder.bitcast(arg, actual_self_type, name="self_cast")
|
||
call_args.append(casted_self)
|
||
else:
|
||
call_args.append(arg)
|
||
|
||
result: ir.Value = Gen.builder.call(parent_func, call_args, name="inherited_call")
|
||
|
||
if isinstance(parent_ret_type, ir.VoidType):
|
||
Gen.builder.ret_void()
|
||
else:
|
||
Gen.builder.ret(result)
|
||
|
||
Gen.builder = saved_builder
|
||
Gen.func = saved_func
|
||
|
||
def _fill_vtable_with_methods(self, ClassName: str, Gen: LlvmGeneratorMixin) -> None:
|
||
methods: list = Gen.class_methods.get(ClassName, [])
|
||
if not methods or ClassName not in Gen.Vtables:
|
||
return
|
||
Vtable: ir.GlobalVariable = Gen.Vtables[ClassName]
|
||
VtableType: ir.Type = Vtable.type.pointee
|
||
null_i8ptr: ir.Constant = ir.Constant(ir.PointerType(ir.IntType(8)), None)
|
||
initializers: list[ir.Constant] = []
|
||
for mi, method_name in enumerate(methods):
|
||
method_short: str = method_name.split('.')[-1] if '.' in method_name else method_name
|
||
func: ir.Function | None = Gen._find_function(f"{ClassName}.{method_short}")
|
||
if not func:
|
||
func = Gen._find_function(f"{ClassName}.{method_short}__")
|
||
if not func:
|
||
p: str | None = Gen.class_parent.get(ClassName)
|
||
while p:
|
||
func = Gen._find_function(f"{p}.{method_short}")
|
||
if not func:
|
||
func = Gen._find_function(f"{p}.{method_short}__")
|
||
if func:
|
||
break
|
||
p = Gen.class_parent.get(p)
|
||
if func:
|
||
initializers.append(func.bitcast(ir.PointerType(ir.IntType(8))))
|
||
else:
|
||
initializers.append(null_i8ptr)
|
||
if initializers:
|
||
Vtable.initializer = ir.Constant(VtableType, initializers)
|
||
|
||
def _scan_method_body_for_self_members(self, body: list[ast.AST], ClassName: str, existing_members: set[str], Gen: LlvmGeneratorMixin) -> None:
|
||
for stmt in body:
|
||
self._scan_node_for_self_assign(stmt, ClassName, existing_members, Gen)
|
||
|
||
def _scan_node_for_self_assign(self, node: ast.AST, ClassName: str, existing_members: set[str], Gen: LlvmGeneratorMixin) -> None:
|
||
if isinstance(node, ast.AnnAssign):
|
||
if (isinstance(node.target, ast.Attribute)
|
||
and isinstance(node.target.value, ast.Name)
|
||
and node.target.value.id == 'self'):
|
||
VarName: str = node.target.attr
|
||
if VarName not in existing_members:
|
||
try:
|
||
TypeInfo: CTypeInfo | None = CTypeInfo.FromNode(node.annotation, self.Trans.SymbolTable)
|
||
if TypeInfo is None:
|
||
TypeInfo = CTypeInfo()
|
||
TypeInfo.BaseType = t.CInt()
|
||
MemberType: ir.Type = Gen._ctype_to_llvm(TypeInfo)
|
||
if isinstance(MemberType, ir.VoidType):
|
||
MemberType = ir.IntType(32)
|
||
except Exception as e: # 回退:成员类型解析失败时使用默认 i32
|
||
_vlog().warning(f"HandlesClassDef: 忽略异常 {e}", exc_info=e)
|
||
MemberType = ir.IntType(32)
|
||
Gen.class_members[ClassName].append((VarName, MemberType))
|
||
Gen.class_member_signeds[ClassName][VarName] = None
|
||
Gen.class_member_bitfields[ClassName][VarName] = 0
|
||
Gen.class_member_byteorders[ClassName][VarName] = ""
|
||
Gen.class_member_bitoffsets[ClassName][VarName] = 0
|
||
existing_members.add(VarName)
|
||
len_name = f'{VarName}__len'
|
||
if isinstance(MemberType, ir.PointerType) and node.value and isinstance(node.value, ast.List):
|
||
if len_name not in existing_members:
|
||
Gen.class_members[ClassName].append((len_name, ir.IntType(64)))
|
||
Gen.class_member_signeds[ClassName][len_name] = None
|
||
Gen.class_member_bitfields[ClassName][len_name] = 0
|
||
Gen.class_member_byteorders[ClassName][len_name] = ""
|
||
Gen.class_member_bitoffsets[ClassName][len_name] = 0
|
||
Gen.class_member_defaults[ClassName][len_name] = ir.Constant(ir.IntType(64), len(node.value.elts))
|
||
existing_members.add(len_name)
|
||
elif isinstance(node, ast.Assign):
|
||
for target in node.targets:
|
||
if (isinstance(target, ast.Attribute)
|
||
and isinstance(target.value, ast.Name)
|
||
and target.value.id == 'self'):
|
||
VarName = target.attr
|
||
if VarName not in existing_members:
|
||
MemberType = ir.IntType(32)
|
||
if node.value:
|
||
try:
|
||
if isinstance(node.value, ast.Constant):
|
||
if isinstance(node.value.value, int):
|
||
MemberType = ir.IntType(32)
|
||
elif isinstance(node.value.value, float):
|
||
MemberType = ir.DoubleType()
|
||
elif isinstance(node.value.value, str):
|
||
MemberType = ir.PointerType(ir.IntType(8))
|
||
elif isinstance(node.value, ast.Name):
|
||
if hasattr(self, '_current_method_args'):
|
||
arg_info = self._current_method_args.get(node.value.id)
|
||
if arg_info:
|
||
TypeInfo = CTypeInfo.FromNode(arg_info, self.Trans.SymbolTable)
|
||
if TypeInfo:
|
||
InferredType = Gen._ctype_to_llvm(TypeInfo)
|
||
if not isinstance(InferredType, ir.VoidType):
|
||
MemberType = InferredType
|
||
elif isinstance(node.value, ast.Call):
|
||
if isinstance(node.value.func, ast.Name):
|
||
if node.value.func.id in ('float', 'double'):
|
||
MemberType = ir.DoubleType()
|
||
elif node.value.func.id in ('int', 'long', 'short', 'char'):
|
||
MemberType = ir.IntType(32)
|
||
elif isinstance(node.value.func, ast.Attribute):
|
||
if node.value.func.attr == 'len':
|
||
MemberType = ir.IntType(32)
|
||
except Exception as _e:
|
||
if _config_mode == "strict":
|
||
self.Trans.LogWarning(f"异常被忽略: {_e}")
|
||
Gen.class_members[ClassName].append((VarName, MemberType))
|
||
Gen.class_member_signeds[ClassName][VarName] = None
|
||
Gen.class_member_bitfields[ClassName][VarName] = 0
|
||
Gen.class_member_byteorders[ClassName][VarName] = ""
|
||
Gen.class_member_bitoffsets[ClassName][VarName] = 0
|
||
existing_members.add(VarName)
|
||
for child in ast.iter_child_nodes(node):
|
||
if isinstance(child, (ast.FunctionDef, ast.AsyncFunctionDef, ast.ClassDef)):
|
||
continue
|
||
self._scan_node_for_self_assign(child, ClassName, existing_members, Gen)
|
||
|
||
def _EmitUnionLlvm(self, Node: ast.ClassDef, Gen: LlvmGeneratorMixin) -> None:
|
||
ClassName: str = Node.name
|
||
union_member_types: list[ir.Type] = []
|
||
for item in Node.body:
|
||
if isinstance(item, ast.ClassDef):
|
||
nested_class_name: str = item.name
|
||
nested_member_types: list[ir.Type] = []
|
||
for nested_item in item.body:
|
||
parsed = self.CollectAnnAssignMember(nested_item, Gen)
|
||
if parsed:
|
||
nested_member_types.append(parsed[1])
|
||
if nested_member_types:
|
||
nested_struct_type: ir.IdentifiedStructType = ir.IdentifiedStructType(Gen.module, f"{ClassName}_{nested_class_name}")
|
||
nested_struct_type.set_body(*nested_member_types)
|
||
Gen.structs[f"{ClassName}_{nested_class_name}"] = nested_struct_type
|
||
union_member_types.append(nested_struct_type)
|
||
nested_class_full_name: str = f"{ClassName}_{nested_class_name}"
|
||
if nested_class_full_name not in Gen.class_members:
|
||
Gen.class_members[nested_class_full_name] = []
|
||
if nested_class_full_name not in Gen.class_member_signeds:
|
||
Gen.class_member_signeds[nested_class_full_name] = {}
|
||
for nested_item in item.body:
|
||
parsed = self.CollectAnnAssignMember(nested_item, Gen)
|
||
if parsed:
|
||
VarName, MemberType, TypeInfo = parsed
|
||
Gen.class_members[nested_class_full_name].append((VarName, MemberType))
|
||
if TypeInfo and hasattr(TypeInfo.BaseType, 'IsSigned'):
|
||
Gen.class_member_signeds[nested_class_full_name][VarName] = TypeInfo.BaseType.IsSigned
|
||
else:
|
||
Gen.class_member_signeds[nested_class_full_name][VarName] = None
|
||
if union_member_types:
|
||
max_size: int = 0
|
||
for member_type in union_member_types:
|
||
try:
|
||
size: int = member_type.get_abi_size(ir.DataLayout(Gen.module.data_layout))
|
||
except Exception as e: # 回退:获取类型大小失败时使用默认值 8
|
||
_vlog().warning(f"HandlesClassDef: 忽略异常 {e}", exc_info=e)
|
||
size = 8
|
||
max_size = max(max_size, size)
|
||
union_type: ir.IdentifiedStructType = ir.IdentifiedStructType(Gen.module, ClassName)
|
||
union_type.set_body(ir.ArrayType(ir.IntType(8), max_size))
|
||
Gen.structs[ClassName] = union_type
|
||
UnionNode: CTypeInfo = CTypeInfo()
|
||
UnionNode.Name = ClassName
|
||
UnionNode.IsUnion = True
|
||
self.Trans.SymbolTable.insert(ClassName, UnionNode)
|
||
|
||
def _EmitREnumLlvm(self, Node: ast.ClassDef, Gen: LlvmGeneratorMixin) -> None:
|
||
ClassName: str = Node.name
|
||
variant_info: list[tuple] = []
|
||
variant_names: list[str] = []
|
||
|
||
# 预注册 REnum opaque 结构体到 Gen.structs 和 SymbolTable,
|
||
# 使自引用成员(如 LLVMType | t.CPtr)在收集成员时能正确解析为 %LLVMType*。
|
||
# 若不预注册,GetCTypeInfo 找不到 LLVMType → 回退到 IsEnum → i32 → | t.CPtr → i32*(错误)。
|
||
PreRenumType: ir.IdentifiedStructType = ir.IdentifiedStructType(Gen.module, ClassName)
|
||
Gen.structs[ClassName] = PreRenumType
|
||
PreTypeInfo: CTypeInfo = CTypeInfo()
|
||
PreTypeInfo.Name = ClassName
|
||
PreTypeInfo.BaseType = t.REnum(ClassName)
|
||
PreTypeInfo.IsRenum = True
|
||
PreTypeInfo.IsEnum = True
|
||
# REnum 在内存布局上是 struct({ i32 __tag, <max_payload> }),
|
||
# 必须设置 IsStruct=True 才能让 HandlesTypeMerge 的 CPtr 吸收逻辑生效:
|
||
# `REnumType | t.CPtr` 应得到 REnumType*(PtrCount=1)而非 REnumType**(PtrCount=2)。
|
||
# 否则 include-imported 函数返回类型会出现双指针,与声明单指针不匹配 → 运行时崩溃。
|
||
PreTypeInfo.IsStruct = True
|
||
PreTypeInfo.RenumVariants = []
|
||
self.Trans.SymbolTable.insert(ClassName, PreTypeInfo)
|
||
|
||
# 第一遍:收集显式赋值的 tag 值,确定起始索引
|
||
explicit_values: dict[str, int] = {}
|
||
for item in Node.body:
|
||
if isinstance(item, ast.Assign):
|
||
for target in item.targets:
|
||
if isinstance(target, ast.Name):
|
||
if item.value and isinstance(item.value, ast.Constant):
|
||
explicit_values[target.id] = item.value.value
|
||
# 类变体从 max(explicit_values, default=-1) + 1 开始
|
||
next_class_tag: int = max(explicit_values.values()) + 1 if explicit_values else 0
|
||
variant_index: int = 0
|
||
|
||
for item in Node.body:
|
||
if isinstance(item, ast.ClassDef):
|
||
VariantName: str = item.name
|
||
variant_names.append(VariantName)
|
||
member_types: list[ir.Type] = []
|
||
member_names: list[str] = []
|
||
member_annotations: list[ast.AST | None] = []
|
||
for nested_item in item.body:
|
||
parsed = self.CollectAnnAssignMember(nested_item, Gen)
|
||
if parsed:
|
||
VarName, MemberType, TypeInfo = parsed
|
||
member_types.append(MemberType)
|
||
member_names.append(VarName)
|
||
member_annotations.append(nested_item.annotation if TypeInfo else None)
|
||
# 类变体使用专用计数器,避免与显式值冲突
|
||
tag: int = next_class_tag
|
||
next_class_tag += 1
|
||
variant_info.append((VariantName, member_types, member_names, member_annotations, item.lineno, tag))
|
||
elif isinstance(item, ast.Assign):
|
||
for target in item.targets:
|
||
if isinstance(target, ast.Name):
|
||
VarName = target.id
|
||
variant_names.append(VarName)
|
||
value: int | None = None
|
||
if item.value and isinstance(item.value, ast.Constant):
|
||
value = item.value.value
|
||
else:
|
||
value = variant_index
|
||
variant_index += 1
|
||
variant_info.append((VarName, [], [], [], item.lineno, value))
|
||
# REnum 布局是所有变体的联合体。每个字段位置必须能容纳任何变体在该位置的字段。
|
||
# Bug 修复:原来只选总尺寸最大的变体,但不同变体在同一位置可能有不同尺寸的字段。
|
||
# 例如 MetaType: Concrete 位置3是 i32(4字节),但 Var 位置3是 MetaType*(8字节)。
|
||
# 用 Concrete 的布局会导致 Var.Instance 指针被截断为4字节 → 运行时崩溃。
|
||
# 修复:按每个位置的 max 字段尺寸构建布局。
|
||
def _ir_type_size(t: ir.Type) -> int:
|
||
if isinstance(t, ir.IntType):
|
||
return max(4, t.width // 8)
|
||
elif isinstance(t, ir.PointerType):
|
||
return 8
|
||
elif isinstance(t, ir.FloatType):
|
||
return 4
|
||
elif isinstance(t, ir.DoubleType):
|
||
return 8
|
||
elif isinstance(t, ir.ArrayType):
|
||
if isinstance(t.element, ir.IntType):
|
||
return t.element.width // 8 * t.count
|
||
return 8 * t.count
|
||
else:
|
||
return 8
|
||
|
||
all_variant_types: list[list[ir.Type]] = []
|
||
max_field_count: int = 0
|
||
for _, member_types, _, _, _, _ in variant_info:
|
||
if member_types:
|
||
full_types: list[ir.Type] = [ir.IntType(32)] + member_types
|
||
all_variant_types.append(full_types)
|
||
if len(full_types) > max_field_count:
|
||
max_field_count = len(full_types)
|
||
max_variant_struct: list[ir.Type] = []
|
||
for pos in range(max_field_count):
|
||
pos_max_size: int = 0
|
||
for vt in all_variant_types:
|
||
if pos < len(vt):
|
||
sz: int = _ir_type_size(vt[pos])
|
||
if sz > pos_max_size:
|
||
pos_max_size = sz
|
||
# 按最大尺寸选择 LLVM 类型:<=4 用 i32,>4 用 i64(8字节,可容纳指针)
|
||
if pos_max_size <= 4:
|
||
max_variant_struct.append(ir.IntType(32))
|
||
else:
|
||
max_variant_struct.append(ir.IntType(64))
|
||
if not max_variant_struct:
|
||
max_variant_struct = [ir.IntType(32), ir.IntType(32)]
|
||
# 复用预注册的 opaque 结构体,设置 body 使其完整
|
||
PreRenumType.set_body(*max_variant_struct)
|
||
for VariantName, member_types, member_names, member_annotations, lineno, tag_value in variant_info:
|
||
NestedStructName: str = f"{ClassName}_{VariantName}"
|
||
if member_types:
|
||
padded_member_types: list[ir.Type] = list(max_variant_struct)
|
||
nested_struct_type: ir.IdentifiedStructType = ir.IdentifiedStructType(Gen.module, NestedStructName)
|
||
nested_struct_type.set_body(*padded_member_types)
|
||
Gen.structs[NestedStructName] = nested_struct_type
|
||
if NestedStructName not in Gen.class_members:
|
||
Gen.class_members[NestedStructName] = []
|
||
if NestedStructName not in Gen.class_member_signeds:
|
||
Gen.class_member_signeds[NestedStructName] = {}
|
||
Gen.class_members[NestedStructName].append(('__tag', ir.IntType(32)))
|
||
Gen.class_member_signeds[NestedStructName]['__tag'] = None
|
||
for i, (mname, mtype) in enumerate(zip(member_names, member_types)):
|
||
Gen.class_members[NestedStructName].append((mname, mtype))
|
||
try:
|
||
ti: CTypeInfo | None = CTypeInfo.FromNode(member_annotations[i], self.Trans.SymbolTable)
|
||
if ti and hasattr(ti.BaseType, 'IsSigned'):
|
||
Gen.class_member_signeds[NestedStructName][mname] = ti.BaseType.IsSigned
|
||
else:
|
||
Gen.class_member_signeds[NestedStructName][mname] = None
|
||
except Exception as e: # 回退:签名信息解析失败时设为 None
|
||
_vlog().warning(f"HandlesClassDef: 忽略异常 {e}", exc_info=e)
|
||
Gen.class_member_signeds[NestedStructName][mname] = None
|
||
MemberNode: CTypeInfo = CTypeInfo()
|
||
MemberNode.Name = VariantName
|
||
MemberNode.BaseType = t.CEnum(ClassName)
|
||
MemberNode.value = tag_value
|
||
MemberNode.EnumName = ClassName
|
||
MemberNode.Lineno = lineno
|
||
MemberNode.IsEnumMember = True
|
||
self.Trans.SymbolTable.insert(VariantName, MemberNode)
|
||
# 更新预注册的 REnum 类型信息(填充变体列表)
|
||
PreTypeInfo.RenumVariants = variant_names
|
||
|
||
def _RegisterEnumMembers(self, Node: ast.ClassDef) -> None:
|
||
ClassName: str = Node.name
|
||
EnumTypeInfo: CTypeInfo = CTypeInfo()
|
||
EnumTypeInfo.Name = ClassName
|
||
EnumTypeInfo.BaseType = t.CEnum(ClassName)
|
||
EnumTypeInfo.IsEnum = True
|
||
self.Trans.SymbolTable.insert(ClassName, EnumTypeInfo)
|
||
enum_export = self.Trans.Exportable.add_enum(
|
||
name=ClassName,
|
||
lineno=Node.lineno,
|
||
is_public=True
|
||
)
|
||
next_enum_value: int = 0
|
||
for item in Node.body:
|
||
if isinstance(item, ast.Assign):
|
||
for target in item.targets:
|
||
if isinstance(target, ast.Name):
|
||
VarName: str = target.id
|
||
value: int | str | None = None
|
||
if item.value:
|
||
if isinstance(item.value, ast.Constant):
|
||
value = item.value.value
|
||
next_enum_value = value + 1
|
||
elif isinstance(item.value, ast.UnaryOp) and isinstance(item.value.op, ast.USub):
|
||
if isinstance(item.value.operand, ast.Constant):
|
||
value = -item.value.operand.value
|
||
next_enum_value = value + 1
|
||
elif isinstance(item.value, ast.Name):
|
||
value = item.value.id
|
||
ref_info: CTypeInfo | None = self.Trans.SymbolTable.lookup(value)
|
||
if ref_info:
|
||
if ref_info.value is not None and isinstance(ref_info.value, int):
|
||
next_enum_value = ref_info.value + 1
|
||
else:
|
||
value = next_enum_value
|
||
next_enum_value += 1
|
||
MemberNode: CTypeInfo = CTypeInfo()
|
||
MemberNode.Name = VarName
|
||
MemberNode.BaseType = t.CEnum(ClassName)
|
||
MemberNode.value = value
|
||
MemberNode.EnumName = ClassName
|
||
MemberNode.Lineno = item.lineno
|
||
MemberNode.IsEnumMember = True
|
||
self.Trans.SymbolTable.insert(VarName, MemberNode)
|
||
enum_export.members.append(ExportEnumMember(
|
||
name=VarName,
|
||
value=value,
|
||
lineno=item.lineno
|
||
))
|
||
elif isinstance(item, ast.AnnAssign):
|
||
if isinstance(item.target, ast.Name):
|
||
VarName = item.target.id
|
||
value = None
|
||
if item.value:
|
||
if isinstance(item.value, ast.Constant):
|
||
value = item.value.value
|
||
next_enum_value = value + 1
|
||
elif isinstance(item.value, ast.UnaryOp) and isinstance(item.value.op, ast.USub):
|
||
if isinstance(item.value.operand, ast.Constant):
|
||
value = -item.value.operand.value
|
||
next_enum_value = value + 1
|
||
elif isinstance(item.value, ast.Name):
|
||
value = item.value.id
|
||
ref_info: CTypeInfo | None = self.Trans.SymbolTable.lookup(value)
|
||
if ref_info:
|
||
if ref_info.value is not None and isinstance(ref_info.value, int):
|
||
next_enum_value = ref_info.value + 1
|
||
else:
|
||
value = next_enum_value
|
||
next_enum_value += 1
|
||
MemberNode: CTypeInfo = CTypeInfo()
|
||
MemberNode.Name = VarName
|
||
MemberNode.BaseType = t.CEnum(ClassName)
|
||
MemberNode.value = value
|
||
MemberNode.EnumName = ClassName
|
||
MemberNode.Lineno = item.lineno
|
||
MemberNode.IsEnumMember = True
|
||
self.Trans.SymbolTable.insert(VarName, MemberNode)
|
||
enum_export.members.append(ExportEnumMember(
|
||
name=VarName,
|
||
value=value,
|
||
lineno=item.lineno
|
||
))
|
||
|
||
def _EmitNewFunctionLlvm(self, ClassName: str, Gen: LlvmGeneratorMixin, IsCVTable: bool = False, IsCpythonObject: bool = False) -> None:
|
||
NewFuncName: str = f'{ClassName}.__before_init__'
|
||
existing_func: ir.Function | None = Gen.functions.get(NewFuncName)
|
||
if existing_func and len(existing_func.blocks) > 0:
|
||
return
|
||
MangledName: str = Gen._mangle_name(NewFuncName)
|
||
StructType: ir.Type = Gen.structs[ClassName]
|
||
if isinstance(StructType, ir.IdentifiedStructType) and (StructType.elements is None or len(StructType.elements) == 0):
|
||
self.Trans.ImportHandler._TryLoadStructFromStub(ClassName, Gen)
|
||
StructType = Gen.structs.get(ClassName, StructType)
|
||
StructPtrType: ir.PointerType = ir.PointerType(StructType)
|
||
FuncType: ir.FunctionType = ir.FunctionType(ir.VoidType(), [StructPtrType])
|
||
if existing_func:
|
||
func: ir.Function = existing_func
|
||
else:
|
||
func = Gen._get_or_declare_function(MangledName, FuncType)
|
||
Gen.functions[NewFuncName] = func
|
||
EntryBlock: ir.Block = func.append_basic_block(name="entry")
|
||
saved_builder: ir.IRBuilder = Gen.builder
|
||
saved_func: ir.Function = Gen.func
|
||
Gen.builder = ir.IRBuilder(EntryBlock)
|
||
Gen.func = func
|
||
StructPtr: ir.Argument = func.args[0]
|
||
base: int = 1 if IsCVTable else 0
|
||
if IsCVTable and ClassName in Gen.Vtables:
|
||
VtablePtr: ir.Value = Gen.builder.gep(StructPtr, [ir.Constant(ir.IntType(32), 0), ir.Constant(ir.IntType(32), 0)], name="vtable_slot")
|
||
VtableAddr: ir.Value = Gen.builder.bitcast(Gen.Vtables[ClassName], ir.PointerType(ir.IntType(8)), name="vtable_addr")
|
||
Gen.builder.store(VtableAddr, VtablePtr)
|
||
members: list[tuple] = Gen.class_members.get(ClassName, [])
|
||
defaults: dict = Gen.class_member_defaults.get(ClassName, {})
|
||
struct_elems: tuple = StructType.elements if hasattr(StructType, 'elements') and StructType.elements is not None else ()
|
||
for i, (member_name, member_type) in enumerate(members):
|
||
elem_idx: int = base + i
|
||
if len(struct_elems) > 0 and elem_idx >= len(struct_elems):
|
||
break
|
||
ElemPtr: ir.Value = Gen.builder.gep(StructPtr, [ir.Constant(ir.IntType(32), 0), ir.Constant(ir.IntType(32), elem_idx)], name=f"{ClassName}_{member_name}")
|
||
if member_name in defaults:
|
||
try:
|
||
val: ir.Constant = defaults[member_name]
|
||
if not isinstance(val, ir.Constant):
|
||
val = ir.Constant(ElemPtr.type.pointee, val)
|
||
Gen.builder.store(val, ElemPtr)
|
||
except Exception as _e:
|
||
if _config_mode == "strict":
|
||
self.Trans.LogWarning(f"异常被忽略: {_e}")
|
||
else:
|
||
try:
|
||
ZeroVal: ir.Constant = ir.Constant(ElemPtr.type.pointee, None)
|
||
Gen.builder.store(ZeroVal, ElemPtr)
|
||
except Exception:
|
||
pass
|
||
Gen.builder.ret_void()
|
||
Gen.builder = saved_builder
|
||
Gen.func = saved_func
|
||
|
||
def _BuildScalarConstant(self, node: ast.AST, llvm_type: ir.Type, Gen: LlvmGeneratorMixin | None = None) -> ir.Constant | None:
|
||
"""构建标量常量,委托给统一的 _BuildScalarConstantUnified 方法。"""
|
||
if Gen is None:
|
||
Gen = self.Trans.LlvmGen
|
||
return self.Trans._BuildScalarConstantUnified(node, llvm_type, Gen)
|
||
|
||
def _BuildStructConstant(self, call_node: ast.Call, StructName: str, Gen: LlvmGeneratorMixin) -> ir.Constant | None:
|
||
struct_type: ir.Type = Gen.structs[StructName]
|
||
members: list[tuple] = Gen.class_members.get(StructName, [])
|
||
defaults: dict = Gen.class_member_defaults.get(StructName, {})
|
||
member_values: list[ir.Constant] = []
|
||
for member_name, member_type in members:
|
||
if member_name in defaults:
|
||
val: ir.Constant = defaults[member_name]
|
||
if not isinstance(val, ir.Constant):
|
||
try:
|
||
val = ir.Constant(member_type, val)
|
||
except Exception: # 回退:常量转换失败时使用零值
|
||
val = ir.Constant(member_type, 0)
|
||
member_values.append(val)
|
||
else:
|
||
try:
|
||
if isinstance(member_type, (ir.IdentifiedStructType, ir.LiteralStructType, ir.PointerType, ir.ArrayType)):
|
||
member_values.append(ir.Constant(member_type, None))
|
||
else:
|
||
member_values.append(ir.Constant(member_type, ir.Undefined))
|
||
except Exception: # 回退:常量创建失败时使用零值
|
||
member_values.append(ir.Constant(member_type, 0))
|
||
if call_node.args:
|
||
for i, arg in enumerate(call_node.args):
|
||
if i < len(members):
|
||
_, member_type = members[i]
|
||
const: ir.Constant | None = self._BuildScalarConstant(arg, member_type, Gen)
|
||
if const is not None:
|
||
member_values[i] = const
|
||
try:
|
||
return ir.Constant(struct_type, member_values)
|
||
except Exception: # 回退:结构体常量创建失败
|
||
return None
|