diff --git a/App/lib/StubGen/VpiReader.vp b/App/lib/StubGen/VpiReader.vp index c2bafca..1bdaa84 100644 --- a/App/lib/StubGen/VpiReader.vp +++ b/App/lib/StubGen/VpiReader.vp @@ -1130,10 +1130,16 @@ def _inject_method_declare(pool: memhub.MemBuddy | t.CPtr, llvmlite.add_param(pool, func, param_ty, pname) # 注册到函数表(用裸名 ClassName.method,与调用方 lookup_name 一致) + # ParamCount 不含 self(方法首参 self/cls 不计入,与 _translate_method 的 + # md_param_count = args.__len__() - 1 保持一致)——默认参数填充按非 self + # 参数计数,若含 self 会导致 mdf_param_count 虚高、填充逻辑错位/越界。 if funcs_ptr is not None: cur_count: int = trans._func_count + param_count_no_self: int = param_count + if param_count_no_self > 0: + param_count_no_self -= 1 if HandlesExprCall.add_func_to_table(funcs_ptr, cur_count, lookup_name, func, max_funcs, - None, 0, param_count) == 0: + None, 0, param_count_no_self) == 0: trans._func_count = cur_count + 1 diff --git a/App/lib/core/BuildPipeline.vp b/App/lib/core/BuildPipeline.vp index e3b6baf..d4f7357 100644 --- a/App/lib/core/BuildPipeline.vp +++ b/App/lib/core/BuildPipeline.vp @@ -17,6 +17,8 @@ import lib.core.Handles.HandlesType as HandlesType import lib.core.Handles.HandlesExpr as HandlesExpr import lib.core.Handles.HandlesExprOps as HandlesExprOps import lib.core.Handles.HandlesExprCall as HandlesExprCall +import lib.core.Handles.HandlesFunctions as HandlesFunctions +import lib.core.Handles.HandlesClassDef as HandlesClassDef import lib.core.Handles.HandlesImports as HandlesImports import lib.core.StubMerger as StubMerger import lib.StubGen.Converter as StubConverter @@ -145,13 +147,15 @@ def TranslateFileGetTrans(mb: memhub.MemBuddy | t.CPtr, file_path: str, gen.__before_init__() gen.__init__(mb) GenGenerator.set_global_gen(gen) - # P2/P3/P4: 注入 HandlesType/HandlesStruct/HandlesExpr/HandlesExprOps/HandlesExprCall - # 模块级单例(委托函数经本地 _g_gen 访问,避免函数体 import 包模块与类/模块名歧义) + # P2-P5: 注入各 Handles 模块级单例(委托函数经本地 _g_gen 访问, + # 避免函数体 import 包模块与类/模块名歧义) HandlesType.set_global_gen(gen) HandlesStruct.set_global_gen(gen) HandlesExpr.set_global_gen(gen) HandlesExprOps.set_global_gen(gen) HandlesExprCall.set_global_gen(gen) + HandlesFunctions.set_global_gen(gen) + HandlesClassDef.set_global_gen(gen) # 设置当前文件名(供报错使用) HandlesType.set_current_file(file_path) # 同步到 HandlesImports(import 时 SHA1 检查报错需要当前文件名,循环依赖无法直接读 HandlesType) diff --git a/App/lib/core/Gen/CallGenMixin.vp b/App/lib/core/Gen/CallGenMixin.vp index 12a1031..b1cc92d 100644 --- a/App/lib/core/Gen/CallGenMixin.vp +++ b/App/lib/core/Gen/CallGenMixin.vp @@ -2483,24 +2483,24 @@ class CallGenMixin: if mdf_defaults is not None and mdf_default_count > 0 and mdf_pi >= mdf_offset: mdf_di: int = mdf_pi - mdf_offset if mdf_di < mdf_default_count: - # 优先用 stdlib 常量快照重建(mdf_gd.Defaults 的 pool 内 AST 可能已被 reset 回收) + # 用 stdlib 常量快照重建(mdf_gd.Defaults 的 pool 内 AST 可能已被 reset 回收, + # 直接回退读 AST 会 use-after-free——快照失败时 fail-fast 暴露,绝不读悬空 AST) mdf_val: llvmlite.Value | t.CPtr = None if mdf_gd is not None: mdf_val = HandlesExprCall._build_const_from_snapshot( pool, mod, mdf_gd, mdf_di, trans, builder) if mdf_val is None: - mdf_defaults_list: list[ast.AST | t.CPtr] | t.CPtr = (list[ast.AST | t.CPtr] | t.CPtr)(t.CVoid(t.CUInt64T(mdf_defaults), t.CPtr)) - mdf_node: ast.AST | t.CPtr = mdf_defaults_list.get(mdf_di) - if mdf_node is not None: - mdf_val = HandlesExpr.translate_value( - builder, pool, mod, mdf_node, None, 0, trans) - if mdf_val is not None: - llvmlite.value_set_next(mdf_val, None) - llvmlite.value_set_next(tail, mdf_val) - tail = mdf_val - total_count += 1 - mdf_pi += 1 + HandlesType.fatal_error( + cl, + f"跨模块默认参数无法重建(快照缺失,默认值需为简单常量): {lookup_name}", + "TypeError") continue + llvmlite.value_set_next(mdf_val, None) + llvmlite.value_set_next(tail, mdf_val) + tail = mdf_val + total_count += 1 + mdf_pi += 1 + continue # 无默认值时用零值兜底(需要 found_func 获取参数类型) if found_func is not None: param_node_z: llvmlite.Param | t.CPtr = llvmlite.function_get_param_head(found_func) @@ -3608,24 +3608,24 @@ class CallGenMixin: if mdf_defaults is not None and mdf_default_count > 0 and mdf_pi >= mdf_offset: mdf_di: int = mdf_pi - mdf_offset if mdf_di < mdf_default_count: - # 优先用 stdlib 常量快照重建(mdf_gd.Defaults 的 pool 内 AST 可能已被 reset 回收) + # 用 stdlib 常量快照重建(mdf_gd.Defaults 的 pool 内 AST 可能已被 reset 回收, + # 直接回退读 AST 会 use-after-free——快照失败时 fail-fast 暴露,绝不读悬空 AST) mdf_val: llvmlite.Value | t.CPtr = None if mdf_gd is not None: mdf_val = HandlesExprCall._build_const_from_snapshot( pool, mod, mdf_gd, mdf_di, trans, builder) if mdf_val is None: - mdf_defaults_list: list[ast.AST | t.CPtr] | t.CPtr = (list[ast.AST | t.CPtr] | t.CPtr)(t.CVoid(t.CUInt64T(mdf_defaults), t.CPtr)) - mdf_node: ast.AST | t.CPtr = mdf_defaults_list.get(mdf_di) - if mdf_node is not None: - mdf_val = HandlesExpr.translate_value( - builder, pool, mod, mdf_node, None, 0, trans) - if mdf_val is not None: - llvmlite.value_set_next(mdf_val, None) - llvmlite.value_set_next(tail, mdf_val) - tail = mdf_val - total_count += 1 - mdf_pi += 1 + HandlesType.fatal_error( + cl, + f"跨模块默认参数无法重建(快照缺失,默认值需为简单常量): {lookup_name}", + "TypeError") continue + llvmlite.value_set_next(mdf_val, None) + llvmlite.value_set_next(tail, mdf_val) + tail = mdf_val + total_count += 1 + mdf_pi += 1 + continue # 无默认值时用零值兜底(需要 found_func 获取参数类型) if found_func is not None: param_node_z: llvmlite.Param | t.CPtr = llvmlite.function_get_param_head(found_func) diff --git a/App/lib/core/Gen/ClassGenMixin.vp b/App/lib/core/Gen/ClassGenMixin.vp new file mode 100644 index 0000000..87bc87a --- /dev/null +++ b/App/lib/core/Gen/ClassGenMixin.vp @@ -0,0 +1,3716 @@ +import t, c +from stdint import * +import ast +import llvmlite +import memhub +import string +import stdio +import stdlib +import viperlib +import lib.core.VLogger as VLogger +import lib.core.Handles.HandlesTranslator as HT +import lib.core.Handles.HandlesType as HandlesType +import lib.core.Handles.HandlesStruct as HandlesStruct +import lib.core.Handles.HandlesVar as HandlesVar +import lib.core.Handles.HandlesEnum as HandlesEnum +import lib.core.StubMerger as StubMerger + + +# ============================================================ +# ClassGenMixin - 类定义/泛型特化/vtable 生成 Mixin(对象化 P5-2) +# +# 从 HandlesClassDef.vp 迁移:模块级纯函数(trans 首参)→ 类方法; +# 全局状态(_g_method_meta_*/_renum_*/_spec_*/_g_vt_*)→ 本类字段。 +# +# 迁移原则(与 P2-P5-1 一致,行为零变化): +# 1. 方法保留原函数签名(含 trans/pool 首参),仅函数体内的 +# 本模块函数调用改为 self.xxx(...) +# 2. 外部模块调用(HandlesType.xxx/HandlesStruct.xxx 等)保留模块前缀 +# 3. HandlesClassDef.vp 原函数保留为"委托":本地模块级单例 _g_gen +# (BuildPipeline/main 注入)cast 成 Generator 类型 +# 4. 多继承/vtable/泛型特化等 M5 成果逻辑零改动 +# +# @t.NoVTable:静态绑定(方法沿 MRO 直接调用 + this 调整)。 +# ============================================================ + + +# ============================================================ +# 常量(与 HandlesClassDef 保持一致) +# ============================================================ +ENUM_MEMBER_MAX_LOCAL: t.CDefine = 128 +RENUM_CLASS_MAX: t.CDefine = 64 +SCOPE_FUNCTION: t.CDefine = 1 +RENUM_VARIANT_PER_CLASS: t.CDefine = 32 +RENUM_FIELD_PER_VARIANT: t.CDefine = 16 + +# 方法元数据位掩码(与 HandlesClassDef.META_* 一致) +META_STATIC: t.CDefine = 1 +META_CLASS: t.CDefine = 2 +META_PROP_GETTER: t.CDefine = 4 +META_PROP_SETTER: t.CDefine = 8 +META_PROP_DELETER: t.CDefine = 16 + +META_MAX: t.CDefine = 512 +META_KEY_LEN: t.CDefine = 128 + +# 泛型特化缓存容量上限(与 HandlesClassDef.SPEC_CACHE_MAX 一致) +SPEC_CACHE_MAX: t.CDefine = 512 + +# vtable 方法最大数量(与 HandlesClassDef.VTBL_METHOD_MAX 一致) +VTBL_METHOD_MAX: t.CDefine = 32 + + +# ============================================================ +# ClassGenMixin - 类定义/继承/泛型/vtable/enum/union/renum +# ============================================================ +@t.NoVTable +class ClassGenMixin: + """类定义处理 Mixin(状态从 HandlesClassDef 全局变量迁入)""" + + # --- 方法元数据表(原 _g_method_meta_keys/_g_method_meta_flags/_g_method_meta_count) --- + MethodMetaKeys: bytes + MethodMetaFlags: bytes + MethodMetaCount: int + + # --- REnum 变体表(原 _renum_class_names/_renum_class_variant_counts/ + # _renum_variant_names/_renum_variant_tags/_renum_class_count) --- + RenumClassNames: t.CSizeT | t.CPtr + RenumClassVariantCounts: t.CSizeT | t.CPtr + RenumVariantNames: t.CSizeT | t.CPtr + RenumVariantTags: t.CSizeT | t.CPtr + RenumClassCount: int + + # --- REnum 字段别名表(原 _renum_alias_class/_renum_alias_field/ + # _renum_alias_index/_renum_alias_count) --- + RenumAliasClass: t.CSizeT | t.CPtr + RenumAliasField: t.CSizeT | t.CPtr + RenumAliasIndex: t.CSizeT | t.CPtr + RenumAliasCount: int + + # --- 泛型特化缓存(原 _spec_keys/_spec_names/_spec_count) --- + SpecKeys: t.CSizeT | t.CPtr + SpecNames: t.CSizeT | t.CPtr + SpecCount: int + + # --- 泛型模板表(原 HandlesClassDef._generic_class_names/ + # _generic_class_nodes/_generic_class_sha1s) --- + GenericClassNames: list[str] | t.CPtr + GenericClassNodes: list[ast.ClassDef | t.CPtr] | t.CPtr + GenericClassSha1s: list[str] | t.CPtr + + # --- vtable 方法收集表(原 _g_vt_full_names/_g_vt_method_names/ + # _g_vt_parent_sha1s/_g_vt_method_count) --- + VtFullNames: t.CSizeT | t.CPtr + VtMethodNames: t.CSizeT | t.CPtr + VtParentSha1s: t.CSizeT | t.CPtr + VtMethodCount: int + + # ============================================================ + # 以下方法由 P5-2 分簇迁移填充(函数体来自 HandlesClassDef.vp, + # 本模块函数调用改 self.,外部模块调用保留模块前缀) + # ============================================================ + + def _is_cenum_base(self, base_node: ast.AST | t.CPtr) -> int: + """检查 base 节点是否为 t.CEnum,返回 1=是 / 0=否""" + if base_node is None: + return 0 + k: int = base_node.kind() + # Name('CEnum') 形式(from t import CEnum) + if k == ast.ASTKind.Name: + nm: ast.Name | t.CPtr = (ast.Name | t.CPtr)(base_node) + if nm.id is not None and string.strcmp(nm.id, "CEnum") == 0: + return 1 + return 0 + # Attribute(t.CEnum) 形式 + if k == ast.ASTKind.Attribute: + at: ast.Attribute | t.CPtr = (ast.Attribute | t.CPtr)(base_node) + if at.attr is not None and string.strcmp(at.attr, "CEnum") == 0: + return 1 + return 0 + return 0 + + def _is_enum_class(self, cd: ast.ClassDef | t.CPtr) -> int: + """检查 ClassDef 是否继承自 t.CEnum,返回 1=是 / 0=否""" + if cd is None or cd.bases is None: + return 0 + bases: list[ast.AST | t.CPtr] | t.CPtr = cd.bases + bn: t.CSizeT = bases.__len__() + if bn == 0: + return 0 + for bi in range(bn): + base_node: ast.AST | t.CPtr = bases.get(bi) + if base_node is None: + continue + if self._is_cenum_base(base_node) == 1: + return 1 + return 0 + + def _is_cunion_base(self, base_node: ast.AST | t.CPtr) -> int: + """检查 base 节点是否为 t.CUnion,返回 1=是 / 0=否""" + if base_node is None: + return 0 + k: int = base_node.kind() + # Name('CUnion') 形式(from t import CUnion) + if k == ast.ASTKind.Name: + nm: ast.Name | t.CPtr = (ast.Name | t.CPtr)(base_node) + if nm.id is not None and string.strcmp(nm.id, "CUnion") == 0: + return 1 + return 0 + # Attribute(t.CUnion) 形式 + if k == ast.ASTKind.Attribute: + at: ast.Attribute | t.CPtr = (ast.Attribute | t.CPtr)(base_node) + if at.attr is not None and string.strcmp(at.attr, "CUnion") == 0: + return 1 + return 0 + return 0 + + def _is_union_class(self, cd: ast.ClassDef | t.CPtr) -> int: + """检查 ClassDef 是否继承自 t.CUnion,返回 1=是 / 0=否""" + if cd is None or cd.bases is None: + return 0 + bases: list[ast.AST | t.CPtr] | t.CPtr = cd.bases + bn: t.CSizeT = bases.__len__() + if bn == 0: + return 0 + for bi in range(bn): + base_node: ast.AST | t.CPtr = bases.get(bi) + if base_node is None: + continue + if self._is_cunion_base(base_node) == 1: + return 1 + return 0 + + def _is_crenum_base(self, base_node: ast.AST | t.CPtr) -> int: + """检查 base 节点是否为 t.REnum,返回 1=是 / 0=否""" + if base_node is None: + return 0 + k: int = base_node.kind() + # Name('REnum') 形式(from t import REnum) + if k == ast.ASTKind.Name: + nm: ast.Name | t.CPtr = (ast.Name | t.CPtr)(base_node) + if nm.id is not None and string.strcmp(nm.id, "REnum") == 0: + return 1 + return 0 + # Attribute(t.REnum) 形式 + if k == ast.ASTKind.Attribute: + at: ast.Attribute | t.CPtr = (ast.Attribute | t.CPtr)(base_node) + if at.attr is not None and string.strcmp(at.attr, "REnum") == 0: + return 1 + return 0 + return 0 + + def _is_renum_class(self, cd: ast.ClassDef | t.CPtr) -> int: + """检查 ClassDef 是否继承自 t.REnum,返回 1=是 / 0=否""" + if cd is None or cd.bases is None: + return 0 + bases: list[ast.AST | t.CPtr] | t.CPtr = cd.bases + bn: t.CSizeT = bases.__len__() + if bn == 0: + return 0 + for bi in range(bn): + base_node: ast.AST | t.CPtr = bases.get(bi) + if base_node is None: + continue + if self._is_crenum_base(base_node) == 1: + return 1 + return 0 + + def _has_decorator(self, decorator_list: list[ast.AST | t.CPtr] | t.CPtr, + deco_name: str) -> int: + """检查 decorator_list 中是否有指定装饰器名""" + if decorator_list is None: + return 0 + dn: t.CSizeT = decorator_list.__len__() + if dn == 0: + return 0 + for di in range(dn): + deco: ast.AST | t.CPtr = decorator_list.get(di) + if deco is None: + continue + k: int = deco.kind() + # @t.NoVTable 形式(Attribute) + if k == ast.ASTKind.Attribute: + at: ast.Attribute | t.CPtr = (ast.Attribute | t.CPtr)(deco) + if at.attr is not None and string.strcmp(at.attr, deco_name) == 0: + # 检查 value 是 Name('t') + if at.value is not None and at.value.kind() == ast.ASTKind.Name: + vn: ast.Name | t.CPtr = (ast.Name | t.CPtr)(at.value) + if vn.id is not None and string.strcmp(vn.id, "t") == 0: + return 1 + return 0 + # @NoVTable 形式(Name,from t import NoVTable) + if k == ast.ASTKind.Name: + nm: ast.Name | t.CPtr = (ast.Name | t.CPtr)(deco) + if nm.id is not None and string.strcmp(nm.id, deco_name) == 0: + return 1 + return 0 + + def _extract_func_meta(self, decorator_list: list[ast.AST | t.CPtr] | t.CPtr) -> int: + """从装饰器列表提取元数据位掩码,返回 0=无装饰器元数据""" + meta: int = 0 + if decorator_list is None: + return meta + dn: t.CSizeT = decorator_list.__len__() + if dn == 0: + return meta + for di in range(dn): + deco: ast.AST | t.CPtr = decorator_list.get(di) + if deco is None: + continue + k: int = deco.kind() + if k == ast.ASTKind.Name: + nm: ast.Name | t.CPtr = (ast.Name | t.CPtr)(deco) + if nm.id is not None: + if string.strcmp(nm.id, "staticmethod") == 0: + meta |= META_STATIC + elif string.strcmp(nm.id, "property") == 0: + meta |= META_PROP_GETTER + elif string.strcmp(nm.id, "classmethod") == 0: + meta |= META_CLASS + elif k == ast.ASTKind.Attribute: + at: ast.Attribute | t.CPtr = (ast.Attribute | t.CPtr)(deco) + if at.attr is not None and at.value is not None: + if at.value.kind() == ast.ASTKind.Name: + vn: ast.Name | t.CPtr = (ast.Name | t.CPtr)(at.value) + is_prop_name: int = 0 + if vn.id is not None and string.strcmp(vn.id, "property") == 0: + is_prop_name = 1 + # @property.setter 或 @x.setter/getter/deleter 都识别 + if is_prop_name != 0 or string.strcmp(at.attr, "setter") == 0 \ + or string.strcmp(at.attr, "getter") == 0 or string.strcmp(at.attr, "deleter") == 0: + if string.strcmp(at.attr, "setter") == 0: + meta |= META_PROP_SETTER + elif string.strcmp(at.attr, "getter") == 0: + meta |= META_PROP_GETTER + elif string.strcmp(at.attr, "deleter") == 0: + meta |= META_PROP_DELETER + return meta + + def register_method_meta(self, class_name: str, method_name: str, + meta: int) -> None: + """注册方法元数据(幂等)""" + if class_name is None or method_name is None or meta == 0: + return + # 懒初始化 + if self.MethodMetaKeys is None: + self.MethodMetaKeys = stdlib.malloc(META_MAX * META_KEY_LEN) + self.MethodMetaFlags = stdlib.malloc(META_MAX * 4) + if self.MethodMetaKeys is None or self.MethodMetaFlags is None: + return + string.memset(self.MethodMetaKeys, 0, META_MAX * META_KEY_LEN) + string.memset(self.MethodMetaFlags, 0, META_MAX * 4) + # 构造 key "ClassName.method" + cl_len: t.CSizeT = string.strlen(class_name) + mn_len: t.CSizeT = string.strlen(method_name) + key_buf: bytes = stdlib.malloc(cl_len + mn_len + 2) + if key_buf is None: + return + viperlib.snprintf(key_buf, cl_len + mn_len + 2, "%s.%s", class_name, method_name) + # 去重更新 + i: int + for i in range(self.MethodMetaCount): + if string.strcmp(self.MethodMetaKeys + i * META_KEY_LEN, key_buf) == 0: + flags_ptr: t.CPtr = (t.CInt | t.CPtr)(t.CVoid( + t.CUInt64T(self.MethodMetaFlags) + i * 4, t.CPtr)) + flags_ptr[0] = meta + stdlib.free(key_buf) + return + if self.MethodMetaCount < META_MAX: + string.strcpy(self.MethodMetaKeys + self.MethodMetaCount * META_KEY_LEN, key_buf) + flags_ptr2: t.CPtr = (t.CInt | t.CPtr)(t.CVoid( + t.CUInt64T(self.MethodMetaFlags) + self.MethodMetaCount * 4, t.CPtr)) + flags_ptr2[0] = meta + self.MethodMetaCount += 1 + stdlib.free(key_buf) + + def lookup_method_meta(self, class_name: str, method_name: str) -> int: + """查找方法元数据位掩码,返回 0=未注册或非装饰器方法""" + if class_name is None or method_name is None: + return 0 + if self.MethodMetaKeys is None or self.MethodMetaCount <= 0: + return 0 + cl_len: t.CSizeT = string.strlen(class_name) + mn_len: t.CSizeT = string.strlen(method_name) + key_buf: bytes = stdlib.malloc(cl_len + mn_len + 2) + if key_buf is None: + return 0 + viperlib.snprintf(key_buf, cl_len + mn_len + 2, "%s.%s", class_name, method_name) + found: int = 0 + i: int + for i in range(self.MethodMetaCount): + if string.strcmp(self.MethodMetaKeys + i * META_KEY_LEN, key_buf) == 0: + flags_ptr: t.CPtr = (t.CInt | t.CPtr)(t.CVoid( + t.CUInt64T(self.MethodMetaFlags) + i * 4, t.CPtr)) + found = flags_ptr[0] + break + stdlib.free(key_buf) + return found + + def _is_marker_base(self, base_name: str) -> int: + """检查基类名是否为标记基类,返回 1=是 / 0=否 + + 含 t.Struct:t.py 未定义 Struct 类(不被编译),`class X(t.Struct)` + 的 Struct 只是"普通结构体"标记。若不当成标记基类,会被误判为真实父类: + - 自动启用虚表 → 结构体多出 i8* 槽位(与 TPC 的 {i32,i32} 布局不符) + - Phase A-pre(declare_only=1)父类延迟检查找不到 "Struct" → 类被延迟注册 + → forward_declare 时类型未注册 → 裸类形参退化为 i32 → 函数签名与 + 函数体 alloca(Ptr(struct))不一致 → llc 报 "'%p' defined with type + 'i32' but expected 'ptr'"。 + 与 TPC(_resolve_base_kind 对 t.Struct 返回 None → 无父类)保持一致。 + """ + if base_name is None: + return 0 + if string.strcmp(base_name, "Object") == 0: + return 1 + if string.strcmp(base_name, "CVTable") == 0: + return 1 + if string.strcmp(base_name, "Exception") == 0: + return 1 + if string.strcmp(base_name, "CEnum") == 0: + return 1 + if string.strcmp(base_name, "Enum") == 0: + return 1 + if string.strcmp(base_name, "CStruct") == 0: + return 1 + if string.strcmp(base_name, "Struct") == 0: + return 1 + if string.strcmp(base_name, "CUnion") == 0: + return 1 + if string.strcmp(base_name, "REnum") == 0: + return 1 + return 0 + + def _get_base_name(self, base_node: ast.AST | t.CPtr, + pool: memhub.MemBuddy | t.CPtr = None) -> str: + """从 base AST 节点提取基类名,返回 None=失败 + + 对于 Subscript 节点,需要 pool 分配内存拼接特化名; + pool=None 时降级返回基类名(不含类型实参) + """ + if base_node is None: + return None + k: int = base_node.kind() + # Name(id) 形式 + if k == ast.ASTKind.Name: + nm: ast.Name | t.CPtr = (ast.Name | t.CPtr)(base_node) + return nm.id + # Attribute(attr) 形式 + if k == ast.ASTKind.Attribute: + at: ast.Attribute | t.CPtr = (ast.Attribute | t.CPtr)(base_node) + return at.attr + # Subscript(value, slice) 形式 — 如 GSListNode[Value] + if k == ast.ASTKind.Subscript: + sub: ast.Subscript | t.CPtr = (ast.Subscript | t.CPtr)(base_node) + if sub is None or sub.value is None or sub.slice is None: + return None + # 提取基类名(如 "GSListNode") + base_nm: str = self._get_base_name(sub.value, pool) + if base_nm is None: + return None + # 提取类型实参名(如 "Value") + slice_k: int = sub.slice.kind() + arg_nm: str = None + if slice_k == ast.ASTKind.Name: + sl_nm: ast.Name | t.CPtr = (ast.Name | t.CPtr)(sub.slice) + arg_nm = sl_nm.id + # 如果无法提取类型实参,返回基类名(降级) + if arg_nm is None: + return base_nm + # 无 pool 时返回基类名(降级,无法拼接特化名) + if pool is None: + return base_nm + # 拼接特化名 "GSListNode[Value]" + base_len: t.CSizeT = string.strlen(base_nm) + arg_len: t.CSizeT = string.strlen(arg_nm) + total_len: t.CSizeT = base_len + arg_len + 3 # "[" + arg + "]" + NUL + mangled: str = pool.alloc(total_len) + if mangled is None: + return base_nm # 降级 + mangled[0] = '\0' + string.strcat(mangled, base_nm) + string.strcat(mangled, "[") + string.strcat(mangled, arg_nm) + string.strcat(mangled, "]") + return mangled + return None + + def _get_parent_class(self, cd: ast.ClassDef | t.CPtr, + trans: HT.Translator | t.CPtr = None) -> str: + """获取 ClassDef 的真实父类名,返回 None=无真实父类""" + if cd is None or cd.bases is None: + return None + pool: memhub.MemBuddy | t.CPtr = None + if trans is not None: + pool = trans.Pool + bases: list[ast.AST | t.CPtr] | t.CPtr = cd.bases + bn: t.CSizeT = bases.__len__() + if bn == 0: + return None + for bi in range(bn): + base_node: ast.AST | t.CPtr = bases.get(bi) + if base_node is None: + continue + bname: str = self._get_base_name(base_node, pool) + if bname is not None and self._is_marker_base(bname) == 0: + return bname + return None + + def _collect_parents(self, pool: memhub.MemBuddy | t.CPtr, + cd: ast.ClassDef | t.CPtr, + parents_buf: t.CSizeT | t.CPtr, + max_parents: int) -> int: + """收集所有非 marker 父类名到 parents_buf,返回数量""" + if pool is None or cd is None or cd.bases is None or parents_buf is None: + return 0 + bases: list[ast.AST | t.CPtr] | t.CPtr = cd.bases + bn: t.CSizeT = bases.__len__() + count: int = 0 + for bi in range(bn): + if count >= max_parents: + break + base_node: ast.AST | t.CPtr = bases.get(bi) + if base_node is None: + continue + bname: str = self._get_base_name(base_node, pool) + if bname is not None and self._is_marker_base(bname) == 0: + parents_buf[count] = t.CSizeT(bname) + count += 1 + return count + + def _field_name_exists(self, names_buf: t.CSizeT | t.CPtr, + count: int, name: str) -> int: + """检查字段名是否已在 names_buf 中(先声明父类优先,重复跳过)""" + if names_buf is None or name is None: + return 0 + for fi in range(count): + addr: t.CSizeT = names_buf[fi] + if addr != 0: + existing: str = (str | t.CPtr)(t.CVoid(addr, t.CPtr)) + if existing is not None and string.strcmp(existing, name) == 0: + return 1 + return 0 + + def _class_body_has_field(self, cd: ast.ClassDef | t.CPtr) -> int: + """检查类体是否声明了字段(AnnAssign),0=纯方法/无字段类""" + if cd is None or cd.children is None: + return 0 + cn: t.CSizeT = cd.children.__len__() + for ci in range(cn): + stmt: ast.AST | t.CPtr = cd.children.get(ci) + if stmt is None: + continue + if stmt.kind() == ast.ASTKind.AnnAssign: + return 1 + return 0 + + def _trigger_base_specialization(self, trans: HT.Translator | t.CPtr, + cd: ast.ClassDef | t.CPtr): + """触发 base 中 Subscript 的泛型特化(如 GSListNode[Value])""" + if trans is None or cd is None or cd.bases is None: + return + pool: memhub.MemBuddy | t.CPtr = trans.Pool + bases: list[ast.AST | t.CPtr] | t.CPtr = cd.bases + bn: t.CSizeT = bases.__len__() + if bn == 0: + return + for bi in range(bn): + base_node: ast.AST | t.CPtr = bases.get(bi) + if base_node is None: + continue + bk: int = base_node.kind() + if bk != ast.ASTKind.Subscript: + continue + sub: ast.Subscript | t.CPtr = (ast.Subscript | t.CPtr)(base_node) + if sub is None or sub.value is None or sub.slice is None: + continue + # 提取泛型类名(如 "GSListNode") + gen_class_name: str = self._get_base_name(sub.value, pool) + if gen_class_name is None: + continue + # 跳过标记基类 + if self._is_marker_base(gen_class_name) == 1: + continue + # 提取类型实参名(如 "Value") + slice_k: int = sub.slice.kind() + arg_nm: str = None + if slice_k == ast.ASTKind.Name: + sl_nm: ast.Name | t.CPtr = (ast.Name | t.CPtr)(sub.slice) + arg_nm = sl_nm.id + if arg_nm is None: + continue + # 构建 type_args 列表(elem_size=8:str 是指针,1 会导致双元素重叠损坏) + type_args: list[str] | t.CPtr = list[str](pool, 8) + if type_args is None: + continue + type_args.append(arg_nm) + # 触发特化(_specialize_generic_class 有缓存,重复调用安全) + self._specialize_generic_class(trans, gen_class_name, type_args) + + def _has_any_func_cvtable(self, cd: ast.ClassDef | t.CPtr) -> int: + """检查类中是否有任何函数标记了 @t.CVTable,返回 1=有 / 0=无""" + if cd is None or cd.children is None: + return 0 + children: list[ast.AST | t.CPtr] | t.CPtr = cd.children + cn: t.CSizeT = children.__len__() + for ci in range(cn): + stmt: ast.AST | t.CPtr = children.get(ci) + if stmt is None: + continue + if stmt.kind() != ast.ASTKind.FunctionDef: + continue + fd: ast.FunctionDef | t.CPtr = (ast.FunctionDef | t.CPtr)(stmt) + if fd is None or fd.name is None: + continue + # 跳过构造函数 + if string.strcmp(fd.name, "__init__") == 0: + continue + if string.strcmp(fd.name, "__before_init__") == 0: + continue + if string.strcmp(fd.name, "__new__") == 0: + continue + if fd.decorator_list is not None: + if self._has_decorator(fd.decorator_list, "CVTable") == 1: + return 1 + return 0 + + def _should_method_be_virtual(self, cd: ast.ClassDef | t.CPtr, + fd: ast.FunctionDef | t.CPtr, + trans: HT.Translator | t.CPtr = None) -> int: + """判断方法是否应该进入虚表,返回 1=包含 / 0=排除""" + if fd is None: + return 0 + # 1. 检查函数级 @t.NoVTable(最高优先级,排除) + if fd.decorator_list is not None: + if self._has_decorator(fd.decorator_list, "NoVTable") == 1: + return 0 + # 2. 检查函数级 @t.CVTable(明确包含) + if self._has_decorator(fd.decorator_list, "CVTable") == 1: + return 1 + + # 3. 检查类级别 @t.CVTable + if cd is not None and cd.decorator_list is not None: + if self._has_decorator(cd.decorator_list, "CVTable") == 1: + return 1 + + # 4. 检查继承关系 + parent_name: str = self._get_parent_class(cd, trans) + if parent_name is not None: + # 用 SHA1 感知查找父类,规避跨模块同名找错 + is_nvt: int = 0 + if trans is not None: + p_entry: HandlesStruct.StructEntry | t.CPtr = HandlesStruct.find_struct_by_module( + parent_name, trans.ModuleSha1) + if p_entry is None: + # 跨模块父类回退全局查找(父类注册在父模块 SHA1 下,如 linkedlist.LinkedNode), + # 与字段展平(1.5 节)的回退保持一致,否则父类 NoVTable 被误判为有虚表 → 子类插 vptr + # 导致子类布局比父类多一个指针,父类方法按无 vptr 布局操作错位 + p_entry = HandlesStruct.find_struct(parent_name) + if p_entry is not None: + is_nvt = p_entry.IsNoVTable + else: + is_nvt = HandlesStruct.is_novtable_by_name(parent_name) + if is_nvt != 1: + # 继承链统一虚表:父类有虚表 → 方法进虚表;父类无虚表 → 静态方法。 + # 与 _detect_vtable_status 规则一致,避免父类无 vptr 布局/子类有 vptr 的错位。 + if p_entry is None: + return 1 # 父类信息未知,保守进虚表 + if p_entry.HasVTable == 1: + return 1 + return 0 + + # 5. 默认排除 + return 0 + + def _detect_vtable_status(self, cd: ast.ClassDef | t.CPtr, + trans: HT.Translator | t.CPtr = None) -> int: + """检测类是否应该启用虚表""" + if cd is None: + return 0 + + # 检查类装饰器 + if cd.decorator_list is not None: + # @t.CVTable 优先级最高,直接启用 + if self._has_decorator(cd.decorator_list, "CVTable") == 1: + return 1 + # @t.NoVTable:类级别禁用,但检查函数级 @t.CVTable + if self._has_decorator(cd.decorator_list, "NoVTable") == 1: + return self._has_any_func_cvtable(cd) + + # 检查是否有真实父类(继承自动启用 CVTable) + parent_name: str = self._get_parent_class(cd, trans) + if parent_name is not None: + # 用 SHA1 感知查找父类,规避跨模块同名找错 + is_nvt: int = 0 + if trans is not None: + p_entry: HandlesStruct.StructEntry | t.CPtr = HandlesStruct.find_struct_by_module( + parent_name, trans.ModuleSha1) + if p_entry is None: + # 跨模块父类回退全局查找(同 _detect_vtable_status 的回退) + p_entry = HandlesStruct.find_struct(parent_name) + if p_entry is not None: + is_nvt = p_entry.IsNoVTable + else: + is_nvt = HandlesStruct.is_novtable_by_name(parent_name) + if is_nvt == 1: + # 父类是 NoVTable,检查函数级 @t.CVTable + return self._has_any_func_cvtable(cd) + # 继承链统一虚表:父类有虚表 → 子类启用;父类无虚表 → 子类静态。 + # 若父类无 vtable 而子类有,父类方法按无 vptr 布局(self.field@0)操作 + # 子类实例(有 vptr@0)会字段错位 → 运行时错误(父类方法读 vptr 当字段)。 + if p_entry is None: + return 1 # 父类信息未知(跨模块/未注册),保守启用虚表 + if p_entry.HasVTable == 1: + return 1 + return 0 + + # 默认(无装饰器无继承),检查函数级 @t.CVTable + return self._has_any_func_cvtable(cd) + + def _resolve_enum_member_type(self, pool: memhub.MemBuddy | t.CPtr, + ann_node: ast.AST | t.CPtr, + imported_modules: str, + from_imports: str) -> llvmlite.LLVMType | t.CPtr: + """解析枚举成员的类型注解为 LLVM 整数类型""" + if ann_node is None: + return llvmlite.Int32(pool) + + k: int = ann_node.kind() + + # Attribute 节点: t.State / int / t.CInt8T 等 + if k == ast.ASTKind.Attribute: + at: ast.Attribute | t.CPtr = (ast.Attribute | t.CPtr)(ann_node) + if at.attr is None: + return llvmlite.Int32(pool) + # t.State → 默认 i32 + if string.strcmp(at.attr, "State") == 0: + return llvmlite.Int32(pool) + # 其他 t.CXxx 类型 + ty: llvmlite.LLVMType | t.CPtr = HandlesType.map_t_type(pool, at.attr) + if ty is not None: + return ty + return llvmlite.Int32(pool) + + # Name 节点: from-import 形式(State / CInt) + if k == ast.ASTKind.Name: + nm: ast.Name | t.CPtr = (ast.Name | t.CPtr)(ann_node) + if nm.id is None: + return llvmlite.Int32(pool) + if string.strcmp(nm.id, "State") == 0: + return llvmlite.Int32(pool) + ty2: llvmlite.LLVMType | t.CPtr = HandlesType.map_t_type(pool, nm.id) + if ty2 is not None: + return ty2 + return llvmlite.Int32(pool) + + # BinOp 节点: t.State | t.CInt8T(递归查找实际类型) + if k == ast.ASTKind.BinOp: + bop: ast.BinOp | t.CPtr = (ast.BinOp | t.CPtr)(ann_node) + if bop.op == ast.OpKind.BitOr: + left_ty: llvmlite.LLVMType | t.CPtr = self._resolve_enum_member_type( + pool, bop.left, imported_modules, from_imports) + # 跳过 t.State(i32 默认),优先返回具体类型 + left_bits: int = HandlesType.get_llvm_type_bits(left_ty) + if left_bits != 0 and not self._is_state_annotation(bop.left): + return left_ty + right_ty: llvmlite.LLVMType | t.CPtr = self._resolve_enum_member_type( + pool, bop.right, imported_modules, from_imports) + if right_ty is not None and not self._is_state_annotation(bop.right): + return right_ty + # 两边都是 State 或无法确定,返回较宽的 + right_bits: int = HandlesType.get_llvm_type_bits(right_ty) + if left_bits >= right_bits: + return left_ty + return right_ty + return llvmlite.Int32(pool) + + return llvmlite.Int32(pool) + + def _is_state_annotation(self, node: ast.AST | t.CPtr) -> int: + """检查注解节点是否为 t.State,返回 1=是 / 0=否""" + if node is None: + return 0 + k: int = node.kind() + if k == ast.ASTKind.Attribute: + at: ast.Attribute | t.CPtr = (ast.Attribute | t.CPtr)(node) + if at.attr is not None and string.strcmp(at.attr, "State") == 0: + return 1 + return 0 + if k == ast.ASTKind.Name: + nm: ast.Name | t.CPtr = (ast.Name | t.CPtr)(node) + if nm.id is not None and string.strcmp(nm.id, "State") == 0: + return 1 + return 0 + return 0 + + def _extract_int_value(self, node: ast.AST | t.CPtr) -> t.CInt64T: + """从 AST 节点提取整数值,失败返回 0""" + if node is None: + return 0 + k: int = node.kind() + if k == ast.ASTKind.Constant: + cn: ast.Constant | t.CPtr = (ast.Constant | t.CPtr)(node) + if cn.const_kind == ast.CONST_INT: + return cn.int_val + return 0 + if k == ast.ASTKind.UnaryOp: + uo: ast.UnaryOp | t.CPtr = (ast.UnaryOp | t.CPtr)(node) + if uo.op == ast.OpKind.USub: + inner: t.CInt64T = self._extract_int_value(uo.operand) + return -inner + return 0 + return 0 + + def _translate_enum_def(self, trans: HT.Translator | t.CPtr, + cd: ast.ClassDef | t.CPtr) -> int: + """翻译枚举类定义,返回 0""" + if cd is None or cd.name is None or trans is None: + return 0 + + pool: memhub.MemBuddy | t.CPtr = trans.Pool + class_name: str = cd.name + + # 已注册则跳过 + if HandlesEnum.is_enum_class(class_name) == 1: + return 0 + + children: list[ast.AST | t.CPtr] | t.CPtr = cd.children + if children is None: + fb: t.CChar | t.CPtr = VLogger.fmt_buf() + if fb is not None: + viperlib.snprintf(fb, 1024, "%s has no body", class_name) + VLogger.warning(fb, "ENUM") + return 0 + + cn: t.CSizeT = children.__len__() + + # 临时数组存储成员信息 + member_names_buf: t.CSizeT | t.CPtr = pool.alloc(8 * ENUM_MEMBER_MAX_LOCAL) + member_types_buf: t.CSizeT | t.CPtr = pool.alloc(8 * ENUM_MEMBER_MAX_LOCAL) + member_values_buf: t.CInt64T | t.CPtr = pool.alloc(8 * ENUM_MEMBER_MAX_LOCAL) + if member_names_buf is None or member_types_buf is None or member_values_buf is None: + return 0 + string.memset(member_names_buf, 0, 8 * ENUM_MEMBER_MAX_LOCAL) + string.memset(member_types_buf, 0, 8 * ENUM_MEMBER_MAX_LOCAL) + string.memset(member_values_buf, 0, 8 * ENUM_MEMBER_MAX_LOCAL) + + member_count: int = 0 + next_val: t.CInt64T = 0 + + for ci in range(cn): + stmt: ast.AST | t.CPtr = children.get(ci) + if stmt is None: + continue + sk: int = stmt.kind() + + if sk == ast.ASTKind.AnnAssign: + aa: ast.AnnAssign | t.CPtr = (ast.AnnAssign | t.CPtr)(stmt) + if aa is None or aa.target is None: + continue + + # 获取成员名 + if aa.target.kind() != ast.ASTKind.Name: + continue + tgt: ast.Name | t.CPtr = (ast.Name | t.CPtr)(aa.target) + if tgt.id is None: + continue + + # 解析成员类型 + member_ty: llvmlite.LLVMType | t.CPtr = self._resolve_enum_member_type( + pool, aa.annotation, trans._imported_modules, trans._from_imports) + + # 解析成员值 + has_value: int = 0 + cur_val: t.CInt64T = 0 + if aa.value is not None: + cur_val = self._extract_int_value(aa.value) + has_value = 1 + else: + cur_val = next_val + + # 下一个自动值 + next_val = cur_val + 1 + + # 存储 + if member_count < ENUM_MEMBER_MAX_LOCAL: + member_names_buf[member_count] = t.CSizeT(tgt.id) + member_types_buf[member_count] = t.CSizeT(member_ty) + member_values_buf[member_count] = cur_val + member_count += 1 + + elif sk == ast.ASTKind.Assign: + # 处理 Assign 形式的枚举成员: DEBUG = 0, INFO = 1 等 + # CEnum 子类中无类型注释的赋值也视为枚举成员 + ag: ast.Assign | t.CPtr = (ast.Assign | t.CPtr)(stmt) + if ag is None or ag.targets is None: + continue + tgts: list[ast.AST | t.CPtr] | t.CPtr = ag.targets + tn: t.CSizeT = tgts.__len__() + if tn == 0: + continue + # 取第一个 target 作为成员名 + t0: ast.AST | t.CPtr = tgts.get(0) + if t0 is None or t0.kind() != ast.ASTKind.Name: + continue + tgt_a: ast.Name | t.CPtr = (ast.Name | t.CPtr)(t0) + if tgt_a.id is None: + continue + + # Assign 无类型注释,默认使用 i32 + member_ty_a: llvmlite.LLVMType | t.CPtr = llvmlite.Int32(pool) + + # 解析成员值 + cur_val_a: t.CInt64T = 0 + if ag.value is not None: + cur_val_a = self._extract_int_value(ag.value) + else: + cur_val_a = next_val + + # 下一个自动值 + next_val = cur_val_a + 1 + + # 存储 + if member_count < ENUM_MEMBER_MAX_LOCAL: + member_names_buf[member_count] = t.CSizeT(tgt_a.id) + member_types_buf[member_count] = t.CSizeT(member_ty_a) + member_values_buf[member_count] = cur_val_a + member_count += 1 + + if member_count == 0: + fb: t.CChar | t.CPtr = VLogger.fmt_buf() + if fb is not None: + viperlib.snprintf(fb, 1024, "%s has no members", class_name) + VLogger.warning(fb, "ENUM") + return 0 + + # 确定基准类型:所有成员类型中 Bits 最大的 + base_ty: llvmlite.LLVMType | t.CPtr = llvmlite.Int32(pool) + max_bits: int = 0 + for mi in range(member_count): + ty_addr: t.CSizeT = member_types_buf[mi] + if ty_addr == 0: + continue + mty: llvmlite.LLVMType | t.CPtr = (llvmlite.LLVMType | t.CPtr)( + t.CVoid(ty_addr, t.CPtr)) + bits: int = HandlesType.get_llvm_type_bits(mty) + if bits > max_bits: + max_bits = bits + base_ty = mty + + # 注册枚举 + entry: HandlesEnum.EnumEntry | t.CPtr = HandlesEnum.register_enum( + pool, class_name, base_ty) + if entry is None: + fb: t.CChar | t.CPtr = VLogger.fmt_buf() + if fb is not None: + viperlib.snprintf(fb, 1024, "failed to register %s", class_name) + VLogger.error(fb, "ENUM") + return 0 + + # 添加成员 + for mi in range(member_count): + fname_addr: t.CSizeT = member_names_buf[mi] + if fname_addr == 0: + continue + mname: str = (str | t.CPtr)(t.CVoid(fname_addr, t.CPtr)) + fty_addr2: t.CSizeT = member_types_buf[mi] + if fty_addr2 == 0: + continue + mty2: llvmlite.LLVMType | t.CPtr = (llvmlite.LLVMType | t.CPtr)( + t.CVoid(fty_addr2, t.CPtr)) + mval: t.CInt64T = member_values_buf[mi] + if mname is not None and mty2 is not None: + HandlesEnum.add_enum_member(pool, entry, mname, mval, mty2) + + fb: t.CChar | t.CPtr = VLogger.fmt_buf() + if fb is not None: + viperlib.snprintf(fb, 1024, "registered %s with %d members, base_bits=%d", + class_name, member_count, max_bits) + VLogger.info(fb, "ENUM") + return 0 + + def _get_type_size(self, ty: llvmlite.LLVMType | t.CPtr) -> int: + """计算 LLVM 类型的字节大小(含对齐 padding)""" + if ty is None: + return 0 + match ty: + case llvmlite.LLVMType.Int(bits): + return (bits + 7) // 8 + case llvmlite.LLVMType.Float(bits): + return bits // 8 + case llvmlite.LLVMType.Ptr(pointee): + return 8 + case llvmlite.LLVMType.Array(elem_ty, count): + return self._get_type_size(elem_ty) * count + case llvmlite.LLVMType.Struct(fields, fcount, name): + # 计算结构体大小,考虑字段对齐 padding + # 规则: 每个字段的对齐 = 该字段类型的自然对齐 + # 指针/i64 → 8, i32 → 4, i16 → 2, i8 → 1 + # 结构体总大小需对齐到最大字段对齐的倍数 + total: int = 0 + max_align: int = 1 + cur: llvmlite.ParamNode | t.CPtr = fields + i: int = 0 + while cur is not None and i < fcount: + if cur.Ty is not None: + fty: llvmlite.LLVMType | t.CPtr = (llvmlite.LLVMType | t.CPtr)(cur.Ty) + fsize: int = self._get_type_size(fty) + falign: int = self._get_type_align(fty) + # 对齐当前偏移到字段对齐边界 + if falign > 0: + rem: int = total % falign + if rem != 0: + total += falign - rem + total += fsize + if falign > max_align: + max_align = falign + cur = cur.Next + i += 1 + # 结构体总大小对齐到最大字段对齐的倍数 + rem2: int = total % max_align + if rem2 != 0: + total += max_align - rem2 + return total + case _: + return 8 + + def _get_type_align(self, ty: llvmlite.LLVMType | t.CPtr) -> int: + """返回类型的自然对齐(字节)""" + if ty is None: + return 1 + match ty: + case llvmlite.LLVMType.Int(bits): + if bits <= 8: + return 1 + elif bits <= 16: + return 2 + elif bits <= 32: + return 4 + else: + return 8 + case llvmlite.LLVMType.Float(bits): + if bits <= 32: + return 4 + else: + return 8 + case llvmlite.LLVMType.Ptr(pointee): + return 8 + case llvmlite.LLVMType.Array(elem_ty, count): + return self._get_type_align(elem_ty) + case llvmlite.LLVMType.Struct(fields, fcount, name): + # 结构体的对齐 = 最大字段对齐 + max_align: int = 1 + cur: llvmlite.ParamNode | t.CPtr = fields + i: int = 0 + while cur is not None and i < fcount: + if cur.Ty is not None: + fty: llvmlite.LLVMType | t.CPtr = (llvmlite.LLVMType | t.CPtr)(cur.Ty) + fa: int = self._get_type_align(fty) + if fa > max_align: + max_align = fa + cur = cur.Next + i += 1 + return max_align + case _: + return 8 + + def _translate_union_def(self, trans: HT.Translator | t.CPtr, + cd: ast.ClassDef | t.CPtr) -> int: + """翻译联合体定义,返回 0""" + if cd is None or cd.name is None or trans is None: + return 0 + + pool: memhub.MemBuddy | t.CPtr = trans.Pool + class_name: str = cd.name + + # 命名空间隔离:标记为当前文件可见(必须在 existing 检查之前) + HandlesStruct.add_visible_struct(pool, class_name) + + # 检查是否已注册(用 SHA1 区分跨模块同名类) + existing: HandlesStruct.StructEntry | t.CPtr = HandlesStruct.find_struct_by_module( + class_name, trans.ModuleSha1) + if existing is not None: + # Phase B: 将已存在的命名结构体注册到当前模块 + if existing.Ty is not None: + llvmlite.module_add_named_type(trans.Module, pool, existing.Ty) + # SHA1 已在 register_struct 时设置,无需再补 + return 0 + + children: list[ast.AST | t.CPtr] | t.CPtr = cd.children + if children is None: + fb: t.CChar | t.CPtr = VLogger.fmt_buf() + if fb is not None: + viperlib.snprintf(fb, 1024, "%s has no body", class_name) + VLogger.warning(fb, "UNION") + return 0 + + cn: t.CSizeT = children.__len__() + + # 临时数组存储字段信息 + field_names_buf: t.CSizeT | t.CPtr = pool.alloc(8 * 64) + field_types_buf: t.CSizeT | t.CPtr = pool.alloc(8 * 64) + if field_names_buf is None or field_types_buf is None: + return 0 + string.memset(field_names_buf, 0, 8 * 64) + string.memset(field_types_buf, 0, 8 * 64) + + field_count: int = 0 + max_size: int = 0 + + for ci in range(cn): + stmt: ast.AST | t.CPtr = children.get(ci) + if stmt is None: + continue + sk: int = stmt.kind() + + if sk == ast.ASTKind.AnnAssign: + aa: ast.AnnAssign | t.CPtr = (ast.AnnAssign | t.CPtr)(stmt) + if aa is None or aa.target is None: + continue + + # 获取字段名 + if aa.target.kind() != ast.ASTKind.Name: + continue + tgt: ast.Name | t.CPtr = (ast.Name | t.CPtr)(aa.target) + if tgt.id is None: + continue + + # 解析字段类型 + field_ty: llvmlite.LLVMType | t.CPtr = HandlesType.resolve_annotation_type( + pool, aa.annotation, trans._imported_modules, trans._from_imports, trans) + if field_ty is None: + # Phase A-pre(declare_only=1):依赖的类可能尚未注册, + # 静默 return 1 让多遍收敛机制生效(renum 返回 1=跳过该类) + if trans._declare_only == 1: + return 1 + # Phase B(declare_only=0):真正的类型解析错误,fast-fail 终止 + type_name: str = HandlesType.annotation_to_str(aa.annotation) + HandlesType.fatal_error( + aa, + f"'{type_name}' is not defined", + "NameError") + field_ty = llvmlite.Int32(pool) + + # 计算字段大小,更新 max_size + fsize: int = self._get_type_size(field_ty) + if fsize > max_size: + max_size = fsize + + # 存储到数组 + if field_count < 64: + field_names_buf[field_count] = t.CSizeT(tgt.id) + field_types_buf[field_count] = t.CSizeT(field_ty) + field_count += 1 + + if field_count == 0: + fb: t.CChar | t.CPtr = VLogger.fmt_buf() + if fb is not None: + viperlib.snprintf(fb, 1024, "%s has no fields", class_name) + VLogger.warning(fb, "UNION") + return 0 + + if max_size < 1: + max_size = 1 + + # 创建联合体的 LLVM 类型: Struct([Array(Int8, max_size)]) + # 即 { [max_size x i8] } + i8_ty: llvmlite.LLVMType | t.CPtr = llvmlite.Int8(pool) + array_ty: llvmlite.LLVMType | t.CPtr = llvmlite.Array(pool, i8_ty, max_size) + + # 构建 ParamNode 链表(单字段:字节数组) + pnode: llvmlite.ParamNode | t.CPtr = pool.alloc(llvmlite.ParamNode.__sizeof__()) + if pnode is None: + return 0 + string.memset(pnode, 0, llvmlite.ParamNode.__sizeof__()) + pnode.Ty = array_ty + + # 构造命名结构体类型名: "sha1.ClassName" 或 "ClassName" + union_type_name: str = class_name + if trans.ModuleSha1 is not None: + union_name_buf: t.CChar | t.CPtr = pool.alloc(64) + if union_name_buf is not None: + viperlib.snprintf(union_name_buf, 64, "%s.%s", trans.ModuleSha1, class_name) + union_type_name = union_name_buf + + union_ty: llvmlite.LLVMType | t.CPtr = llvmlite.Struct(pool, pnode, 1, union_type_name) + if union_ty is None: + fb: t.CChar | t.CPtr = VLogger.fmt_buf() + if fb is not None: + viperlib.snprintf(fb, 1024, "failed to create type for %s", class_name) + VLogger.error(fb, "UNION") + return 0 + + # Phase 1b 新注册的 union struct_ty 深拷贝到 stdlib(跨文件 reset 存活) + if trans._declare_only == 0: + union_copy: llvmlite.LLVMType | t.CPtr = llvmlite.DeepCopyType(pool, union_ty) + if union_copy is not None: + union_ty = union_copy + + # 注册命名结构体到模块 + llvmlite.module_add_named_type(trans.Module, pool, union_ty) + + # 注册到 HandlesStruct(传递 SHA1 在注册时直接设置,避免跨模块同名找错 entry) + entry: HandlesStruct.StructEntry | t.CPtr = HandlesStruct.register_struct( + pool, class_name, union_ty, trans.ModuleSha1) + if entry is None: + fb: t.CChar | t.CPtr = VLogger.fmt_buf() + if fb is not None: + viperlib.snprintf(fb, 1024, "failed to register %s", class_name) + VLogger.error(fb, "UNION") + return 0 + + # 标记为当前文件可见(命名空间隔离) + HandlesStruct.add_visible_struct(pool, class_name) + + # 标记为联合体(直接用 entry,规避跨模块同名 find_struct 找错) + entry.IsUnion = 1 + + # 添加字段信息(所有字段 Index=0,因为共享偏移 0) + for fi in range(field_count): + fname_addr: t.CSizeT = field_names_buf[fi] + if fname_addr == 0: + continue + fname: str = (str | t.CPtr)(t.CVoid(fname_addr, t.CPtr)) + fty_addr2: t.CSizeT = field_types_buf[fi] + if fty_addr2 == 0: + continue + fty2: llvmlite.LLVMType | t.CPtr = (llvmlite.LLVMType | t.CPtr)( + t.CVoid(fty_addr2, t.CPtr)) + if fname is not None and fty2 is not None: + HandlesStruct.add_field(pool, entry, fname, fty2, None, None) + + fb: t.CChar | t.CPtr = VLogger.fmt_buf() + if fb is not None: + viperlib.snprintf(fb, 1024, "registered %s with %d fields, max_size=%d", + class_name, field_count, max_size) + VLogger.info(fb, "UNION") + return 0 + + def _get_annotation_field_size(self, annotation: ast.AST | t.CPtr) -> int: + """计算注解类型的字节大小,用于 REnum 布局计算""" + if annotation is None: + return 8 + k: int = annotation.kind() + # 联合类型 A | B → 指针大小 8 + if k == ast.ASTKind.BinOp: + return 8 + # Name(id) 或 Attribute(attr) → 解析类型名 + type_name: str = None + if k == ast.ASTKind.Name: + nm: ast.Name | t.CPtr = (ast.Name | t.CPtr)(annotation) + if nm is not None: + type_name = nm.id + elif k == ast.ASTKind.Attribute: + at: ast.Attribute | t.CPtr = (ast.Attribute | t.CPtr)(annotation) + if at is not None: + type_name = at.attr + if type_name is None: + return 8 + # 内置类型 + if string.strcmp(type_name, "int") == 0: + return 4 + if string.strcmp(type_name, "CInt") == 0: + return 4 + if string.strcmp(type_name, "CInt8T") == 0: + return 1 + if string.strcmp(type_name, "CInt16T") == 0: + return 2 + if string.strcmp(type_name, "CInt32T") == 0: + return 4 + if string.strcmp(type_name, "CInt64T") == 0: + return 8 + if string.strcmp(type_name, "CChar") == 0: + return 1 + if string.strcmp(type_name, "CDouble") == 0: + return 8 + if string.strcmp(type_name, "CFloat") == 0: + return 4 + if string.strcmp(type_name, "CPtr") == 0: + return 8 + if string.strcmp(type_name, "CSizeT") == 0: + return 8 + if string.strcmp(type_name, "str") == 0: + return 8 + if string.strcmp(type_name, "bytes") == 0: + return 8 + if string.strcmp(type_name, "bool") == 0: + # bool = t.CBool = i8(1 字节) + return 1 + # 已注册的结构体类型 + struct_ty: llvmlite.LLVMType | t.CPtr = HandlesStruct.get_struct_type(type_name) + if struct_ty is not None: + sz: int = self._get_type_size(struct_ty) + if sz > 0: + return sz + # 未注册类型 → 默认指针大小 8(可能是自引用或前向引用) + return 8 + + def _translate_renum_def(self, trans: HT.Translator | t.CPtr, + cd: ast.ClassDef | t.CPtr) -> int: + """翻译 REnum 类定义,返回 0""" + if cd is None or cd.name is None or trans is None: + return 0 + + pool: memhub.MemBuddy | t.CPtr = trans.Pool + class_name: str = cd.name + + # 命名空间隔离:标记为当前文件可见 + HandlesStruct.add_visible_struct(pool, class_name) + + # 检查是否已注册(用 SHA1 区分跨模块同名类) + existing: HandlesStruct.StructEntry | t.CPtr = HandlesStruct.find_struct_by_module( + class_name, trans.ModuleSha1) + if existing is not None: + if existing.Ty is not None: + llvmlite.module_add_named_type(trans.Module, pool, existing.Ty) + return 0 + + children: list[ast.AST | t.CPtr] | t.CPtr = cd.children + if children is None: + fb: t.CChar | t.CPtr = VLogger.fmt_buf() + if fb is not None: + viperlib.snprintf(fb, 1024, "%s has no body", class_name) + VLogger.warning(fb, "RENUM") + return 0 + + cn: t.CSizeT = children.__len__() + + # 变体最多 32 个,每个变体最多 16 个字段 + # variant_field_sizes[i][j] = 变体 i 的第 j 个字段大小 + variant_field_sizes: t.CSizeT | t.CPtr = pool.alloc(8 * 64 * 16) + if variant_field_sizes is None: + return 0 + string.memset(variant_field_sizes, 0, 8 * 64 * 16) + + variant_count: int = 0 + max_field_count: int = 0 # 所有变体中最大字段数 + + for ci in range(cn): + stmt: ast.AST | t.CPtr = children.get(ci) + if stmt is None: + continue + sk: int = stmt.kind() + + if sk == ast.ASTKind.ClassDef: + # 嵌套变体类 + variant_cd: ast.ClassDef | t.CPtr = (ast.ClassDef | t.CPtr)(stmt) + if variant_cd is None or variant_cd.children is None: + variant_count += 1 + continue + variant_children: list[ast.AST | t.CPtr] | t.CPtr = variant_cd.children + vcn: t.CSizeT = variant_children.__len__() + field_idx: int = 0 + for vi in range(vcn): + vstmt: ast.AST | t.CPtr = variant_children.get(vi) + if vstmt is None: + continue + vk: int = vstmt.kind() + if vk != ast.ASTKind.AnnAssign: + continue + vaa: ast.AnnAssign | t.CPtr = (ast.AnnAssign | t.CPtr)(vstmt) + if vaa is None or vaa.target is None or vaa.annotation is None: + continue + if vaa.target.kind() != ast.ASTKind.Name: + continue + # 提取字段名 + vnm: ast.Name | t.CPtr = (ast.Name | t.CPtr)(vaa.target) + # 计算字段大小 + fsize: int = self._get_annotation_field_size(vaa.annotation) + if variant_count < 32 and field_idx < 16: + # variant_field_sizes[variant_count][field_idx] = fsize + offset: t.CSizeT = variant_count * 16 + field_idx + variant_field_sizes[offset] = t.CSizeT(fsize) + # 直接注册变体字段名别名(避免 CSizeT→str 转换问题) + if vnm is not None and vnm.id is not None: + self._register_renum_field_alias(pool, class_name, vnm.id, field_idx + 1) + field_idx += 1 + if field_idx > max_field_count: + max_field_count = field_idx + variant_count += 1 + + if variant_count == 0: + fb2: t.CChar | t.CPtr = VLogger.fmt_buf() + if fb2 is not None: + viperlib.snprintf(fb2, 1024, "%s has no variants", class_name) + VLogger.warning(fb2, "RENUM") + return 0 + + # 计算每个位置的最大字段大小 + # 位置 0 = __tag (i32, 4 字节) + # 位置 1+ = 变体字段 + total_positions: int = max_field_count + 1 # +1 for tag + if total_positions < 2: + total_positions = 2 # 至少 {i32, i32} + + position_max_sizes: t.CSizeT | t.CPtr = pool.alloc(8 * total_positions) + if position_max_sizes is None: + return 0 + string.memset(position_max_sizes, 0, 8 * total_positions) + + # 位置 0 = tag = 4 字节 + position_max_sizes[0] = t.CSizeT(4) + + # 位置 1+ = 每个位置取所有变体的最大字段大小 + for pos in range(1, total_positions): + pos_max: int = 0 + for vi in range(variant_count): + field_pos: int = pos - 1 # 变体字段从位置 0 开始 + offset2: t.CSizeT = vi * 16 + field_pos + fsize_val: t.CSizeT = variant_field_sizes[offset2] + if fsize_val > pos_max: + pos_max = fsize_val + position_max_sizes[pos] = t.CSizeT(pos_max) + + # 构建 ParamNode 链表 + i32_ty: llvmlite.LLVMType | t.CPtr = llvmlite.Int32(pool) + i64_ty: llvmlite.LLVMType | t.CPtr = llvmlite.Int64(pool) + + first_node: llvmlite.ParamNode | t.CPtr = None + tail_node: llvmlite.ParamNode | t.CPtr = None + + for pos in range(total_positions): + psize: int = position_max_sizes[pos] + field_ty: llvmlite.LLVMType | t.CPtr = i32_ty + if psize > 4: + field_ty = i64_ty + pnode: llvmlite.ParamNode | t.CPtr = llvmlite.new_param_node(pool, field_ty) + if pnode is None: + continue + tail_node = llvmlite.param_list_append(first_node, tail_node, pnode) + if first_node is None: + first_node = tail_node + + if first_node is None: + fb3: t.CChar | t.CPtr = VLogger.fmt_buf() + if fb3 is not None: + viperlib.snprintf(fb3, 1024, "failed to build field list for %s", class_name) + VLogger.error(fb3, "RENUM") + return 0 + + # 构造命名结构体类型名: "sha1.ClassName" 或 "ClassName" + renum_type_name: str = class_name + if trans.ModuleSha1 is not None: + renum_name_buf: t.CChar | t.CPtr = pool.alloc(64) + if renum_name_buf is not None: + viperlib.snprintf(renum_name_buf, 64, "%s.%s", trans.ModuleSha1, class_name) + renum_type_name = renum_name_buf + + renum_ty: llvmlite.LLVMType | t.CPtr = llvmlite.Struct( + pool, first_node, total_positions, renum_type_name) + if renum_ty is None: + fb4: t.CChar | t.CPtr = VLogger.fmt_buf() + if fb4 is not None: + viperlib.snprintf(fb4, 1024, "failed to create type for %s", class_name) + VLogger.error(fb4, "RENUM") + return 0 + + # Phase 1b 新注册的 REnum struct_ty 深拷贝到 stdlib(跨文件 reset 存活, + # 与 entry.Ty 保持同一指针,find_struct_by_type 匹配不失效) + if trans._declare_only == 0: + renum_copy: llvmlite.LLVMType | t.CPtr = llvmlite.DeepCopyType(pool, renum_ty) + if renum_copy is not None: + renum_ty = renum_copy + + # 注册命名结构体到模块 + llvmlite.module_add_named_type(trans.Module, pool, renum_ty) + + # 注册到 HandlesStruct + entry: HandlesStruct.StructEntry | t.CPtr = HandlesStruct.register_struct( + pool, class_name, renum_ty, trans.ModuleSha1) + if entry is None: + fb5: t.CChar | t.CPtr = VLogger.fmt_buf() + if fb5 is not None: + viperlib.snprintf(fb5, 1024, "failed to register %s", class_name) + VLogger.error(fb5, "RENUM") + return 0 + + # 修复 class_name 指针不匹配: + # 别名注册时用 class_name(= cd.name,AST 原始指针), + # 但查找时用 entry.Name(register_struct 通过 pool.alloc+strcpy 复制的副本指针)。 + # 两者是不同指针,CSizeT 指针值比较会失败。 + # 调用辅助函数将已注册别名的 class_name 统一更新为 entry.Name。 + if entry.Name is not None: + self._update_renum_alias_class_ptr(t.CSizeT(class_name), t.CSizeT(entry.Name)) + + # 添加 __tag 字段(位置 0,i32) + HandlesStruct.add_field(pool, entry, "__tag", i32_ty, None, None) + + # 添加 payload 字段(位置 1+,i32 或 i64) + for pos in range(1, total_positions): + psize2: int = position_max_sizes[pos] + payload_ty: llvmlite.LLVMType | t.CPtr = i32_ty + if psize2 > 4: + payload_ty = i64_ty + field_name_buf: t.CChar | t.CPtr = pool.alloc(16) + if field_name_buf is not None: + viperlib.snprintf(field_name_buf, 16, "_p%d", pos) + HandlesStruct.add_field(pool, entry, field_name_buf, payload_ty, None, None) + + # 注册变体名到全局变体表(供 translate_call 检测 REnum 变体构造) + self._register_renum_variants(pool, class_name, cd, variant_count) + + # 注册变体字段名别名已在变体遍历时直接完成(避免 CSizeT→str 转换问题) + + fb6: t.CChar | t.CPtr = VLogger.fmt_buf() + if fb6 is not None: + viperlib.snprintf(fb6, 1024, "registered %s with %d variants, %d positions", + class_name, variant_count, total_positions) + VLogger.info(fb6, "RENUM") + return 0 + + def _register_renum_variants(self, pool: memhub.MemBuddy | t.CPtr, + class_name: str, + cd: ast.ClassDef | t.CPtr, + variant_count: int): + """注册 REnum 类的变体名和 tag 值到全局变体表""" + if pool is None or class_name is None or cd is None: + return + if variant_count == 0: + return + children: list[ast.AST | t.CPtr] | t.CPtr = cd.children + if children is None: + return + + # 懒初始化表(首次注册时分配) + # 注意: 必须用 stdlib 分配——这些表在 1b 阶段(mark1 之后)首次分配, + # 若用 pool 会被 reset_to(mark1) 回收导致悬空(LLVMType 的 match 在 + # parser.vp 等后续文件翻译时访问已回收的表 → 崩溃)。 + if self.RenumClassNames is None: + self.RenumClassNames = stdlib.malloc(8 * RENUM_CLASS_MAX) + self.RenumClassVariantCounts = stdlib.malloc(8 * RENUM_CLASS_MAX) + self.RenumVariantNames = stdlib.malloc(8 * RENUM_CLASS_MAX * RENUM_VARIANT_PER_CLASS) + self.RenumVariantTags = stdlib.malloc(8 * RENUM_CLASS_MAX * RENUM_VARIANT_PER_CLASS) + if (self.RenumClassNames is None or self.RenumClassVariantCounts is None + or self.RenumVariantNames is None or self.RenumVariantTags is None): + self.RenumClassNames = None + return + string.memset(self.RenumClassNames, 0, 8 * RENUM_CLASS_MAX) + string.memset(self.RenumClassVariantCounts, 0, 8 * RENUM_CLASS_MAX) + string.memset(self.RenumVariantNames, 0, 8 * RENUM_CLASS_MAX * RENUM_VARIANT_PER_CLASS) + string.memset(self.RenumVariantTags, 0, 8 * RENUM_CLASS_MAX * RENUM_VARIANT_PER_CLASS) + self.RenumClassCount = 0 + + # 检查是否已注册(避免重复注册) + for i in range(self.RenumClassCount): + existing: str = self.RenumClassNames[i] + if existing is not None and string.strcmp(existing, class_name) == 0: + return + + # 表已满 + if self.RenumClassCount >= RENUM_CLASS_MAX: + return + + # 注册类名 + idx: int = self.RenumClassCount + self.RenumClassNames[idx] = t.CSizeT(class_name) + self.RenumClassVariantCounts[idx] = variant_count + + # 遍历 children,提取嵌套变体类名并注册 + cn: t.CSizeT = children.__len__() + tag: int = 0 + for ci in range(cn): + if tag >= variant_count: + break + stmt: ast.AST | t.CPtr = children.get(ci) + if stmt is None: + continue + if stmt.kind() != ast.ASTKind.ClassDef: + continue + vcd: ast.ClassDef | t.CPtr = (ast.ClassDef | t.CPtr)(stmt) + if vcd is None or vcd.name is None: + continue + name_offset: t.CSizeT = idx * RENUM_VARIANT_PER_CLASS + tag + self.RenumVariantNames[name_offset] = t.CSizeT(vcd.name) + self.RenumVariantTags[name_offset] = tag + tag += 1 + + self.RenumClassCount = idx + 1 + + def _lookup_renum_variant(self, variant_name: str) -> str: + """查找变体名所属的 REnum 类名 + + 返回: class_name (str),或 None + """ + if variant_name is None or self.RenumClassNames is None: + return None + + for i in range(self.RenumClassCount): + vcount: int = self.RenumClassVariantCounts[i] + for j in range(vcount): + name_offset: t.CSizeT = i * RENUM_VARIANT_PER_CLASS + j + vname: str = self.RenumVariantNames[name_offset] + if vname is not None and string.strcmp(vname, variant_name) == 0: + cls_nm: str = self.RenumClassNames[i] + return cls_nm + return None + + def _is_renum_class_name(self, class_name: str) -> int: + """检查名称是否是已注册的 REnum 类名,返回 1=是 / 0=否""" + if class_name is None or self.RenumClassNames is None: + return 0 + for i in range(self.RenumClassCount): + existing: str = self.RenumClassNames[i] + if existing is not None and string.strcmp(existing, class_name) == 0: + return 1 + return 0 + + def _lookup_renum_variant_in_class(self, class_name: str, variant_name: str) -> int: + """在指定 REnum 类中查找变体,返回 tag 值或 -1""" + if class_name is None or variant_name is None or self.RenumClassNames is None: + return -1 + for i in range(self.RenumClassCount): + existing: str = self.RenumClassNames[i] + if existing is None or string.strcmp(existing, class_name) != 0: + continue + vcount: int = self.RenumClassVariantCounts[i] + for j in range(vcount): + name_offset: t.CSizeT = i * RENUM_VARIANT_PER_CLASS + j + vname: str = self.RenumVariantNames[name_offset] + if vname is not None and string.strcmp(vname, variant_name) == 0: + return self.RenumVariantTags[name_offset] + return -1 + return -1 + + def _register_renum_field_alias(self, pool: memhub.MemBuddy | t.CPtr, + class_name: str, + field_name: str, + payload_idx: int): + """注册 REnum 变体字段名别名到全局表""" + if pool is None or class_name is None or field_name is None: + return + if payload_idx < 1: + return + + # 懒初始化表 + if self.RenumAliasClass is None: + self.RenumAliasClass = pool.alloc(8 * RENUM_ALIAS_MAX) + self.RenumAliasField = pool.alloc(8 * RENUM_ALIAS_MAX) + self.RenumAliasIndex = pool.alloc(8 * RENUM_ALIAS_MAX) + if (self.RenumAliasClass is None or self.RenumAliasField is None + or self.RenumAliasIndex is None): + self.RenumAliasClass = None + return + string.memset(self.RenumAliasClass, 0, 8 * RENUM_ALIAS_MAX) + string.memset(self.RenumAliasField, 0, 8 * RENUM_ALIAS_MAX) + string.memset(self.RenumAliasIndex, 0, 8 * RENUM_ALIAS_MAX) + self.RenumAliasCount = 0 + + if self.RenumAliasCount >= RENUM_ALIAS_MAX: + return + + # 检查是否已注册(避免重复)— 用 CSizeT 指针值比较,避免 CSizeT→str 转换问题 + cls_key: t.CSizeT = t.CSizeT(class_name) + fld_key: t.CSizeT = t.CSizeT(field_name) + for i in range(self.RenumAliasCount): + cls_existing: t.CSizeT = self.RenumAliasClass[i] + fld_existing: t.CSizeT = self.RenumAliasField[i] + if cls_existing == cls_key and fld_existing == fld_key: + return + + idx: int = self.RenumAliasCount + self.RenumAliasClass[idx] = cls_key + self.RenumAliasField[idx] = fld_key + self.RenumAliasIndex[idx] = t.CSizeT(payload_idx) + self.RenumAliasCount = idx + 1 + + def _update_renum_alias_class_ptr(self, old_ptr: t.CSizeT, new_ptr: t.CSizeT): + """更新别名表中的 class_name 指针,从 old_ptr 更新为 new_ptr""" + if old_ptr == new_ptr: + return + if self.RenumAliasClass is None: + return + for i in range(self.RenumAliasCount): + if self.RenumAliasClass[i] == old_ptr: + self.RenumAliasClass[i] = new_ptr + + def _lookup_renum_field_alias(self, class_name: str, field_name: str) -> int: + """查找 REnum 变体字段名的 payload 索引,返回索引或 -1 + + class_name: 用 CSizeT 指针值比较(_update_renum_alias_class_ptr 已统一指针) + field_name: 用 strcmp 内容比较(注册时 vnm.id 与查找时 at.attr 是不同指针) + """ + if class_name is None or field_name is None or self.RenumAliasClass is None: + return -1 + cls_key: t.CSizeT = t.CSizeT(class_name) + for i in range(self.RenumAliasCount): + cls_existing: t.CSizeT = self.RenumAliasClass[i] + if cls_existing == cls_key: + # field_name 用 strcmp 内容比较(指针不同但内容相同) + fld_existing_ptr: str = (str | t.CPtr)( + t.CVoid(self.RenumAliasField[i], t.CPtr)) + if fld_existing_ptr is not None and string.strcmp(fld_existing_ptr, field_name) == 0: + return self.RenumAliasIndex[i] + return -1 + + # ============================================================ + # 簇 C:泛型模板注册/特化(P5-2 第三阶段迁移,函数体来自 + # HandlesClassDef.vp,逻辑零改动) + # + # 说明: + # - _generic_class_* 全局表已迁入 self.GenericClassNames/ + # GenericClassNodes/GenericClassSha1s(P5-2 收尾) + # - _spec_* 全局缓存迁移为 self.SpecKeys/SpecNames/SpecCount + # ============================================================ + + def _is_generic_class(self, tp: list[str] | t.CPtr) -> int: + """检查 ClassDef 是否有类型参数(泛型类),返回 1=是 / 0=否 + + 接收 type_params 而非 cd,避免 cd.type_params 属性访问 + 因跨模块类型推断失败返回 None。 + """ + if tp is None: + return 0 + return 1 + + def _register_generic_template(self, pool: memhub.MemBuddy | t.CPtr, + cd: ast.ClassDef | t.CPtr, + module_sha1: str): + """注册泛型类模板(类名 + ClassDef 节点 + 来源模块 SHA1)""" + if self.GenericClassNames is None: + self.GenericClassNames = list[str](pool, 8) + self.GenericClassNodes = list[ast.ClassDef | t.CPtr](pool, 8) + self.GenericClassSha1s = list[str](pool, 8) + # 用局部变量接收 list,触发类型推断(避免字段 __len__ 失败) + names_local: list[str] | t.CPtr = self.GenericClassNames + cn: t.CSizeT = names_local.__len__() + i: t.CSizeT + for i in range(cn): + nm: str = names_local.get(i) + if nm is not None and string.strcmp(nm, cd.name) == 0: + return + self.GenericClassNames.append(cd.name) + self.GenericClassNodes.append(cd) + self.GenericClassSha1s.append(module_sha1) + # 诊断日志:确认泛型模板注册 + fb_rg: t.CChar | t.CPtr = VLogger.fmt_buf() + if fb_rg is not None: + viperlib.snprintf(fb_rg, 1024, "注册泛型模板: %s (module=%s)", cd.name, module_sha1) + VLogger.info(fb_rg, "SPEC") + + def _find_generic_template(self, class_name: str) -> ast.ClassDef | t.CPtr: + """查找泛型类模板,返回 ClassDef 节点或 None""" + if self.GenericClassNames is None or class_name is None: + return None + # 用局部变量接收 list,触发类型推断(避免字段 __len__ 失败) + names_local: list[str] | t.CPtr = self.GenericClassNames + nodes_local: list[ast.ClassDef | t.CPtr] | t.CPtr = self.GenericClassNodes + cn: t.CSizeT = names_local.__len__() + i: t.CSizeT + for i in range(cn): + nm: str = names_local.get(i) + if nm is not None and string.strcmp(nm, class_name) == 0: + node: ast.ClassDef | t.CPtr = nodes_local.get(i) + return node + return None + + def _find_generic_template_sha1(self, class_name: str) -> str: + """查找泛型类模板的来源模块 SHA1,未找到返回 None""" + if self.GenericClassNames is None or class_name is None: + return None + # 用局部变量接收 list,触发类型推断 + names_local: list[str] | t.CPtr = self.GenericClassNames + sha1s_local: list[str] | t.CPtr = self.GenericClassSha1s + cn: t.CSizeT = names_local.__len__() + i: t.CSizeT + for i in range(cn): + nm: str = names_local.get(i) + if nm is not None and string.strcmp(nm, class_name) == 0: + sha1_val: str = sha1s_local.get(i) + return sha1_val + return None + + def _mangle_generic_class_name(self, pool: memhub.MemBuddy | t.CPtr, + class_name: str, + type_args: list[str] | t.CPtr) -> str: + """生成特化类名: list + [int] -> list[int] + + 分配新缓冲区拼接,避免原地 strcat 导致缓冲区溢出 + """ + if class_name is None or type_args is None or pool is None: + return class_name + n: t.CSizeT = type_args.__len__() + if n == 0: + return class_name + # 计算总长度: class_name + "[" + arg0 + "," + arg1 + ... + "]" + NUL + total_len: t.CSizeT = string.strlen(class_name) + 2 # "[" 和 "]" + i: t.CSizeT + for i in range(n): + if i > 0: + total_len += 1 # "," + ta: str = type_args.get(i) + if ta is not None: + total_len += string.strlen(ta) + total_len += 1 # NUL + # 分配新缓冲区 + mangled: str = pool.alloc(total_len) + if mangled is None: + return class_name + mangled[0] = '\0' + string.strcat(mangled, class_name) + string.strcat(mangled, "[") + for i in range(n): + if i > 0: + string.strcat(mangled, ",") + ta: str = type_args.get(i) + if ta is not None: + string.strcat(mangled, ta) + string.strcat(mangled, "]") + return mangled + + def _clone_annotation(self, pool: memhub.MemBuddy | t.CPtr, + node: ast.AST | t.CPtr, + tp_names: list[str] | t.CPtr, + type_args: list[str] | t.CPtr) -> ast.AST | t.CPtr: + """拷贝类型注解表达式,替换类型参数 T 为具体类型名 + + tp_names: 类型参数名列表 ['T'] + type_args: 类型实参名列表 ['int'] + """ + if node is None: + return None + k: int = node.kind() + + # Name: 可能是类型参数 T + if k == ast.ASTKind.Name: + nm: ast.Name | t.CPtr = (ast.Name | t.CPtr)(node) + if nm.id is not None: + n: t.CSizeT = tp_names.__len__() if tp_names is not None else 0 + i: t.CSizeT + for i in range(n): + tpn: str = tp_names.get(i) + if tpn is not None and string.strcmp(nm.id, tpn) == 0: + ta: str = type_args.get(i) + # 类型实参可能是复合类型(如 "AST|t.CPtr"),用 _parse_type_string 解析 + parsed_node: ast.AST | t.CPtr = HandlesType._parse_type_string(pool, ta, nm.ctx) + return parsed_node + return ast.Name(pool, nm.id, nm.ctx) + return None + + # Attribute: t.CPtr 等 + if k == ast.ASTKind.Attribute: + at: ast.Attribute | t.CPtr = (ast.Attribute | t.CPtr)(node) + new_value: ast.AST | t.CPtr = self._clone_annotation(pool, at.value, tp_names, type_args) + return ast.Attribute(pool, new_value, at.attr, at.ctx) + + # BinOp: T | t.CPtr 等 + if k == ast.ASTKind.BinOp: + bop: ast.BinOp | t.CPtr = (ast.BinOp | t.CPtr)(node) + new_left: ast.AST | t.CPtr = self._clone_annotation(pool, bop.left, tp_names, type_args) + new_right: ast.AST | t.CPtr = self._clone_annotation(pool, bop.right, tp_names, type_args) + return ast.BinOp(pool, new_left, bop.op, new_right) + + # Subscript: list[int] 等 + if k == ast.ASTKind.Subscript: + sub: ast.Subscript | t.CPtr = (ast.Subscript | t.CPtr)(node) + new_value2: ast.AST | t.CPtr = self._clone_annotation(pool, sub.value, tp_names, type_args) + new_slice: ast.AST | t.CPtr = self._clone_annotation(pool, sub.slice, tp_names, type_args) + return ast.Subscript(pool, new_value2, new_slice, sub.ctx) + + # Tuple: (T, int) 等 + if k == ast.ASTKind.Tuple: + tup: ast.Tuple | t.CPtr = (ast.Tuple | t.CPtr)(node) + new_elts: list[ast.AST | t.CPtr] | t.CPtr = list[ast.AST | t.CPtr](pool, 8) + if tup.elts is not None: + tup_elts: list[ast.AST | t.CPtr] | t.CPtr = tup.elts + en: t.CSizeT = tup_elts.__len__() + ei: t.CSizeT + for ei in range(en): + el: ast.AST | t.CPtr = tup_elts.get(ei) + new_el: ast.AST | t.CPtr = self._clone_annotation(pool, el, tp_names, type_args) + if new_el is not None: + new_elts.append(new_el) + return ast.Tuple(pool, new_elts, tup.ctx) + + # Constant: 默认值等 + if k == ast.ASTKind.Constant: + cnst: ast.Constant | t.CPtr = (ast.Constant | t.CPtr)(node) + return ast.Constant(pool, cnst.const_kind, cnst.int_val, cnst.float_val, + cnst.str_val, cnst.lineno, cnst.col_offset) + + # 其他: 直接引用(不拷贝) + return node + + def _clone_arguments(self, pool: memhub.MemBuddy | t.CPtr, + args: ast.AST | t.CPtr, + tp_names: list[str] | t.CPtr, + type_args: list[str] | t.CPtr) -> ast.AST | t.CPtr: + """拷贝 Arguments 节点,替换 arg annotation 中的 T""" + if args is None: + return None + if args.kind() != ast.ASTKind.Arguments: + return args + old_args: ast.Arguments | t.CPtr = (ast.Arguments | t.CPtr)(args) + # 拷贝 args 列表,替换每个 Arg 的 annotation + new_arg_list: list[ast.AST | t.CPtr] | t.CPtr = list[ast.AST | t.CPtr](pool, 8) + if old_args.args is not None: + old_arg_list: list[ast.AST | t.CPtr] | t.CPtr = old_args.args + an: t.CSizeT = old_arg_list.__len__() + ai: t.CSizeT + for ai in range(an): + arg_node: ast.AST | t.CPtr = old_arg_list.get(ai) + if arg_node is None: + continue + if arg_node.kind() == ast.ASTKind.Arg: + ag: ast.Arg | t.CPtr = (ast.Arg | t.CPtr)(arg_node) + new_anno: ast.AST | t.CPtr = self._clone_annotation(pool, ag.annotation, tp_names, type_args) + new_arg: ast.Arg | t.CPtr = ast.Arg(pool, ag.arg, new_anno) + new_arg_list.append(new_arg) + else: + new_arg_list.append(arg_node) + return ast.Arguments(pool, new_arg_list, old_args.vararg, old_args.kwarg, + old_args.defaults, old_args.kw_defaults) + + def _clone_classdef_for_spec(self, pool: memhub.MemBuddy | t.CPtr, + cd: ast.ClassDef | t.CPtr, + spec_name: str, + tp_names: list[str] | t.CPtr, + type_args: list[str] | t.CPtr) -> ast.ClassDef | t.CPtr: + """拷贝 ClassDef 节点用于泛型特化 + + - 替换类名为 spec_name + - 清除 type_params(特化后不是泛型类) + - 拷贝 children 中的 AnnAssign 和 FunctionDef,替换类型注解中的 T + - 方法体直接引用原始节点(通过 type_map 上下文处理 T) + """ + # 创建新 ClassDef(type_params=None 表示非泛型) + new_cd: ast.ClassDef | t.CPtr = ast.ClassDef(pool, spec_name, cd.bases, cd.keywords, + cd.decorator_list, None) + # 拷贝 children + if cd.children is not None: + cd_children: list[ast.AST | t.CPtr] | t.CPtr = cd.children + cn: t.CSizeT = cd_children.__len__() + ci: t.CSizeT + for ci in range(cn): + child: ast.AST | t.CPtr = cd_children.get(ci) + if child is None: + continue + ck: int = child.kind() + + if ck == ast.ASTKind.AnnAssign: + aa: ast.AnnAssign | t.CPtr = (ast.AnnAssign | t.CPtr)(child) + new_target: ast.AST | t.CPtr = aa.target + new_anno2: ast.AST | t.CPtr = self._clone_annotation(pool, aa.annotation, tp_names, type_args) + new_value3: ast.AST | t.CPtr = aa.value + new_aa: ast.AnnAssign | t.CPtr = ast.AnnAssign(pool, new_target, new_anno2, new_value3, aa.simple) + new_cd.append(new_aa) + + elif ck == ast.ASTKind.FunctionDef: + fd: ast.FunctionDef | t.CPtr = (ast.FunctionDef | t.CPtr)(child) + new_args2: ast.AST | t.CPtr = self._clone_arguments(pool, fd.args, tp_names, type_args) + new_returns2: ast.AST | t.CPtr = self._clone_annotation(pool, fd.returns, tp_names, type_args) + new_fd: ast.FunctionDef | t.CPtr = ast.FunctionDef(pool, fd.name, new_args2, + fd.decorator_list, new_returns2, 0) + # 方法体直接引用原始节点 + if fd.children is not None: + fd_children: list[ast.AST | t.CPtr] | t.CPtr = fd.children + bcn: t.CSizeT = fd_children.__len__() + bci: t.CSizeT + for bci in range(bcn): + body_stmt: ast.AST | t.CPtr = fd_children.get(bci) + if body_stmt is not None: + new_fd.append(body_stmt) + new_cd.append(new_fd) + + else: + new_cd.append(child) + + return new_cd + + def _find_cached_spec(self, spec_key: str) -> str: + """查找已缓存的特化名,未找到返回 None""" + if self.SpecKeys is None or spec_key is None: + return None + i: int + for i in range(self.SpecCount): + key_addr: t.CSizeT = self.SpecKeys[i] + if key_addr != 0: + k: str = (str | t.CPtr)(t.CVoid(key_addr, t.CPtr)) + if k is not None and string.strcmp(k, spec_key) == 0: + name_addr: t.CSizeT = self.SpecNames[i] + if name_addr != 0: + return (str | t.CPtr)(t.CVoid(name_addr, t.CPtr)) + return None + + def _cache_spec(self, pool: memhub.MemBuddy | t.CPtr, spec_key: str, spec_name: str): + """缓存特化结果(stdlib 深拷贝存储,跨文件安全)""" + if spec_key is None or spec_name is None: + return + if self.SpecKeys is None: + self.SpecKeys = stdlib.malloc(SPEC_CACHE_MAX * 8) + self.SpecNames = stdlib.malloc(SPEC_CACHE_MAX * 8) + if self.SpecKeys is None or self.SpecNames is None: + return + string.memset(self.SpecKeys, 0, SPEC_CACHE_MAX * 8) + string.memset(self.SpecNames, 0, SPEC_CACHE_MAX * 8) + self.SpecCount = 0 + if self.SpecCount >= SPEC_CACHE_MAX: + return + # 深拷贝字符串到 stdlib 区 + key_len: t.CSizeT = string.strlen(spec_key) + name_len: t.CSizeT = string.strlen(spec_name) + key_copy: t.CChar | t.CPtr = stdlib.malloc(key_len + 1) + name_copy: t.CChar | t.CPtr = stdlib.malloc(name_len + 1) + if key_copy is None or name_copy is None: + return + string.strcpy(key_copy, spec_key) + string.strcpy(name_copy, spec_name) + self.SpecKeys[self.SpecCount] = t.CSizeT(key_copy) + self.SpecNames[self.SpecCount] = t.CSizeT(name_copy) + self.SpecCount += 1 + + def _merge_template_imports(self, trans: HT.Translator | t.CPtr, + template_sha1: str) -> None: + """将模板模块的 imports 并入 trans._imported_modules(空格分隔)""" + if trans is None or template_sha1 is None: + return + tdeps: str = StubMerger.LookupIncludesDeps(template_sha1) + if tdeps is None or tdeps[0] == '\0': + return + cur: str = trans._imported_modules + if cur is None or cur[0] == '\0': + trans._imported_modules = tdeps + return + cur_len: t.CSizeT = string.strlen(cur) + td_len: t.CSizeT = string.strlen(tdeps) + merged: str = trans.Pool.alloc(cur_len + td_len + 2) + if merged is None: + return + string.strcpy(merged, cur) + merged[cur_len] = ' ' + string.strcpy(merged + cur_len + 1, tdeps) + trans._imported_modules = merged + + def _specialize_generic_class(self, trans: HT.Translator | t.CPtr, + class_name: str, + type_args: list[str] | t.CPtr) -> str: + """特化泛型类,返回特化类名 + + 1. 查找泛型模板 + 2. 生成特化名 + 3. 检查缓存 + 4. 拷贝 ClassDef 节点(替换类型注解中的 T) + 5. 设置 type_map 上下文(用于方法体中的 T 替换) + 6. 调用 translate_class_def 翻译特化类 + 7. 返回特化名 + """ + if trans is None or class_name is None or type_args is None: + return None + # 防御:泛型上下文内收集的 type_args 若残留未替换的类型参数名(如 "T"), + # 统一替换为具体类型名,避免 ndarray[T] 二次递归特化崩溃。 + # 调用方传入的 type_args 均为临时新建列表,就地替换无共享副作用。 + ta_cnt_g: t.CSizeT = type_args.__len__() + ta_i_g: t.CSizeT + for ta_i_g in range(ta_cnt_g): + ta_raw_g: str = type_args.get(ta_i_g) + if ta_raw_g is not None: + ta_rsv_g: str = HandlesType.resolve_generic_type_name(ta_raw_g) + if ta_rsv_g is not None and string.strcmp(ta_raw_g, ta_rsv_g) != 0: + type_args.set(ta_i_g, ta_rsv_g) + + pool: memhub.MemBuddy | t.CPtr = trans.Pool + + # ============================================================ + # 诊断输出:追踪 GSListNode 特化调用路径 + # ============================================================ + if string.strcmp(class_name, "GSListNode") == 0: + VLogger.debug("=== _specialize_generic_class ===", "SPEC") + fb: t.CChar | t.CPtr = VLogger.fmt_buf() + if fb is not None: + viperlib.snprintf(fb, 1024, "class=%s module=%s", class_name, trans.ModuleSha1) + VLogger.debug(fb, "SPEC") + if type_args is not None: + ta_n: t.CSizeT = type_args.__len__() + ta_i: t.CSizeT + for ta_i in range(ta_n): + ta: str = type_args.get(ta_i) + if ta is not None: + if fb is not None: + viperlib.snprintf(fb, 1024, " type_arg[%d]=%s", ta_i, ta) + VLogger.debug(fb, "SPEC") + + # 1. 查找泛型模板 + template_cd: ast.ClassDef | t.CPtr = self._find_generic_template(class_name) + if template_cd is None: + if string.strcmp(class_name, "GSListNode") == 0: + VLogger.debug("template NOT FOUND, return None", "SPEC") + return None + + # 2. 生成特化名 + spec_name: str = self._mangle_generic_class_name(pool, class_name, type_args) + if spec_name is None: + return None + + # 治本修复:Phase B 补译泛型特化类方法体(统一入口,在 cache/existing 检查之前) + # Phase 1a(declare_only==1)特化时只注册结构体不译方法体(MethodsEmitted==0), + # Phase B(declare_only==0)重复进入时若方法体未译,补译方法体生成 define, + # 避免 GSList[Line].append 等符号只有 declare 无 define → 链接失败。 + # 首次 Phase B 特化(Phase 1a 未特化)find_struct 返回 None,不补译,走下方正常全量翻译。 + if trans._declare_only == 0: + pre_existing: HandlesStruct.StructEntry | t.CPtr = HandlesStruct.find_struct(spec_name) + if pre_existing is not None and pre_existing.MethodsEmitted == 0: + # 防重入:先标记 MethodsEmitted=1,避免补译过程中方法体/返回类型注解 + # 再次触发 _specialize_generic_class(如 __iter__ 返回 list[T]|t.CPtr) + # 导致无限递归补译 → OOM。补译完成后已设置,无需恢复。 + pre_existing.MethodsEmitted = 1 + tp_names_pre: list[str] | t.CPtr = template_cd.type_params + spec_cd_pre: ast.ClassDef | t.CPtr = self._clone_classdef_for_spec( + pool, template_cd, spec_name, tp_names_pre, type_args) + if spec_cd_pre is not None: + trans.GenericTypeParamNames = tp_names_pre + trans.GenericTypeArgs = type_args + HandlesType.set_generic_context(tp_names_pre, type_args) + saved_ms_pre: str = trans.ModuleSha1 + saved_imp_pre: str = trans._imported_modules + template_sha1_pre: str = self._find_generic_template_sha1(class_name) + if template_sha1_pre is not None: + trans.ModuleSha1 = template_sha1_pre + self._merge_template_imports(trans, template_sha1_pre) + self._translate_oop_methods(trans, spec_cd_pre, pre_existing.Ty, spec_name, 0) + trans.ModuleSha1 = saved_ms_pre + trans._imported_modules = saved_imp_pre + trans.GenericTypeParamNames = None + trans.GenericTypeArgs = None + HandlesType.clear_generic_context() + + # 3. 检查缓存(spec_key 包含所有类型实参,避免多参数泛型缓存冲突) + # 分配新缓冲区避免原地 strcat 溢出 + sk_n: t.CSizeT = type_args.__len__() + sk_total: t.CSizeT = string.strlen(class_name) + 2 # "<" 和 ">" + sk_i: t.CSizeT + for sk_i in range(sk_n): + if sk_i > 0: + sk_total += 1 # "," + sk_ta: str = type_args.get(sk_i) + if sk_ta is not None: + sk_total += string.strlen(sk_ta) + sk_total += 1 # NUL + spec_key: str = pool.alloc(sk_total) + if spec_key is None: + return None + spec_key[0] = '\0' + string.strcat(spec_key, class_name) + string.strcat(spec_key, "<") + for sk_i in range(sk_n): + if sk_i > 0: + string.strcat(spec_key, ",") + sk_ta: str = type_args.get(sk_i) + if sk_ta is not None: + string.strcat(spec_key, sk_ta) + string.strcat(spec_key, ">") + cached: str = self._find_cached_spec(spec_key) + if cached is not None: + if string.strcmp(class_name, "GSListNode") == 0: + fb: t.CChar | t.CPtr = VLogger.fmt_buf() + if fb is not None: + viperlib.snprintf(fb, 1024, "CACHE HIT, return cached=%s", cached) + VLogger.debug(fb, "SPEC") + return cached + + # 4. 检查是否已注册(Phase B 重复特化) + existing: HandlesStruct.StructEntry | t.CPtr = HandlesStruct.find_struct(spec_name) + if existing is not None: + if string.strcmp(class_name, "GSListNode") == 0: + fb: t.CChar | t.CPtr = VLogger.fmt_buf() + if fb is not None: + viperlib.snprintf(fb, 1024, "EXISTING registered, return spec_name=%s field_count=%d", + spec_name, existing.FieldCount) + VLogger.debug(fb, "SPEC") + self._cache_spec(pool, spec_key, spec_name) + return spec_name + + # 预注册缓存(防止递归) + self._cache_spec(pool, spec_key, spec_name) + + # 5. 拷贝 ClassDef 节点 + tp_names: list[str] | t.CPtr = template_cd.type_params + spec_cd: ast.ClassDef | t.CPtr = self._clone_classdef_for_spec( + pool, template_cd, spec_name, tp_names, type_args) + if spec_cd is None: + return None + + # 6. 设置 type_map 上下文(用于方法体中的 T 替换) + trans.GenericTypeParamNames = tp_names + trans.GenericTypeArgs = type_args + HandlesType.set_generic_context(tp_names, type_args) + + # 7. 翻译特化类 + # 切换 trans.ModuleSha1 为泛型模板定义模块的 SHA1, + # 使结构体类型名和方法定义名都用定义模块的 SHA1 前缀, + # 与调用端 get_struct_sha1(class_name) 查到的 SHA1 一致。 + # 同时并入模板模块的 imports(见 _merge_template_imports 注释), + # 避免模板方法体内的跨模块调用被误报"模块未导入"。 + saved_module_sha1: str = trans.ModuleSha1 + saved_imported: str = trans._imported_modules + template_sha1: str = self._find_generic_template_sha1(class_name) + if template_sha1 is not None: + trans.ModuleSha1 = template_sha1 + self._merge_template_imports(trans, template_sha1) + self.translate_class_def(trans, spec_cd) + # 恢复原始 ModuleSha1 与 imports + trans.ModuleSha1 = saved_module_sha1 + trans._imported_modules = saved_imported + + # 8. 清除 type_map 上下文 + trans.GenericTypeParamNames = None + trans.GenericTypeArgs = None + HandlesType.clear_generic_context() + + # 诊断输出:检查特化结果 + if string.strcmp(class_name, "GSListNode") == 0: + result_entry: HandlesStruct.StructEntry | t.CPtr = HandlesStruct.find_struct(spec_name) + if result_entry is not None: + fb: t.CChar | t.CPtr = VLogger.fmt_buf() + if fb is not None: + viperlib.snprintf(fb, 1024, "DONE spec_name=%s field_count=%d", + spec_name, result_entry.FieldCount) + VLogger.debug(fb, "SPEC") + # 打印每个字段的类型信息 + ri: int + for ri in range(result_entry.FieldCount): + rfe: HandlesStruct.FieldEntry | t.CPtr = HandlesStruct._get_field_entry( + result_entry, ri) + if rfe is not None: + rfn: str = HandlesStruct.get_field_name_ptr(rfe) + rft: llvmlite.LLVMType | t.CPtr = HandlesStruct.get_field_type_ptr(rfe) + if fb is not None: + viperlib.snprintf(fb, 1024, " field[%d] name=%s type=%d", + ri, rfn if rfn is not None else "(null)", + t.CSizeT(rft) if rft is not None else 0) + VLogger.debug(fb, "SPEC") + else: + VLogger.debug("DONE but result NOT FOUND in struct table!", "SPEC") + + return spec_name + + # ============================================================ + # translate_class_def — 翻译 class 定义(簇 D) + # ============================================================ + def translate_class_def(self, trans: HT.Translator | t.CPtr, + node: ast.AST | t.CPtr) -> int: + """翻译 class 定义,返回 0""" + if node is None or trans is None: + return 0 + + cd: ast.ClassDef | t.CPtr = (ast.ClassDef | t.CPtr)(node) + if cd is None or cd.name is None: + return 0 + + pool: memhub.MemBuddy | t.CPtr = trans.Pool + class_name: str = cd.name + + # 命名空间隔离:标记为当前文件可见(必须在 existing 检查之前, + # 因为 Phase B 时结构体已注册会提前 return,否则永远无法标记本地类) + HandlesStruct.add_visible_struct(pool, class_name) + + # 枚举类:交给 HandlesEnum 处理 + if self._is_enum_class(cd) == 1: + return self._translate_enum_def(trans, cd) + + # 联合体类:交给联合体处理 + if self._is_union_class(cd) == 1: + return self._translate_union_def(trans, cd) + + # REnum 类:交给 REnum 处理({i32 tag, max_payload} 布局) + if self._is_renum_class(cd) == 1: + return self._translate_renum_def(trans, cd) + + # 泛型类:存储为模板,不发射 IR(等实例化时特化) + # 用局部变量接收 cd.type_params,触发类型推断 + tp_val: list[str] | t.CPtr = cd.type_params + if self._is_generic_class(tp_val) == 1: + self._register_generic_template(pool, cd, trans.ModuleSha1) + return 0 + + # 检查是否已注册(用 SHA1 区分跨模块同名类) + existing: HandlesStruct.StructEntry | t.CPtr = HandlesStruct.find_struct_by_module( + class_name, trans.ModuleSha1) + if existing is not None: + # BUG 5 方案1修改点2:existing 时字段完整性检查 + # 结构体已注册,但需验证字段信息是否完整(防止 i32 回退残留或注册不完整) + # 注意:无字段类(接口/标记类,类体无 AnnAssign)合法(空 struct + 方法), + # 仅当"类体声明了字段但 FieldCount==0"才算注册不完整(Phase A-pre 漏注册)。 + if existing.FieldCount == 0 and trans._declare_only == 0: + if self._class_body_has_field(cd) != 0: + # Phase B 时字段数为 0 说明注册不完整(Phase A-pre 可能漏注册) + HandlesType.fatal_error( + node, + f"结构体已注册但字段数为0,类: {class_name},可能注册不完整", + "InternalCompilerError") + # 结构体已注册(Phase A-pre 多遍扫描或 Phase B 重新翻译),但仍需在当前模块中翻译方法 + if existing.Ty is not None: + # Phase 1b(declare_only=0):existing.Ty 是 Phase 1a 注册的 struct_ty, + # 其 Name(如 "sha1.ClassName")指向 Phase 1a 的 pool 内存。虽然 mark1 + # 之前分配不被 reset 回收,但 struct_ty 会被后续文件翻译引用(vtable/ + # self 参数类型打印),部分实现下 pool 块被复用导致 Name 悬空崩溃。 + # 保险起见:深拷贝 Name 到 stdlib,确保跨文件永久存活。 + if trans._declare_only == 0: + old_name: t.CChar | t.CPtr = llvmlite.get_struct_name(existing.Ty) + if old_name is not None: + on_len: t.CSizeT = string.strlen(old_name) + on_copy: t.CChar | t.CPtr = stdlib.malloc(on_len + 1) + if on_copy is not None: + string.strcpy(on_copy, old_name) + c.DerefAs(existing.Ty, llvmlite.LLVMType.Struct( + llvmlite.get_struct_fields(existing.Ty), + llvmlite.get_struct_fcount(existing.Ty), + on_copy)) + # Phase B: 将已存在的命名结构体注册到当前模块(输出类型定义行) + llvmlite.module_add_named_type(trans.Module, pool, existing.Ty) + # Phase A-pre(declare_only=1)多遍扫描时,类已注册但不应翻译方法体 + # Phase B(declare_only=0)时全量翻译方法体 + if trans._declare_only == 1: + self._translate_oop_methods(trans, cd, existing.Ty, class_name, 1) + else: + self._translate_oop_methods(trans, cd, existing.Ty, class_name) + # SHA1 已在 register_struct 时设置,无需再补 + return 0 + + # ============================================================ + # 触发 base 中 Subscript 的泛型特化(如 GSListNode[Value]) + # 必须在 _detect_vtable_status 和父类字段继承之前调用, + # 否则 find_struct_by_module("GSListNode[Value]") 返回 None + # ============================================================ + self._trigger_base_specialization(trans, cd) + + # ============================================================ + # VTable 检测:判断是否启用虚表 + # ============================================================ + has_vtable: int = self._detect_vtable_status(cd, trans) + parent_name: str = self._get_parent_class(cd, trans) + # 多继承:收集所有真实父类名(跳过 marker base),供字段展平/vtable/MRO 使用 + parents_buf: t.CSizeT | t.CPtr = pool.alloc(8 * HandlesStruct.PARENT_MAX) + parents_count: int = 0 + if parents_buf is not None: + parents_count = self._collect_parents(pool, cd, parents_buf, HandlesStruct.PARENT_MAX) + is_novtable_deco: int = 0 + if cd.decorator_list is not None: + if self._has_decorator(cd.decorator_list, "NoVTable") == 1: + is_novtable_deco = 1 + + # ============================================================ + # PhaseA 预注册延迟检查:父类未注册时延迟注册当前类 + # + # 根因:AssignHandle(HandlesBase.Mixin) 有自己的字段 _CurrentClass, + # 当 Mixin 未注册时(字母序:HandlesAssign.py 在 HandlesBase.py 之前), + # field_count=1(不是0),field_count==0 静默返回不触发, + # AssignHandle 被注册为只有 _CurrentClass 字段(缺 Trans)。 + # 后续遍 existing is not None,不补字段 → attribute ptr is None: self.Trans + # + # 修复:declare_only==1 且父类未注册时,延迟注册到下一遍。 + # 多遍 PhaseA-pre 会在后续遍中重试(父类已注册后完整注册)。 + # Phase B(declare_only==0)不延迟,避免死锁。 + # ============================================================ + if trans._declare_only == 1 and parent_name is not None: + parent_check: HandlesStruct.StructEntry | t.CPtr = HandlesStruct.find_struct_by_module( + parent_name, trans.ModuleSha1) + if parent_check is None: + parent_check = HandlesStruct.find_struct(parent_name) + if parent_check is None: + return 0 + + # ============================================================ + # 1. 遍历 class body,收集字段信息 + # ============================================================ + # 用 CSizeT 数组存储指针值(64 位系统上 8 字节) + field_names_buf: t.CSizeT | t.CPtr = pool.alloc(8 * 64) + field_types_buf: t.CSizeT | t.CPtr = pool.alloc(8 * 64) + field_defaults_buf: t.CSizeT | t.CPtr = pool.alloc(8 * 64) + field_annot_buf: t.CSizeT | t.CPtr = pool.alloc(8 * 64) + if field_names_buf is None or field_types_buf is None or field_defaults_buf is None: + return 0 + if field_annot_buf is None: + return 0 + string.memset(field_names_buf, 0, 8 * 64) + string.memset(field_types_buf, 0, 8 * 64) + string.memset(field_defaults_buf, 0, 8 * 64) + string.memset(field_annot_buf, 0, 8 * 64) + + field_count: int = 0 + + # ============================================================ + # 1.5 继承父类字段(字段展平) + # ============================================================ + # + # 父类字段排在子类字段之前,结构体布局: + # [vtable_ptr?, parent_field1, ..., child_field1, ...] + # 跳过父类的 __vtable__ 字段(子类会有自己的 vtable 指针) + # ============================================================ + # 多继承字段展平:遍历所有父类(声明顺序),字段名去重(先声明优先) + if parents_count > 0 and parents_buf is not None: + for pi in range(parents_count): + pname_addr: t.CSizeT = parents_buf[pi] + if pname_addr == 0: + continue + pname: str = (str | t.CPtr)(t.CVoid(pname_addr, t.CPtr)) + if pname is None: + continue + # 用 SHA1 感知查找父类,规避跨模块同名找错 + parent_entry: HandlesStruct.StructEntry | t.CPtr = HandlesStruct.find_struct_by_module( + pname, trans.ModuleSha1) + if parent_entry is None: + # 父类可能定义在另一个模块(不同 SHA1,如 HandlesBase.Mixin), + # find_struct_by_module 不回退全局查找,此处手动回退到 find_struct, + # 否则子类无法继承父类字段 → field_count==0 → __sizeof__ 失败 + parent_entry = HandlesStruct.find_struct(pname) + if parent_entry is None: + continue + pfc: int = parent_entry.FieldCount + for pfi in range(pfc): + pfe: HandlesStruct.FieldEntry | t.CPtr = HandlesStruct._get_field_entry( + parent_entry, pfi) + if pfe is None: + continue + pfn: str = HandlesStruct.get_field_name_ptr(pfe) + if pfn is None: + continue + # 跳过父类的 vtable 指针字段 + if string.strcmp(pfn, "__vtable__") == 0: + continue + # 多继承去重:字段名已存在跳过(先声明父类优先) + if self._field_name_exists(field_names_buf, field_count, pfn) != 0: + continue + if field_count < 64: + pft: llvmlite.LLVMType | t.CPtr = HandlesStruct.get_field_type_ptr(pfe) + pfd: ast.AST | t.CPtr = HandlesStruct.get_field_default_ptr(pfe) + pfa: str = HandlesStruct.get_field_annot_class_name(pfe) + field_names_buf[field_count] = t.CSizeT(pfn) + field_types_buf[field_count] = t.CSizeT(pft) + if pfd is not None: + field_defaults_buf[field_count] = t.CSizeT(pfd) + else: + field_defaults_buf[field_count] = 0 + if pfa is not None: + stored_val: t.CSizeT = t.CSizeT(pfa) + field_annot_buf[field_count] = stored_val + else: + field_annot_buf[field_count] = 0 + field_count += 1 + + children: list[ast.AST | t.CPtr] | t.CPtr = cd.children + if children is None: + return 0 + + cn: t.CSizeT = children.__len__() + for ci in range(cn): + stmt: ast.AST | t.CPtr = children.get(ci) + if stmt is None: + continue + sk: int = stmt.kind() + + if sk != ast.ASTKind.AnnAssign: continue + + # AnnAssign(target=Name(id), annotation=type, value=...) + aa: ast.AnnAssign | t.CPtr = (ast.AnnAssign | t.CPtr)(stmt) + if aa is None or aa.target is None: + continue + + # 获取字段名 + if aa.target.kind() != ast.ASTKind.Name: + continue + tgt: ast.Name | t.CPtr = (ast.Name | t.CPtr)(aa.target) + if tgt.id is None: + continue + + # 跳过编译期元数据字段(__provides__/__requires__/__require_must__) + # 这些字段只用于 with 上下文的静态可达性检查,不生成运行时代码 + # 避免类体中 list 字面量翻译失败(类体无 pool 变量上下文) + if string.strcmp(tgt.id, "__provides__") == 0: + continue + if string.strcmp(tgt.id, "__requires__") == 0: + continue + if string.strcmp(tgt.id, "__require_must__") == 0: + continue + + # 解析字段类型 + field_ty: llvmlite.LLVMType | t.CPtr = HandlesType.resolve_annotation_type( + pool, aa.annotation, trans._imported_modules, trans._from_imports, trans) + if field_ty is None: + # BUG 5 方案1修改点1:消除 i32 静默回退 + # Phase A-pre(declare_only=1):依赖的类可能尚未注册,延迟到下一遍 + # Phase B(declare_only=0):真正的类型解析错误,fast-fail 终止该类翻译 + # 不再用 i32 回退(会导致结构体布局错误 + GEP 索引错乱) + # 例外:泛型 Subscript(如 list[AST|t.CPtr])未特化时回退为 Ptr(i8), + # 因为泛型特化可能延迟到构造调用时。AnnotClassName 会携带 mangled name + # 供 translate_attribute 做后续 bitcast。 + is_generic_sub: int = 0 + if aa.annotation is not None and aa.annotation.kind() == ast.ASTKind.Subscript: + is_generic_sub = 1 + if is_generic_sub != 0: + # 泛型未特化:回退为 Ptr(i8),依赖 AnnotClassName 做后续类型恢复 + field_ty = llvmlite.Ptr(pool, llvmlite.Int8(pool)) + else: + # Phase A-pre(declare_only=1):依赖的类可能尚未注册, + # 静默 return 0 让多遍收敛机制生效(下一遍依赖类已注册即可成功) + if trans._declare_only == 1: + return 0 + # Phase B(declare_only=0):真正的类型解析错误,fast-fail 终止 + type_name2: str = HandlesType.annotation_to_str(aa.annotation) + HandlesType.fatal_error( + aa, + f"'{type_name2}' is not defined", + "NameError") + return 0 + + # 存储到数组(指针转 CSizeT) + if field_count < 64: + diag_name_val: t.CSizeT = t.CSizeT(tgt.id) + field_names_buf[field_count] = diag_name_val + field_types_buf[field_count] = t.CSizeT(field_ty) + # 存储默认值 AST 指针(None=无默认值) + if aa.value is not None: + field_defaults_buf[field_count] = t.CSizeT(aa.value) + else: + field_defaults_buf[field_count] = 0 + # 提取原始类型注解的类名(联合类型简化为 Ptr(i8) 时回退查找结构体) + # BUG 1 方案3:传 pool 使泛型 Subscript 返回 mangled name(如 "list[ast.AST|t.CPtr]") + if aa.annotation is not None: + annot_cn: str = HandlesType.extract_class_name_from_annotation( + aa.annotation, trans._imported_modules, pool) + if annot_cn is not None: + diag_cn_val: t.CSizeT = t.CSizeT(annot_cn) + field_annot_buf[field_count] = diag_cn_val + else: + field_annot_buf[field_count] = 0 + else: + field_annot_buf[field_count] = 0 + field_count += 1 + + if field_count == 0: + # PhaseA 预注册时,父类可能尚未注册(字母序单遍扫描), + # 导致子类无法继承父类字段 → field_count==0。 + # 静默返回,Phase2.py 的多遍 PhaseA-pre 会在后续遍中重试。 + if trans._declare_only == 1 and parent_name is not None: + return 0 + # 无字段类(接口/标记类):不能整体跳过——类可能只有方法 + # (如多继承中的 ShapeM/Vec2Extra),需注册类并翻译方法。 + # 空 struct 在 LLVM 中合法({});@t.CVTable 类由下方补 vtable 指针字段。 + fb_cf: t.CChar | t.CPtr = VLogger.fmt_buf() + if fb_cf is not None: + viperlib.snprintf(fb_cf, 1024, "%s has no fields", class_name) + VLogger.info(fb_cf, "CLASS") + + # ============================================================ + # 2. 创建 LLVM StructType + # ============================================================ + # 构建 ParamNode 链表 + first_node: llvmlite.ParamNode | t.CPtr = None + prev_node: llvmlite.ParamNode | t.CPtr = None + total_field_count: int = field_count + + # 如果有虚表,首字段添加 i8* vtable 指针 + if has_vtable == 1: + i8_ptr_ty: llvmlite.LLVMType | t.CPtr = llvmlite.Ptr(pool, llvmlite.Int8(pool)) + vtable_node: llvmlite.ParamNode | t.CPtr = pool.alloc(llvmlite.ParamNode.__sizeof__()) + if vtable_node is None: + fb_vn: t.CChar | t.CPtr = VLogger.fmt_buf() + if fb_vn is not None: + viperlib.snprintf(fb_vn, 1024, "failed to alloc vtable node for %s", class_name) + VLogger.error(fb_vn, "CLASS") + return 0 + string.memset(vtable_node, 0, llvmlite.ParamNode.__sizeof__()) + vtable_node.Ty = i8_ptr_ty + first_node = vtable_node + prev_node = vtable_node + total_field_count = field_count + 1 + + for fi in range(field_count): + fty_addr: t.CSizeT = field_types_buf[fi] + if fty_addr == 0: + continue + fty: llvmlite.LLVMType | t.CPtr = (llvmlite.LLVMType | t.CPtr)(t.CVoid(fty_addr, t.CPtr)) + + # 创建 ParamNode + pnode: llvmlite.ParamNode | t.CPtr = pool.alloc(llvmlite.ParamNode.__sizeof__()) + if pnode is None: + continue + string.memset(pnode, 0, llvmlite.ParamNode.__sizeof__()) + pnode.Ty = fty + + if first_node is None: + first_node = pnode + if prev_node is not None: + prev_node.Next = pnode + prev_node = pnode + + # 构造命名结构体类型名: "sha1.ClassName" 或 "ClassName" + # 注意: Phase 1b(declare_only=0)时 struct_ty 会注册到全局表并被后续 + # 文件翻译引用(vtable/self 参数类型打印),其 Name 必须跨 1b 每文件 + # reset_to(mark1) 存活 → 用 stdlib 深拷贝;Phase 1a 仍用 pool(无需跨文件)。 + type_name: str = class_name + if trans.ModuleSha1 is not None: + name_buf: t.CChar | t.CPtr = pool.alloc(64) + if name_buf is not None: + viperlib.snprintf(name_buf, 64, "%s.%s", trans.ModuleSha1, class_name) + type_name = name_buf + if trans._declare_only == 0 and type_name is not None: + tn_len: t.CSizeT = string.strlen(type_name) + tn_copy: t.CChar | t.CPtr = stdlib.malloc(tn_len + 1) + if tn_copy is not None: + string.strcpy(tn_copy, type_name) + type_name = tn_copy + + # 创建 StructType(命名结构体) + struct_ty: llvmlite.LLVMType | t.CPtr = llvmlite.Struct(pool, first_node, total_field_count, type_name) + if struct_ty is None: + fb_st: t.CChar | t.CPtr = VLogger.fmt_buf() + if fb_st is not None: + viperlib.snprintf(fb_st, 1024, "failed to create StructType for %s", class_name) + VLogger.error(fb_st, "CLASS") + return 0 + + # Phase 1b(declare_only=0)新注册的 struct_ty 会被注册到全局表并被后续文件 + # 翻译引用(vtable/self 参数类型打印/find_struct_by_type 指针匹配)。LLVMType + # 对象和 Fields 链是 pool 分配的,本文件 reset_to(mark1) 后悬空。深拷贝整棵树 + # 到 stdlib,并替换 struct_ty 指针,保证 entry.Ty 与调用方持有的 struct_ty + # 指向同一个 stdlib 拷贝(指针匹配不失效)且跨文件永久存活。 + if trans._declare_only == 0: + st_copy: llvmlite.LLVMType | t.CPtr = llvmlite.DeepCopyType(pool, struct_ty) + if st_copy is not None: + struct_ty = st_copy + type_name = llvmlite.get_struct_name(struct_ty) + + # 注册命名结构体到模块(输出 %"name" = type { ... } 定义行) + llvmlite.module_add_named_type(trans.Module, pool, struct_ty) + + # 扫描字段类型,为跨模块结构体引用添加 opaque 声明 + # 例如 list[int].__pool__ 引用 memhub.MemManager,需要在当前模块添加 %"sha1.MemManager" = type opaque + for fi in range(field_count): + fty_addr_op: t.CSizeT = field_types_buf[fi] + if fty_addr_op == 0: + continue + fty_op: llvmlite.LLVMType | t.CPtr = (llvmlite.LLVMType | t.CPtr)(t.CVoid(fty_addr_op, t.CPtr)) + llvmlite.module_ensure_opaque_for_type(trans.Module, pool, fty_op) + + # ============================================================ + # 3. 注册到 HandlesStruct + # ============================================================ + entry: HandlesStruct.StructEntry | t.CPtr = HandlesStruct.register_struct( + pool, class_name, struct_ty, trans.ModuleSha1) + if entry is None: + fb_re: t.CChar | t.CPtr = VLogger.fmt_buf() + if fb_re is not None: + viperlib.snprintf(fb_re, 1024, "failed to register %s", class_name) + VLogger.error(fb_re, "CLASS") + return 0 + + # 标记 VTable 状态(直接用 entry,规避跨模块同名 find_struct 找错) + if has_vtable == 1: + entry.HasVTable = 1 + if is_novtable_deco == 1: + entry.IsNoVTable = 1 + if parent_name is not None: + entry.ParentName = parent_name + # 多继承:设置父类数组(供 MRO/字段/vtable 查询,stdlib 深拷贝跨文件存活) + if parents_count > 0 and parents_buf is not None: + HandlesStruct.set_parent_names(class_name, parents_buf, parents_count) + + # 添加字段信息 + # 如果有虚表,先添加 __vtable__ 字段占位(索引 0),用户字段从索引 1 开始 + if has_vtable == 1: + i8_ptr_ty2: llvmlite.LLVMType | t.CPtr = llvmlite.Ptr(pool, llvmlite.Int8(pool)) + HandlesStruct.add_field(pool, entry, "__vtable__", i8_ptr_ty2, None, None) + + for fi in range(field_count): + fname_addr: t.CSizeT = field_names_buf[fi] + if fname_addr == 0: + continue + fname: str = (str | t.CPtr)(t.CVoid(fname_addr, t.CPtr)) + fty_addr2: t.CSizeT = field_types_buf[fi] + if fty_addr2 == 0: + continue + fty2: llvmlite.LLVMType | t.CPtr = (llvmlite.LLVMType | t.CPtr)(t.CVoid(fty_addr2, t.CPtr)) + # 恢复默认值 AST 指针 + fdef_addr: t.CSizeT = field_defaults_buf[fi] + fdef: ast.AST | t.CPtr = None + if fdef_addr != 0: + fdef = (ast.AST | t.CPtr)(t.CVoid(fdef_addr, t.CPtr)) + # 恢复注解类名指针 + fannot_addr: t.CSizeT = field_annot_buf[fi] + fannot: t.CChar | t.CPtr = None + if fannot_addr != 0: + fannot = (t.CChar | t.CPtr)(t.CVoid(fannot_addr, t.CPtr)) + if fname is not None and fty2 is not None: + HandlesStruct.add_field(pool, entry, fname, fty2, fdef, fannot) + + # Phase 1a 声明模式:只注册 struct + 设置 OOP 标志,不翻译方法体 + if trans._declare_only == 1: + self._translate_oop_methods(trans, cd, struct_ty, class_name, 1) + return 0 + + # ============================================================ + # 4. OOP 方法处理:扫描 FunctionDef,标记 OOP,翻译方法,生成 __before_init__ + # ============================================================ + self._translate_oop_methods(trans, cd, struct_ty, class_name) + + return 0 + + # ============================================================ + # _vtable_strcat — 将 src 追加到 dst 末尾 + # ============================================================ + def _vtable_strcat(self, dst: t.CChar | t.CPtr, dst_size: t.CSizeT, + src: t.CChar | t.CPtr): + """将 src 追加到 dst 末尾""" + if dst is None or src is None: + return + dlen: t.CSizeT = string.strlen(dst) + slen: t.CSizeT = string.strlen(src) + remain: t.CSizeT = dst_size - dlen + if remain <= 0: + return + i: t.CSizeT = 0 + while i < slen and i + 1 < remain: + dst[dlen + i] = src[i] + i += 1 + dst[dlen + i] = '\0' + + # ============================================================ + # _vtable_name_needs_quote — 检查 LLVM 标识符是否需要引号 + # ============================================================ + def _vtable_name_needs_quote(self, name: str) -> int: + """检查 LLVM 标识符是否需要引号(以数字开头或含 '.')""" + if name is None: + return 0 + if '0' <= name[0] <= '9': + return 1 + for i in name: + if i == '.': + return 1 + return 0 + + # ============================================================ + # _format_func_type_str — 从 Function 对象生成函数类型字符串 + # + # 格式: ret_ty (param1_ty, param2_ty, ...) + # 例如: void ({i32, i32}*, i32) + # ============================================================ + def _format_func_type_str(self, pool: memhub.MemBuddy | t.CPtr, + buf: t.CChar | t.CPtr, buf_size: t.CSizeT, + func: llvmlite.Function | t.CPtr) -> int: + """从 Function 对象生成函数类型字符串""" + if buf is None or func is None or buf_size == 0: + return 0 + buf[0] = '\0' + # 打印返回类型(使用访问器函数避免跨模块直接字段访问) + ret_ty: llvmlite.LLVMType | t.CPtr = llvmlite.function_get_ret_ty(func) + ret_buf: t.CChar | t.CPtr = pool.alloc(128) + if ret_buf is not None and ret_ty is not None: + ret_buf[0] = '\0' + llvmlite.TypePrint(ret_buf, 128, ret_ty, pool) + self._vtable_strcat(buf, buf_size, ret_buf) + self._vtable_strcat(buf, buf_size, " (") + + # 遍历参数(使用访问器函数避免跨模块直接字段访问) + cur: llvmlite.Param | t.CPtr = llvmlite.function_get_param_head(func) + first: int = 1 + param_buf: t.CChar | t.CPtr = pool.alloc(128) + _pc: int = 0 + while cur is not None: + _pc += 1 + if _pc > 100: + break + if first == 0: + self._vtable_strcat(buf, buf_size, ", ") + if param_buf is not None: + param_buf[0] = '\0' + param_ty: llvmlite.LLVMType | t.CPtr = llvmlite.param_get_ty(cur) + if param_ty is not None: + llvmlite.TypePrint(param_buf, 128, param_ty, pool) + self._vtable_strcat(buf, buf_size, param_buf) + cur = llvmlite.param_get_next(cur) + first = 0 + self._vtable_strcat(buf, buf_size, ")") + return 1 + + # ============================================================ + # _collect_vtable_methods — 收集类的虚方法信息 + # + # 1. 继承父类虚方法(父类方法排在子类方法之前,保持槽位顺序一致) + # 2. 收集当前类虚方法(跳过已继承的) + # + # 结果存入 self.VtFullNames/VtMethodNames/VtParentSha1s/VtMethodCount + # (原模块级 _g_vt_*),并设置 entry.VTableMethodCount / + # VTableMethods(stdlib 分配,供虚分派跨模块查询)。 + # + # 返回 1=有虚方法 / 0=无方法或失败 + # ============================================================ + def _collect_vtable_methods(self, trans: HT.Translator | t.CPtr, + cd: ast.ClassDef | t.CPtr, + class_name: str) -> int: + """收集虚方法信息,设置 entry.VTableMethods/VTableMethodCount""" + if trans is None or cd is None or class_name is None: + return 0 + + pool: memhub.MemBuddy | t.CPtr = trans.Pool + mod: llvmlite.LLVMModule | t.CPtr = trans.Module + # 懒导入(find_func_global 探测方法实际定义类用) + import lib.core.Handles.HandlesExprCall as HandlesExprCall + + children: list[ast.AST | t.CPtr] | t.CPtr = cd.children + if children is None: + return 0 + cn: t.CSizeT = children.__len__() + + # 1. 收集虚方法信息 + # stdlib 分配:method_names_buf 存到 StructEntry.VTableMethods(跨文件永久存活), + # 必须迁出 mb 池 reset 区间,否则 1b 每文件 reset_to(mark1) 会回收导致悬空。 + full_names_buf: t.CSizeT | t.CPtr = stdlib.malloc(8 * VTBL_METHOD_MAX) + method_names_buf: t.CSizeT | t.CPtr = stdlib.malloc(8 * VTBL_METHOD_MAX) + # 记录每个方法的父类 SHA1(非 0=继承方法用父模块 SHA1 mangling,0=当前类方法) + method_parent_sha1s: t.CSizeT | t.CPtr = stdlib.malloc(8 * VTBL_METHOD_MAX) + if full_names_buf is None or method_names_buf is None or method_parent_sha1s is None: + return 0 + string.memset(full_names_buf, 0, 8 * VTBL_METHOD_MAX) + string.memset(method_names_buf, 0, 8 * VTBL_METHOD_MAX) + string.memset(method_parent_sha1s, 0, 8 * VTBL_METHOD_MAX) + + method_count: int = 0 + + # ============================================================ + # 1.5 继承父类虚方法 + # + # 父类虚方法排在子类虚方法之前,保持 vtable 槽位顺序一致。 + # 如果子类覆盖了方法,full_name 用子类的;否则用父类的。 + # 用 SHA1 感知查找,规避跨模块同名 find_struct 找错 + # ============================================================ + vt_self_entry: HandlesStruct.StructEntry | t.CPtr = HandlesStruct.find_struct_by_module( + class_name, trans.ModuleSha1) + # 多继承:遍历所有父类(声明顺序),vtable 方法合并(短名去重,先声明父类优先) + parent_count: int = HandlesStruct.get_parent_count(class_name) + if parent_count > 0: + for pi in range(parent_count): + pname: str = HandlesStruct.get_parent_name_at(class_name, pi) + if pname is None: + continue + # 查找父类 entry(优先同模块 SHA1 匹配) + vt_parent_entry: HandlesStruct.StructEntry | t.CPtr = HandlesStruct.find_struct_by_module( + pname, trans.ModuleSha1) + if vt_parent_entry is None: + # 跨模块继承: 父类在不同模块定义(SHA1 不同),回退到按类名查找 + vt_parent_entry = HandlesStruct.find_struct(pname) + parent_vt_count: int = 0 + if vt_parent_entry is not None: + parent_vt_count = vt_parent_entry.VTableMethodCount + if parent_vt_count > 0: + for pvi in range(parent_vt_count): + if method_count >= VTBL_METHOD_MAX: + break + pmethod_name: str = None + if vt_parent_entry is not None: + pmethod_name = HandlesStruct.get_vtable_method_name(pname, pvi) + if pmethod_name is None: + continue + # 多继承 vtable 去重:方法短名已存在跳过(先声明父类优先) + if self._field_name_exists(method_names_buf, method_count, pmethod_name) != 0: + continue + # 检查子类是否覆盖了该方法,以及是否标记 @t.NoVTable + child_overrides: int = 0 + child_nvt: int = 0 + for ci2 in range(cn): + stmt2: ast.AST | t.CPtr = children.get(ci2) + if stmt2 is None: + continue + if stmt2.kind() != ast.ASTKind.FunctionDef: + continue + fd2: ast.FunctionDef | t.CPtr = (ast.FunctionDef | t.CPtr)(stmt2) + if fd2 is not None and fd2.name is not None: + if string.strcmp(fd2.name, pmethod_name) == 0: + child_overrides = 1 + # 检查子类覆盖方法是否标记 @t.NoVTable + if fd2.decorator_list is not None: + if self._has_decorator(fd2.decorator_list, "NoVTable") == 1: + child_nvt = 1 + break + # 构造 full_name + # 子类覆盖且未标记 NoVTable → 用子类实现 + # 子类未覆盖 或 子类覆盖但标记 NoVTable → 用实际定义类实现(保持 vtable 槽位) + # + # 多层继承修复: 直接父类可能只是继承而非定义该方法 + # (如 ElectricCar 继承 Car 的 is_running 实际定义在 Vehicle), + # 沿父类链向上用 find_func_global("类名.方法名") 探测实际定义类, + # 避免生成 "Car.is_running" 这类找不到函数的 full_name → vtable 槽变 null。 + def_class: str = class_name + if child_overrides == 1 and child_nvt == 0: + def_class = class_name + else: + def_class = pname + # 多继承:沿 pname 的 MRO 祖先链探测实际定义类(跳过自身,先声明父类优先) + mro_ptr: t.CSizeT | t.CPtr = HandlesStruct.get_mro_chain(pool, pname) + mro_i: int = 1 + while mro_ptr is not None and mro_ptr[mro_i] != 0: + anc: str = (str | t.CPtr)(t.CVoid(mro_ptr[mro_i], t.CPtr)) + if anc is not None: + probe_buf: t.CChar | t.CPtr = pool.alloc(128) + if probe_buf is not None: + viperlib.snprintf(probe_buf, 128, "%s.%s", anc, pmethod_name) + if HandlesExprCall.find_func_global(probe_buf) is not None: + def_class = anc + break + mro_i += 1 + pfname_buf: t.CChar | t.CPtr = pool.alloc(128) + if pfname_buf is not None: + viperlib.snprintf(pfname_buf, 128, "%s.%s", def_class, pmethod_name) + full_names_buf[method_count] = t.CSizeT(pfname_buf) + # 复制方法名(短名) + pmname_len: t.CSizeT = string.strlen(pmethod_name) + pmname_buf: t.CChar | t.CPtr = stdlib.malloc(pmname_len + 1) + if pmname_buf is not None: + string.strcpy(pmname_buf, pmethod_name) + method_names_buf[method_count] = t.CSizeT(pmname_buf) + # 记录 mangling 用的 SHA1(继承未覆盖的方法用实际定义类的模块 SHA1) + if child_overrides == 1 and child_nvt == 0: + # 子类覆盖: 用当前模块 SHA1(保持 0) + method_parent_sha1s[method_count] = 0 + else: + # 继承未覆盖: 用实际定义类的模块 SHA1(跨模块继承时 mangling 正确) + def_entry2: HandlesStruct.StructEntry | t.CPtr = HandlesStruct.find_struct( + def_class) + if def_entry2 is not None and def_entry2.ModuleSha1 is not None: + method_parent_sha1s[method_count] = t.CSizeT(def_entry2.ModuleSha1) + else: + method_parent_sha1s[method_count] = 0 + method_count += 1 + + # 2. 收集当前类的虚方法(跳过已从父类继承的) + for ci in range(cn): + stmt: ast.AST | t.CPtr = children.get(ci) + if stmt is None: + continue + if stmt.kind() != ast.ASTKind.FunctionDef: + continue + fd: ast.FunctionDef | t.CPtr = (ast.FunctionDef | t.CPtr)(stmt) + if fd is None or fd.name is None: + continue + if method_count >= VTBL_METHOD_MAX: + break + + mname: str = fd.name + # 跳过构造函数和特殊方法(不应放入虚表) + if string.strcmp(mname, "__init__") == 0: + continue + if string.strcmp(mname, "__before_init__") == 0: + continue + if string.strcmp(mname, "__new__") == 0: + continue + # 函数级装饰器过滤:判断方法是否应该进入虚表 + if self._should_method_be_virtual(cd, fd, trans) == 0: + continue + # 检查是否已从父类继承(避免重复) + already_in_vt: int = 0 + for mi in range(method_count): + exist_addr: t.CSizeT = method_names_buf[mi] + if exist_addr != 0: + exist_name: str = (str | t.CPtr)(t.CVoid(exist_addr, t.CPtr)) + if exist_name is not None and string.strcmp(exist_name, mname) == 0: + already_in_vt = 1 + break + if already_in_vt == 1: + continue + # 构造 full_name = "ClassName.method_name" + fname_buf: t.CChar | t.CPtr = pool.alloc(128) + if fname_buf is not None: + viperlib.snprintf(fname_buf, 128, "%s.%s", class_name, mname) + full_names_buf[method_count] = t.CSizeT(fname_buf) + + # 复制方法名 + mname_len: t.CSizeT = string.strlen(mname) + mname_buf: t.CChar | t.CPtr = stdlib.malloc(mname_len + 1) + if mname_buf is not None: + string.strcpy(mname_buf, mname) + method_names_buf[method_count] = t.CSizeT(mname_buf) + + method_count += 1 + + # 暂存结果(_generate_vtable 复用) + self.VtFullNames = full_names_buf + self.VtMethodNames = method_names_buf + self.VtParentSha1s = method_parent_sha1s + self.VtMethodCount = method_count + + # 设置 entry 元数据(虚分派查询用;必须在本类方法体翻译前就绪, + # 否则方法体内 self.虚方法 调用无法虚分派) + if vt_self_entry is not None and method_count > 0: + vt_self_entry.VTableMethodCount = method_count + vt_self_entry.VTableMethods = method_names_buf + + if method_count == 0: + return 0 + return 1 + + # ============================================================ + # _generate_vtable — 生成 VTable 全局变量 + # + # 1. 收集 class body 中所有 FunctionDef 作为虚方法 + # 2. 构造 VTable 类型 { i8*, i8*, ... } + # 3. 构造初始化字符串 { i8* bitcast (...), ... } + # 4. 创建全局变量 @"SHA1.ClassName.vtable" + # 5. 存储虚方法名列表到 StructEntry + # ============================================================ + def _generate_vtable(self, trans: HT.Translator | t.CPtr, + cd: ast.ClassDef | t.CPtr, + class_name: str) -> int: + """生成 VTable 全局变量""" + if trans is None or cd is None or class_name is None: + return 0 + + # 懒导入 + import lib.core.Handles.HandlesFunctions as HandlesFunctions + import lib.core.Handles.HandlesExprCall as HandlesExprCall + + pool: memhub.MemBuddy | t.CPtr = trans.Pool + mod: llvmlite.LLVMModule | t.CPtr = trans.Module + + # 收集虚方法信息(继承父类 + 自身,结果存 self.VtFullNames 等暂存区) + # 同时设置 entry.VTableMethodCount/VTableMethods(虚分派查询用) + if self._collect_vtable_methods(trans, cd, class_name) == 0: + return 0 + full_names_buf: t.CSizeT | t.CPtr = self.VtFullNames + method_names_buf: t.CSizeT | t.CPtr = self.VtMethodNames + method_parent_sha1s: t.CSizeT | t.CPtr = self.VtParentSha1s + method_count: int = self.VtMethodCount + # 重新获取 entry(后续存储 VTableMethods 用) + vt_self_entry: HandlesStruct.StructEntry | t.CPtr = HandlesStruct.find_struct_by_module( + class_name, trans.ModuleSha1) + + # 2. 构造 VTable 类型: { i8*, i8*, ..., i8* } + i8_ty: llvmlite.LLVMType | t.CPtr = llvmlite.Int8(pool) + i8_ptr_ty: llvmlite.LLVMType | t.CPtr = llvmlite.Ptr(pool, i8_ty) + + first_node: llvmlite.ParamNode | t.CPtr = None + tail_node: llvmlite.ParamNode | t.CPtr = None + for i in range(method_count): + pnode: llvmlite.ParamNode | t.CPtr = llvmlite.new_param_node(pool, i8_ptr_ty) + if pnode is None: + continue + tail_node = llvmlite.param_list_append(first_node, tail_node, pnode) + if first_node is None: + first_node = tail_node + + vtable_ty: llvmlite.LLVMType | t.CPtr = llvmlite.Struct(pool, first_node, method_count, None) + if vtable_ty is None: + return 0 + + # 3. 构造初始化字符串 + # 大 vtable(如 MemBuddy 28+ 方法)每个方法 bitcast 约 100+ 字节, + # 4096 可能写满导致截断/strlen 越界,用 16384 预留足够空间。 + init_buf: t.CChar | t.CPtr = pool.alloc(16384) + if init_buf is None: + return 0 + init_buf[0] = '\0' + self._vtable_strcat(init_buf, 16384, "{ ") + + for i in range(method_count): + if i > 0: + self._vtable_strcat(init_buf, 16384, ", ") + + full_name_addr: t.CSizeT = full_names_buf[i] + if full_name_addr == 0: + self._vtable_strcat(init_buf, 16384, "i8* null") + continue + + full_name: str = (str | t.CPtr)(t.CVoid(full_name_addr, t.CPtr)) + + # 检查是否是继承方法(method_parent_sha1s 非 0 表示用父模块 SHA1 mangling) + parent_sha1_addr: t.CSizeT = method_parent_sha1s[i] + if parent_sha1_addr != 0: + # 继承方法: 用父类模块 SHA1 做 mangling + parent_sha1: str = (str | t.CPtr)(t.CVoid(parent_sha1_addr, t.CPtr)) + mangled_name: str = HandlesFunctions._mangle_name_with_sha1(parent_sha1, full_name) + # 从全局函数表查找(跨模块函数不在当前模块表中) + func: llvmlite.Function | t.CPtr = HandlesExprCall.find_func_global(full_name) + else: + # 当前类方法: 用当前模块 SHA1 + mangled_name: str = HandlesFunctions._mangle_name(trans, full_name) + func: llvmlite.Function | t.CPtr = HandlesExprCall.find_func_in_table( + trans._funcs, trans._func_count, full_name) + # 当前模块表找不到时,回退到全局表 + if func is None: + func = HandlesExprCall.find_func_global(full_name) + + # func 可能已被 1b reset_to(mark1) 回收(跨模块继承方法在定义文件翻译后被 reset)。 + # 悬空指针非 NULL 但内容已被复用,_format_func_type_str 解引用会沿垃圾 Next 链 + # 指针追逐导致无限分配(TypePrint 每次 pool.alloc(512) → 单文件暴涨 900MB OOM)。 + # 因此 func 非 NULL 时也须用 _is_valid_ptr 校验,失败回退到 TypeStr。 + func_valid: int = 0 + if func is not None: + if trans.Pool is not None: + # 继承方法(parent_sha1_addr != 0):func 来自其他模块,该模块 1b 翻译 + # 后已被 reset_to(mark1) 回收,_is_valid_ptr 存在假阳性(块头复用后仍 + # 看似有效),直接判定无效走 TypeStr 回退,避免解引用悬空 func 崩溃。 + if parent_sha1_addr != 0: + func_valid = 0 + elif trans.Pool._is_valid_ptr(func) != 0: + func_valid = 1 + if func_valid == 0: + # 回退到全局表完整 entry 的 TypeStr(stdlib 深拷贝,跨文件永久存活)。 + ge: HandlesExprCall.FuncEntry | t.CPtr = HandlesExprCall.find_func_entry_global(full_name) + if ge is not None and ge.TypeStr is not None: + self._vtable_strcat(init_buf, 16384, "i8* bitcast (") + self._vtable_strcat(init_buf, 16384, ge.TypeStr) + self._vtable_strcat(init_buf, 16384, "* @") + if self._vtable_name_needs_quote(mangled_name) != 0: + self._vtable_strcat(init_buf, 16384, "\"") + self._vtable_strcat(init_buf, 16384, mangled_name) + self._vtable_strcat(init_buf, 16384, "\"") + else: + self._vtable_strcat(init_buf, 16384, mangled_name) + self._vtable_strcat(init_buf, 16384, " to i8*)") + continue + self._vtable_strcat(init_buf, 16384, "i8* null") + continue + + # 构造函数类型字符串 + func_ty_buf: t.CChar | t.CPtr = pool.alloc(512) + if func_ty_buf is None: + self._vtable_strcat(init_buf, 16384, "i8* null") + continue + self._format_func_type_str(pool, func_ty_buf, 512, func) + + # 构造 bitcast 字符串: i8* bitcast (func_ty* @mangled to i8*) + self._vtable_strcat(init_buf, 16384, "i8* bitcast (") + self._vtable_strcat(init_buf, 16384, func_ty_buf) + self._vtable_strcat(init_buf, 16384, "* @") + + if self._vtable_name_needs_quote(mangled_name) != 0: + self._vtable_strcat(init_buf, 16384, "\"") + self._vtable_strcat(init_buf, 16384, mangled_name) + self._vtable_strcat(init_buf, 16384, "\"") + else: + self._vtable_strcat(init_buf, 16384, mangled_name) + self._vtable_strcat(init_buf, 16384, " to i8*)") + + self._vtable_strcat(init_buf, 16384, " }") + + # 4. 构造 VTable 全局变量名 + vtable_name_buf: t.CChar | t.CPtr = pool.alloc(128) + if vtable_name_buf is None: + return 0 + viperlib.snprintf(vtable_name_buf, 128, "%s.vtable", class_name) + vtable_mangled: str = HandlesFunctions._mangle_name(trans, vtable_name_buf) + + # 5. 创建全局变量 + gv: llvmlite.GlobalVariable | t.CPtr = llvmlite.new_global_variable( + pool, vtable_mangled, vtable_ty) + if gv is None: + return 0 + gv.Initializer = init_buf + gv.IsConstant = 1 + gv.Linkage = "internal" + + # 添加到模块 + llvmlite.module_add_global(mod, gv) + + # 6. 存储虚方法名列表到 StructEntry(直接用 entry,规避跨模块同名 find_struct 找错) + if vt_self_entry is not None: + vt_self_entry.VTableMethods = method_names_buf + vt_self_entry.VTableMethodCount = method_count + + return 0 + + # ============================================================ + # _translate_oop_methods — 扫描 class body 中的方法并翻译 + # + # 遍历 ClassDef.children,对每个 FunctionDef: + # - 标记 OOP(mark_as_oop) + # - 如果是 __init__,标记 has_init + # - 翻译方法(生成 SHA1.ClassName.method_name 函数) + # 翻译完所有方法后,生成 __before_init__ 函数 + # ============================================================ + def _translate_oop_methods(self, trans: HT.Translator | t.CPtr, + cd: ast.ClassDef | t.CPtr, + struct_ty: llvmlite.LLVMType | t.CPtr, + class_name: str, + mark_only: int = 0) -> int: + """扫描 class body 中的方法并翻译,生成 __before_init__ + + mark_only: 0=全量翻译(默认),1=只设置 IsOOP/HasNew/HasInit 标志(不翻译方法体) + """ + if trans is None or cd is None or struct_ty is None or class_name is None: + return 0 + + children: list[ast.AST | t.CPtr] | t.CPtr = cd.children + if children is None: + return 0 + + cn: t.CSizeT = children.__len__() + has_method: int = 0 + has_init: int = 0 + has_new: int = 0 + + # 提前用类型指针定位 entry(规避跨模块同名类 find_struct 找错) + oop_entry: HandlesStruct.StructEntry | t.CPtr = HandlesStruct.find_struct_by_type(struct_ty) + + # 第一遍:检测是否有方法,标记 OOP,并注册装饰器元数据 + for ci in range(cn): + stmt: ast.AST | t.CPtr = children.get(ci) + if stmt is None: + continue + if stmt.kind() == ast.ASTKind.FunctionDef: + has_method = 1 + fd_check: ast.FunctionDef | t.CPtr = (ast.FunctionDef | t.CPtr)(stmt) + if fd_check is not None and fd_check.name is not None: + if string.strcmp(fd_check.name, "__init__") == 0: + has_init = 1 + if string.strcmp(fd_check.name, "__new__") == 0: + has_new = 1 + # 注册装饰器元数据(@property/@staticmethod/@classmethod/@x.setter 等)。 + # 此处(含 mark_only=1 的 struct 预注册阶段)注册, + # 确保其他模块在 App 文件翻译时能识别属性访问。 + fd_meta: int = self._extract_func_meta(fd_check.decorator_list) + if fd_meta != 0: + self.register_method_meta(class_name, fd_check.name, fd_meta) + + if has_method == 0: + # 子类没有自己的方法,但可能继承了父类的虚方法 + # 用 oop_entry 直接获取 ParentName,规避 find_struct 按名查找找错 + parent_name: str = None + if oop_entry is not None: + parent_name = oop_entry.ParentName + if parent_name is not None: + parent_vt_count: int = HandlesStruct.get_vtable_method_count(parent_name) + if parent_vt_count > 0: + has_method = 1 # 标记为有方法(继承的虚方法) + if has_method == 0: + return 0 + + # 标记为 OOP 结构体 + if oop_entry is not None: + oop_entry.IsOOP = 1 + if has_init != 0: + oop_entry.HasInit = 1 + if has_new != 0: + oop_entry.HasNew = 1 + + # mark_only 模式:只设置标志,不翻译方法体 + if mark_only != 0: + return 0 + + # 防重入:方法体翻译前先标记 MethodsEmitted=1。 + # 根因:若等全部方法译完再标记,翻译 __iter__(返回 list[T]|t.CPtr)时, + # 返回类型注解会再次触发 _specialize_generic_class,此时 MethodsEmitted + # 仍为 0,走补译分支把同一特化类方法全部重发 → invalid redefinition。 + if oop_entry is not None: + oop_entry.MethodsEmitted = 1 + + # 第二遍:翻译每个方法 + # 翻译方法体前先预注册 vtable 元数据(VTableMethods/VTableMethodCount)。 + # 根因:方法体翻译先于 _generate_vtable,若不预注册,方法体内的 + # self.虚方法 调用(如 MemManager.calloc 里的 self.alloc)读不到 + # VTableMethods,虚分派失败,被静态绑定到本类实现(基类 alloc 返回 + # None),导致 calloc 永远返回 NULL。 + oop_has_vt_pre: int = 0 + if oop_entry is not None: + oop_has_vt_pre = oop_entry.HasVTable + if oop_has_vt_pre == 1: + self._collect_vtable_methods(trans, cd, class_name) + for ci in range(cn): + stmt: ast.AST | t.CPtr = children.get(ci) + if stmt is None: + continue + if stmt.kind() == ast.ASTKind.FunctionDef: + fd: ast.FunctionDef | t.CPtr = (ast.FunctionDef | t.CPtr)(stmt) + if fd is not None and fd.name is not None: + self._translate_method(trans, fd, struct_ty, class_name) + + # 如果有虚表,先生成 VTable 全局变量(设置 VTableMethodCount) + # 必须在 __before_init__ 之前,否则 __before_init__ 读不到 VTableMethodCount + # 用 oop_entry 直接检查,规避跨模块同名 find_struct 找错 + has_vt_flag: int = 0 + if oop_entry is not None: + has_vt_flag = oop_entry.HasVTable + if has_vt_flag == 1: + self._generate_vtable(trans, cd, class_name) + + # 生成 __before_init__ 函数(零值填充 + 默认值赋值 + vtable 指针设置) + self._generate_before_init(trans, struct_ty, class_name) + + return 0 + + # ============================================================ + # _translate_method — 翻译单个方法 + # + # 生成: define @SHA1.ClassName.method_name(Ptr(StructTy) %self, ...) + # + # self 参数处理: + # - 类型 Ptr(struct_ty),直接注册为 SSA 值(不创建 alloca) + # - 使 self.field 能通过 GEP 直接访问原始结构体 + # ============================================================ + def _translate_method(self, trans: HT.Translator | t.CPtr, + fd: ast.FunctionDef | t.CPtr, + struct_ty: llvmlite.LLVMType | t.CPtr, + class_name: str) -> int: + """翻译单个方法,返回 0""" + if trans is None or fd is None or struct_ty is None or class_name is None: + return 0 + + # 懒导入 + import lib.core.Handles.HandlesFunctions as HandlesFunctions + import lib.core.Handles.HandlesVar as HandlesVar + import lib.core.Handles.HandlesBody as HandlesBody + import lib.core.Handles.HandlesType as HandlesType + import lib.core.Handles.HandlesExprCall as HandlesExprCall + + pool: memhub.MemBuddy | t.CPtr = trans.Pool + mod: llvmlite.LLVMModule | t.CPtr = trans.Module + imported_modules: str = trans._imported_modules + from_imports: str = trans._from_imports + funcs_ptr: HandlesExprCall.FuncEntry | t.CPtr = trans._funcs + func_count: int = trans._func_count + + i32_ty: llvmlite.LLVMType | t.CPtr = llvmlite.Int32(pool) + self_ptr_ty: llvmlite.LLVMType | t.CPtr = llvmlite.Ptr(pool, struct_ty) + + method_name: str = fd.name + + # 提取装饰器元数据(@property/@staticmethod/@classmethod/@x.setter/@x.deleter) + func_meta: int = self._extract_func_meta(fd.decorator_list) + # property setter/deleter 函数名带 $set/$del 后缀,避免与 getter 冲突 + method_name_buf: t.CChar | t.CPtr = pool.alloc(128) + if method_name_buf is None: + return 0 + viperlib.snprintf(method_name_buf, 128, "%s", fd.name) + if func_meta & META_PROP_SETTER != 0: + string.strcat(method_name_buf, "$set") + elif func_meta & META_PROP_DELETER != 0: + string.strcat(method_name_buf, "$del") + method_name = method_name_buf + + is_static_m: int = 0 + is_class_m: int = 0 + if func_meta & META_STATIC != 0: + is_static_m = 1 + if func_meta & META_CLASS != 0: + is_class_m = 1 + + # 构建方法全名: ClassName.method_name + full_name_buf: t.CChar | t.CPtr = pool.alloc(128) + if full_name_buf is None: + return 0 + viperlib.snprintf(full_name_buf, 128, "%s.%s", class_name, method_name) + full_name: str = full_name_buf + + # SHA1 命名空间混淆 + mangled_name: str = HandlesFunctions._mangle_name(trans, full_name) + + # 推断返回类型 + ret_ty: llvmlite.LLVMType | t.CPtr = None + if fd.returns is not None: + ret_ty = HandlesType.resolve_annotation_type( + pool, fd.returns, imported_modules, from_imports, trans) + if ret_ty is None and fd.returns is not None: + if HandlesType.has_decorator_marker(fd.returns, "State") != 0: + ret_ty = llvmlite.Void(pool) + if ret_ty is None: + # __init__ 和 __before_init__ 返回 void + if string.strcmp(method_name, "__init__") == 0: + ret_ty = llvmlite.Void(pool) + # __new__ 返回 Ptr(struct_ty)(结构体指针作为存储空间) + elif string.strcmp(method_name, "__new__") == 0: + ret_ty = llvmlite.Ptr(pool, struct_ty) + else: + param_types_str: str = HandlesType.build_param_types_str(pool, fd.args) + ret_ty = HandlesType.infer_return_type( + pool, fd.children, param_types_str) + + # 创建 LLVM 函数 + func: llvmlite.Function | t.CPtr = llvmlite.create_function( + pool, mod, mangled_name, ret_ty) + if func is None: + return 0 + + # 提取默认参数信息(普通方法 args[0] 是 self,不含在 param_count 中; + # @staticmethod 无 self,param_count 为完整参数数) + # 注意: 必须先把属性赋给显式类型为 list[...] | t.CPtr 的局部变量再调用 __len__(), + # 否则编译器无法识别属性返回的 list 类型,GEP base 会变成 i32 0 导致 llc 报错 + md_defaults: t.CVoid | t.CPtr = None + md_default_count: int = 0 + md_param_count: int = 0 + md_args_node: ast.Arguments | t.CPtr = fd.args + if md_args_node is not None: + md_ags: ast.Arguments | t.CPtr = (ast.Arguments | t.CPtr)(md_args_node) + if md_ags.args is not None: + md_alist: list[ast.AST | t.CPtr] | t.CPtr = md_ags.args + if is_static_m != 0: + md_param_count = md_alist.__len__() + else: + md_param_count = md_alist.__len__() - 1 + if md_ags.defaults is not None: + md_dlist: list[ast.AST | t.CPtr] | t.CPtr = md_ags.defaults + md_defaults = md_dlist + md_default_count = md_dlist.__len__() + + # 注册到函数表(用 ClassName.method_name 作为查找名,支持后缀匹配) + max_funcs: int = 256 + if HandlesExprCall.add_func_to_table(funcs_ptr, func_count, full_name, func, max_funcs, + md_defaults, md_default_count, md_param_count, + pool) == 0: + trans._func_count = func_count + 1 + + # 添加 self/cls 参数(Ptr(struct_ty));@staticmethod 无 self,跳过 + # @classmethod 的 cls 也用 Ptr(struct_ty),首参名取 args[0](如 cls) + if is_static_m == 0: + first_pname: str = "self" + if is_class_m != 0 and fd.args is not None: + fd_ags: ast.Arguments | t.CPtr = (ast.Arguments | t.CPtr)(fd.args) + if fd_ags.args is not None and fd_ags.args.__len__() > 0: + fd_first_arg: ast.Arg | t.CPtr = (ast.Arg | t.CPtr)(fd_ags.args.get(0)) + if fd_first_arg is not None and fd_first_arg.arg is not None: + first_pname = fd_first_arg.arg + first_pname_buf: t.CChar | t.CPtr = pool.alloc(32) + if first_pname_buf is not None: + viperlib.snprintf(first_pname_buf, 32, "%%%s", first_pname) + llvmlite.add_param(pool, func, self_ptr_ty, first_pname_buf) + + # 添加其他参数(支持类型注解;@staticmethod 从索引 0 开始,其余跳过索引 0 的 self/cls) + args_node: ast.Arguments | t.CPtr = fd.args + if args_node is not None: + ags: ast.Arguments | t.CPtr = (ast.Arguments | t.CPtr)(args_node) + if ags.args is not None: + alist: list[ast.AST | t.CPtr] | t.CPtr = ags.args + an: t.CSizeT = alist.__len__() + start_idx: int = 0 + if is_static_m == 0: + start_idx = 1 + for ai in range(start_idx, an): + arg: ast.Arg | t.CPtr = (ast.Arg | t.CPtr)(alist.get(ai)) + if arg is not None and arg.arg is not None: + param_ty: llvmlite.LLVMType | t.CPtr = i32_ty + if arg.annotation is not None: + resolved: llvmlite.LLVMType | t.CPtr = HandlesType.resolve_annotation_type( + pool, arg.annotation, imported_modules, from_imports, trans) + if resolved is not None: + # 裸类形参 → Ptr(struct):按"对象即指针"引用传参。 + # 若按 struct 值传参,self.Head = node 会取局部拷贝地址 + # (append 返回后悬垂,G5 Test4 head.Value 读到垃圾)。 + match resolved: + case llvmlite.LLVMType.Struct(_, _, _): + param_ty = llvmlite.Ptr(pool, resolved) + case _: + param_ty = resolved + pname: t.CChar | t.CPtr = pool.alloc(32) + if pname is not None: + viperlib.snprintf(pname, 32, "%%%s", arg.arg) + llvmlite.add_param(pool, func, param_ty, pname) + + # 参数添加完成,补全全局函数表的 TypeStr(供 vtable 在 func 被 reset 后使用) + HandlesExprCall.update_global_func_typestr(pool, full_name, func) + + # 创建 entry 块 + entry_blk: llvmlite.BasicBlock | t.CPtr = llvmlite.create_block(pool, func, "entry") + if entry_blk is None: + return 0 + + # 创建方法专属 builder + func_builder: llvmlite.IRBuilder | t.CPtr = llvmlite.new_builder(pool, func) + if func_builder is None: + return 0 + llvmlite.position_at_end(func_builder, entry_blk) + + # 进入函数作用域 + HandlesVar.enter_scope(trans.SymTab, SCOPE_FUNCTION) + + # 为 self/cls 创建 alloca 并 store(与其他参数一致);@staticmethod 无 self,跳过 + # 修复: 之前 self 注册为 SSA 值导致 translate_name_value 错误地 load 一次 + # 将 Ptr(struct_ty) 变成 struct 值,引发变参函数 ABI 不匹配崩溃 + if is_static_m == 0: + self_alloca: llvmlite.Value | t.CPtr = llvmlite.build_alloca(func_builder, self_ptr_ty) + if self_alloca is not None: + self_var_name: str = "self" + self_ssa_name: str = "%self" + if is_class_m != 0 and args_node is not None: + cags: ast.Arguments | t.CPtr = (ast.Arguments | t.CPtr)(args_node) + if cags.args is not None and cags.args.__len__() > 0: + cfirst: ast.Arg | t.CPtr = (ast.Arg | t.CPtr)(cags.args.get(0)) + if cfirst is not None and cfirst.arg is not None: + self_var_name = cfirst.arg + self_ssa_name_buf: t.CChar | t.CPtr = pool.alloc(32) + if self_ssa_name_buf is not None: + viperlib.snprintf(self_ssa_name_buf, 32, "%%%s", cfirst.arg) + self_ssa_name = self_ssa_name_buf + HandlesVar.define_var(trans.SymTab, self_var_name, self_alloca) + # 设置 self/cls 的类型注解类名(属性访问 lookup_field 回退查找用) + HandlesVar.set_var_annot_class_name(trans.SymTab, self_var_name, class_name) + self_val: llvmlite.Value | t.CPtr = llvmlite.SSAValue(pool, self_ptr_ty, self_ssa_name) + llvmlite.build_store(func_builder, self_val, self_alloca) + + # 为其他参数创建 alloca 并 store(与普通函数一致; + # @staticmethod 从索引 0 开始,其余跳过索引 0 的 self/cls 参数) + if args_node is not None: + ags2: ast.Arguments | t.CPtr = (ast.Arguments | t.CPtr)(args_node) + if ags2.args is not None: + alist2: list[ast.AST | t.CPtr] | t.CPtr = ags2.args + an2: t.CSizeT = alist2.__len__() + start_idx2: int = 0 + if is_static_m == 0: + start_idx2 = 1 + for ai2 in range(start_idx2, an2): + arg2: ast.Arg | t.CPtr = (ast.Arg | t.CPtr)(alist2.get(ai2)) + if arg2 is not None and arg2.arg is not None: + param_ty2: llvmlite.LLVMType | t.CPtr = i32_ty + if arg2.annotation is not None: + resolved2: llvmlite.LLVMType | t.CPtr = HandlesType.resolve_annotation_type( + pool, arg2.annotation, imported_modules, from_imports, trans) + if resolved2 is not None: + # 与 add_param 保持一致:裸类形参 → Ptr(struct)(对象即指针) + match resolved2: + case llvmlite.LLVMType.Struct(_, _, _): + param_ty2 = llvmlite.Ptr(pool, resolved2) + case _: + param_ty2 = resolved2 + alloca: llvmlite.Value | t.CPtr = llvmlite.build_alloca(func_builder, param_ty2) + if alloca is not None: + HandlesVar.define_var(trans.SymTab, arg2.arg, alloca) + # 存储原始类型注解的类名(方法调用检测时,Ptr(i8) 回退到类名查找结构体) + if arg2.annotation is not None: + cls_nm_oc: str = HandlesType.extract_class_name_from_annotation( + arg2.annotation, imported_modules) + if cls_nm_oc is not None: + HandlesVar.set_var_annot_class_name( + trans.SymTab, arg2.arg, cls_nm_oc) + pname2: t.CChar | t.CPtr = pool.alloc(32) + if pname2 is not None: + viperlib.snprintf(pname2, 32, "%%%s", arg2.arg) + param_val: llvmlite.Value | t.CPtr = llvmlite.SSAValue( + pool, param_ty2, pname2) + llvmlite.build_store(func_builder, param_val, alloca) + + # 保存模块级作用域状态 + old_func: llvmlite.Function | t.CPtr = trans._cur_func + old_builder: llvmlite.IRBuilder | t.CPtr = trans._cur_builder + old_global_count: int = trans._global_name_count + old_nonlocal_count: int = trans._nonlocal_name_count + old_env_count: int = trans._closure_env_count + + trans._cur_func = func + trans._cur_builder = func_builder + HT.clear_scope_names(trans) + + # 预扫描方法体:为局部变量提前创建 alloca + body: list[ast.AST | t.CPtr] | t.CPtr = fd.children + if body is not None: + bn: t.CSizeT = body.__len__() + for bi in range(bn): + stmt: ast.AST | t.CPtr = body.get(bi) + if stmt is not None: + HandlesBody.pre_scan_allocas(trans, stmt) + + # 翻译方法体 + if body is not None: + bn2: t.CSizeT = body.__len__() + for bi2 in range(bn2): + stmt2: ast.AST | t.CPtr = body.get(bi2) + if stmt2 is not None: + HandlesBody.translate_stmt(trans, stmt2) + + # 如果返回类型为 void,添加 ret void;否则添加隐式 ret 0 + is_void: int = 0 + if ret_ty is not None: + match ret_ty: + case llvmlite.LLVMType.Void(): + is_void = 1 + + if is_void != 0: + if llvmlite.builder_cur_block_is_terminated(func_builder) == 0: + llvmlite.build_ret_void(func_builder) + else: + last_is_return: int = 0 + if body is not None: + bn3: t.CSizeT = body.__len__() + if bn3 > 0: + last_stmt: ast.AST | t.CPtr = body.get(bn3 - 1) + if last_stmt is not None and last_stmt.kind() == ast.ASTKind.Return: + last_is_return = 1 + if last_is_return == 0: + if llvmlite.builder_cur_block_is_terminated(func_builder) == 0: + # 根据返回类型生成正确的零值返回 + _m_is_void: int = 0 + _m_is_ptr: int = 0 + if ret_ty is not None: + match ret_ty: + case llvmlite.LLVMType.Void(): + _m_is_void = 1 + case llvmlite.LLVMType.Ptr(_m_pe): + _m_is_ptr = 1 + if _m_is_void != 0: + llvmlite.build_ret_void(func_builder) + elif _m_is_ptr != 0: + _m_null_val: llvmlite.Value | t.CPtr = llvmlite.ConstNull(pool, ret_ty, "null") + llvmlite.build_ret(func_builder, _m_null_val) + else: + _m_zero_val: llvmlite.Value | t.CPtr = llvmlite.const_int32(pool, 0) + llvmlite.build_ret(func_builder, _m_zero_val) + + # 恢复模块级作用域 + HandlesVar.exit_scope(trans.SymTab) + trans._cur_func = old_func + trans._cur_builder = old_builder + trans._global_name_count = old_global_count + trans._nonlocal_name_count = old_nonlocal_count + trans._closure_env_count = old_env_count + + return 0 + + # ============================================================ + # _generate_before_init — 生成 __before_init__ 函数 + # + # 生成: define void @SHA1.ClassName.__before_init__(Ptr(StructTy) %self) + # + # 执行: + # 1. store zeroinitializer 到 %self(零值填充) + # 2. 逐字段 store 默认值(如有) + # 3. ret void + # ============================================================ + def _generate_before_init(self, trans: HT.Translator | t.CPtr, + struct_ty: llvmlite.LLVMType | t.CPtr, + class_name: str) -> int: + """生成 __before_init__ 函数,返回 0""" + if trans is None or struct_ty is None or class_name is None: + return 0 + + import lib.core.Handles.HandlesFunctions as HandlesFunctions + import lib.core.Handles.HandlesVar as HandlesVar + import lib.core.Handles.HandlesExpr as HandlesExpr + import lib.core.Handles.HandlesExprCall as HandlesExprCall + + pool: memhub.MemBuddy | t.CPtr = trans.Pool + mod: llvmlite.LLVMModule | t.CPtr = trans.Module + funcs_ptr: HandlesExprCall.FuncEntry | t.CPtr = trans._funcs + func_count: int = trans._func_count + + self_ptr_ty: llvmlite.LLVMType | t.CPtr = llvmlite.Ptr(pool, struct_ty) + void_ty: llvmlite.LLVMType | t.CPtr = llvmlite.Void(pool) + + # 构建函数名: ClassName.__before_init__ + full_name_buf: t.CChar | t.CPtr = pool.alloc(128) + if full_name_buf is None: + return 0 + viperlib.snprintf(full_name_buf, 128, "%s.__before_init__", class_name) + full_name: str = full_name_buf + + mangled_name: str = HandlesFunctions._mangle_name(trans, full_name) + + # 创建函数 + func: llvmlite.Function | t.CPtr = llvmlite.create_function( + pool, mod, mangled_name, void_ty) + if func is None: + return 0 + + # 注册到函数表 + max_funcs: int = 256 + rc_add: int = HandlesExprCall.add_func_to_table(funcs_ptr, func_count, full_name, func, max_funcs, None, 0, 0, pool) + if rc_add == 0: + trans._func_count = func_count + 1 + + # 添加 self 参数 + llvmlite.add_param(pool, func, self_ptr_ty, "%self") + + # 参数添加完成,补全全局函数表的 TypeStr + rc_ut: int = HandlesExprCall.update_global_func_typestr(pool, full_name, func) + + # 创建 entry 块 + builder + entry_blk: llvmlite.BasicBlock | t.CPtr = llvmlite.create_block(pool, func, "entry") + if entry_blk is None: + return 0 + func_builder: llvmlite.IRBuilder | t.CPtr = llvmlite.new_builder(pool, func) + if func_builder is None: + return 0 + llvmlite.position_at_end(func_builder, entry_blk) + + # 注册 self 为 SSA 值 + self_val: llvmlite.Value | t.CPtr = llvmlite.SSAValue(pool, self_ptr_ty, "%self") + + # 1. 零值填充: store zeroinitializer, Ptr(struct_ty)* %self + # 空 struct({})在 LLVM 中不允许 zeroinitializer(invalid type for null constant), + # 无字段类(接口/标记类,如多继承的 Vec2Extra)跳过零值填充; + # @t.CVTable 类必有 vtable 指针字段(非空),不受影响。 + struct_fcount_zi: int = llvmlite.get_struct_fcount(struct_ty) + if struct_fcount_zi > 0: + zero: llvmlite.Value | t.CPtr = llvmlite.ConstZero(pool, struct_ty) + if zero is not None: + llvmlite.build_store(func_builder, zero, self_val) + + # 1.5 如果有虚表,store vtable 全局地址到 __vtable__ 字段(索引 0) + # 用 find_struct_by_type 定位 entry,规避跨模块同名 find_struct 找错 + bi_entry: HandlesStruct.StructEntry | t.CPtr = HandlesStruct.find_struct_by_type(struct_ty) + bi_has_vt: int = 0 + if bi_entry is not None: + bi_has_vt = bi_entry.HasVTable + if bi_has_vt == 1: + vt_method_count: int = 0 + if bi_entry is not None: + vt_method_count = bi_entry.VTableMethodCount + if vt_method_count > 0: + # 构造 vtable 类型 { i8*, i8*, ..., i8* } + vt_i8_ty: llvmlite.LLVMType | t.CPtr = llvmlite.Int8(pool) + vt_i8_ptr_ty: llvmlite.LLVMType | t.CPtr = llvmlite.Ptr(pool, vt_i8_ty) + + vt_first_node: llvmlite.ParamNode | t.CPtr = None + vt_prev_node: llvmlite.ParamNode | t.CPtr = None + for vti in range(vt_method_count): + vtnode: llvmlite.ParamNode | t.CPtr = llvmlite.new_param_node(pool, vt_i8_ptr_ty) + if vtnode is None: + continue + if vt_first_node is None: + vt_first_node = vtnode + if vt_prev_node is not None: + llvmlite.paramnode_set_next(vt_prev_node, vtnode) + vt_prev_node = vtnode + + vt_ty: llvmlite.LLVMType | t.CPtr = llvmlite.Struct(pool, vt_first_node, vt_method_count, None) + vt_ptr_ty: llvmlite.LLVMType | t.CPtr = llvmlite.Ptr(pool, vt_ty) + + # 构造 vtable 全局变量名 + vt_name_buf: t.CChar | t.CPtr = pool.alloc(128) + if vt_name_buf is not None: + viperlib.snprintf(vt_name_buf, 128, "%s.vtable", class_name) + vt_full_name: str = vt_name_buf + vt_mangled: str = HandlesFunctions._mangle_name(trans, vt_full_name) + + # GEP 到 __vtable__ 字段(索引 0) + vt_slot: llvmlite.Value | t.CPtr = llvmlite.build_gep_struct( + func_builder, struct_ty, vt_i8_ptr_ty, self_val, 0) + if vt_slot is not None: + # 创建全局变量引用 Value + vt_ref: llvmlite.Value | t.CPtr = llvmlite.new_value(pool) + if vt_ref is not None: + llvmlite.value_set_ty(vt_ref, vt_ptr_ty) + llvmlite.value_set_isconst(vt_ref, 1) + # Name 格式: @"mangled" 或 @mangled + vt_ref_name: t.CChar | t.CPtr = pool.alloc(256) + if vt_ref_name is not None: + vt_ref_name[0] = '\0' + if self._vtable_name_needs_quote(vt_mangled) != 0: + viperlib.snprintf(vt_ref_name, 256, "@\"%s\"", vt_mangled) + else: + viperlib.snprintf(vt_ref_name, 256, "@%s", vt_mangled) + llvmlite.value_set_name(vt_ref, vt_ref_name) + + # bitcast 到 i8* + vt_as_i8: llvmlite.Value | t.CPtr = llvmlite.build_bitcast( + func_builder, vt_ref, vt_i8_ptr_ty) + if vt_as_i8 is not None: + llvmlite.build_store(func_builder, vt_as_i8, vt_slot) + + # 2. 逐字段 store 默认值(用 bi_entry 直接访问,规避跨模块同名 find_struct 找错) + if bi_entry is not None: + for fi in range(bi_entry.FieldCount): + fe: HandlesStruct.FieldEntry | t.CPtr = HandlesStruct._get_field_entry( + bi_entry, fi) + if fe is None or fe.DefaultVal is None: + continue + # 翻译默认值表达式 + default_val: llvmlite.Value | t.CPtr = HandlesExpr.translate_value( + func_builder, pool, mod, fe.DefaultVal, None, 0, trans) + if default_val is None: + continue + # GEP 到字段 + field_ptr: llvmlite.Value | t.CPtr = llvmlite.build_gep_struct( + func_builder, struct_ty, fe.Ty, self_val, fe.Index) + if field_ptr is None: + continue + # 类型转换并 store + default_val = HandlesExpr.coerce_to_type(func_builder, default_val, fe.Ty, fe.DefaultVal) + llvmlite.build_store(func_builder, default_val, field_ptr) + + # 3. ret void + llvmlite.build_ret_void(func_builder) + + return 0 diff --git a/App/lib/core/Gen/FuncGenMixin.vp b/App/lib/core/Gen/FuncGenMixin.vp new file mode 100644 index 0000000..f79fd82 --- /dev/null +++ b/App/lib/core/Gen/FuncGenMixin.vp @@ -0,0 +1,1128 @@ +import t, c +from stdint import * +import ast +import llvmlite +import memhub +import string +import viperlib +import stdio +import stdlib +import lib.core.VLogger as VLogger +import lib.core.Handles.HandlesTranslator as HT +import lib.core.Handles.HandlesVar as HandlesVar +import lib.core.Handles.HandlesExprCall as HandlesExprCall +import lib.core.Handles.HandlesType as HandlesType +import lib.core.Handles.HandlesBody as HandlesBody +import lib.core.Handles.HandlesImports as HandlesImports + + +# ============================================================ +# FuncGenMixin - 函数/方法声明与翻译 Mixin(对象化 P5-1,wiki/14-oo-refactor.md) +# +# 从 HandlesFunctions.vp 迁移:模块级纯函数(trans 首参,无全局状态) +# → 类方法(self 替代,trans 参数保留)。 +# +# 迁移原则(与 P2/P3/P4 一致,行为零变化): +# 1. 方法保留原函数签名(含 trans 首参),仅函数体内的 +# 本模块函数调用改为 self.xxx(...) +# 2. 外部模块调用(HandlesExprCall.xxx/HandlesType.xxx 等)保留模块前缀 +# 3. HandlesFunctions.vp 原函数保留为"委托":本地模块级单例 _g_gen +# (BuildPipeline/main 注入)cast 成 Generator 类型 +# +# @t.NoVTable:静态绑定(方法沿 MRO 直接调用 + this 调整)。 +# ============================================================ + + +# ============================================================ +# HandlesFunctions - 函数定义处理(trans 单参模式) +# +# 参考 Python 版 TransPyC FunctionHandle +# +# 函数有自己的局部作用域,通过 HandlesVar.enter_scope/exit_scope +# 管理嵌套作用域链,翻译函数体前进入函数作用域,翻译完退出。 +# ============================================================ + + +# 作用域类型常量(本地副本,与 HandlesFunctions.vp 保持一致) +SCOPE_FUNCTION: t.CDefine = 1 + + +# ============================================================ +# FuncGenMixin - 函数属性/命名/声明/翻译 +# ============================================================ +@t.NoVTable +class FuncGenMixin: + """函数/方法翻译 Mixin(纯方法化迁移,无状态字段)""" + + # ============================================================ + # extract_func_attrs - 从 decorator_list 提取 c.Attribute 属性 + # + # 支持 @c.Attribute(t.attr.xxx()) 和 @c.Attribute(t.attr.xxx) 形式 + # 也支持 @c.Attribute(t.attr.llvm.xxx) 形式 + # + # 返回 LLVM IR 属性字符串(如 "alwaysinline nounwind"),无属性返回 None + # ============================================================ + def extract_func_attrs(self, pool: memhub.MemBuddy | t.CPtr, + decorator_list: list[ast.AST | t.CPtr] | t.CPtr, + imported_modules: str) -> t.CChar | t.CPtr: + """从 decorator_list 提取 c.Attribute 属性,返回 LLVM IR 属性字符串""" + if decorator_list is None: + return None + dn: t.CSizeT = decorator_list.__len__() + if dn == 0: + return None + + attrs_buf: t.CChar | t.CPtr = pool.alloc(256) + if attrs_buf is None: + return None + attrs_buf[0] = '\0' + found_any: int = 0 + + for di in range(dn): + deco: ast.AST | t.CPtr = decorator_list.get(di) + if deco is None or deco.kind() != ast.ASTKind.Call: + continue + call_node: ast.Call | t.CPtr = (ast.Call | t.CPtr)(deco) + if call_node.func is None or call_node.func.kind() != ast.ASTKind.Attribute: + continue + + # 检测 c.Attribute + func_attr: ast.Attribute | t.CPtr = (ast.Attribute | t.CPtr)(call_node.func) + if func_attr.attr is None or string.strcmp(func_attr.attr, "Attribute") != 0: + continue + if func_attr.value is None or func_attr.value.kind() != ast.ASTKind.Name: + continue + c_name: ast.Name | t.CPtr = (ast.Name | t.CPtr)(func_attr.value) + if c_name.id is None or string.strcmp(c_name.id, "c") != 0: + continue + if HandlesImports.is_module_imported(imported_modules, "c") == 0: + continue + + # 遍历参数提取属性 + if call_node.args is None: + continue + args_list: list[ast.AST | t.CPtr] | t.CPtr = call_node.args + an: t.CSizeT = args_list.__len__() + for ai in range(an): + arg_node: ast.AST | t.CPtr = args_list.get(ai) + if arg_node is None: + continue + + # 提取属性名(t.attr.xxx / t.attr.xxx() / t.attr.llvm.xxx) + attr_name: str = self._get_attr_name_from_node(arg_node) + if attr_name is None: + continue + + # 映射到 LLVM 属性名并追加 + if self._append_llvm_attr(attrs_buf, attr_name) != 0: + found_any = 1 + # 追加成功后,如果不是最后一个属性,添加空格分隔 + # 在下一次追加前由 _append_str 处理 + + if found_any == 0: + return None + return attrs_buf + + def _get_attr_name_from_node(self, node: ast.AST | t.CPtr) -> str: + """从 AST 节点提取属性名 + + 支持: + - Call(func=Attribute(...)): t.attr.always_inline() -> "always_inline" + - Attribute: t.attr.packed -> "packed" + - Attribute(t.attr.llvm.xxx): t.attr.llvm.nounwind -> "nounwind" + """ + if node is None: + return None + k: int = node.kind() + + # Call 节点: t.attr.always_inline() + if k == ast.ASTKind.Call: + call: ast.Call | t.CPtr = (ast.Call | t.CPtr)(node) + if call.func is None or call.func.kind() != ast.ASTKind.Attribute: + return None + at: ast.Attribute | t.CPtr = (ast.Attribute | t.CPtr)(call.func) + return at.attr + + # Attribute 节点: t.attr.packed 或 t.attr.llvm.nounwind + if k == ast.ASTKind.Attribute: + at2: ast.Attribute | t.CPtr = (ast.Attribute | t.CPtr)(node) + return at2.attr + + return None + + def _append_llvm_attr(self, attrs_buf: t.CChar | t.CPtr, attr_name: str) -> int: + """将属性名映射到 LLVM 属性名并追加到缓冲区 + + 返回 1 表示已追加,0 表示不支持该属性 + """ + if attrs_buf is None or attr_name is None: + return 0 + + # 先确定映射的 LLVM 属性名 + llvm_name: str = None + if string.strcmp(attr_name, "always_inline") == 0: + llvm_name = "alwaysinline" + elif string.strcmp(attr_name, "noinline") == 0: + llvm_name = "noinline" + elif string.strcmp(attr_name, "noreturn") == 0: + llvm_name = "noreturn" + elif string.strcmp(attr_name, "pure") == 0: + llvm_name = "readonly" + elif string.strcmp(attr_name, "const") == 0: + llvm_name = "readnone" + elif string.strcmp(attr_name, "nounwind") == 0: + llvm_name = "nounwind" + elif string.strcmp(attr_name, "noredzone") == 0: + llvm_name = "noredzone" + elif string.strcmp(attr_name, "willreturn") == 0: + llvm_name = "willreturn" + elif string.strcmp(attr_name, "mustprogress") == 0: + llvm_name = "mustprogress" + else: + # packed/aligned/section/visibility/weak 等不支持作为函数内联属性 + return 0 + + # 支持的属性:如果缓冲区非空,先追加空格分隔 + if attrs_buf[0] != '\0': + self._append_str(attrs_buf, " ") + self._append_str(attrs_buf, llvm_name) + return 1 + + def _append_str(self, buf: t.CChar | t.CPtr, s: str) -> None: + """将字符串追加到 buf 末尾(用 strlen+strcpy 模拟 strcat)""" + if buf is None or s is None: + return + cur_len: t.CSizeT = string.strlen(buf) + string.strcpy(buf + cur_len, s) + + # ============================================================ + # _mangle_name - 为名称添加 SHA1 前缀 + # + # 返回 "sha1.name" 格式的混淆名。若 ModuleSha1 为 None 或名称已带 + # SHA1 前缀(16 hex + '.'),则原样返回。 + # ============================================================ + def _mangle_name(self, trans: HT.Translator | t.CPtr, name: str) -> str: + """为任意名称添加 SHA1 前缀(不做 main/export 检查)""" + if trans is None or name is None: + return name + if trans.ModuleSha1 is None: + return name + name_len: t.CSizeT = string.strlen(name) + # 已带 SHA1 前缀(16 hex + '.')则跳过 + if name_len > 17: + is_sha1: int = 1 + for i in range(16): + c: t.CChar = name[i] + if not (('0' <= c <= '9') or ('a' <= c <= 'f')): + is_sha1 = 0 + break + if is_sha1 != 0 and name[16] == '.': + return name + sha1: str = trans.ModuleSha1 + sha1_len: t.CSizeT = string.strlen(sha1) + mangled: str = stdlib.malloc(sha1_len + name_len + 2) + if mangled is None: + return name + string.strcpy(mangled, sha1) + mangled[sha1_len] = '.' + string.strcpy(mangled + sha1_len + 1, name) + return mangled + + # ============================================================ + # _mangle_name_with_sha1 — 用指定 SHA1 为名称添加前缀 + # + # 用于跨模块 vtable 继承: 继承方法需要用父模块的 SHA1 做 mangling, + # 而非当前模块的 SHA1。 + # ============================================================ + def _mangle_name_with_sha1(self, sha1: str, name: str) -> str: + """用指定 SHA1 为名称添加前缀(不做 main/export 检查)""" + if sha1 is None or name is None: + return name + name_len: t.CSizeT = string.strlen(name) + # 已带 SHA1 前缀(16 hex + '.')则跳过 + if name_len > 17: + is_sha1: int = 1 + for i in range(16): + c2: t.CChar = name[i] + if not (('0' <= c2 <= '9') or ('a' <= c2 <= 'f')): + is_sha1 = 0 + break + if is_sha1 != 0 and name[16] == '.': + return name + sha1_len: t.CSizeT = string.strlen(sha1) + mangled: str = stdlib.malloc(sha1_len + name_len + 2) + if mangled is None: + return name + string.strcpy(mangled, sha1) + mangled[sha1_len] = '.' + string.strcpy(mangled + sha1_len + 1, name) + return mangled + + # ============================================================ + # _mangle_func_name - 为函数名添加 SHA1 前缀(含 main/export 检查) + # + # 规则: + # - main 函数不加前缀(程序入口点) + # - has_export 非 0 时不加前缀(t.CExport 导出函数) + # - 已带 SHA1 前缀的不再加 + # - ModuleSha1 为 None 时不加前缀 + # ============================================================ + def _mangle_func_name(self, trans: HT.Translator | t.CPtr, name: str, + has_export: int) -> str: + """为函数名添加 SHA1 前缀(检查 main/export)""" + if trans is None or name is None: + return name + if has_export != 0: + return name + if string.strcmp(name, "main") == 0: + return name + return self._mangle_name(trans, name) + + # ============================================================ + # forward_declare_functions - 预扫描所有顶层 FunctionDef,创建前向声明 + # + # 解决同模块内前向引用问题:如 viperlib.py 中 sprintf(行15) 调用 + # vsnprintf(行41),但 vsnprintf 定义在后面。 + # + # 对每个顶层 FunctionDef: + # 1. 推断返回类型和参数类型 + # 2. 计算 mangled name(含 SHA1 前缀) + # 3. 创建 declare(IsDeclared=1) + # 4. 添加参数 + # 5. 注册到函数表 + # + # 后续 translate_function_def 会通过 find_func_in_module 找到已有的 declare, + # 复用之(清除 IsDeclared,跳过参数创建,直接添加函数体)。 + # ============================================================ + def forward_declare_functions(self, trans: HT.Translator | t.CPtr, + tree: ast.AST | t.CPtr) -> int: + """预扫描所有顶层 FunctionDef,创建前向声明""" + if trans is None or tree is None: + return 0 + pool: memhub.MemBuddy | t.CPtr = trans.Pool + mod: llvmlite.LLVMModule | t.CPtr = trans.Module + if pool is None or mod is None: + return 0 + + imported_modules: str = trans._imported_modules + from_imports: str = trans._from_imports + funcs_ptr: HandlesExprCall.FuncEntry | t.CPtr = trans._funcs + + i32_ty: llvmlite.LLVMType | t.CPtr = llvmlite.Int32(pool) + i8_ty: llvmlite.LLVMType | t.CPtr = llvmlite.Int8(pool) + i8_ptr_ty: llvmlite.LLVMType | t.CPtr = llvmlite.Ptr(pool, i8_ty) + + ch: list[ast.AST | t.CPtr] | t.CPtr = tree.children + if ch is None: + return 0 + + # 解析函数签名期间临时切换到"仅声明"模式: + # 签名里的泛型类注解(如 _empty_like(a: ndarray[t.CDouble]))会触发泛型特化, + # 若此时特化立即翻译方法体,方法体前向引用同模块后续函数(如 _empty_like 自身) + # 会因 declare 尚未创建而报"裸名调用未定义且未导入"。 + # 临时 declare_only=1 使特化只注册结构体(mark_only 不译方法体), + # 方法体由后续 resolve_annotation_type 命中已注册结构体时补译 + # (_specialize_generic_class 的 Phase B 补译分支)。 + saved_declare_only: int = trans._declare_only + trans._declare_only = 1 + cn_count: t.CSizeT = ch.__len__() + + for ci in range(cn_count): + child: ast.AST | t.CPtr = ch.get(ci) + if child is None: + continue + if child.kind() != ast.ASTKind.FunctionDef: + continue + fd: ast.FunctionDef | t.CPtr = (ast.FunctionDef | t.CPtr)(child) + if fd is None or fd.name is None: + continue + + # 推断返回类型 + ret_ty: llvmlite.LLVMType | t.CPtr = None + if fd.returns is not None: + ret_ty = HandlesType.resolve_annotation_type( + pool, fd.returns, imported_modules, from_imports, trans) + if ret_ty is None and fd.returns is not None: + if HandlesType.has_decorator_marker(fd.returns, "State") != 0: + ret_ty = llvmlite.Void(pool) + if ret_ty is None: + ret_ty = i32_ty + + # 检测 CExtern/State/CExport + has_extern: int = 0 + has_state: int = 0 + has_export: int = 0 + if fd.returns is not None: + has_extern = HandlesType.has_decorator_marker(fd.returns, "CExtern") + has_state = HandlesType.has_decorator_marker(fd.returns, "State") + has_export = HandlesType.has_decorator_marker(fd.returns, "CExport") + is_extern_decl: int = 0 + if has_extern != 0 or has_state != 0: + is_extern_decl = 1 + + # 计算 mangled name + if has_extern != 0 or has_state != 0 or has_export != 0 or string.strcmp(fd.name, "main") == 0: + mangled_name: str = fd.name + else: + mangled_name = self._mangle_func_name(trans, fd.name, 0) + + # 如果函数已存在(如重复定义),跳过 + existing: llvmlite.Function | t.CPtr = HandlesExprCall.find_func_in_module(mod, mangled_name) + if existing is not None: + continue + + # 创建 declare + func: llvmlite.Function | t.CPtr = llvmlite.create_declare( + pool, mod, mangled_name, ret_ty) + if func is None: + continue + + # 提取默认参数信息 + # 注意: 必须先把属性赋给显式类型为 list[...] | t.CPtr 的局部变量再调用 __len__(), + # 否则编译器无法识别属性返回的 list 类型,GEP base 会变成 i32 0 导致 llc 报错 + fd_args_node: ast.Arguments | t.CPtr = fd.args + fd_defaults: t.CVoid | t.CPtr = None + fd_default_count: int = 0 + fd_param_count: int = 0 + if fd_args_node is not None: + fd_ags: ast.Arguments | t.CPtr = (ast.Arguments | t.CPtr)(fd_args_node) + if fd_ags.args is not None: + fd_alist: list[ast.AST | t.CPtr] | t.CPtr = fd_ags.args + fd_param_count = fd_alist.__len__() + if fd_ags.defaults is not None: + fd_dlist: list[ast.AST | t.CPtr] | t.CPtr = fd_ags.defaults + fd_defaults = fd_dlist + fd_default_count = fd_dlist.__len__() + + # 注册到函数表(用裸名 fd.name,不是 mangled_name) + max_funcs: int = 256 + cur_count: int = trans._func_count + if HandlesExprCall.add_func_to_table(funcs_ptr, cur_count, fd.name, func, max_funcs, + fd_defaults, fd_default_count, fd_param_count, + trans.Pool) == 0: + trans._func_count = cur_count + 1 + + # 注册 CExport 函数到全局表 + if (has_export != 0 or has_state != 0) and trans.ModuleSha1 is not None: + HandlesExprCall.register_cexport_func(trans.ModuleSha1, fd.name) + + # 添加参数 + args_node: ast.Arguments | t.CPtr = fd.args + if args_node is not None: + ags: ast.Arguments | t.CPtr = (ast.Arguments | t.CPtr)(args_node) + if ags.args is not None: + alist: list[ast.AST | t.CPtr] | t.CPtr = ags.args + an: t.CSizeT = alist.__len__() + for ai in range(an): + arg: ast.Arg | t.CPtr = (ast.Arg | t.CPtr)(alist.get(ai)) + if arg is None or arg.arg is None: + continue + # t.CVoid 表示空参:跳过 + if arg.annotation is not None: + if HandlesType._is_t_attr(arg.annotation, "CVoid", imported_modules) != 0: + continue + param_ty: llvmlite.LLVMType | t.CPtr = i32_ty + if arg.annotation is not None: + resolved: llvmlite.LLVMType | t.CPtr = HandlesType.resolve_annotation_type( + pool, arg.annotation, imported_modules, from_imports, trans) + if resolved is not None: + # 裸类形参 → Ptr(struct)(对象即指针,与方法形参一致) + match resolved: + case llvmlite.LLVMType.Struct(_, _, _): + param_ty = llvmlite.Ptr(pool, resolved) + case _: + param_ty = resolved + pname: t.CChar | t.CPtr = pool.alloc(32) + if pname is not None: + viperlib.snprintf(pname, 32, "%%%s", arg.arg) + llvmlite.add_param(pool, func, param_ty, pname) + + # *args 变长参数:设置 IsVarArg=1,生成 ... 后缀 + if ags.vararg is not None: + func.IsVarArg = 1 + + # 参数添加完成,补全全局函数表的 TypeStr(供 vtable 在 func 被 reset 后使用) + HandlesExprCall.update_global_func_typestr(trans.Pool, fd.name, func) + + # 恢复原始声明模式 + trans._declare_only = saved_declare_only + return 0 + + # ============================================================ + # 翻译函数定义 FunctionDef(name, args, body, ...) + # + # trans 单参模式:所有共享状态从 trans 获取 + # 函数局部作用域通过 enter_scope/exit_scope 管理 + # ============================================================ + def translate_function_def(self, trans: HT.Translator | t.CPtr, + node: ast.AST | t.CPtr) -> int: + """翻译函数定义,返回新增的变量数(通常为 0,函数定义不增加当前作用域变量)""" + fd: ast.FunctionDef | t.CPtr = (ast.FunctionDef | t.CPtr)(node) + if fd is None or fd.name is None: + return 0 + + pool: memhub.MemBuddy | t.CPtr = trans.Pool + mod: llvmlite.LLVMModule | t.CPtr = trans.Module + imported_modules: str = trans._imported_modules + from_imports: str = trans._from_imports + funcs_ptr: HandlesExprCall.FuncEntry | t.CPtr = trans._funcs + func_count: int = trans._func_count + + i32_ty: llvmlite.LLVMType | t.CPtr = llvmlite.Int32(pool) + + # 推断返回类型:优先使用返回类型注解 + ret_ty: llvmlite.LLVMType | t.CPtr = None + if fd.returns is not None: + ret_ty = HandlesType.resolve_annotation_type( + pool, fd.returns, imported_modules, from_imports, trans) + + # 如果返回类型注解纯装饰器标记(如 t.State,无实际类型),使用 void + # 注意:必须在 infer_return_type 之前检测,因为 infer_return_type 至少返回 i32 + if ret_ty is None and fd.returns is not None: + if HandlesType.has_decorator_marker(fd.returns, "State") != 0: + ret_ty = llvmlite.Void(pool) + + # 如果仍然为 None,扫描 return 语句推断(至少返回 i32) + if ret_ty is None: + param_types_str: str = HandlesType.build_param_types_str(pool, fd.args) + ret_ty = HandlesType.infer_return_type( + pool, fd.children, param_types_str) + # 检测是否为外部声明函数(t.CExtern 或 t.State) + # 语义:t.CExtern 忽略 body 体,仅生成 declare(由链接器解析符号) + # t.State = t.CExtern + t.CExport(既是声明又是导出) + # t.CExport 导出函数不加 SHA1 前缀 + # t.CExtern/t.State/t.CExport 都不加 SHA1 前缀,直接映射到 C 标准库函数名 + is_extern_decl: int = 0 + has_export: int = 0 + has_extern: int = 0 + has_state: int = 0 + if fd.returns is not None: + has_extern = HandlesType.has_decorator_marker(fd.returns, "CExtern") + has_state = HandlesType.has_decorator_marker(fd.returns, "State") + has_export = HandlesType.has_decorator_marker(fd.returns, "CExport") + # t.CExtern/t.State 忽略 body 体,仅声明(无论 body 是否为 pass) + if has_extern != 0 or has_state != 0: + is_extern_decl = 1 + + # SHA1 命名空间:t.CExtern/t.State/t.CExport 不加前缀,直接用裸名 + # (裸名映射到 C 标准库符号,带 sha1 前缀会导致 undefined reference) + # main 函数也不加前缀(程序入口点) + if has_extern != 0 or has_state != 0 or has_export != 0 or string.strcmp(fd.name, "main") == 0: + mangled_name: str = fd.name + else: + mangled_name: str = self._mangle_func_name(trans, fd.name, 0) + + # 注册 CExport 函数到全局表(供跨模块调用查表) + # t.CExport 函数定义用裸名(@strlen),跨模块调用需查表确认用裸名而非 @{sha1}.func + if (has_export != 0 or has_state != 0) and trans.ModuleSha1 is not None: + HandlesExprCall.register_cexport_func(trans.ModuleSha1, fd.name) + + if is_extern_decl != 0: + # 外部声明函数:生成 declare(仅声明,不定义) + # 先检查是否已由 forward_declare_functions 创建,避免重复 declare + existing_extern: llvmlite.Function | t.CPtr = HandlesExprCall.find_func_in_module(mod, mangled_name) + if existing_extern is not None: + # 已存在前向声明,复用之,不再重复创建 + return 0 + + func: llvmlite.Function | t.CPtr = llvmlite.create_declare( + pool, mod, mangled_name, ret_ty) + if func is None: + return 0 + + # 注册到函数表 + max_funcs_extern: int = 256 + if HandlesExprCall.add_func_to_table(funcs_ptr, func_count, fd.name, func, max_funcs_extern, None, 0, 0, pool) == 0: + trans._func_count = func_count + 1 + + # 添加参数(支持类型注解) + args_node_extern: ast.Arguments | t.CPtr = fd.args + if args_node_extern is not None: + ags_e: ast.Arguments | t.CPtr = (ast.Arguments | t.CPtr)(args_node_extern) + if ags_e.args is not None: + alist_e: list[ast.AST | t.CPtr] | t.CPtr = ags_e.args + an_e: t.CSizeT = alist_e.__len__() + for ai_e in range(an_e): + arg_e: ast.Arg | t.CPtr = (ast.Arg | t.CPtr)(alist_e.get(ai_e)) + if arg_e is not None and arg_e.arg is not None: + # t.CVoid 表示空参:跳过,不添加到函数签名 + if arg_e.annotation is not None: + if HandlesType._is_t_attr(arg_e.annotation, "CVoid", imported_modules) != 0: + continue + param_ty_e: llvmlite.LLVMType | t.CPtr = i32_ty + if arg_e.annotation is not None: + resolved_e: llvmlite.LLVMType | t.CPtr = HandlesType.resolve_annotation_type( + pool, arg_e.annotation, imported_modules, from_imports, trans) + if resolved_e is not None: + # 裸类形参 → Ptr(struct)(对象即指针,与方法形参一致) + match resolved_e: + case llvmlite.LLVMType.Struct(_, _, _): + param_ty_e = llvmlite.Ptr(pool, resolved_e) + case _: + param_ty_e = resolved_e + pname_e: t.CChar | t.CPtr = pool.alloc(32) + if pname_e is not None: + viperlib.snprintf(pname_e, 32, "%%%s", arg_e.arg) + llvmlite.add_param(pool, func, param_ty_e, pname_e) + + # 提取 @c.Attribute 装饰器属性并设置到函数 + func_attrs_e: t.CChar | t.CPtr = self.extract_func_attrs(pool, fd.decorator_list, imported_modules) + if func_attrs_e is not None: + llvmlite.function_set_attrs(func, func_attrs_e) + + # 参数添加完成,补全全局函数表的 TypeStr + HandlesExprCall.update_global_func_typestr(pool, fd.name, func) + + return 0 + + # args_node 用于后续 alloca 创建,提前赋值 + args_node: ast.Arguments | t.CPtr = fd.args + + # 检查是否已有前向声明(由 forward_declare_functions 创建) + func: llvmlite.Function | t.CPtr = HandlesExprCall.find_func_in_module(mod, mangled_name) + if func is not None and llvmlite.function_is_declared(func) != 0: + # 复用前向声明:清除 IsDeclared 标记,转为 define + func.IsDeclared = 0 + # 装饰器属性设置(前向声明时未设置) + func_attrs_reuse: t.CChar | t.CPtr = self.extract_func_attrs(pool, fd.decorator_list, imported_modules) + if func_attrs_reuse is not None: + llvmlite.function_set_attrs(func, func_attrs_reuse) + else: + # 创建新的 LLVM 函数(使用 SHA1 混淆名) + func = llvmlite.create_function(pool, mod, mangled_name, ret_ty) + if func is None: + fb_cf: t.CChar | t.CPtr = VLogger.fmt_buf() + if fb_cf is not None: + viperlib.snprintf(fb_cf, 1024, "create_function %s failed", fd.name) + VLogger.error(fb_cf, "FUNC") + return 0 + + # 提取 @c.Attribute 装饰器属性并设置到函数 + func_attrs: t.CChar | t.CPtr = self.extract_func_attrs(pool, fd.decorator_list, imported_modules) + if func_attrs is not None: + llvmlite.function_set_attrs(func, func_attrs) + + # 提取默认参数信息 + tfd_defaults: t.CVoid | t.CPtr = None + tfd_default_count: int = 0 + tfd_param_count: int = 0 + if args_node is not None: + tfd_ags: ast.Arguments | t.CPtr = (ast.Arguments | t.CPtr)(args_node) + if tfd_ags.args is not None: + tfd_alist: list[ast.AST | t.CPtr] | t.CPtr = tfd_ags.args + tfd_param_count = tfd_alist.__len__() + if tfd_ags.defaults is not None: + tfd_dlist: list[ast.AST | t.CPtr] | t.CPtr = tfd_ags.defaults + tfd_defaults = tfd_dlist + tfd_default_count = tfd_dlist.__len__() + + # 注册到函数表 + max_funcs: int = 256 + if HandlesExprCall.add_func_to_table(funcs_ptr, func_count, fd.name, func, max_funcs, + tfd_defaults, tfd_default_count, tfd_param_count, + trans.Pool) == 0: + trans._func_count = func_count + 1 + + # 添加参数(支持类型注解) + if args_node is not None: + ags: ast.Arguments | t.CPtr = (ast.Arguments | t.CPtr)(args_node) + if ags.args is not None: + alist: list[ast.AST | t.CPtr] | t.CPtr = ags.args + an: t.CSizeT = alist.__len__() + for ai in range(an): + arg: ast.Arg | t.CPtr = (ast.Arg | t.CPtr)(alist.get(ai)) + if arg is not None and arg.arg is not None: + # t.CVoid 表示空参:跳过,不添加到函数签名 + if arg.annotation is not None: + if HandlesType._is_t_attr(arg.annotation, "CVoid", imported_modules) != 0: + continue + param_ty: llvmlite.LLVMType | t.CPtr = i32_ty + if arg.annotation is not None: + resolved: llvmlite.LLVMType | t.CPtr = HandlesType.resolve_annotation_type( + pool, arg.annotation, imported_modules, from_imports, trans) + if resolved is not None: + # 裸类形参 → Ptr(struct)(对象即指针,与方法形参一致) + match resolved: + case llvmlite.LLVMType.Struct(_, _, _): + param_ty = llvmlite.Ptr(pool, resolved) + case _: + param_ty = resolved + pname: t.CChar | t.CPtr = pool.alloc(32) + if pname is not None: + viperlib.snprintf(pname, 32, "%%%s", arg.arg) + llvmlite.add_param(pool, func, param_ty, pname) + + # *args 变长参数:设置 IsVarArg=1,生成 ... 后缀 + if ags.vararg is not None: + func.IsVarArg = 1 + + # 参数添加完成,补全全局函数表的 TypeStr + HandlesExprCall.update_global_func_typestr(trans.Pool, fd.name, func) + + # 创建 entry 块 + entry_blk: llvmlite.BasicBlock | t.CPtr = llvmlite.create_block(pool, func, "entry") + if entry_blk is None: + return 0 + + # 创建函数专属 builder + func_builder: llvmlite.IRBuilder | t.CPtr = llvmlite.new_builder(pool, func) + if func_builder is None: + return 0 + llvmlite.position_at_end(func_builder, entry_blk) + + # 进入函数作用域(嵌套符号表) + HandlesVar.enter_scope(trans.SymTab, SCOPE_FUNCTION) + + # PEP 695 泛型函数: def f[T](...) — 设置泛型上下文,类型参数映射到 "int" 兜底。 + # TPV 无泛型函数特化机制(类泛型走 _specialize_generic_class),泛型函数按普通 + # 函数编译;设置上下文使参数注解 T / 方法体中的 T(x) 转换可解析为 int。 + # (注意与类特化的 set_generic_context 一样是全局状态,需在退出作用域前清除。) + tp_names_fn: list[str] | t.CPtr = None + if fd.type_params is not None: + tp_names_fn = fd.type_params + tp_args_fn: list[str] | t.CPtr = list[str](pool, 8) + if tp_args_fn is not None: + tpn_fn: t.CSizeT = fd.type_params.__len__() + tpi_fn: t.CSizeT = 0 + for tpi_fn in range(tpn_fn): + tp_args_fn.append("int") + HandlesType.set_generic_context(tp_names_fn, tp_args_fn) + + # 为参数创建 alloca + if args_node is not None: + ags2: ast.Arguments | t.CPtr = (ast.Arguments | t.CPtr)(args_node) + if ags2.args is not None: + alist2: list[ast.AST | t.CPtr] | t.CPtr = ags2.args + an2: t.CSizeT = alist2.__len__() + for ai2 in range(an2): + arg2: ast.Arg | t.CPtr = (ast.Arg | t.CPtr)(alist2.get(ai2)) + if arg2 is not None and arg2.arg is not None: + # t.CVoid 表示空参:跳过,不创建 alloca + if arg2.annotation is not None: + if HandlesType._is_t_attr(arg2.annotation, "CVoid", imported_modules) != 0: + continue + param_ty2: llvmlite.LLVMType | t.CPtr = i32_ty + if arg2.annotation is not None: + resolved2: llvmlite.LLVMType | t.CPtr = HandlesType.resolve_annotation_type( + pool, arg2.annotation, imported_modules, from_imports, trans) + if resolved2 is not None: + # 与 add_param 保持一致:裸类形参 → Ptr(struct)(对象即指针) + match resolved2: + case llvmlite.LLVMType.Struct(_, _, _): + param_ty2 = llvmlite.Ptr(pool, resolved2) + case _: + param_ty2 = resolved2 + alloca: llvmlite.Value | t.CPtr = llvmlite.build_alloca(func_builder, param_ty2) + if alloca is not None: + HandlesVar.define_var(trans.SymTab, arg2.arg, alloca) + # 存储原始类型注解的类名(方法调用检测时,Ptr(i8) 回退到类名查找结构体) + if arg2.annotation is not None: + cls_nm: str = HandlesType.extract_class_name_from_annotation( + arg2.annotation, imported_modules) + if cls_nm is not None: + HandlesVar.set_var_annot_class_name( + trans.SymTab, arg2.arg, cls_nm) + pname2: t.CChar | t.CPtr = pool.alloc(32) + if pname2 is not None: + viperlib.snprintf(pname2, 32, "%%%s", arg2.arg) + param_val: llvmlite.Value | t.CPtr = llvmlite.SSAValue( + pool, param_ty2, pname2) + llvmlite.build_store(func_builder, param_val, alloca) + + # *args 变长参数:创建 va_list 缓冲区 + 调用 va_start + 注册到符号表 + # 生成 IR: + # %args_va = alloca [24 x i8], align 16 ; va_list 缓冲区(Win64 __va_list_tag) + # %args = bitcast [24 x i8]* %args_va to i8* + # call void @llvm.va_start(i8* %args) ; 初始化 va_list + # 用户函数体内可通过 args 名字读取 va_list 地址(i8*),或用 arg(type) 糖函数 + if ags2.vararg is not None: + vararg_node: ast.Arg | t.CPtr = (ast.Arg | t.CPtr)(ags2.vararg) + if vararg_node is not None and vararg_node.arg is not None: + vararg_name_str: str = vararg_node.arg + # va_list 缓冲区 24 字节(Win64 的 __va_list_tag = {i32,i32,i8*,i8*})+ 16 对齐 + # (对齐 TPC HandlesFunctions.py:1739-1741) + i8_ty_va: llvmlite.LLVMType | t.CPtr = llvmlite.Int8(pool) + i8_ptr_ty_va: llvmlite.LLVMType | t.CPtr = llvmlite.Ptr(pool, i8_ty_va) + va_buf_ty: llvmlite.LLVMType | t.CPtr = llvmlite.Array(pool, i8_ty_va, 24) + va_list_alloca: llvmlite.Value | t.CPtr = llvmlite.build_alloca_aligned( + func_builder, va_buf_ty, 16) + if va_list_alloca is not None: + # i8* 地址(指向 24 字节 va_list 缓冲区)——vararg 名的值语义 + va_list_addr: llvmlite.Value | t.CPtr = llvmlite.build_bitcast( + func_builder, va_list_alloca, i8_ptr_ty_va) + if va_list_addr is not None: + # 注册到符号表(translate_name_value 对 vararg 名特殊处理返回地址) + HandlesVar.define_var(trans.SymTab, vararg_name_str, va_list_alloca) + # 调用 @llvm.va_start(i8* %va_list_addr) + void_ty_va: llvmlite.LLVMType | t.CPtr = llvmlite.Void(pool) + llvmlite.build_call(func_builder, "llvm.va_start", + va_list_addr, 1, void_ty_va, 0) + # 保存到 trans 供 arg(type) 糖函数与 vararg 名翻译使用 + trans._va_list_ptr = va_list_addr + trans._vararg_name = vararg_name_str + + # 保存模块级作用域状态(仅非变量表相关) + old_func: llvmlite.Function | t.CPtr = trans._cur_func + old_builder: llvmlite.IRBuilder | t.CPtr = trans._cur_builder + old_global_count: int = trans._global_name_count + old_nonlocal_count: int = trans._nonlocal_name_count + old_env_count: int = trans._closure_env_count + old_va_list_ptr: llvmlite.Value | t.CPtr = trans._va_list_ptr + old_vararg_name: str = trans._vararg_name + + trans._cur_func = func + trans._cur_builder = func_builder + # 清空 global/nonlocal 名称集合(新函数作用域) + HT.clear_scope_names(trans) + + # 预扫描函数体: + # 1. 先预扫描 Global/Nonlocal 声明(Python 语义:global/nonlocal + # 对整个函数作用域生效,与声明位置无关,故须在任何赋值前注册) + # 2. 再预扫描 AnnAssign 为局部变量提前创建 alloca + body: list[ast.AST | t.CPtr] | t.CPtr = fd.children + if body is not None: + bn: t.CSizeT = body.__len__() + for bi in range(bn): + stmt: ast.AST | t.CPtr = body.get(bi) + if stmt is not None: + HandlesBody.pre_scan_scope_decls(trans, stmt) + for bi in range(bn): + stmt: ast.AST | t.CPtr = body.get(bi) + if stmt is not None: + HandlesBody.pre_scan_allocas(trans, stmt) + + # 翻译函数体 + if body is not None: + bn2: t.CSizeT = body.__len__() + for bi2 in range(bn2): + stmt2: ast.AST | t.CPtr = body.get(bi2) + if stmt2 is not None: + HandlesBody.translate_stmt(trans, stmt2) + + # 如果函数体最后一条语句不是 Return,添加隐式 ret + last_is_return: int = 0 + if body is not None: + bn3: t.CSizeT = body.__len__() + if bn3 > 0: + last_stmt: ast.AST | t.CPtr = body.get(bn3 - 1) + if last_stmt is not None and last_stmt.kind() == ast.ASTKind.Return: + last_is_return = 1 + if last_is_return == 0: + if llvmlite.builder_cur_block_is_terminated(func_builder) == 0: + # 根据返回类型生成正确的零值返回 + # 必须覆盖浮点返回类型:double/float 函数生成 ConstFloat(0.0), + # 否则默认 ret i32 0 类型不匹配(llc: value doesn't match function result type) + _is_void: int = 0 + _is_ptr: int = 0 + _is_float: int = 0 + if ret_ty is not None: + match ret_ty: + case llvmlite.LLVMType.Void(): + _is_void = 1 + case llvmlite.LLVMType.Ptr(_pe): + _is_ptr = 1 + case llvmlite.LLVMType.Float(_fb): + _is_float = 1 + if _is_void != 0: + llvmlite.build_ret_void(func_builder) + elif _is_ptr != 0: + _null_val: llvmlite.Value | t.CPtr = llvmlite.ConstNull(pool, ret_ty, "null") + llvmlite.build_ret(func_builder, _null_val) + elif _is_float != 0: + _zero_f: llvmlite.Value | t.CPtr = llvmlite.ConstFloat(pool, ret_ty, 0.0) + llvmlite.build_ret(func_builder, _zero_f) + else: + _zero_val: llvmlite.Value | t.CPtr = llvmlite.const_int32(pool, 0) + llvmlite.build_ret(func_builder, _zero_val) + + # 恢复模块级作用域(退出函数作用域) + if tp_names_fn is not None: + HandlesType.clear_generic_context() + HandlesVar.exit_scope(trans.SymTab) + trans._cur_func = old_func + trans._cur_builder = old_builder + trans._global_name_count = old_global_count + trans._nonlocal_name_count = old_nonlocal_count + trans._closure_env_count = old_env_count + trans._va_list_ptr = old_va_list_ptr + trans._vararg_name = old_vararg_name + + return 0 + + # ============================================================ + # translate_nested_function_def - 嵌套函数提升 + 闭包创建 + # + # 将嵌套函数提升为顶层函数 @__closure_{name}(i8* %env) -> i32, + # 在父函数中创建闭包对象 {i8* fn_ptr, i8* env_ptr} 并存储到 + # 以函数名命名的局部变量中。 + # + # 闭包结构: {i8* fn_ptr, i8* env_ptr} (16 字节, malloc 分配) + # Env 结构: {i8* ptr0, i8* ptr1, ...} (每个 nonlocal 变量 8 字节,指向父函数 alloca) + # ============================================================ + def translate_nested_function_def(self, trans: HT.Translator | t.CPtr, + node: ast.AST | t.CPtr) -> int: + """翻译嵌套函数定义:提升为顶层函数 + 创建闭包""" + fd: ast.FunctionDef | t.CPtr = (ast.FunctionDef | t.CPtr)(node) + if fd is None or fd.name is None: + return 0 + + pool: memhub.MemBuddy | t.CPtr = trans.Pool + mod: llvmlite.LLVMModule | t.CPtr = trans.Module + func_name: str = fd.name + + i32_ty: llvmlite.LLVMType | t.CPtr = llvmlite.Int32(pool) + i8_ty: llvmlite.LLVMType | t.CPtr = llvmlite.Int8(pool) + i8_ptr_ty: llvmlite.LLVMType | t.CPtr = llvmlite.Ptr(pool, i8_ty) + + # 1. 构建提升后的函数名: __closure_{name}(加 SHA1 前缀避免跨模块冲突) + promoted_name: t.CChar | t.CPtr = pool.alloc(64) + if promoted_name is not None: + viperlib.snprintf(promoted_name, 64, "__closure_%s", func_name) + mangled_promoted: str = self._mangle_name(trans, promoted_name) + + # 2. 创建提升后的函数: define i32 @__closure_{name}(i8* %env) + func: llvmlite.Function | t.CPtr = llvmlite.create_function( + pool, mod, mangled_promoted, i32_ty) + if func is None: + return 0 + llvmlite.add_param(pool, func, i8_ptr_ty, "%env") + + # 3. 创建 entry 块 + builder + entry_blk: llvmlite.BasicBlock | t.CPtr = llvmlite.create_block(pool, func, "entry") + if entry_blk is None: + return 0 + func_builder: llvmlite.IRBuilder | t.CPtr = llvmlite.new_builder(pool, func) + if func_builder is None: + return 0 + llvmlite.position_at_end(func_builder, entry_blk) + + # 4. 进入嵌套函数作用域(嵌套符号表) + HandlesVar.enter_scope(trans.SymTab, SCOPE_FUNCTION) + + # 5. 创建 _env_ptr alloca 并存储 %env 参数 + env_alloca: llvmlite.Value | t.CPtr = llvmlite.build_alloca(func_builder, i8_ptr_ty) + if env_alloca is not None: + HandlesVar.define_var(trans.SymTab, "_env_ptr", env_alloca) + env_param_val: llvmlite.Value | t.CPtr = llvmlite.SSAValue(pool, i8_ptr_ty, "%env") + llvmlite.build_store(func_builder, env_param_val, env_alloca) + + # 6. 保存父函数作用域状态(仅非变量表相关) + old_func: llvmlite.Function | t.CPtr = trans._cur_func + old_builder: llvmlite.IRBuilder | t.CPtr = trans._cur_builder + old_func_name: str = trans._cur_func_name + old_global_count: int = trans._global_name_count + old_nonlocal_count: int = trans._nonlocal_name_count + old_env_count: int = trans._closure_env_count + + # 7. 切换到嵌套函数作用域 + 清空 scope names + trans._cur_func = func + trans._cur_builder = func_builder + trans._cur_func_name = func_name + HT.clear_scope_names(trans) + + # 8. 预扫描函数体: + # a. 先预扫描 Global/Nonlocal 声明(Python 语义:对整个函数作用域生效) + # b. 再预扫描 AnnAssign 为局部变量提前创建 alloca + body: list[ast.AST | t.CPtr] | t.CPtr = fd.children + if body is not None: + bn: t.CSizeT = body.__len__() + for bi in range(bn): + stmt: ast.AST | t.CPtr = body.get(bi) + if stmt is not None: + HandlesBody.pre_scan_scope_decls(trans, stmt) + for bi in range(bn): + stmt: ast.AST | t.CPtr = body.get(bi) + if stmt is not None: + HandlesBody.pre_scan_allocas(trans, stmt) + + # 9. 翻译函数体(Nonlocal 语句会填充 _nonlocal_names) + if body is not None: + bn2: t.CSizeT = body.__len__() + for bi2 in range(bn2): + stmt2: ast.AST | t.CPtr = body.get(bi2) + if stmt2 is not None: + HandlesBody.translate_stmt(trans, stmt2) + + # 10. 隐式 ret + last_is_return: int = 0 + if body is not None: + bn3: t.CSizeT = body.__len__() + if bn3 > 0: + last_stmt: ast.AST | t.CPtr = body.get(bn3 - 1) + if last_stmt is not None and last_stmt.kind() == ast.ASTKind.Return: + last_is_return = 1 + if last_is_return == 0: + zero_val: llvmlite.Value | t.CPtr = llvmlite.const_int32(pool, 0) + llvmlite.build_ret(func_builder, zero_val) + + # 11. 保存嵌套函数的 nonlocal 信息 + nested_nonlocal_count: int = trans._nonlocal_name_count + + # 12. 退出嵌套函数作用域,回到父函数作用域(保留 _nonlocal_names 用于 env 创建) + HandlesVar.exit_scope(trans.SymTab) + trans._cur_func = old_func + trans._cur_builder = old_builder + # NOTE: _nonlocal_names 和 _nonlocal_name_count 仍为嵌套函数的值 + + # 13. 在父函数中创建闭包对象 + parent_builder: llvmlite.IRBuilder | t.CPtr = old_builder + if parent_builder is None: + # 无 builder(模块级嵌套函数?)→ 无法创建闭包,仅恢复状态 + trans._cur_func_name = old_func_name + trans._global_name_count = old_global_count + trans._nonlocal_name_count = old_nonlocal_count + trans._closure_env_count = old_env_count + return 0 + + # 13a. 创建 env: malloc(8 * nested_nonlocal_count) — env 存储指针数组 + # 每个 nonlocal 变量占 8 字节(i8*),指向父函数的 alloca(共享存储) + env_ptr: llvmlite.Value | t.CPtr = None + if nested_nonlocal_count > 0: + env_size: t.CInt64T = nested_nonlocal_count * 8 + env_size_val: llvmlite.Value | t.CPtr = llvmlite.const_int64(pool, env_size) + if env_size_val is not None: + env_size_val.Next = None + env_ptr = llvmlite.build_call( + parent_builder, "malloc", env_size_val, 1, i8_ptr_ty, 0) + + # 为每个 nonlocal 变量存储 alloca 指针到 env(共享存储,修改互相可见) + if env_ptr is not None: + i8_ptr_ptr_ty: llvmlite.LLVMType | t.CPtr = llvmlite.Ptr(pool, i8_ptr_ty) + for ni in range(nested_nonlocal_count): + # 从 _nonlocal_names 缓冲区读取名称 + name_addr: t.CUInt64T = t.CUInt64T(trans._nonlocal_names) + ni * 8 + nl_slot: str | t.CPtr = (t.CVoid | t.CPtr)(name_addr) + nl_name: str = nl_slot[0] + if nl_name is not None: + # 在父函数作用域中查找(Current 已回到父作用域) + var_alloca: llvmlite.Value | t.CPtr = HandlesVar.lookup_var( + trans.SymTab, nl_name) + if var_alloca is not None: + # bitcast alloca 指针为 i8*(擦除类型信息) + alloca_as_i8: llvmlite.Value | t.CPtr = llvmlite.build_bitcast( + parent_builder, var_alloca, i8_ptr_ty) + if alloca_as_i8 is not None: + # GEP to env[ni*8] + offset_val: llvmlite.Value | t.CPtr = llvmlite.const_int32(pool, ni * 8) + slot: llvmlite.Value | t.CPtr = llvmlite.build_gep( + parent_builder, i8_ty, env_ptr, offset_val) + if slot is not None: + # bitcast to i8** and store alloca pointer + slot_typed: llvmlite.Value | t.CPtr = llvmlite.build_bitcast( + parent_builder, slot, i8_ptr_ptr_ty) + if slot_typed is not None: + llvmlite.build_store(parent_builder, alloca_as_i8, slot_typed) + + # 13b. 创建闭包结构: malloc(16) + closure_size_val: llvmlite.Value | t.CPtr = llvmlite.const_int64(pool, 16) + if closure_size_val is not None: + closure_size_val.Next = None + closure_ptr: llvmlite.Value | t.CPtr = llvmlite.build_call( + parent_builder, "malloc", closure_size_val, 1, i8_ptr_ty, 0) + if closure_ptr is None: + # malloc 失败,恢复状态 + trans._cur_func_name = old_func_name + trans._global_name_count = old_global_count + trans._nonlocal_name_count = old_nonlocal_count + trans._closure_env_count = old_env_count + return 0 + + # 13c. 存储 fn_ptr 到 offset 0 + # 创建函数指针类型 i32(i8*)* + fn_param_node: llvmlite.ParamNode | t.CPtr = llvmlite.new_param_node(pool, i8_ptr_ty) + fn_func_ty: llvmlite.LLVMType | t.CPtr = llvmlite.Func(pool, i32_ty, fn_param_node, 1) + fn_func_ptr_ty: llvmlite.LLVMType | t.CPtr = llvmlite.Ptr(pool, fn_func_ty) + + # 创建函数引用 Value(类型为 i32(i8*)*,使用 SHA1 混淆名) + fn_ptr_name: t.CChar | t.CPtr = pool.alloc(64) + if fn_ptr_name is not None: + # SHA1 前缀名含 '.' 需要加引号(如 @"sha1.__closure_func") + if string.strchr(mangled_promoted, '.') is not None: + viperlib.snprintf(fn_ptr_name, 64, "@\"%s\"", mangled_promoted) + else: + viperlib.snprintf(fn_ptr_name, 64, "@%s", mangled_promoted) + fn_ptr_val: llvmlite.Value | t.CPtr = llvmlite.SSAValue(pool, fn_func_ptr_ty, fn_ptr_name) + + # bitcast 函数指针到 i8*(闭包存储 i8* 类型) + fn_as_i8ptr: llvmlite.Value | t.CPtr = llvmlite.build_bitcast( + parent_builder, fn_ptr_val, i8_ptr_ty) + fn_slot: llvmlite.Value | t.CPtr = llvmlite.build_bitcast( + parent_builder, closure_ptr, llvmlite.Ptr(pool, i8_ptr_ty)) + if fn_slot is not None and fn_as_i8ptr is not None: + llvmlite.build_store(parent_builder, fn_as_i8ptr, fn_slot) + + # 13d. 存储 env_ptr 到 offset 8 + eight_val: llvmlite.Value | t.CPtr = llvmlite.const_int32(pool, 8) + env_slot_addr: llvmlite.Value | t.CPtr = llvmlite.build_gep( + parent_builder, i8_ty, closure_ptr, eight_val) + if env_slot_addr is not None: + env_slot: llvmlite.Value | t.CPtr = llvmlite.build_bitcast( + parent_builder, env_slot_addr, llvmlite.Ptr(pool, i8_ptr_ty)) + if env_slot is not None: + if env_ptr is not None: + llvmlite.build_store(parent_builder, env_ptr, env_slot) + else: + # 无 nonlocal 变量,存储 null + null_val: llvmlite.Value | t.CPtr = llvmlite.SSAValue(pool, i8_ptr_ty, "null") + llvmlite.build_store(parent_builder, null_val, env_slot) + + # 13e. 将闭包指针存储到父函数的局部变量 {func_name} + closure_alloca: llvmlite.Value | t.CPtr = llvmlite.build_alloca(parent_builder, i8_ptr_ty) + if closure_alloca is not None: + llvmlite.build_store(parent_builder, closure_ptr, closure_alloca) + HandlesVar.define_var(trans.SymTab, func_name, closure_alloca) + # 注册闭包变量名(供调用时区分闭包 vs 函数指针变量, + # 两者 alloca 类型同为 i8**,_is_func_ptr_alloca 无法区分) + HandlesExprCall.register_closure_name(func_name) + + # 14. 恢复 scope names + trans._cur_func_name = old_func_name + trans._global_name_count = old_global_count + trans._nonlocal_name_count = old_nonlocal_count + trans._closure_env_count = old_env_count + + return 1 + + # ============================================================ + # 创建 LLVM 函数(简单版本,仅声明) + # ============================================================ + def create_function(self, pool: memhub.MemBuddy | t.CPtr, + mod: llvmlite.LLVMModule | t.CPtr, + name: str, + args_node: ast.AST | t.CPtr, + ret_ty: llvmlite.LLVMType | t.CPtr) -> llvmlite.Function | t.CPtr: + """创建 LLVM 函数并添加参数""" + if name is None or mod is None: + return None + + func: llvmlite.Function | t.CPtr = llvmlite.create_function(pool, mod, name, ret_ty) + if func is None: + return None + + if args_node is not None: + ags: ast.Arguments | t.CPtr = (ast.Arguments | t.CPtr)(args_node) + if ags.args is not None: + alist: list[ast.AST | t.CPtr] | t.CPtr = ags.args + an: t.CSizeT = alist.__len__() + i32_ty: llvmlite.LLVMType | t.CPtr = llvmlite.Int32(pool) + for ai in range(an): + arg: ast.Arg | t.CPtr = (ast.Arg | t.CPtr)(alist.get(ai)) + if arg is not None and arg.arg is not None: + # t.CVoid 表示空参:跳过 + if arg.annotation is not None: + if arg.annotation.kind() == ast.ASTKind.Attribute: + at_cf: ast.Attribute | t.CPtr = (ast.Attribute | t.CPtr)(arg.annotation) + if at_cf.attr is not None and string.strcmp(at_cf.attr, "CVoid") == 0: + continue + param_ty: llvmlite.LLVMType | t.CPtr = i32_ty + if arg.annotation is not None: + resolved: llvmlite.LLVMType | t.CPtr = HandlesType.resolve_annotation_type( + pool, arg.annotation, None, None, None) + if resolved is not None: + param_ty = resolved + pname: t.CChar | t.CPtr = pool.alloc(32) + if pname is not None: + viperlib.snprintf(pname, 32, "%%%s", arg.arg) + llvmlite.add_param(pool, func, param_ty, pname) + + return func diff --git a/App/lib/core/Gen/Generator.vp b/App/lib/core/Gen/Generator.vp index 6accb8d..4f75422 100644 --- a/App/lib/core/Gen/Generator.vp +++ b/App/lib/core/Gen/Generator.vp @@ -7,6 +7,8 @@ import lib.core.Gen.TypeGenMixin as TypeGenMixin import lib.core.Gen.StructGenMixin as StructGenMixin import lib.core.Gen.ExprGenMixin as ExprGenMixin import lib.core.Gen.CallGenMixin as CallGenMixin +import lib.core.Gen.FuncGenMixin as FuncGenMixin +import lib.core.Gen.ClassGenMixin as ClassGenMixin import lib.core.Handles.HandlesVar as HandlesVar import lib.core.Handles.HandlesExprCall as HandlesExprCall @@ -26,7 +28,8 @@ import lib.core.Handles.HandlesExprCall as HandlesExprCall @t.NoVTable class Generator(BaseGenMixin.BaseGenMixin, TypeGenMixin.TypeGenMixin, StructGenMixin.StructGenMixin, ExprGenMixin.ExprGenMixin, - CallGenMixin.CallGenMixin): + CallGenMixin.CallGenMixin, FuncGenMixin.FuncGenMixin, + ClassGenMixin.ClassGenMixin): """生成器:多继承 Mixin 组合(对象化迁移宿主)""" def __init__(self, pool: memhub.MemBuddy | t.CPtr): @@ -86,6 +89,29 @@ class Generator(BaseGenMixin.BaseGenMixin, TypeGenMixin.TypeGenMixin, self.GlobalFuncCount = 0 self.GlobalDefaults = None self.GlobalDefaultsCount = 0 + # ---- ClassGenMixin 字段 ---- + self.MethodMetaKeys = None + self.MethodMetaFlags = None + self.MethodMetaCount = 0 + self.RenumClassNames = None + self.RenumClassVariantCounts = None + self.RenumVariantNames = None + self.RenumVariantTags = None + self.RenumClassCount = 0 + self.RenumAliasClass = None + self.RenumAliasField = None + self.RenumAliasIndex = None + self.RenumAliasCount = 0 + self.SpecKeys = None + self.SpecNames = None + self.SpecCount = 0 + self.GenericClassNames = None + self.GenericClassNodes = None + self.GenericClassSha1s = None + self.VtFullNames = None + self.VtMethodNames = None + self.VtParentSha1s = None + self.VtMethodCount = 0 # ============================================================ diff --git a/App/lib/core/Handles/HandlesClassDef.vp b/App/lib/core/Handles/HandlesClassDef.vp index d3aa1d7..6531f1b 100644 --- a/App/lib/core/Handles/HandlesClassDef.vp +++ b/App/lib/core/Handles/HandlesClassDef.vp @@ -16,6 +16,22 @@ import lib.core.Handles.HandlesEnum as HandlesEnum import lib.core.StubMerger as StubMerger +# ============================================================ +# 全局 gen 单例(模块级镜像,同 HandlesType/HandlesStruct 模式) +# +# 由 BuildPipeline/main 在 gen 创建后调用 set_global_gen 注入。 +# P5-2 委托函数用本地 _g_gen(cast 成 Generator 类型)调 +# ClassGenMixin 方法,避免函数体 import 包模块与类/模块名歧义。 +# ============================================================ +_g_gen: t.CVoid | t.CPtr = None + + +def set_global_gen(gen: t.CVoid | t.CPtr) -> None: + """注入全局 gen 单例(BuildPipeline/main 调用)""" + global _g_gen + _g_gen = gen + + # 枚举成员临时数组最大数量(本地常量) ENUM_MEMBER_MAX_LOCAL: t.CDefine = 128 @@ -49,22 +65,11 @@ RENUM_FIELD_PER_VARIANT: t.CDefine = 16 # 支持 Name(id='CEnum') 和 Attribute(value=Name('t'), attr='CEnum') # ============================================================ def _is_cenum_base(base_node: ast.AST | t.CPtr) -> int: - """检查 base 节点是否为 t.CEnum,返回 1=是 / 0=否""" - if base_node is None: - return 0 - k: int = base_node.kind() - # Name('CEnum') 形式(from t import CEnum) - if k == ast.ASTKind.Name: - nm: ast.Name | t.CPtr = (ast.Name | t.CPtr)(base_node) - if nm.id is not None and string.strcmp(nm.id, "CEnum") == 0: - return 1 - return 0 - # Attribute(t.CEnum) 形式 - if k == ast.ASTKind.Attribute: - at: ast.Attribute | t.CPtr = (ast.Attribute | t.CPtr)(base_node) - if at.attr is not None and string.strcmp(at.attr, "CEnum") == 0: - return 1 - return 0 + """检查 base 节点是否为 t.CEnum,返回 1=是 / 0=否(委托到 gen._is_cenum_base)""" + import lib.core.Gen.Generator as Generator + g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(_g_gen, t.CPtr)) + if g is not None: + return g._is_cenum_base(base_node) return 0 @@ -72,19 +77,11 @@ def _is_cenum_base(base_node: ast.AST | t.CPtr) -> int: # _is_enum_class — 检查 ClassDef 是否继承自 t.CEnum # ============================================================ def _is_enum_class(cd: ast.ClassDef | t.CPtr) -> int: - """检查 ClassDef 是否继承自 t.CEnum,返回 1=是 / 0=否""" - if cd is None or cd.bases is None: - return 0 - bases: list[ast.AST | t.CPtr] | t.CPtr = cd.bases - bn: t.CSizeT = bases.__len__() - if bn == 0: - return 0 - for bi in range(bn): - base_node: ast.AST | t.CPtr = bases.get(bi) - if base_node is None: - continue - if _is_cenum_base(base_node) == 1: - return 1 + """检查 ClassDef 是否继承自 t.CEnum,返回 1=是 / 0=否(委托到 gen._is_enum_class)""" + import lib.core.Gen.Generator as Generator + g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(_g_gen, t.CPtr)) + if g is not None: + return g._is_enum_class(cd) return 0 @@ -94,22 +91,11 @@ def _is_enum_class(cd: ast.ClassDef | t.CPtr) -> int: # 支持 Name(id='CUnion') 和 Attribute(value=Name('t'), attr='CUnion') # ============================================================ def _is_cunion_base(base_node: ast.AST | t.CPtr) -> int: - """检查 base 节点是否为 t.CUnion,返回 1=是 / 0=否""" - if base_node is None: - return 0 - k: int = base_node.kind() - # Name('CUnion') 形式(from t import CUnion) - if k == ast.ASTKind.Name: - nm: ast.Name | t.CPtr = (ast.Name | t.CPtr)(base_node) - if nm.id is not None and string.strcmp(nm.id, "CUnion") == 0: - return 1 - return 0 - # Attribute(t.CUnion) 形式 - if k == ast.ASTKind.Attribute: - at: ast.Attribute | t.CPtr = (ast.Attribute | t.CPtr)(base_node) - if at.attr is not None and string.strcmp(at.attr, "CUnion") == 0: - return 1 - return 0 + """检查 base 节点是否为 t.CUnion,返回 1=是 / 0=否(委托到 gen._is_cunion_base)""" + import lib.core.Gen.Generator as Generator + g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(_g_gen, t.CPtr)) + if g is not None: + return g._is_cunion_base(base_node) return 0 @@ -117,19 +103,11 @@ def _is_cunion_base(base_node: ast.AST | t.CPtr) -> int: # _is_union_class — 检查 ClassDef 是否继承自 t.CUnion # ============================================================ def _is_union_class(cd: ast.ClassDef | t.CPtr) -> int: - """检查 ClassDef 是否继承自 t.CUnion,返回 1=是 / 0=否""" - if cd is None or cd.bases is None: - return 0 - bases: list[ast.AST | t.CPtr] | t.CPtr = cd.bases - bn: t.CSizeT = bases.__len__() - if bn == 0: - return 0 - for bi in range(bn): - base_node: ast.AST | t.CPtr = bases.get(bi) - if base_node is None: - continue - if _is_cunion_base(base_node) == 1: - return 1 + """检查 ClassDef 是否继承自 t.CUnion,返回 1=是 / 0=否(委托到 gen._is_union_class)""" + import lib.core.Gen.Generator as Generator + g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(_g_gen, t.CPtr)) + if g is not None: + return g._is_union_class(cd) return 0 @@ -139,22 +117,11 @@ def _is_union_class(cd: ast.ClassDef | t.CPtr) -> int: # 支持 Name(id='REnum') 和 Attribute(value=Name('t'), attr='REnum') # ============================================================ def _is_crenum_base(base_node: ast.AST | t.CPtr) -> int: - """检查 base 节点是否为 t.REnum,返回 1=是 / 0=否""" - if base_node is None: - return 0 - k: int = base_node.kind() - # Name('REnum') 形式(from t import REnum) - if k == ast.ASTKind.Name: - nm: ast.Name | t.CPtr = (ast.Name | t.CPtr)(base_node) - if nm.id is not None and string.strcmp(nm.id, "REnum") == 0: - return 1 - return 0 - # Attribute(t.REnum) 形式 - if k == ast.ASTKind.Attribute: - at: ast.Attribute | t.CPtr = (ast.Attribute | t.CPtr)(base_node) - if at.attr is not None and string.strcmp(at.attr, "REnum") == 0: - return 1 - return 0 + """检查 base 节点是否为 t.REnum,返回 1=是 / 0=否(委托到 gen._is_crenum_base)""" + import lib.core.Gen.Generator as Generator + g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(_g_gen, t.CPtr)) + if g is not None: + return g._is_crenum_base(base_node) return 0 @@ -162,19 +129,11 @@ def _is_crenum_base(base_node: ast.AST | t.CPtr) -> int: # _is_renum_class — 检查 ClassDef 是否继承自 t.REnum # ============================================================ def _is_renum_class(cd: ast.ClassDef | t.CPtr) -> int: - """检查 ClassDef 是否继承自 t.REnum,返回 1=是 / 0=否""" - if cd is None or cd.bases is None: - return 0 - bases: list[ast.AST | t.CPtr] | t.CPtr = cd.bases - bn: t.CSizeT = bases.__len__() - if bn == 0: - return 0 - for bi in range(bn): - base_node: ast.AST | t.CPtr = bases.get(bi) - if base_node is None: - continue - if _is_crenum_base(base_node) == 1: - return 1 + """检查 ClassDef 是否继承自 t.REnum,返回 1=是 / 0=否(委托到 gen._is_renum_class)""" + import lib.core.Gen.Generator as Generator + g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(_g_gen, t.CPtr)) + if g is not None: + return g._is_renum_class(cd) return 0 @@ -196,32 +155,11 @@ _MARKER_BASES: t.CDefine = 9 # ============================================================ def _has_decorator(decorator_list: list[ast.AST | t.CPtr] | t.CPtr, deco_name: str) -> int: - """检查 decorator_list 中是否有指定装饰器名""" - if decorator_list is None: - return 0 - dn: t.CSizeT = decorator_list.__len__() - if dn == 0: - return 0 - for di in range(dn): - deco: ast.AST | t.CPtr = decorator_list.get(di) - if deco is None: - continue - k: int = deco.kind() - # @t.NoVTable 形式(Attribute) - if k == ast.ASTKind.Attribute: - at: ast.Attribute | t.CPtr = (ast.Attribute | t.CPtr)(deco) - if at.attr is not None and string.strcmp(at.attr, deco_name) == 0: - # 检查 value 是 Name('t') - if at.value is not None and at.value.kind() == ast.ASTKind.Name: - vn: ast.Name | t.CPtr = (ast.Name | t.CPtr)(at.value) - if vn.id is not None and string.strcmp(vn.id, "t") == 0: - return 1 - return 0 - # @NoVTable 形式(Name,from t import NoVTable) - if k == ast.ASTKind.Name: - nm: ast.Name | t.CPtr = (ast.Name | t.CPtr)(deco) - if nm.id is not None and string.strcmp(nm.id, deco_name) == 0: - return 1 + """检查 decorator_list 中是否有指定装饰器名(委托到 gen._has_decorator)""" + import lib.core.Gen.Generator as Generator + g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(_g_gen, t.CPtr)) + if g is not None: + return g._has_decorator(decorator_list, deco_name) return 0 @@ -249,10 +187,6 @@ META_PROP_DELETER: t.CDefine = 16 META_MAX: t.CDefine = 512 META_KEY_LEN: t.CDefine = 128 -_g_method_meta_keys: bytes = None -_g_method_meta_flags: bytes = None -_g_method_meta_count: int = 0 - # ============================================================ # _extract_func_meta — 从 decorator_list 提取方法元数据位掩码 @@ -262,45 +196,12 @@ _g_method_meta_count: int = 0 # @property.setter / @x.setter / @x.getter / @x.deleter(Attribute 形式) # ============================================================ def _extract_func_meta(decorator_list: list[ast.AST | t.CPtr] | t.CPtr) -> int: - """从装饰器列表提取元数据位掩码,返回 0=无装饰器元数据""" - meta: int = 0 - if decorator_list is None: - return meta - dn: t.CSizeT = decorator_list.__len__() - if dn == 0: - return meta - for di in range(dn): - deco: ast.AST | t.CPtr = decorator_list.get(di) - if deco is None: - continue - k: int = deco.kind() - if k == ast.ASTKind.Name: - nm: ast.Name | t.CPtr = (ast.Name | t.CPtr)(deco) - if nm.id is not None: - if string.strcmp(nm.id, "staticmethod") == 0: - meta |= META_STATIC - elif string.strcmp(nm.id, "property") == 0: - meta |= META_PROP_GETTER - elif string.strcmp(nm.id, "classmethod") == 0: - meta |= META_CLASS - elif k == ast.ASTKind.Attribute: - at: ast.Attribute | t.CPtr = (ast.Attribute | t.CPtr)(deco) - if at.attr is not None and at.value is not None: - if at.value.kind() == ast.ASTKind.Name: - vn: ast.Name | t.CPtr = (ast.Name | t.CPtr)(at.value) - is_prop_name: int = 0 - if vn.id is not None and string.strcmp(vn.id, "property") == 0: - is_prop_name = 1 - # @property.setter 或 @x.setter/getter/deleter 都识别 - if is_prop_name != 0 or string.strcmp(at.attr, "setter") == 0 \ - or string.strcmp(at.attr, "getter") == 0 or string.strcmp(at.attr, "deleter") == 0: - if string.strcmp(at.attr, "setter") == 0: - meta |= META_PROP_SETTER - elif string.strcmp(at.attr, "getter") == 0: - meta |= META_PROP_GETTER - elif string.strcmp(at.attr, "deleter") == 0: - meta |= META_PROP_DELETER - return meta + """从装饰器列表提取元数据位掩码,返回 0=无装饰器元数据(委托到 gen._extract_func_meta)""" + import lib.core.Gen.Generator as Generator + g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(_g_gen, t.CPtr)) + if g is not None: + return g._extract_func_meta(decorator_list) + return 0 # ============================================================ @@ -310,41 +211,11 @@ def _extract_func_meta(decorator_list: list[ast.AST | t.CPtr] | t.CPtr) -> int: # ============================================================ def register_method_meta(class_name: str, method_name: str, meta: int) -> None: - """注册方法元数据(幂等)""" - global _g_method_meta_keys, _g_method_meta_flags, _g_method_meta_count - if class_name is None or method_name is None or meta == 0: - return - # 懒初始化 - if _g_method_meta_keys is None: - _g_method_meta_keys = stdlib.malloc(META_MAX * META_KEY_LEN) - _g_method_meta_flags = stdlib.malloc(META_MAX * 4) - if _g_method_meta_keys is None or _g_method_meta_flags is None: - return - string.memset(_g_method_meta_keys, 0, META_MAX * META_KEY_LEN) - string.memset(_g_method_meta_flags, 0, META_MAX * 4) - # 构造 key "ClassName.method" - cl_len: t.CSizeT = string.strlen(class_name) - mn_len: t.CSizeT = string.strlen(method_name) - key_buf: bytes = stdlib.malloc(cl_len + mn_len + 2) - if key_buf is None: - return - viperlib.snprintf(key_buf, cl_len + mn_len + 2, "%s.%s", class_name, method_name) - # 去重更新 - i: int - for i in range(_g_method_meta_count): - if string.strcmp(_g_method_meta_keys + i * META_KEY_LEN, key_buf) == 0: - flags_ptr: t.CPtr = (t.CInt | t.CPtr)(t.CVoid( - t.CUInt64T(_g_method_meta_flags) + i * 4, t.CPtr)) - flags_ptr[0] = meta - stdlib.free(key_buf) - return - if _g_method_meta_count < META_MAX: - string.strcpy(_g_method_meta_keys + _g_method_meta_count * META_KEY_LEN, key_buf) - flags_ptr2: t.CPtr = (t.CInt | t.CPtr)(t.CVoid( - t.CUInt64T(_g_method_meta_flags) + _g_method_meta_count * 4, t.CPtr)) - flags_ptr2[0] = meta - _g_method_meta_count += 1 - stdlib.free(key_buf) + """注册方法元数据(幂等,委托到 gen.register_method_meta)""" + import lib.core.Gen.Generator as Generator + g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(_g_gen, t.CPtr)) + if g is not None: + g.register_method_meta(class_name, method_name, meta) # ============================================================ @@ -353,27 +224,12 @@ def register_method_meta(class_name: str, method_name: str, # 返回位掩码;未注册返回 0。跨模块持久,供属性访问/赋值/删除识别。 # ============================================================ def lookup_method_meta(class_name: str, method_name: str) -> int: - """查找方法元数据位掩码,返回 0=未注册或非装饰器方法""" - if class_name is None or method_name is None: - return 0 - if _g_method_meta_keys is None or _g_method_meta_count <= 0: - return 0 - cl_len: t.CSizeT = string.strlen(class_name) - mn_len: t.CSizeT = string.strlen(method_name) - key_buf: bytes = stdlib.malloc(cl_len + mn_len + 2) - if key_buf is None: - return 0 - viperlib.snprintf(key_buf, cl_len + mn_len + 2, "%s.%s", class_name, method_name) - found: int = 0 - i: int - for i in range(_g_method_meta_count): - if string.strcmp(_g_method_meta_keys + i * META_KEY_LEN, key_buf) == 0: - flags_ptr: t.CPtr = (t.CInt | t.CPtr)(t.CVoid( - t.CUInt64T(_g_method_meta_flags) + i * 4, t.CPtr)) - found = flags_ptr[0] - break - stdlib.free(key_buf) - return found + """查找方法元数据位掩码,返回 0=未注册或非装饰器方法(委托到 gen.lookup_method_meta)""" + import lib.core.Gen.Generator as Generator + g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(_g_gen, t.CPtr)) + if g is not None: + return g.lookup_method_meta(class_name, method_name) + return 0 # ============================================================ @@ -392,27 +248,12 @@ def _is_marker_base(base_name: str) -> int: 函数体 alloca(Ptr(struct))不一致 → llc 报 "'%p' defined with type 'i32' but expected 'ptr'"。 与 TPC(_resolve_base_kind 对 t.Struct 返回 None → 无父类)保持一致。 + (委托到 gen._is_marker_base) """ - if base_name is None: - return 0 - if string.strcmp(base_name, "Object") == 0: - return 1 - if string.strcmp(base_name, "CVTable") == 0: - return 1 - if string.strcmp(base_name, "Exception") == 0: - return 1 - if string.strcmp(base_name, "CEnum") == 0: - return 1 - if string.strcmp(base_name, "Enum") == 0: - return 1 - if string.strcmp(base_name, "CStruct") == 0: - return 1 - if string.strcmp(base_name, "Struct") == 0: - return 1 - if string.strcmp(base_name, "CUnion") == 0: - return 1 - if string.strcmp(base_name, "REnum") == 0: - return 1 + import lib.core.Gen.Generator as Generator + g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(_g_gen, t.CPtr)) + if g is not None: + return g._is_marker_base(base_name) return 0 @@ -428,52 +269,12 @@ def _get_base_name(base_node: ast.AST | t.CPtr, 对于 Subscript 节点,需要 pool 分配内存拼接特化名; pool=None 时降级返回基类名(不含类型实参) + (委托到 gen._get_base_name) """ - if base_node is None: - return None - k: int = base_node.kind() - # Name(id) 形式 - if k == ast.ASTKind.Name: - nm: ast.Name | t.CPtr = (ast.Name | t.CPtr)(base_node) - return nm.id - # Attribute(attr) 形式 - if k == ast.ASTKind.Attribute: - at: ast.Attribute | t.CPtr = (ast.Attribute | t.CPtr)(base_node) - return at.attr - # Subscript(value, slice) 形式 — 如 GSListNode[Value] - if k == ast.ASTKind.Subscript: - sub: ast.Subscript | t.CPtr = (ast.Subscript | t.CPtr)(base_node) - if sub is None or sub.value is None or sub.slice is None: - return None - # 提取基类名(如 "GSListNode") - base_nm: str = _get_base_name(sub.value, pool) - if base_nm is None: - return None - # 提取类型实参名(如 "Value") - slice_k: int = sub.slice.kind() - arg_nm: str = None - if slice_k == ast.ASTKind.Name: - sl_nm: ast.Name | t.CPtr = (ast.Name | t.CPtr)(sub.slice) - arg_nm = sl_nm.id - # 如果无法提取类型实参,返回基类名(降级) - if arg_nm is None: - return base_nm - # 无 pool 时返回基类名(降级,无法拼接特化名) - if pool is None: - return base_nm - # 拼接特化名 "GSListNode[Value]" - base_len: t.CSizeT = string.strlen(base_nm) - arg_len: t.CSizeT = string.strlen(arg_nm) - total_len: t.CSizeT = base_len + arg_len + 3 # "[" + arg + "]" + NUL - mangled: str = pool.alloc(total_len) - if mangled is None: - return base_nm # 降级 - mangled[0] = '\0' - string.strcat(mangled, base_nm) - string.strcat(mangled, "[") - string.strcat(mangled, arg_nm) - string.strcat(mangled, "]") - return mangled + import lib.core.Gen.Generator as Generator + g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(_g_gen, t.CPtr)) + if g is not None: + return g._get_base_name(base_node, pool) return None @@ -486,23 +287,11 @@ def _get_base_name(base_node: ast.AST | t.CPtr, # ============================================================ def _get_parent_class(cd: ast.ClassDef | t.CPtr, trans: HT.Translator | t.CPtr = None) -> str: - """获取 ClassDef 的真实父类名,返回 None=无真实父类""" - if cd is None or cd.bases is None: - return None - pool: memhub.MemBuddy | t.CPtr = None - if trans is not None: - pool = trans.Pool - bases: list[ast.AST | t.CPtr] | t.CPtr = cd.bases - bn: t.CSizeT = bases.__len__() - if bn == 0: - return None - for bi in range(bn): - base_node: ast.AST | t.CPtr = bases.get(bi) - if base_node is None: - continue - bname: str = _get_base_name(base_node, pool) - if bname is not None and _is_marker_base(bname) == 0: - return bname + """获取 ClassDef 的真实父类名,返回 None=无真实父类(委托到 gen._get_parent_class)""" + import lib.core.Gen.Generator as Generator + g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(_g_gen, t.CPtr)) + if g is not None: + return g._get_parent_class(cd, trans) return None @@ -517,23 +306,12 @@ def _collect_parents(pool: memhub.MemBuddy | t.CPtr, cd: ast.ClassDef | t.CPtr, parents_buf: t.CSizeT | t.CPtr, max_parents: int) -> int: - """收集所有非 marker 父类名到 parents_buf,返回数量""" - if pool is None or cd is None or cd.bases is None or parents_buf is None: - return 0 - bases: list[ast.AST | t.CPtr] | t.CPtr = cd.bases - bn: t.CSizeT = bases.__len__() - count: int = 0 - for bi in range(bn): - if count >= max_parents: - break - base_node: ast.AST | t.CPtr = bases.get(bi) - if base_node is None: - continue - bname: str = _get_base_name(base_node, pool) - if bname is not None and _is_marker_base(bname) == 0: - parents_buf[count] = t.CSizeT(bname) - count += 1 - return count + """收集所有非 marker 父类名到 parents_buf,返回数量(委托到 gen._collect_parents)""" + import lib.core.Gen.Generator as Generator + g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(_g_gen, t.CPtr)) + if g is not None: + return g._collect_parents(pool, cd, parents_buf, max_parents) + return 0 # ============================================================ @@ -541,15 +319,11 @@ def _collect_parents(pool: memhub.MemBuddy | t.CPtr, # ============================================================ def _field_name_exists(names_buf: t.CSizeT | t.CPtr, count: int, name: str) -> int: - """检查字段名是否已在 names_buf 中(先声明父类优先,重复跳过)""" - if names_buf is None or name is None: - return 0 - for fi in range(count): - addr: t.CSizeT = names_buf[fi] - if addr != 0: - existing: str = (str | t.CPtr)(t.CVoid(addr, t.CPtr)) - if existing is not None and string.strcmp(existing, name) == 0: - return 1 + """检查字段名是否已在 names_buf 中(先声明父类优先,重复跳过)(委托到 gen._field_name_exists)""" + import lib.core.Gen.Generator as Generator + g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(_g_gen, t.CPtr)) + if g is not None: + return g._field_name_exists(names_buf, count, name) return 0 @@ -560,16 +334,11 @@ def _field_name_exists(names_buf: t.CSizeT | t.CPtr, # (类体有字段但 FieldCount==0,漏注册报错)。 # ============================================================ def _class_body_has_field(cd: ast.ClassDef | t.CPtr) -> int: - """检查类体是否声明了字段(AnnAssign),0=纯方法/无字段类""" - if cd is None or cd.children is None: - return 0 - cn: t.CSizeT = cd.children.__len__() - for ci in range(cn): - stmt: ast.AST | t.CPtr = cd.children.get(ci) - if stmt is None: - continue - if stmt.kind() == ast.ASTKind.AnnAssign: - return 1 + """检查类体是否声明了字段(AnnAssign),0=纯方法/无字段类(委托到 gen._class_body_has_field)""" + import lib.core.Gen.Generator as Generator + g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(_g_gen, t.CPtr)) + if g is not None: + return g._class_body_has_field(cd) return 0 @@ -585,46 +354,11 @@ def _class_body_has_field(cd: ast.ClassDef | t.CPtr) -> int: # ============================================================ def _trigger_base_specialization(trans: HT.Translator | t.CPtr, cd: ast.ClassDef | t.CPtr): - """触发 base 中 Subscript 的泛型特化(如 GSListNode[Value])""" - if trans is None or cd is None or cd.bases is None: - return - pool: memhub.MemBuddy | t.CPtr = trans.Pool - bases: list[ast.AST | t.CPtr] | t.CPtr = cd.bases - bn: t.CSizeT = bases.__len__() - if bn == 0: - return - for bi in range(bn): - base_node: ast.AST | t.CPtr = bases.get(bi) - if base_node is None: - continue - bk: int = base_node.kind() - if bk != ast.ASTKind.Subscript: - continue - sub: ast.Subscript | t.CPtr = (ast.Subscript | t.CPtr)(base_node) - if sub is None or sub.value is None or sub.slice is None: - continue - # 提取泛型类名(如 "GSListNode") - gen_class_name: str = _get_base_name(sub.value, pool) - if gen_class_name is None: - continue - # 跳过标记基类 - if _is_marker_base(gen_class_name) == 1: - continue - # 提取类型实参名(如 "Value") - slice_k: int = sub.slice.kind() - arg_nm: str = None - if slice_k == ast.ASTKind.Name: - sl_nm: ast.Name | t.CPtr = (ast.Name | t.CPtr)(sub.slice) - arg_nm = sl_nm.id - if arg_nm is None: - continue - # 构建 type_args 列表(elem_size=8:str 是指针,1 会导致双元素重叠损坏) - type_args: list[str] | t.CPtr = list[str](pool, 8) - if type_args is None: - continue - type_args.append(arg_nm) - # 触发特化(_specialize_generic_class 有缓存,重复调用安全) - _specialize_generic_class(trans, gen_class_name, type_args) + """触发 base 中 Subscript 的泛型特化(如 GSListNode[Value])(委托到 gen._trigger_base_specialization)""" + import lib.core.Gen.Generator as Generator + g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(_g_gen, t.CPtr)) + if g is not None: + g._trigger_base_specialization(trans, cd) # ============================================================ @@ -634,30 +368,11 @@ def _trigger_base_specialization(trans: HT.Translator | t.CPtr, # 跳过 __init__ 和 __before_init__(构造函数不进入虚表)。 # ============================================================ def _has_any_func_cvtable(cd: ast.ClassDef | t.CPtr) -> int: - """检查类中是否有任何函数标记了 @t.CVTable,返回 1=有 / 0=无""" - if cd is None or cd.children is None: - return 0 - children: list[ast.AST | t.CPtr] | t.CPtr = cd.children - cn: t.CSizeT = children.__len__() - for ci in range(cn): - stmt: ast.AST | t.CPtr = children.get(ci) - if stmt is None: - continue - if stmt.kind() != ast.ASTKind.FunctionDef: - continue - fd: ast.FunctionDef | t.CPtr = (ast.FunctionDef | t.CPtr)(stmt) - if fd is None or fd.name is None: - continue - # 跳过构造函数 - if string.strcmp(fd.name, "__init__") == 0: - continue - if string.strcmp(fd.name, "__before_init__") == 0: - continue - if string.strcmp(fd.name, "__new__") == 0: - continue - if fd.decorator_list is not None: - if _has_decorator(fd.decorator_list, "CVTable") == 1: - return 1 + """检查类中是否有任何函数标记了 @t.CVTable,返回 1=有 / 0=无(委托到 gen._has_any_func_cvtable)""" + import lib.core.Gen.Generator as Generator + g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(_g_gen, t.CPtr)) + if g is not None: + return g._has_any_func_cvtable(cd) return 0 @@ -674,49 +389,11 @@ def _has_any_func_cvtable(cd: ast.ClassDef | t.CPtr) -> int: def _should_method_be_virtual(cd: ast.ClassDef | t.CPtr, fd: ast.FunctionDef | t.CPtr, trans: HT.Translator | t.CPtr = None) -> int: - """判断方法是否应该进入虚表,返回 1=包含 / 0=排除""" - if fd is None: - return 0 - # 1. 检查函数级 @t.NoVTable(最高优先级,排除) - if fd.decorator_list is not None: - if _has_decorator(fd.decorator_list, "NoVTable") == 1: - return 0 - # 2. 检查函数级 @t.CVTable(明确包含) - if _has_decorator(fd.decorator_list, "CVTable") == 1: - return 1 - - # 3. 检查类级别 @t.CVTable - if cd is not None and cd.decorator_list is not None: - if _has_decorator(cd.decorator_list, "CVTable") == 1: - return 1 - - # 4. 检查继承关系 - parent_name: str = _get_parent_class(cd, trans) - if parent_name is not None: - # 用 SHA1 感知查找父类,规避跨模块同名找错 - is_nvt: int = 0 - if trans is not None: - p_entry: HandlesStruct.StructEntry | t.CPtr = HandlesStruct.find_struct_by_module( - parent_name, trans.ModuleSha1) - if p_entry is None: - # 跨模块父类回退全局查找(父类注册在父模块 SHA1 下,如 linkedlist.LinkedNode), - # 与字段展平(1.5 节)的回退保持一致,否则父类 NoVTable 被误判为有虚表 → 子类插 vptr - # 导致子类布局比父类多一个指针,父类方法按无 vptr 布局操作错位 - p_entry = HandlesStruct.find_struct(parent_name) - if p_entry is not None: - is_nvt = p_entry.IsNoVTable - else: - is_nvt = HandlesStruct.is_novtable_by_name(parent_name) - if is_nvt != 1: - # 继承链统一虚表:父类有虚表 → 方法进虚表;父类无虚表 → 静态方法。 - # 与 _detect_vtable_status 规则一致,避免父类无 vptr 布局/子类有 vptr 的错位。 - if p_entry is None: - return 1 # 父类信息未知,保守进虚表 - if p_entry.HasVTable == 1: - return 1 - return 0 - - # 5. 默认排除 + """判断方法是否应该进入虚表,返回 1=包含 / 0=排除(委托到 gen._should_method_be_virtual)""" + import lib.core.Gen.Generator as Generator + g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(_g_gen, t.CPtr)) + if g is not None: + return g._should_method_be_virtual(cd, fd, trans) return 0 @@ -733,48 +410,12 @@ def _should_method_be_virtual(cd: ast.ClassDef | t.CPtr, # ============================================================ def _detect_vtable_status(cd: ast.ClassDef | t.CPtr, trans: HT.Translator | t.CPtr = None) -> int: - """检测类是否应该启用虚表""" - if cd is None: - return 0 - - # 检查类装饰器 - if cd.decorator_list is not None: - # @t.CVTable 优先级最高,直接启用 - if _has_decorator(cd.decorator_list, "CVTable") == 1: - return 1 - # @t.NoVTable:类级别禁用,但检查函数级 @t.CVTable - if _has_decorator(cd.decorator_list, "NoVTable") == 1: - return _has_any_func_cvtable(cd) - - # 检查是否有真实父类(继承自动启用 CVTable) - parent_name: str = _get_parent_class(cd, trans) - if parent_name is not None: - # 用 SHA1 感知查找父类,规避跨模块同名找错 - is_nvt: int = 0 - if trans is not None: - p_entry: HandlesStruct.StructEntry | t.CPtr = HandlesStruct.find_struct_by_module( - parent_name, trans.ModuleSha1) - if p_entry is None: - # 跨模块父类回退全局查找(同 _detect_vtable_status 的回退) - p_entry = HandlesStruct.find_struct(parent_name) - if p_entry is not None: - is_nvt = p_entry.IsNoVTable - else: - is_nvt = HandlesStruct.is_novtable_by_name(parent_name) - if is_nvt == 1: - # 父类是 NoVTable,检查函数级 @t.CVTable - return _has_any_func_cvtable(cd) - # 继承链统一虚表:父类有虚表 → 子类启用;父类无虚表 → 子类静态。 - # 若父类无 vtable 而子类有,父类方法按无 vptr 布局(self.field@0)操作 - # 子类实例(有 vptr@0)会字段错位 → 运行时错误(父类方法读 vptr 当字段)。 - if p_entry is None: - return 1 # 父类信息未知(跨模块/未注册),保守启用虚表 - if p_entry.HasVTable == 1: - return 1 - return 0 - - # 默认(无装饰器无继承),检查函数级 @t.CVTable - return _has_any_func_cvtable(cd) + """检测类是否应该启用虚表(委托到 gen._detect_vtable_status)""" + import lib.core.Gen.Generator as Generator + g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(_g_gen, t.CPtr)) + if g is not None: + return g._detect_vtable_status(cd, trans) + return 0 # ============================================================ @@ -788,80 +429,23 @@ def _resolve_enum_member_type(pool: memhub.MemBuddy | t.CPtr, ann_node: ast.AST | t.CPtr, imported_modules: str, from_imports: str) -> llvmlite.LLVMType | t.CPtr: - """解析枚举成员的类型注解为 LLVM 整数类型""" - if ann_node is None: - return llvmlite.Int32(pool) - - k: int = ann_node.kind() - - # Attribute 节点: t.State / int / t.CInt8T 等 - if k == ast.ASTKind.Attribute: - at: ast.Attribute | t.CPtr = (ast.Attribute | t.CPtr)(ann_node) - if at.attr is None: - return llvmlite.Int32(pool) - # t.State → 默认 i32 - if string.strcmp(at.attr, "State") == 0: - return llvmlite.Int32(pool) - # 其他 t.CXxx 类型 - ty: llvmlite.LLVMType | t.CPtr = HandlesType.map_t_type(pool, at.attr) - if ty is not None: - return ty - return llvmlite.Int32(pool) - - # Name 节点: from-import 形式(State / CInt) - if k == ast.ASTKind.Name: - nm: ast.Name | t.CPtr = (ast.Name | t.CPtr)(ann_node) - if nm.id is None: - return llvmlite.Int32(pool) - if string.strcmp(nm.id, "State") == 0: - return llvmlite.Int32(pool) - ty2: llvmlite.LLVMType | t.CPtr = HandlesType.map_t_type(pool, nm.id) - if ty2 is not None: - return ty2 - return llvmlite.Int32(pool) - - # BinOp 节点: t.State | t.CInt8T(递归查找实际类型) - if k == ast.ASTKind.BinOp: - bop: ast.BinOp | t.CPtr = (ast.BinOp | t.CPtr)(ann_node) - if bop.op == ast.OpKind.BitOr: - left_ty: llvmlite.LLVMType | t.CPtr = _resolve_enum_member_type( - pool, bop.left, imported_modules, from_imports) - # 跳过 t.State(i32 默认),优先返回具体类型 - left_bits: int = HandlesType.get_llvm_type_bits(left_ty) - if left_bits != 0 and not _is_state_annotation(bop.left): - return left_ty - right_ty: llvmlite.LLVMType | t.CPtr = _resolve_enum_member_type( - pool, bop.right, imported_modules, from_imports) - if right_ty is not None and not _is_state_annotation(bop.right): - return right_ty - # 两边都是 State 或无法确定,返回较宽的 - right_bits: int = HandlesType.get_llvm_type_bits(right_ty) - if left_bits >= right_bits: - return left_ty - return right_ty - return llvmlite.Int32(pool) - - return llvmlite.Int32(pool) + """解析枚举成员的类型注解为 LLVM 整数类型(委托到 gen._resolve_enum_member_type)""" + import lib.core.Gen.Generator as Generator + g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(_g_gen, t.CPtr)) + if g is not None: + return g._resolve_enum_member_type(pool, ann_node, imported_modules, from_imports) + return None # ============================================================ # _is_state_annotation — 检查注解节点是否为 t.State # ============================================================ def _is_state_annotation(node: ast.AST | t.CPtr) -> int: - """检查注解节点是否为 t.State,返回 1=是 / 0=否""" - if node is None: - return 0 - k: int = node.kind() - if k == ast.ASTKind.Attribute: - at: ast.Attribute | t.CPtr = (ast.Attribute | t.CPtr)(node) - if at.attr is not None and string.strcmp(at.attr, "State") == 0: - return 1 - return 0 - if k == ast.ASTKind.Name: - nm: ast.Name | t.CPtr = (ast.Name | t.CPtr)(node) - if nm.id is not None and string.strcmp(nm.id, "State") == 0: - return 1 - return 0 + """检查注解节点是否为 t.State,返回 1=是 / 0=否(委托到 gen._is_state_annotation)""" + import lib.core.Gen.Generator as Generator + g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(_g_gen, t.CPtr)) + if g is not None: + return g._is_state_annotation(node) return 0 @@ -871,21 +455,11 @@ def _is_state_annotation(node: ast.AST | t.CPtr) -> int: # 支持 Constant(int) 和 UnaryOp(USub, Constant(int)) # ============================================================ def _extract_int_value(node: ast.AST | t.CPtr) -> t.CInt64T: - """从 AST 节点提取整数值,失败返回 0""" - if node is None: - return 0 - k: int = node.kind() - if k == ast.ASTKind.Constant: - cn: ast.Constant | t.CPtr = (ast.Constant | t.CPtr)(node) - if cn.const_kind == ast.CONST_INT: - return cn.int_val - return 0 - if k == ast.ASTKind.UnaryOp: - uo: ast.UnaryOp | t.CPtr = (ast.UnaryOp | t.CPtr)(node) - if uo.op == ast.OpKind.USub: - inner: t.CInt64T = _extract_int_value(uo.operand) - return -inner - return 0 + """从 AST 节点提取整数值,失败返回 0(委托到 gen._extract_int_value)""" + import lib.core.Gen.Generator as Generator + g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(_g_gen, t.CPtr)) + if g is not None: + return g._extract_int_value(node) return 0 @@ -898,170 +472,11 @@ def _extract_int_value(node: ast.AST | t.CPtr) -> t.CInt64T: # ============================================================ def _translate_enum_def(trans: HT.Translator | t.CPtr, cd: ast.ClassDef | t.CPtr) -> int: - """翻译枚举类定义,返回 0""" - if cd is None or cd.name is None or trans is None: - return 0 - - pool: memhub.MemBuddy | t.CPtr = trans.Pool - class_name: str = cd.name - - # 已注册则跳过 - if HandlesEnum.is_enum_class(class_name) == 1: - return 0 - - children: list[ast.AST | t.CPtr] | t.CPtr = cd.children - if children is None: - fb: t.CChar | t.CPtr = VLogger.fmt_buf() - if fb is not None: - viperlib.snprintf(fb, 1024, "%s has no body", class_name) - VLogger.warning(fb, "ENUM") - return 0 - - cn: t.CSizeT = children.__len__() - - # 临时数组存储成员信息 - member_names_buf: t.CSizeT | t.CPtr = pool.alloc(8 * ENUM_MEMBER_MAX_LOCAL) - member_types_buf: t.CSizeT | t.CPtr = pool.alloc(8 * ENUM_MEMBER_MAX_LOCAL) - member_values_buf: t.CInt64T | t.CPtr = pool.alloc(8 * ENUM_MEMBER_MAX_LOCAL) - if member_names_buf is None or member_types_buf is None or member_values_buf is None: - return 0 - string.memset(member_names_buf, 0, 8 * ENUM_MEMBER_MAX_LOCAL) - string.memset(member_types_buf, 0, 8 * ENUM_MEMBER_MAX_LOCAL) - string.memset(member_values_buf, 0, 8 * ENUM_MEMBER_MAX_LOCAL) - - member_count: int = 0 - next_val: t.CInt64T = 0 - - for ci in range(cn): - stmt: ast.AST | t.CPtr = children.get(ci) - if stmt is None: - continue - sk: int = stmt.kind() - - if sk == ast.ASTKind.AnnAssign: - aa: ast.AnnAssign | t.CPtr = (ast.AnnAssign | t.CPtr)(stmt) - if aa is None or aa.target is None: - continue - - # 获取成员名 - if aa.target.kind() != ast.ASTKind.Name: - continue - tgt: ast.Name | t.CPtr = (ast.Name | t.CPtr)(aa.target) - if tgt.id is None: - continue - - # 解析成员类型 - member_ty: llvmlite.LLVMType | t.CPtr = _resolve_enum_member_type( - pool, aa.annotation, trans._imported_modules, trans._from_imports) - - # 解析成员值 - has_value: int = 0 - cur_val: t.CInt64T = 0 - if aa.value is not None: - cur_val = _extract_int_value(aa.value) - has_value = 1 - else: - cur_val = next_val - - # 下一个自动值 - next_val = cur_val + 1 - - # 存储 - if member_count < ENUM_MEMBER_MAX_LOCAL: - member_names_buf[member_count] = t.CSizeT(tgt.id) - member_types_buf[member_count] = t.CSizeT(member_ty) - member_values_buf[member_count] = cur_val - member_count += 1 - - elif sk == ast.ASTKind.Assign: - # 处理 Assign 形式的枚举成员: DEBUG = 0, INFO = 1 等 - # CEnum 子类中无类型注释的赋值也视为枚举成员 - ag: ast.Assign | t.CPtr = (ast.Assign | t.CPtr)(stmt) - if ag is None or ag.targets is None: - continue - tgts: list[ast.AST | t.CPtr] | t.CPtr = ag.targets - tn: t.CSizeT = tgts.__len__() - if tn == 0: - continue - # 取第一个 target 作为成员名 - t0: ast.AST | t.CPtr = tgts.get(0) - if t0 is None or t0.kind() != ast.ASTKind.Name: - continue - tgt_a: ast.Name | t.CPtr = (ast.Name | t.CPtr)(t0) - if tgt_a.id is None: - continue - - # Assign 无类型注释,默认使用 i32 - member_ty_a: llvmlite.LLVMType | t.CPtr = llvmlite.Int32(pool) - - # 解析成员值 - cur_val_a: t.CInt64T = 0 - if ag.value is not None: - cur_val_a = _extract_int_value(ag.value) - else: - cur_val_a = next_val - - # 下一个自动值 - next_val = cur_val_a + 1 - - # 存储 - if member_count < ENUM_MEMBER_MAX_LOCAL: - member_names_buf[member_count] = t.CSizeT(tgt_a.id) - member_types_buf[member_count] = t.CSizeT(member_ty_a) - member_values_buf[member_count] = cur_val_a - member_count += 1 - - if member_count == 0: - fb: t.CChar | t.CPtr = VLogger.fmt_buf() - if fb is not None: - viperlib.snprintf(fb, 1024, "%s has no members", class_name) - VLogger.warning(fb, "ENUM") - return 0 - - # 确定基准类型:所有成员类型中 Bits 最大的 - base_ty: llvmlite.LLVMType | t.CPtr = llvmlite.Int32(pool) - max_bits: int = 0 - for mi in range(member_count): - ty_addr: t.CSizeT = member_types_buf[mi] - if ty_addr == 0: - continue - mty: llvmlite.LLVMType | t.CPtr = (llvmlite.LLVMType | t.CPtr)( - t.CVoid(ty_addr, t.CPtr)) - bits: int = HandlesType.get_llvm_type_bits(mty) - if bits > max_bits: - max_bits = bits - base_ty = mty - - # 注册枚举 - entry: HandlesEnum.EnumEntry | t.CPtr = HandlesEnum.register_enum( - pool, class_name, base_ty) - if entry is None: - fb: t.CChar | t.CPtr = VLogger.fmt_buf() - if fb is not None: - viperlib.snprintf(fb, 1024, "failed to register %s", class_name) - VLogger.error(fb, "ENUM") - return 0 - - # 添加成员 - for mi in range(member_count): - fname_addr: t.CSizeT = member_names_buf[mi] - if fname_addr == 0: - continue - mname: str = (str | t.CPtr)(t.CVoid(fname_addr, t.CPtr)) - fty_addr2: t.CSizeT = member_types_buf[mi] - if fty_addr2 == 0: - continue - mty2: llvmlite.LLVMType | t.CPtr = (llvmlite.LLVMType | t.CPtr)( - t.CVoid(fty_addr2, t.CPtr)) - mval: t.CInt64T = member_values_buf[mi] - if mname is not None and mty2 is not None: - HandlesEnum.add_enum_member(pool, entry, mname, mval, mty2) - - fb: t.CChar | t.CPtr = VLogger.fmt_buf() - if fb is not None: - viperlib.snprintf(fb, 1024, "registered %s with %d members, base_bits=%d", - class_name, member_count, max_bits) - VLogger.info(fb, "ENUM") + """翻译枚举类定义,返回 0(委托到 gen._translate_enum_def)""" + import lib.core.Gen.Generator as Generator + g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(_g_gen, t.CPtr)) + if g is not None: + return g._translate_enum_def(trans, cd) return 0 @@ -1071,90 +486,21 @@ def _translate_enum_def(trans: HT.Translator | t.CPtr, # 用于联合体确定最大字段大小 # ============================================================ def _get_type_size(ty: llvmlite.LLVMType | t.CPtr) -> int: - """计算 LLVM 类型的字节大小(含对齐 padding)""" - if ty is None: - return 0 - match ty: - case llvmlite.LLVMType.Int(bits): - return (bits + 7) // 8 - case llvmlite.LLVMType.Float(bits): - return bits // 8 - case llvmlite.LLVMType.Ptr(pointee): - return 8 - case llvmlite.LLVMType.Array(elem_ty, count): - return _get_type_size(elem_ty) * count - case llvmlite.LLVMType.Struct(fields, fcount, name): - # 计算结构体大小,考虑字段对齐 padding - # 规则: 每个字段的对齐 = 该字段类型的自然对齐 - # 指针/i64 → 8, i32 → 4, i16 → 2, i8 → 1 - # 结构体总大小需对齐到最大字段对齐的倍数 - total: int = 0 - max_align: int = 1 - cur: llvmlite.ParamNode | t.CPtr = fields - i: int = 0 - while cur is not None and i < fcount: - if cur.Ty is not None: - fty: llvmlite.LLVMType | t.CPtr = (llvmlite.LLVMType | t.CPtr)(cur.Ty) - fsize: int = _get_type_size(fty) - falign: int = _get_type_align(fty) - # 对齐当前偏移到字段对齐边界 - if falign > 0: - rem: int = total % falign - if rem != 0: - total += falign - rem - total += fsize - if falign > max_align: - max_align = falign - cur = cur.Next - i += 1 - # 结构体总大小对齐到最大字段对齐的倍数 - rem2: int = total % max_align - if rem2 != 0: - total += max_align - rem2 - return total - case _: - return 8 + """计算 LLVM 类型的字节大小(含对齐 padding)(委托到 gen._get_type_size)""" + import lib.core.Gen.Generator as Generator + g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(_g_gen, t.CPtr)) + if g is not None: + return g._get_type_size(ty) + return 0 def _get_type_align(ty: llvmlite.LLVMType | t.CPtr) -> int: - """返回类型的自然对齐(字节)""" - if ty is None: - return 1 - match ty: - case llvmlite.LLVMType.Int(bits): - if bits <= 8: - return 1 - elif bits <= 16: - return 2 - elif bits <= 32: - return 4 - else: - return 8 - case llvmlite.LLVMType.Float(bits): - if bits <= 32: - return 4 - else: - return 8 - case llvmlite.LLVMType.Ptr(pointee): - return 8 - case llvmlite.LLVMType.Array(elem_ty, count): - return _get_type_align(elem_ty) - case llvmlite.LLVMType.Struct(fields, fcount, name): - # 结构体的对齐 = 最大字段对齐 - max_align: int = 1 - cur: llvmlite.ParamNode | t.CPtr = fields - i: int = 0 - while cur is not None and i < fcount: - if cur.Ty is not None: - fty: llvmlite.LLVMType | t.CPtr = (llvmlite.LLVMType | t.CPtr)(cur.Ty) - fa: int = _get_type_align(fty) - if fa > max_align: - max_align = fa - cur = cur.Next - i += 1 - return max_align - case _: - return 8 + """返回类型的自然对齐(字节)(委托到 gen._get_type_align)""" + import lib.core.Gen.Generator as Generator + g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(_g_gen, t.CPtr)) + if g is not None: + return g._get_type_align(ty) + return 0 # ============================================================ @@ -1175,174 +521,11 @@ def _get_type_align(ty: llvmlite.LLVMType | t.CPtr) -> int: # ============================================================ def _translate_union_def(trans: HT.Translator | t.CPtr, cd: ast.ClassDef | t.CPtr) -> int: - """翻译联合体定义,返回 0""" - if cd is None or cd.name is None or trans is None: - return 0 - - pool: memhub.MemBuddy | t.CPtr = trans.Pool - class_name: str = cd.name - - # 命名空间隔离:标记为当前文件可见(必须在 existing 检查之前) - HandlesStruct.add_visible_struct(pool, class_name) - - # 检查是否已注册(用 SHA1 区分跨模块同名类) - existing: HandlesStruct.StructEntry | t.CPtr = HandlesStruct.find_struct_by_module( - class_name, trans.ModuleSha1) - if existing is not None: - # Phase B: 将已存在的命名结构体注册到当前模块 - if existing.Ty is not None: - llvmlite.module_add_named_type(trans.Module, pool, existing.Ty) - # SHA1 已在 register_struct 时设置,无需再补 - return 0 - - children: list[ast.AST | t.CPtr] | t.CPtr = cd.children - if children is None: - fb: t.CChar | t.CPtr = VLogger.fmt_buf() - if fb is not None: - viperlib.snprintf(fb, 1024, "%s has no body", class_name) - VLogger.warning(fb, "UNION") - return 0 - - cn: t.CSizeT = children.__len__() - - # 临时数组存储字段信息 - field_names_buf: t.CSizeT | t.CPtr = pool.alloc(8 * 64) - field_types_buf: t.CSizeT | t.CPtr = pool.alloc(8 * 64) - if field_names_buf is None or field_types_buf is None: - return 0 - string.memset(field_names_buf, 0, 8 * 64) - string.memset(field_types_buf, 0, 8 * 64) - - field_count: int = 0 - max_size: int = 0 - - for ci in range(cn): - stmt: ast.AST | t.CPtr = children.get(ci) - if stmt is None: - continue - sk: int = stmt.kind() - - if sk == ast.ASTKind.AnnAssign: - aa: ast.AnnAssign | t.CPtr = (ast.AnnAssign | t.CPtr)(stmt) - if aa is None or aa.target is None: - continue - - # 获取字段名 - if aa.target.kind() != ast.ASTKind.Name: - continue - tgt: ast.Name | t.CPtr = (ast.Name | t.CPtr)(aa.target) - if tgt.id is None: - continue - - # 解析字段类型 - field_ty: llvmlite.LLVMType | t.CPtr = HandlesType.resolve_annotation_type( - pool, aa.annotation, trans._imported_modules, trans._from_imports, trans) - if field_ty is None: - # Phase A-pre(declare_only=1):依赖的类可能尚未注册, - # 静默 return 1 让多遍收敛机制生效(renum 返回 1=跳过该类) - if trans._declare_only == 1: - return 1 - # Phase B(declare_only=0):真正的类型解析错误,fast-fail 终止 - type_name: str = HandlesType.annotation_to_str(aa.annotation) - HandlesType.fatal_error( - aa, - f"'{type_name}' is not defined", - "NameError") - field_ty = llvmlite.Int32(pool) - - # 计算字段大小,更新 max_size - fsize: int = _get_type_size(field_ty) - if fsize > max_size: - max_size = fsize - - # 存储到数组 - if field_count < 64: - field_names_buf[field_count] = t.CSizeT(tgt.id) - field_types_buf[field_count] = t.CSizeT(field_ty) - field_count += 1 - - if field_count == 0: - fb: t.CChar | t.CPtr = VLogger.fmt_buf() - if fb is not None: - viperlib.snprintf(fb, 1024, "%s has no fields", class_name) - VLogger.warning(fb, "UNION") - return 0 - - if max_size < 1: - max_size = 1 - - # 创建联合体的 LLVM 类型: Struct([Array(Int8, max_size)]) - # 即 { [max_size x i8] } - i8_ty: llvmlite.LLVMType | t.CPtr = llvmlite.Int8(pool) - array_ty: llvmlite.LLVMType | t.CPtr = llvmlite.Array(pool, i8_ty, max_size) - - # 构建 ParamNode 链表(单字段:字节数组) - pnode: llvmlite.ParamNode | t.CPtr = pool.alloc(llvmlite.ParamNode.__sizeof__()) - if pnode is None: - return 0 - string.memset(pnode, 0, llvmlite.ParamNode.__sizeof__()) - pnode.Ty = array_ty - - # 构造命名结构体类型名: "sha1.ClassName" 或 "ClassName" - union_type_name: str = class_name - if trans.ModuleSha1 is not None: - union_name_buf: t.CChar | t.CPtr = pool.alloc(64) - if union_name_buf is not None: - viperlib.snprintf(union_name_buf, 64, "%s.%s", trans.ModuleSha1, class_name) - union_type_name = union_name_buf - - union_ty: llvmlite.LLVMType | t.CPtr = llvmlite.Struct(pool, pnode, 1, union_type_name) - if union_ty is None: - fb: t.CChar | t.CPtr = VLogger.fmt_buf() - if fb is not None: - viperlib.snprintf(fb, 1024, "failed to create type for %s", class_name) - VLogger.error(fb, "UNION") - return 0 - - # Phase 1b 新注册的 union struct_ty 深拷贝到 stdlib(跨文件 reset 存活) - if trans._declare_only == 0: - union_copy: llvmlite.LLVMType | t.CPtr = llvmlite.DeepCopyType(pool, union_ty) - if union_copy is not None: - union_ty = union_copy - - # 注册命名结构体到模块 - llvmlite.module_add_named_type(trans.Module, pool, union_ty) - - # 注册到 HandlesStruct(传递 SHA1 在注册时直接设置,避免跨模块同名找错 entry) - entry: HandlesStruct.StructEntry | t.CPtr = HandlesStruct.register_struct( - pool, class_name, union_ty, trans.ModuleSha1) - if entry is None: - fb: t.CChar | t.CPtr = VLogger.fmt_buf() - if fb is not None: - viperlib.snprintf(fb, 1024, "failed to register %s", class_name) - VLogger.error(fb, "UNION") - return 0 - - # 标记为当前文件可见(命名空间隔离) - HandlesStruct.add_visible_struct(pool, class_name) - - # 标记为联合体(直接用 entry,规避跨模块同名 find_struct 找错) - entry.IsUnion = 1 - - # 添加字段信息(所有字段 Index=0,因为共享偏移 0) - for fi in range(field_count): - fname_addr: t.CSizeT = field_names_buf[fi] - if fname_addr == 0: - continue - fname: str = (str | t.CPtr)(t.CVoid(fname_addr, t.CPtr)) - fty_addr2: t.CSizeT = field_types_buf[fi] - if fty_addr2 == 0: - continue - fty2: llvmlite.LLVMType | t.CPtr = (llvmlite.LLVMType | t.CPtr)( - t.CVoid(fty_addr2, t.CPtr)) - if fname is not None and fty2 is not None: - HandlesStruct.add_field(pool, entry, fname, fty2, None, None) - - fb: t.CChar | t.CPtr = VLogger.fmt_buf() - if fb is not None: - viperlib.snprintf(fb, 1024, "registered %s with %d fields, max_size=%d", - class_name, field_count, max_size) - VLogger.info(fb, "UNION") + """翻译联合体定义,返回 0(委托到 gen._translate_union_def)""" + import lib.core.Gen.Generator as Generator + g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(_g_gen, t.CPtr)) + if g is not None: + return g._translate_union_def(trans, cd) return 0 @@ -1354,63 +537,12 @@ def _translate_union_def(trans: HT.Translator | t.CPtr, # 未知类型默认 8 字节(指针)。 # ============================================================ def _get_annotation_field_size(annotation: ast.AST | t.CPtr) -> int: - """计算注解类型的字节大小,用于 REnum 布局计算""" - if annotation is None: - return 8 - k: int = annotation.kind() - # 联合类型 A | B → 指针大小 8 - if k == ast.ASTKind.BinOp: - return 8 - # Name(id) 或 Attribute(attr) → 解析类型名 - type_name: str = None - if k == ast.ASTKind.Name: - nm: ast.Name | t.CPtr = (ast.Name | t.CPtr)(annotation) - if nm is not None: - type_name = nm.id - elif k == ast.ASTKind.Attribute: - at: ast.Attribute | t.CPtr = (ast.Attribute | t.CPtr)(annotation) - if at is not None: - type_name = at.attr - if type_name is None: - return 8 - # 内置类型 - if string.strcmp(type_name, "int") == 0: - return 4 - if string.strcmp(type_name, "CInt") == 0: - return 4 - if string.strcmp(type_name, "CInt8T") == 0: - return 1 - if string.strcmp(type_name, "CInt16T") == 0: - return 2 - if string.strcmp(type_name, "CInt32T") == 0: - return 4 - if string.strcmp(type_name, "CInt64T") == 0: - return 8 - if string.strcmp(type_name, "CChar") == 0: - return 1 - if string.strcmp(type_name, "CDouble") == 0: - return 8 - if string.strcmp(type_name, "CFloat") == 0: - return 4 - if string.strcmp(type_name, "CPtr") == 0: - return 8 - if string.strcmp(type_name, "CSizeT") == 0: - return 8 - if string.strcmp(type_name, "str") == 0: - return 8 - if string.strcmp(type_name, "bytes") == 0: - return 8 - if string.strcmp(type_name, "bool") == 0: - # bool = t.CBool = i8(1 字节) - return 1 - # 已注册的结构体类型 - struct_ty: llvmlite.LLVMType | t.CPtr = HandlesStruct.get_struct_type(type_name) - if struct_ty is not None: - sz: int = _get_type_size(struct_ty) - if sz > 0: - return sz - # 未注册类型 → 默认指针大小 8(可能是自引用或前向引用) - return 8 + """计算注解类型的字节大小,用于 REnum 布局计算(委托到 gen._get_annotation_field_size)""" + import lib.core.Gen.Generator as Generator + g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(_g_gen, t.CPtr)) + if g is not None: + return g._get_annotation_field_size(annotation) + return 0 # ============================================================ @@ -1434,215 +566,11 @@ def _get_annotation_field_size(annotation: ast.AST | t.CPtr) -> int: # ============================================================ def _translate_renum_def(trans: HT.Translator | t.CPtr, cd: ast.ClassDef | t.CPtr) -> int: - """翻译 REnum 类定义,返回 0""" - if cd is None or cd.name is None or trans is None: - return 0 - - pool: memhub.MemBuddy | t.CPtr = trans.Pool - class_name: str = cd.name - - # 命名空间隔离:标记为当前文件可见 - HandlesStruct.add_visible_struct(pool, class_name) - - # 检查是否已注册(用 SHA1 区分跨模块同名类) - existing: HandlesStruct.StructEntry | t.CPtr = HandlesStruct.find_struct_by_module( - class_name, trans.ModuleSha1) - if existing is not None: - if existing.Ty is not None: - llvmlite.module_add_named_type(trans.Module, pool, existing.Ty) - return 0 - - children: list[ast.AST | t.CPtr] | t.CPtr = cd.children - if children is None: - fb: t.CChar | t.CPtr = VLogger.fmt_buf() - if fb is not None: - viperlib.snprintf(fb, 1024, "%s has no body", class_name) - VLogger.warning(fb, "RENUM") - return 0 - - cn: t.CSizeT = children.__len__() - - # 变体最多 32 个,每个变体最多 16 个字段 - # variant_field_sizes[i][j] = 变体 i 的第 j 个字段大小 - variant_field_sizes: t.CSizeT | t.CPtr = pool.alloc(8 * 64 * 16) - if variant_field_sizes is None: - return 0 - string.memset(variant_field_sizes, 0, 8 * 64 * 16) - - variant_count: int = 0 - max_field_count: int = 0 # 所有变体中最大字段数 - - for ci in range(cn): - stmt: ast.AST | t.CPtr = children.get(ci) - if stmt is None: - continue - sk: int = stmt.kind() - - if sk == ast.ASTKind.ClassDef: - # 嵌套变体类 - variant_cd: ast.ClassDef | t.CPtr = (ast.ClassDef | t.CPtr)(stmt) - if variant_cd is None or variant_cd.children is None: - variant_count += 1 - continue - variant_children: list[ast.AST | t.CPtr] | t.CPtr = variant_cd.children - vcn: t.CSizeT = variant_children.__len__() - field_idx: int = 0 - for vi in range(vcn): - vstmt: ast.AST | t.CPtr = variant_children.get(vi) - if vstmt is None: - continue - vk: int = vstmt.kind() - if vk != ast.ASTKind.AnnAssign: - continue - vaa: ast.AnnAssign | t.CPtr = (ast.AnnAssign | t.CPtr)(vstmt) - if vaa is None or vaa.target is None or vaa.annotation is None: - continue - if vaa.target.kind() != ast.ASTKind.Name: - continue - # 提取字段名 - vnm: ast.Name | t.CPtr = (ast.Name | t.CPtr)(vaa.target) - # 计算字段大小 - fsize: int = _get_annotation_field_size(vaa.annotation) - if variant_count < 32 and field_idx < 16: - # variant_field_sizes[variant_count][field_idx] = fsize - offset: t.CSizeT = variant_count * 16 + field_idx - variant_field_sizes[offset] = t.CSizeT(fsize) - # 直接注册变体字段名别名(避免 CSizeT→str 转换问题) - if vnm is not None and vnm.id is not None: - _register_renum_field_alias(pool, class_name, vnm.id, field_idx + 1) - field_idx += 1 - if field_idx > max_field_count: - max_field_count = field_idx - variant_count += 1 - - if variant_count == 0: - fb2: t.CChar | t.CPtr = VLogger.fmt_buf() - if fb2 is not None: - viperlib.snprintf(fb2, 1024, "%s has no variants", class_name) - VLogger.warning(fb2, "RENUM") - return 0 - - # 计算每个位置的最大字段大小 - # 位置 0 = __tag (i32, 4 字节) - # 位置 1+ = 变体字段 - total_positions: int = max_field_count + 1 # +1 for tag - if total_positions < 2: - total_positions = 2 # 至少 {i32, i32} - - position_max_sizes: t.CSizeT | t.CPtr = pool.alloc(8 * total_positions) - if position_max_sizes is None: - return 0 - string.memset(position_max_sizes, 0, 8 * total_positions) - - # 位置 0 = tag = 4 字节 - position_max_sizes[0] = t.CSizeT(4) - - # 位置 1+ = 每个位置取所有变体的最大字段大小 - for pos in range(1, total_positions): - pos_max: int = 0 - for vi in range(variant_count): - field_pos: int = pos - 1 # 变体字段从位置 0 开始 - offset2: t.CSizeT = vi * 16 + field_pos - fsize_val: t.CSizeT = variant_field_sizes[offset2] - if fsize_val > pos_max: - pos_max = fsize_val - position_max_sizes[pos] = t.CSizeT(pos_max) - - # 构建 ParamNode 链表 - i32_ty: llvmlite.LLVMType | t.CPtr = llvmlite.Int32(pool) - i64_ty: llvmlite.LLVMType | t.CPtr = llvmlite.Int64(pool) - - first_node: llvmlite.ParamNode | t.CPtr = None - tail_node: llvmlite.ParamNode | t.CPtr = None - - for pos in range(total_positions): - psize: int = position_max_sizes[pos] - field_ty: llvmlite.LLVMType | t.CPtr = i32_ty - if psize > 4: - field_ty = i64_ty - pnode: llvmlite.ParamNode | t.CPtr = llvmlite.new_param_node(pool, field_ty) - if pnode is None: - continue - tail_node = llvmlite.param_list_append(first_node, tail_node, pnode) - if first_node is None: - first_node = tail_node - - if first_node is None: - fb3: t.CChar | t.CPtr = VLogger.fmt_buf() - if fb3 is not None: - viperlib.snprintf(fb3, 1024, "failed to build field list for %s", class_name) - VLogger.error(fb3, "RENUM") - return 0 - - # 构造命名结构体类型名: "sha1.ClassName" 或 "ClassName" - renum_type_name: str = class_name - if trans.ModuleSha1 is not None: - renum_name_buf: t.CChar | t.CPtr = pool.alloc(64) - if renum_name_buf is not None: - viperlib.snprintf(renum_name_buf, 64, "%s.%s", trans.ModuleSha1, class_name) - renum_type_name = renum_name_buf - - renum_ty: llvmlite.LLVMType | t.CPtr = llvmlite.Struct( - pool, first_node, total_positions, renum_type_name) - if renum_ty is None: - fb4: t.CChar | t.CPtr = VLogger.fmt_buf() - if fb4 is not None: - viperlib.snprintf(fb4, 1024, "failed to create type for %s", class_name) - VLogger.error(fb4, "RENUM") - return 0 - - # Phase 1b 新注册的 REnum struct_ty 深拷贝到 stdlib(跨文件 reset 存活, - # 与 entry.Ty 保持同一指针,find_struct_by_type 匹配不失效) - if trans._declare_only == 0: - renum_copy: llvmlite.LLVMType | t.CPtr = llvmlite.DeepCopyType(pool, renum_ty) - if renum_copy is not None: - renum_ty = renum_copy - - # 注册命名结构体到模块 - llvmlite.module_add_named_type(trans.Module, pool, renum_ty) - - # 注册到 HandlesStruct - entry: HandlesStruct.StructEntry | t.CPtr = HandlesStruct.register_struct( - pool, class_name, renum_ty, trans.ModuleSha1) - if entry is None: - fb5: t.CChar | t.CPtr = VLogger.fmt_buf() - if fb5 is not None: - viperlib.snprintf(fb5, 1024, "failed to register %s", class_name) - VLogger.error(fb5, "RENUM") - return 0 - - # 修复 class_name 指针不匹配: - # 别名注册时用 class_name(= cd.name,AST 原始指针), - # 但查找时用 entry.Name(register_struct 通过 pool.alloc+strcpy 复制的副本指针)。 - # 两者是不同指针,CSizeT 指针值比较会失败。 - # 调用辅助函数将已注册别名的 class_name 统一更新为 entry.Name。 - if entry.Name is not None: - _update_renum_alias_class_ptr(t.CSizeT(class_name), t.CSizeT(entry.Name)) - - # 添加 __tag 字段(位置 0,i32) - HandlesStruct.add_field(pool, entry, "__tag", i32_ty, None, None) - - # 添加 payload 字段(位置 1+,i32 或 i64) - for pos in range(1, total_positions): - psize2: int = position_max_sizes[pos] - payload_ty: llvmlite.LLVMType | t.CPtr = i32_ty - if psize2 > 4: - payload_ty = i64_ty - field_name_buf: t.CChar | t.CPtr = pool.alloc(16) - if field_name_buf is not None: - viperlib.snprintf(field_name_buf, 16, "_p%d", pos) - HandlesStruct.add_field(pool, entry, field_name_buf, payload_ty, None, None) - - # 注册变体名到全局变体表(供 translate_call 检测 REnum 变体构造) - _register_renum_variants(pool, class_name, cd, variant_count) - - # 注册变体字段名别名已在变体遍历时直接完成(避免 CSizeT→str 转换问题) - - fb6: t.CChar | t.CPtr = VLogger.fmt_buf() - if fb6 is not None: - viperlib.snprintf(fb6, 1024, "registered %s with %d variants, %d positions", - class_name, variant_count, total_positions) - VLogger.info(fb6, "RENUM") + """翻译 REnum 类定义,返回 0(委托到 gen._translate_renum_def)""" + import lib.core.Gen.Generator as Generator + g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(_g_gen, t.CPtr)) + if g is not None: + return g._translate_renum_def(trans, cd) return 0 @@ -1652,17 +580,9 @@ def _translate_renum_def(trans: HT.Translator | t.CPtr, # 存储 ClassName → [VariantName, TagValue] 映射, # 供 translate_call 检测 ClassName.VariantName(args) 形式的变体构造调用。 # -# 布局(所有数组使用 t.CSizeT | t.CPtr 确保 8 字节步长): -# _renum_class_names[i] = 第 i 个 REnum 类名(str 指针,以 CSizeT 存储) -# _renum_class_variant_counts[i] = 第 i 个 REnum 类的变体数量 -# _renum_variant_names[i][j] = 第 i 个类的第 j 个变体名(str 指针,以 CSizeT 存储) -# _renum_variant_tags[i][j] = 第 i 个类的第 j 个变体的 tag 值 +# P5-2 后已迁入 gen 字段(ClassGenMixin.RenumClassNames/RenumClassCount/ +# RenumVariantNames/RenumVariantTags),经下方委托函数访问。 # ============================================================ -_renum_class_names: t.CSizeT | t.CPtr = None -_renum_class_variant_counts: t.CSizeT | t.CPtr = None -_renum_variant_names: t.CSizeT | t.CPtr = None -_renum_variant_tags: t.CSizeT | t.CPtr = None -_renum_class_count: int = 0 # ============================================================ @@ -1681,10 +601,6 @@ _renum_class_count: int = 0 # _renum_alias_index[i] = payload 索引(CSizeT) # ============================================================ RENUM_ALIAS_MAX: t.CDefine = 512 -_renum_alias_class: t.CSizeT | t.CPtr = None -_renum_alias_field: t.CSizeT | t.CPtr = None -_renum_alias_index: t.CSizeT | t.CPtr = None -_renum_alias_count: int = 0 # ============================================================ @@ -1703,72 +619,11 @@ def _register_renum_variants(pool: memhub.MemBuddy | t.CPtr, class_name: str, cd: ast.ClassDef | t.CPtr, variant_count: int): - """注册 REnum 类的变体名和 tag 值到全局变体表""" - global _renum_class_names, _renum_class_variant_counts - global _renum_variant_names, _renum_variant_tags, _renum_class_count - - if pool is None or class_name is None or cd is None: - return - if variant_count == 0: - return - children: list[ast.AST | t.CPtr] | t.CPtr = cd.children - if children is None: - return - - # 懒初始化表(首次注册时分配) - # 注意: 必须用 stdlib 分配——这些表在 1b 阶段(mark1 之后)首次分配, - # 若用 pool 会被 reset_to(mark1) 回收导致悬空(LLVMType 的 match 在 - # parser.vp 等后续文件翻译时访问已回收的表 → 崩溃)。 - if _renum_class_names is None: - _renum_class_names = stdlib.malloc(8 * RENUM_CLASS_MAX) - _renum_class_variant_counts = stdlib.malloc(8 * RENUM_CLASS_MAX) - _renum_variant_names = stdlib.malloc(8 * RENUM_CLASS_MAX * RENUM_VARIANT_PER_CLASS) - _renum_variant_tags = stdlib.malloc(8 * RENUM_CLASS_MAX * RENUM_VARIANT_PER_CLASS) - if (_renum_class_names is None or _renum_class_variant_counts is None - or _renum_variant_names is None or _renum_variant_tags is None): - _renum_class_names = None - return - string.memset(_renum_class_names, 0, 8 * RENUM_CLASS_MAX) - string.memset(_renum_class_variant_counts, 0, 8 * RENUM_CLASS_MAX) - string.memset(_renum_variant_names, 0, 8 * RENUM_CLASS_MAX * RENUM_VARIANT_PER_CLASS) - string.memset(_renum_variant_tags, 0, 8 * RENUM_CLASS_MAX * RENUM_VARIANT_PER_CLASS) - _renum_class_count = 0 - - # 检查是否已注册(避免重复注册) - for i in range(_renum_class_count): - existing: str = _renum_class_names[i] - if existing is not None and string.strcmp(existing, class_name) == 0: - return - - # 表已满 - if _renum_class_count >= RENUM_CLASS_MAX: - return - - # 注册类名 - idx: int = _renum_class_count - _renum_class_names[idx] = t.CSizeT(class_name) - _renum_class_variant_counts[idx] = variant_count - - # 遍历 children,提取嵌套变体类名并注册 - cn: t.CSizeT = children.__len__() - tag: int = 0 - for ci in range(cn): - if tag >= variant_count: - break - stmt: ast.AST | t.CPtr = children.get(ci) - if stmt is None: - continue - if stmt.kind() != ast.ASTKind.ClassDef: - continue - vcd: ast.ClassDef | t.CPtr = (ast.ClassDef | t.CPtr)(stmt) - if vcd is None or vcd.name is None: - continue - name_offset: t.CSizeT = idx * RENUM_VARIANT_PER_CLASS + tag - _renum_variant_names[name_offset] = t.CSizeT(vcd.name) - _renum_variant_tags[name_offset] = tag - tag += 1 - - _renum_class_count = idx + 1 + """注册 REnum 类的变体名和 tag 值到全局变体表(委托到 gen._register_renum_variants)""" + import lib.core.Gen.Generator as Generator + g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(_g_gen, t.CPtr)) + if g is not None: + g._register_renum_variants(pool, class_name, cd, variant_count) # ============================================================ @@ -1785,19 +640,12 @@ def _register_renum_variants(pool: memhub.MemBuddy | t.CPtr, def _lookup_renum_variant(variant_name: str) -> str: """查找变体名所属的 REnum 类名 - 返回: class_name (str),或 None + 返回: class_name (str),或 None(委托到 gen._lookup_renum_variant) """ - if variant_name is None or _renum_class_names is None: - return None - - for i in range(_renum_class_count): - vcount: int = _renum_class_variant_counts[i] - for j in range(vcount): - name_offset: t.CSizeT = i * RENUM_VARIANT_PER_CLASS + j - vname: str = _renum_variant_names[name_offset] - if vname is not None and string.strcmp(vname, variant_name) == 0: - cls_nm: str = _renum_class_names[i] - return cls_nm + import lib.core.Gen.Generator as Generator + g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(_g_gen, t.CPtr)) + if g is not None: + return g._lookup_renum_variant(variant_name) return None @@ -1808,13 +656,11 @@ def _lookup_renum_variant(variant_name: str) -> str: # 先验证 ClassName 是否是 REnum 类。 # ============================================================ def _is_renum_class_name(class_name: str) -> int: - """检查名称是否是已注册的 REnum 类名,返回 1=是 / 0=否""" - if class_name is None or _renum_class_names is None: - return 0 - for i in range(_renum_class_count): - existing: str = _renum_class_names[i] - if existing is not None and string.strcmp(existing, class_name) == 0: - return 1 + """检查名称是否是已注册的 REnum 类名,返回 1=是 / 0=否(委托到 gen._is_renum_class_name)""" + import lib.core.Gen.Generator as Generator + g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(_g_gen, t.CPtr)) + if g is not None: + return g._is_renum_class_name(class_name) return 0 @@ -1830,21 +676,12 @@ def _is_renum_class_name(class_name: str) -> int: # 失败: -1 # ============================================================ def _lookup_renum_variant_in_class(class_name: str, variant_name: str) -> int: - """在指定 REnum 类中查找变体,返回 tag 值或 -1""" - if class_name is None or variant_name is None or _renum_class_names is None: - return -1 - for i in range(_renum_class_count): - existing: str = _renum_class_names[i] - if existing is None or string.strcmp(existing, class_name) != 0: - continue - vcount: int = _renum_class_variant_counts[i] - for j in range(vcount): - name_offset: t.CSizeT = i * RENUM_VARIANT_PER_CLASS + j - vname: str = _renum_variant_names[name_offset] - if vname is not None and string.strcmp(vname, variant_name) == 0: - return _renum_variant_tags[name_offset] - return -1 - return -1 + """在指定 REnum 类中查找变体,返回 tag 值或 -1(委托到 gen._lookup_renum_variant_in_class)""" + import lib.core.Gen.Generator as Generator + g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(_g_gen, t.CPtr)) + if g is not None: + return g._lookup_renum_variant_in_class(class_name, variant_name) + return 0 # ============================================================ @@ -1863,46 +700,11 @@ def _register_renum_field_alias(pool: memhub.MemBuddy | t.CPtr, class_name: str, field_name: str, payload_idx: int): - """注册 REnum 变体字段名别名到全局表""" - global _renum_alias_class, _renum_alias_field, _renum_alias_index - global _renum_alias_count - - if pool is None or class_name is None or field_name is None: - return - if payload_idx < 1: - return - - # 懒初始化表 - if _renum_alias_class is None: - _renum_alias_class = pool.alloc(8 * RENUM_ALIAS_MAX) - _renum_alias_field = pool.alloc(8 * RENUM_ALIAS_MAX) - _renum_alias_index = pool.alloc(8 * RENUM_ALIAS_MAX) - if (_renum_alias_class is None or _renum_alias_field is None - or _renum_alias_index is None): - _renum_alias_class = None - return - string.memset(_renum_alias_class, 0, 8 * RENUM_ALIAS_MAX) - string.memset(_renum_alias_field, 0, 8 * RENUM_ALIAS_MAX) - string.memset(_renum_alias_index, 0, 8 * RENUM_ALIAS_MAX) - _renum_alias_count = 0 - - if _renum_alias_count >= RENUM_ALIAS_MAX: - return - - # 检查是否已注册(避免重复)— 用 CSizeT 指针值比较,避免 CSizeT→str 转换问题 - cls_key: t.CSizeT = t.CSizeT(class_name) - fld_key: t.CSizeT = t.CSizeT(field_name) - for i in range(_renum_alias_count): - cls_existing: t.CSizeT = _renum_alias_class[i] - fld_existing: t.CSizeT = _renum_alias_field[i] - if cls_existing == cls_key and fld_existing == fld_key: - return - - idx: int = _renum_alias_count - _renum_alias_class[idx] = cls_key - _renum_alias_field[idx] = fld_key - _renum_alias_index[idx] = t.CSizeT(payload_idx) - _renum_alias_count = idx + 1 + """注册 REnum 变体字段名别名到全局表(委托到 gen._register_renum_field_alias)""" + import lib.core.Gen.Generator as Generator + g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(_g_gen, t.CPtr)) + if g is not None: + g._register_renum_field_alias(pool, class_name, field_name, payload_idx) # ============================================================ @@ -1918,16 +720,11 @@ def _register_renum_field_alias(pool: memhub.MemBuddy | t.CPtr, # new_ptr: 新 class_name 指针值(CSizeT(entry.Name)) # ============================================================ def _update_renum_alias_class_ptr(old_ptr: t.CSizeT, new_ptr: t.CSizeT): - """更新别名表中的 class_name 指针,从 old_ptr 更新为 new_ptr""" - global _renum_alias_class, _renum_alias_count - - if old_ptr == new_ptr: - return - if _renum_alias_class is None: - return - for i in range(_renum_alias_count): - if _renum_alias_class[i] == old_ptr: - _renum_alias_class[i] = new_ptr + """更新别名表中的 class_name 指针,从 old_ptr 更新为 new_ptr(委托到 gen._update_renum_alias_class_ptr)""" + import lib.core.Gen.Generator as Generator + g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(_g_gen, t.CPtr)) + if g is not None: + g._update_renum_alias_class_ptr(old_ptr, new_ptr) # ============================================================ @@ -1946,19 +743,13 @@ def _lookup_renum_field_alias(class_name: str, field_name: str) -> int: class_name: 用 CSizeT 指针值比较(_update_renum_alias_class_ptr 已统一指针) field_name: 用 strcmp 内容比较(注册时 vnm.id 与查找时 at.attr 是不同指针) + (委托到 gen._lookup_renum_field_alias) """ - if class_name is None or field_name is None or _renum_alias_class is None: - return -1 - cls_key: t.CSizeT = t.CSizeT(class_name) - for i in range(_renum_alias_count): - cls_existing: t.CSizeT = _renum_alias_class[i] - if cls_existing == cls_key: - # field_name 用 strcmp 内容比较(指针不同但内容相同) - fld_existing_ptr: str = (str | t.CPtr)( - t.CVoid(_renum_alias_field[i], t.CPtr)) - if fld_existing_ptr is not None and string.strcmp(fld_existing_ptr, field_name) == 0: - return _renum_alias_index[i] - return -1 + import lib.core.Gen.Generator as Generator + g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(_g_gen, t.CPtr)) + if g is not None: + return g._lookup_renum_field_alias(class_name, field_name) + return 0 # ============================================================ @@ -1968,127 +759,62 @@ def _lookup_renum_field_alias(class_name: str, field_name: str) -> int: # 创建 LLVM StructType 并注册到 HandlesStruct # ============================================================ # ============================================================ -# 泛型类模板存储(模块级) +# 泛型类模板存储 # # 泛型类 class list[T]: 不直接发射 IR,而是存储为模板, -# 等遇到 list[int](pool) 实例化时触发 _specialize_generic_class +# 等遇到 list[int](pool) 实例化时触发 _specialize_generic_class。 +# +# P5-2 收尾:已迁入 gen 字段(ClassGenMixin.GenericClassNames/ +# GenericClassNodes/GenericClassSha1s),经下方委托函数访问。 # ============================================================ -_generic_class_names: list[str] | t.CPtr = None -_generic_class_nodes: list[ast.ClassDef | t.CPtr] | t.CPtr = None -# 追踪每个泛型模板定义模块的 SHA1,用于特化时统一命名空间 -_generic_class_sha1s: list[str] | t.CPtr = None - def _is_generic_class(tp: list[str] | t.CPtr) -> int: - """检查 ClassDef 是否有类型参数(泛型类),返回 1=是 / 0=否 - - 接收 type_params 而非 cd,避免 cd.type_params 属性访问 - 因跨模块类型推断失败返回 None。 - """ - if tp is None: - return 0 - return 1 + """检查 ClassDef 是否有类型参数(泛型类),返回 1=是 / 0=否(委托到 gen._is_generic_class)""" + import lib.core.Gen.Generator as Generator + g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(_g_gen, t.CPtr)) + if g is not None: + return g._is_generic_class(tp) + return 0 def _register_generic_template(pool: memhub.MemBuddy | t.CPtr, cd: ast.ClassDef | t.CPtr, module_sha1: str): - """注册泛型类模板(类名 + ClassDef 节点 + 来源模块 SHA1)""" - global _generic_class_names, _generic_class_nodes, _generic_class_sha1s - if _generic_class_names is None: - _generic_class_names = list[str](pool, 8) - _generic_class_nodes = list[ast.ClassDef | t.CPtr](pool, 8) - _generic_class_sha1s = list[str](pool, 8) - # 用局部变量接收 global list,触发类型推断(避免 global 变量 __len__ 失败) - names_local: list[str] | t.CPtr = _generic_class_names - cn: t.CSizeT = names_local.__len__() - i: t.CSizeT - for i in range(cn): - nm: str = names_local.get(i) - if nm is not None and string.strcmp(nm, cd.name) == 0: - return - _generic_class_names.append(cd.name) - _generic_class_nodes.append(cd) - _generic_class_sha1s.append(module_sha1) - # 诊断日志:确认泛型模板注册 - fb_rg: t.CChar | t.CPtr = VLogger.fmt_buf() - if fb_rg is not None: - viperlib.snprintf(fb_rg, 1024, "注册泛型模板: %s (module=%s)", cd.name, module_sha1) - VLogger.info(fb_rg, "SPEC") + """注册泛型类模板(类名 + ClassDef 节点 + 来源模块 SHA1)(委托到 gen._register_generic_template)""" + import lib.core.Gen.Generator as Generator + g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(_g_gen, t.CPtr)) + if g is not None: + g._register_generic_template(pool, cd, module_sha1) def _find_generic_template(class_name: str) -> ast.ClassDef | t.CPtr: - """查找泛型类模板,返回 ClassDef 节点或 None""" - if _generic_class_names is None or class_name is None: - return None - # 用局部变量接收 global list,触发类型推断(避免 global 变量 __len__ 失败) - names_local: list[str] | t.CPtr = _generic_class_names - nodes_local: list[ast.ClassDef | t.CPtr] | t.CPtr = _generic_class_nodes - cn: t.CSizeT = names_local.__len__() - i: t.CSizeT - for i in range(cn): - nm: str = names_local.get(i) - if nm is not None and string.strcmp(nm, class_name) == 0: - node: ast.ClassDef | t.CPtr = nodes_local.get(i) - return node + """查找泛型类模板,返回 ClassDef 节点或 None(委托到 gen._find_generic_template)""" + import lib.core.Gen.Generator as Generator + g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(_g_gen, t.CPtr)) + if g is not None: + return g._find_generic_template(class_name) return None def _find_generic_template_sha1(class_name: str) -> str: - """查找泛型类模板的来源模块 SHA1,未找到返回 None""" - if _generic_class_names is None or class_name is None: - return None - # 用局部变量接收 global list,触发类型推断 - names_local: list[str] | t.CPtr = _generic_class_names - sha1s_local: list[str] | t.CPtr = _generic_class_sha1s - cn: t.CSizeT = names_local.__len__() - i: t.CSizeT - for i in range(cn): - nm: str = names_local.get(i) - if nm is not None and string.strcmp(nm, class_name) == 0: - sha1_val: str = sha1s_local.get(i) - return sha1_val + """查找泛型类模板的来源模块 SHA1,未找到返回 None(委托到 gen._find_generic_template_sha1)""" + import lib.core.Gen.Generator as Generator + g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(_g_gen, t.CPtr)) + if g is not None: + return g._find_generic_template_sha1(class_name) return None def _mangle_generic_class_name(pool: memhub.MemBuddy | t.CPtr, class_name: str, type_args: list[str] | t.CPtr) -> str: - """生成特化类名: list + [int] -> list[int] - - 分配新缓冲区拼接,避免原地 strcat 导致缓冲区溢出 - """ - if class_name is None or type_args is None or pool is None: - return class_name - n: t.CSizeT = type_args.__len__() - if n == 0: - return class_name - # 计算总长度: class_name + "[" + arg0 + "," + arg1 + ... + "]" + NUL - total_len: t.CSizeT = string.strlen(class_name) + 2 # "[" 和 "]" - i: t.CSizeT - for i in range(n): - if i > 0: - total_len += 1 # "," - ta: str = type_args.get(i) - if ta is not None: - total_len += string.strlen(ta) - total_len += 1 # NUL - # 分配新缓冲区 - mangled: str = pool.alloc(total_len) - if mangled is None: - return class_name - mangled[0] = '\0' - string.strcat(mangled, class_name) - string.strcat(mangled, "[") - for i in range(n): - if i > 0: - string.strcat(mangled, ",") - ta: str = type_args.get(i) - if ta is not None: - string.strcat(mangled, ta) - string.strcat(mangled, "]") - return mangled + """生成特化类名: list + [int] -> list[int](委托到 gen._mangle_generic_class_name)""" + import lib.core.Gen.Generator as Generator + g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(_g_gen, t.CPtr)) + if g is not None: + return g._mangle_generic_class_name(pool, class_name, type_args) + return None # ============================================================ @@ -2103,105 +829,24 @@ def _clone_annotation(pool: memhub.MemBuddy | t.CPtr, node: ast.AST | t.CPtr, tp_names: list[str] | t.CPtr, type_args: list[str] | t.CPtr) -> ast.AST | t.CPtr: - """拷贝类型注解表达式,替换类型参数 T 为具体类型名 - - tp_names: 类型参数名列表 ['T'] - type_args: 类型实参名列表 ['int'] - """ - if node is None: - return None - k: int = node.kind() - - # Name: 可能是类型参数 T - if k == ast.ASTKind.Name: - nm: ast.Name | t.CPtr = (ast.Name | t.CPtr)(node) - if nm.id is not None: - n: t.CSizeT = tp_names.__len__() if tp_names is not None else 0 - i: t.CSizeT - for i in range(n): - tpn: str = tp_names.get(i) - if tpn is not None and string.strcmp(nm.id, tpn) == 0: - ta: str = type_args.get(i) - # 类型实参可能是复合类型(如 "AST|t.CPtr"),用 _parse_type_string 解析 - parsed_node: ast.AST | t.CPtr = HandlesType._parse_type_string(pool, ta, nm.ctx) - return parsed_node - return ast.Name(pool, nm.id, nm.ctx) - return None - - # Attribute: t.CPtr 等 - if k == ast.ASTKind.Attribute: - at: ast.Attribute | t.CPtr = (ast.Attribute | t.CPtr)(node) - new_value: ast.AST | t.CPtr = _clone_annotation(pool, at.value, tp_names, type_args) - return ast.Attribute(pool, new_value, at.attr, at.ctx) - - # BinOp: T | t.CPtr 等 - if k == ast.ASTKind.BinOp: - bop: ast.BinOp | t.CPtr = (ast.BinOp | t.CPtr)(node) - new_left: ast.AST | t.CPtr = _clone_annotation(pool, bop.left, tp_names, type_args) - new_right: ast.AST | t.CPtr = _clone_annotation(pool, bop.right, tp_names, type_args) - return ast.BinOp(pool, new_left, bop.op, new_right) - - # Subscript: list[int] 等 - if k == ast.ASTKind.Subscript: - sub: ast.Subscript | t.CPtr = (ast.Subscript | t.CPtr)(node) - new_value2: ast.AST | t.CPtr = _clone_annotation(pool, sub.value, tp_names, type_args) - new_slice: ast.AST | t.CPtr = _clone_annotation(pool, sub.slice, tp_names, type_args) - return ast.Subscript(pool, new_value2, new_slice, sub.ctx) - - # Tuple: (T, int) 等 - if k == ast.ASTKind.Tuple: - tup: ast.Tuple | t.CPtr = (ast.Tuple | t.CPtr)(node) - new_elts: list[ast.AST | t.CPtr] | t.CPtr = list[ast.AST | t.CPtr](pool, 8) - if tup.elts is not None: - tup_elts: list[ast.AST | t.CPtr] | t.CPtr = tup.elts - en: t.CSizeT = tup_elts.__len__() - ei: t.CSizeT - for ei in range(en): - el: ast.AST | t.CPtr = tup_elts.get(ei) - new_el: ast.AST | t.CPtr = _clone_annotation(pool, el, tp_names, type_args) - if new_el is not None: - new_elts.append(new_el) - return ast.Tuple(pool, new_elts, tup.ctx) - - # Constant: 默认值等 - if k == ast.ASTKind.Constant: - cnst: ast.Constant | t.CPtr = (ast.Constant | t.CPtr)(node) - return ast.Constant(pool, cnst.const_kind, cnst.int_val, cnst.float_val, - cnst.str_val, cnst.lineno, cnst.col_offset) - - # 其他: 直接引用(不拷贝) - return node + """拷贝类型注解表达式,替换类型参数 T 为具体类型名(委托到 gen._clone_annotation)""" + import lib.core.Gen.Generator as Generator + g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(_g_gen, t.CPtr)) + if g is not None: + return g._clone_annotation(pool, node, tp_names, type_args) + return None def _clone_arguments(pool: memhub.MemBuddy | t.CPtr, args: ast.AST | t.CPtr, tp_names: list[str] | t.CPtr, type_args: list[str] | t.CPtr) -> ast.AST | t.CPtr: - """拷贝 Arguments 节点,替换 arg annotation 中的 T""" - if args is None: - return None - if args.kind() != ast.ASTKind.Arguments: - return args - old_args: ast.Arguments | t.CPtr = (ast.Arguments | t.CPtr)(args) - # 拷贝 args 列表,替换每个 Arg 的 annotation - new_arg_list: list[ast.AST | t.CPtr] | t.CPtr = list[ast.AST | t.CPtr](pool, 8) - if old_args.args is not None: - old_arg_list: list[ast.AST | t.CPtr] | t.CPtr = old_args.args - an: t.CSizeT = old_arg_list.__len__() - ai: t.CSizeT - for ai in range(an): - arg_node: ast.AST | t.CPtr = old_arg_list.get(ai) - if arg_node is None: - continue - if arg_node.kind() == ast.ASTKind.Arg: - ag: ast.Arg | t.CPtr = (ast.Arg | t.CPtr)(arg_node) - new_anno: ast.AST | t.CPtr = _clone_annotation(pool, ag.annotation, tp_names, type_args) - new_arg: ast.Arg | t.CPtr = ast.Arg(pool, ag.arg, new_anno) - new_arg_list.append(new_arg) - else: - new_arg_list.append(arg_node) - return ast.Arguments(pool, new_arg_list, old_args.vararg, old_args.kwarg, - old_args.defaults, old_args.kw_defaults) + """拷贝 Arguments 节点,替换 arg annotation 中的 T(委托到 gen._clone_arguments)""" + import lib.core.Gen.Generator as Generator + g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(_g_gen, t.CPtr)) + if g is not None: + return g._clone_arguments(pool, args, tp_names, type_args) + return None def _clone_classdef_for_spec(pool: memhub.MemBuddy | t.CPtr, @@ -2209,114 +854,41 @@ def _clone_classdef_for_spec(pool: memhub.MemBuddy | t.CPtr, spec_name: str, tp_names: list[str] | t.CPtr, type_args: list[str] | t.CPtr) -> ast.ClassDef | t.CPtr: - """拷贝 ClassDef 节点用于泛型特化 - - - 替换类名为 spec_name - - 清除 type_params(特化后不是泛型类) - - 拷贝 children 中的 AnnAssign 和 FunctionDef,替换类型注解中的 T - - 方法体直接引用原始节点(通过 type_map 上下文处理 T) - """ - # 创建新 ClassDef(type_params=None 表示非泛型) - new_cd: ast.ClassDef | t.CPtr = ast.ClassDef(pool, spec_name, cd.bases, cd.keywords, - cd.decorator_list, None) - # 拷贝 children - if cd.children is not None: - cd_children: list[ast.AST | t.CPtr] | t.CPtr = cd.children - cn: t.CSizeT = cd_children.__len__() - ci: t.CSizeT - for ci in range(cn): - child: ast.AST | t.CPtr = cd_children.get(ci) - if child is None: - continue - ck: int = child.kind() - - if ck == ast.ASTKind.AnnAssign: - aa: ast.AnnAssign | t.CPtr = (ast.AnnAssign | t.CPtr)(child) - new_target: ast.AST | t.CPtr = aa.target - new_anno2: ast.AST | t.CPtr = _clone_annotation(pool, aa.annotation, tp_names, type_args) - new_value3: ast.AST | t.CPtr = aa.value - new_aa: ast.AnnAssign | t.CPtr = ast.AnnAssign(pool, new_target, new_anno2, new_value3, aa.simple) - new_cd.append(new_aa) - - elif ck == ast.ASTKind.FunctionDef: - fd: ast.FunctionDef | t.CPtr = (ast.FunctionDef | t.CPtr)(child) - new_args2: ast.AST | t.CPtr = _clone_arguments(pool, fd.args, tp_names, type_args) - new_returns2: ast.AST | t.CPtr = _clone_annotation(pool, fd.returns, tp_names, type_args) - new_fd: ast.FunctionDef | t.CPtr = ast.FunctionDef(pool, fd.name, new_args2, - fd.decorator_list, new_returns2, 0) - # 方法体直接引用原始节点 - if fd.children is not None: - fd_children: list[ast.AST | t.CPtr] | t.CPtr = fd.children - bcn: t.CSizeT = fd_children.__len__() - bci: t.CSizeT - for bci in range(bcn): - body_stmt: ast.AST | t.CPtr = fd_children.get(bci) - if body_stmt is not None: - new_fd.append(body_stmt) - new_cd.append(new_fd) - - else: - new_cd.append(child) - - return new_cd + """拷贝 ClassDef 节点用于泛型特化(委托到 gen._clone_classdef_for_spec)""" + import lib.core.Gen.Generator as Generator + g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(_g_gen, t.CPtr)) + if g is not None: + return g._clone_classdef_for_spec(pool, cd, spec_name, tp_names, type_args) + return None # ============================================================ -# 泛型特化缓存(模块级) +# 泛型特化缓存(容量常量) # # 用扁平 stdlib 数组 + stdlib 深拷贝字符串,保证缓存条目 # 跨文件永久存活(1b 每文件 reset_to(mark1) 不会回收)。 +# 缓存状态(_spec_keys/_spec_names/_spec_count)已迁移为 +# ClassGenMixin.SpecKeys/SpecNames/SpecCount(P5-2 簇 C)。 # ============================================================ SPEC_CACHE_MAX: t.CDefine = 512 -_spec_keys: t.CSizeT | t.CPtr = None -_spec_names: t.CSizeT | t.CPtr = None -_spec_count: int = 0 def _find_cached_spec(spec_key: str) -> str: - """查找已缓存的特化名,未找到返回 None""" - if _spec_keys is None or spec_key is None: - return None - i: int - for i in range(_spec_count): - key_addr: t.CSizeT = _spec_keys[i] - if key_addr != 0: - k: str = (str | t.CPtr)(t.CVoid(key_addr, t.CPtr)) - if k is not None and string.strcmp(k, spec_key) == 0: - name_addr: t.CSizeT = _spec_names[i] - if name_addr != 0: - return (str | t.CPtr)(t.CVoid(name_addr, t.CPtr)) + """查找已缓存的特化名,未找到返回 None(委托到 gen._find_cached_spec)""" + import lib.core.Gen.Generator as Generator + g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(_g_gen, t.CPtr)) + if g is not None: + return g._find_cached_spec(spec_key) return None def _cache_spec(pool: memhub.MemBuddy | t.CPtr, spec_key: str, spec_name: str): - """缓存特化结果(stdlib 深拷贝存储,跨文件安全)""" - global _spec_keys, _spec_names, _spec_count - if spec_key is None or spec_name is None: - return - if _spec_keys is None: - _spec_keys = stdlib.malloc(SPEC_CACHE_MAX * 8) - _spec_names = stdlib.malloc(SPEC_CACHE_MAX * 8) - if _spec_keys is None or _spec_names is None: - return - string.memset(_spec_keys, 0, SPEC_CACHE_MAX * 8) - string.memset(_spec_names, 0, SPEC_CACHE_MAX * 8) - _spec_count = 0 - if _spec_count >= SPEC_CACHE_MAX: - return - # 深拷贝字符串到 stdlib 区 - key_len: t.CSizeT = string.strlen(spec_key) - name_len: t.CSizeT = string.strlen(spec_name) - key_copy: t.CChar | t.CPtr = stdlib.malloc(key_len + 1) - name_copy: t.CChar | t.CPtr = stdlib.malloc(name_len + 1) - if key_copy is None or name_copy is None: - return - string.strcpy(key_copy, spec_key) - string.strcpy(name_copy, spec_name) - _spec_keys[_spec_count] = t.CSizeT(key_copy) - _spec_names[_spec_count] = t.CSizeT(name_copy) - _spec_count += 1 + """缓存特化结果(stdlib 深拷贝存储,跨文件安全)(委托到 gen._cache_spec)""" + import lib.core.Gen.Generator as Generator + g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(_g_gen, t.CPtr)) + if g is not None: + g._cache_spec(pool, spec_key, spec_name) # ============================================================ @@ -2330,687 +902,31 @@ def _cache_spec(pool: memhub.MemBuddy | t.CPtr, spec_key: str, spec_name: str): # ============================================================ def _merge_template_imports(trans: HT.Translator | t.CPtr, template_sha1: str) -> None: - """将模板模块的 imports 并入 trans._imported_modules(空格分隔)""" - if trans is None or template_sha1 is None: - return - tdeps: str = StubMerger.LookupIncludesDeps(template_sha1) - if tdeps is None or tdeps[0] == '\0': - return - cur: str = trans._imported_modules - if cur is None or cur[0] == '\0': - trans._imported_modules = tdeps - return - cur_len: t.CSizeT = string.strlen(cur) - td_len: t.CSizeT = string.strlen(tdeps) - merged: str = trans.Pool.alloc(cur_len + td_len + 2) - if merged is None: - return - string.strcpy(merged, cur) - merged[cur_len] = ' ' - string.strcpy(merged + cur_len + 1, tdeps) - trans._imported_modules = merged + """将模板模块的 imports 并入 trans._imported_modules(空格分隔)(委托到 gen._merge_template_imports)""" + import lib.core.Gen.Generator as Generator + g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(_g_gen, t.CPtr)) + if g is not None: + g._merge_template_imports(trans, template_sha1) def _specialize_generic_class(trans: HT.Translator | t.CPtr, class_name: str, type_args: list[str] | t.CPtr) -> str: - """特化泛型类,返回特化类名 - - 1. 查找泛型模板 - 2. 生成特化名 - 3. 检查缓存 - 4. 拷贝 ClassDef 节点(替换类型注解中的 T) - 5. 设置 type_map 上下文(用于方法体中的 T 替换) - 6. 调用 translate_class_def 翻译特化类 - 7. 返回特化名 - """ - if trans is None or class_name is None or type_args is None: - return None - # 防御:泛型上下文内收集的 type_args 若残留未替换的类型参数名(如 "T"), - # 统一替换为具体类型名,避免 ndarray[T] 二次递归特化崩溃。 - # 调用方传入的 type_args 均为临时新建列表,就地替换无共享副作用。 - ta_cnt_g: t.CSizeT = type_args.__len__() - ta_i_g: t.CSizeT - for ta_i_g in range(ta_cnt_g): - ta_raw_g: str = type_args.get(ta_i_g) - if ta_raw_g is not None: - ta_rsv_g: str = HandlesType.resolve_generic_type_name(ta_raw_g) - if ta_rsv_g is not None and string.strcmp(ta_raw_g, ta_rsv_g) != 0: - type_args.set(ta_i_g, ta_rsv_g) - - pool: memhub.MemBuddy | t.CPtr = trans.Pool - - # ============================================================ - # 诊断输出:追踪 GSListNode 特化调用路径 - # ============================================================ - if string.strcmp(class_name, "GSListNode") == 0: - VLogger.debug("=== _specialize_generic_class ===", "SPEC") - fb: t.CChar | t.CPtr = VLogger.fmt_buf() - if fb is not None: - viperlib.snprintf(fb, 1024, "class=%s module=%s", class_name, trans.ModuleSha1) - VLogger.debug(fb, "SPEC") - if type_args is not None: - ta_n: t.CSizeT = type_args.__len__() - ta_i: t.CSizeT - for ta_i in range(ta_n): - ta: str = type_args.get(ta_i) - if ta is not None: - if fb is not None: - viperlib.snprintf(fb, 1024, " type_arg[%d]=%s", ta_i, ta) - VLogger.debug(fb, "SPEC") - - # 1. 查找泛型模板 - template_cd: ast.ClassDef | t.CPtr = _find_generic_template(class_name) - if template_cd is None: - if string.strcmp(class_name, "GSListNode") == 0: - VLogger.debug("template NOT FOUND, return None", "SPEC") - return None - - # 2. 生成特化名 - spec_name: str = _mangle_generic_class_name(pool, class_name, type_args) - if spec_name is None: - return None - - # 治本修复:Phase B 补译泛型特化类方法体(统一入口,在 cache/existing 检查之前) - # Phase 1a(declare_only==1)特化时只注册结构体不译方法体(MethodsEmitted==0), - # Phase B(declare_only==0)重复进入时若方法体未译,补译方法体生成 define, - # 避免 GSList[Line].append 等符号只有 declare 无 define → 链接失败。 - # 首次 Phase B 特化(Phase 1a 未特化)find_struct 返回 None,不补译,走下方正常全量翻译。 - if trans._declare_only == 0: - pre_existing: HandlesStruct.StructEntry | t.CPtr = HandlesStruct.find_struct(spec_name) - if pre_existing is not None and pre_existing.MethodsEmitted == 0: - # 防重入:先标记 MethodsEmitted=1,避免补译过程中方法体/返回类型注解 - # 再次触发 _specialize_generic_class(如 __iter__ 返回 list[T]|t.CPtr) - # 导致无限递归补译 → OOM。补译完成后已设置,无需恢复。 - pre_existing.MethodsEmitted = 1 - tp_names_pre: list[str] | t.CPtr = template_cd.type_params - spec_cd_pre: ast.ClassDef | t.CPtr = _clone_classdef_for_spec( - pool, template_cd, spec_name, tp_names_pre, type_args) - if spec_cd_pre is not None: - trans.GenericTypeParamNames = tp_names_pre - trans.GenericTypeArgs = type_args - HandlesType.set_generic_context(tp_names_pre, type_args) - saved_ms_pre: str = trans.ModuleSha1 - saved_imp_pre: str = trans._imported_modules - template_sha1_pre: str = _find_generic_template_sha1(class_name) - if template_sha1_pre is not None: - trans.ModuleSha1 = template_sha1_pre - _merge_template_imports(trans, template_sha1_pre) - _translate_oop_methods(trans, spec_cd_pre, pre_existing.Ty, spec_name, 0) - trans.ModuleSha1 = saved_ms_pre - trans._imported_modules = saved_imp_pre - trans.GenericTypeParamNames = None - trans.GenericTypeArgs = None - HandlesType.clear_generic_context() - - # 3. 检查缓存(spec_key 包含所有类型实参,避免多参数泛型缓存冲突) - # 分配新缓冲区避免原地 strcat 溢出 - sk_n: t.CSizeT = type_args.__len__() - sk_total: t.CSizeT = string.strlen(class_name) + 2 # "<" 和 ">" - sk_i: t.CSizeT - for sk_i in range(sk_n): - if sk_i > 0: - sk_total += 1 # "," - sk_ta: str = type_args.get(sk_i) - if sk_ta is not None: - sk_total += string.strlen(sk_ta) - sk_total += 1 # NUL - spec_key: str = pool.alloc(sk_total) - if spec_key is None: - return None - spec_key[0] = '\0' - string.strcat(spec_key, class_name) - string.strcat(spec_key, "<") - for sk_i in range(sk_n): - if sk_i > 0: - string.strcat(spec_key, ",") - sk_ta: str = type_args.get(sk_i) - if sk_ta is not None: - string.strcat(spec_key, sk_ta) - string.strcat(spec_key, ">") - cached: str = _find_cached_spec(spec_key) - if cached is not None: - if string.strcmp(class_name, "GSListNode") == 0: - fb: t.CChar | t.CPtr = VLogger.fmt_buf() - if fb is not None: - viperlib.snprintf(fb, 1024, "CACHE HIT, return cached=%s", cached) - VLogger.debug(fb, "SPEC") - return cached - - # 4. 检查是否已注册(Phase B 重复特化) - existing: HandlesStruct.StructEntry | t.CPtr = HandlesStruct.find_struct(spec_name) - if existing is not None: - if string.strcmp(class_name, "GSListNode") == 0: - fb: t.CChar | t.CPtr = VLogger.fmt_buf() - if fb is not None: - viperlib.snprintf(fb, 1024, "EXISTING registered, return spec_name=%s field_count=%d", - spec_name, existing.FieldCount) - VLogger.debug(fb, "SPEC") - _cache_spec(pool, spec_key, spec_name) - return spec_name - - # 预注册缓存(防止递归) - _cache_spec(pool, spec_key, spec_name) - - # 5. 拷贝 ClassDef 节点 - tp_names: list[str] | t.CPtr = template_cd.type_params - spec_cd: ast.ClassDef | t.CPtr = _clone_classdef_for_spec( - pool, template_cd, spec_name, tp_names, type_args) - if spec_cd is None: - return None - - # 6. 设置 type_map 上下文(用于方法体中的 T 替换) - trans.GenericTypeParamNames = tp_names - trans.GenericTypeArgs = type_args - HandlesType.set_generic_context(tp_names, type_args) - - # 7. 翻译特化类 - # 切换 trans.ModuleSha1 为泛型模板定义模块的 SHA1, - # 使结构体类型名和方法定义名都用定义模块的 SHA1 前缀, - # 与调用端 get_struct_sha1(class_name) 查到的 SHA1 一致。 - # 同时并入模板模块的 imports(见 _merge_template_imports 注释), - # 避免模板方法体内的跨模块调用被误报"模块未导入"。 - saved_module_sha1: str = trans.ModuleSha1 - saved_imported: str = trans._imported_modules - template_sha1: str = _find_generic_template_sha1(class_name) - if template_sha1 is not None: - trans.ModuleSha1 = template_sha1 - _merge_template_imports(trans, template_sha1) - translate_class_def(trans, spec_cd) - # 恢复原始 ModuleSha1 与 imports - trans.ModuleSha1 = saved_module_sha1 - trans._imported_modules = saved_imported - - # 8. 清除 type_map 上下文 - trans.GenericTypeParamNames = None - trans.GenericTypeArgs = None - HandlesType.clear_generic_context() - - # 诊断输出:检查特化结果 - if string.strcmp(class_name, "GSListNode") == 0: - result_entry: HandlesStruct.StructEntry | t.CPtr = HandlesStruct.find_struct(spec_name) - if result_entry is not None: - fb: t.CChar | t.CPtr = VLogger.fmt_buf() - if fb is not None: - viperlib.snprintf(fb, 1024, "DONE spec_name=%s field_count=%d", - spec_name, result_entry.FieldCount) - VLogger.debug(fb, "SPEC") - # 打印每个字段的类型信息 - ri: int - for ri in range(result_entry.FieldCount): - rfe: HandlesStruct.FieldEntry | t.CPtr = HandlesStruct._get_field_entry( - result_entry, ri) - if rfe is not None: - rfn: str = HandlesStruct.get_field_name_ptr(rfe) - rft: llvmlite.LLVMType | t.CPtr = HandlesStruct.get_field_type_ptr(rfe) - if fb is not None: - viperlib.snprintf(fb, 1024, " field[%d] name=%s type=%d", - ri, rfn if rfn is not None else "(null)", - t.CSizeT(rft) if rft is not None else 0) - VLogger.debug(fb, "SPEC") - else: - VLogger.debug("DONE but result NOT FOUND in struct table!", "SPEC") - - return spec_name + """特化泛型类,返回特化类名(委托到 gen._specialize_generic_class)""" + import lib.core.Gen.Generator as Generator + g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(_g_gen, t.CPtr)) + if g is not None: + return g._specialize_generic_class(trans, class_name, type_args) + return None def translate_class_def(trans: HT.Translator | t.CPtr, node: ast.AST | t.CPtr) -> int: - """翻译 class 定义,返回 0""" - if node is None or trans is None: - return 0 - - cd: ast.ClassDef | t.CPtr = (ast.ClassDef | t.CPtr)(node) - if cd is None or cd.name is None: - return 0 - - pool: memhub.MemBuddy | t.CPtr = trans.Pool - class_name: str = cd.name - - # 命名空间隔离:标记为当前文件可见(必须在 existing 检查之前, - # 因为 Phase B 时结构体已注册会提前 return,否则永远无法标记本地类) - HandlesStruct.add_visible_struct(pool, class_name) - - # 枚举类:交给 HandlesEnum 处理 - if _is_enum_class(cd) == 1: - return _translate_enum_def(trans, cd) - - # 联合体类:交给联合体处理 - if _is_union_class(cd) == 1: - return _translate_union_def(trans, cd) - - # REnum 类:交给 REnum 处理({i32 tag, max_payload} 布局) - if _is_renum_class(cd) == 1: - return _translate_renum_def(trans, cd) - - # 泛型类:存储为模板,不发射 IR(等实例化时特化) - # 用局部变量接收 cd.type_params,触发类型推断 - tp_val: list[str] | t.CPtr = cd.type_params - if _is_generic_class(tp_val) == 1: - _register_generic_template(pool, cd, trans.ModuleSha1) - return 0 - - # 检查是否已注册(用 SHA1 区分跨模块同名类) - existing: HandlesStruct.StructEntry | t.CPtr = HandlesStruct.find_struct_by_module( - class_name, trans.ModuleSha1) - if existing is not None: - # BUG 5 方案1修改点2:existing 时字段完整性检查 - # 结构体已注册,但需验证字段信息是否完整(防止 i32 回退残留或注册不完整) - # 注意:无字段类(接口/标记类,类体无 AnnAssign)合法(空 struct + 方法), - # 仅当"类体声明了字段但 FieldCount==0"才算注册不完整(Phase A-pre 漏注册)。 - if existing.FieldCount == 0 and trans._declare_only == 0: - if _class_body_has_field(cd) != 0: - # Phase B 时字段数为 0 说明注册不完整(Phase A-pre 可能漏注册) - HandlesType.fatal_error( - node, - f"结构体已注册但字段数为0,类: {class_name},可能注册不完整", - "InternalCompilerError") - # 结构体已注册(Phase A-pre 多遍扫描或 Phase B 重新翻译),但仍需在当前模块中翻译方法 - if existing.Ty is not None: - # Phase 1b(declare_only=0):existing.Ty 是 Phase 1a 注册的 struct_ty, - # 其 Name(如 "sha1.ClassName")指向 Phase 1a 的 pool 内存。虽然 mark1 - # 之前分配不被 reset 回收,但 struct_ty 会被后续文件翻译引用(vtable/ - # self 参数类型打印),部分实现下 pool 块被复用导致 Name 悬空崩溃。 - # 保险起见:深拷贝 Name 到 stdlib,确保跨文件永久存活。 - if trans._declare_only == 0: - old_name: t.CChar | t.CPtr = llvmlite.get_struct_name(existing.Ty) - if old_name is not None: - on_len: t.CSizeT = string.strlen(old_name) - on_copy: t.CChar | t.CPtr = stdlib.malloc(on_len + 1) - if on_copy is not None: - string.strcpy(on_copy, old_name) - c.DerefAs(existing.Ty, llvmlite.LLVMType.Struct( - llvmlite.get_struct_fields(existing.Ty), - llvmlite.get_struct_fcount(existing.Ty), - on_copy)) - # Phase B: 将已存在的命名结构体注册到当前模块(输出类型定义行) - llvmlite.module_add_named_type(trans.Module, pool, existing.Ty) - # Phase A-pre(declare_only=1)多遍扫描时,类已注册但不应翻译方法体 - # Phase B(declare_only=0)时全量翻译方法体 - if trans._declare_only == 1: - _translate_oop_methods(trans, cd, existing.Ty, class_name, 1) - else: - _translate_oop_methods(trans, cd, existing.Ty, class_name) - # SHA1 已在 register_struct 时设置,无需再补 - return 0 - - # ============================================================ - # 触发 base 中 Subscript 的泛型特化(如 GSListNode[Value]) - # 必须在 _detect_vtable_status 和父类字段继承之前调用, - # 否则 find_struct_by_module("GSListNode[Value]") 返回 None - # ============================================================ - _trigger_base_specialization(trans, cd) - - # ============================================================ - # VTable 检测:判断是否启用虚表 - # ============================================================ - has_vtable: int = _detect_vtable_status(cd, trans) - parent_name: str = _get_parent_class(cd, trans) - # 多继承:收集所有真实父类名(跳过 marker base),供字段展平/vtable/MRO 使用 - parents_buf: t.CSizeT | t.CPtr = pool.alloc(8 * HandlesStruct.PARENT_MAX) - parents_count: int = 0 - if parents_buf is not None: - parents_count = _collect_parents(pool, cd, parents_buf, HandlesStruct.PARENT_MAX) - is_novtable_deco: int = 0 - if cd.decorator_list is not None: - if _has_decorator(cd.decorator_list, "NoVTable") == 1: - is_novtable_deco = 1 - - # ============================================================ - # PhaseA 预注册延迟检查:父类未注册时延迟注册当前类 - # - # 根因:AssignHandle(HandlesBase.Mixin) 有自己的字段 _CurrentClass, - # 当 Mixin 未注册时(字母序:HandlesAssign.py 在 HandlesBase.py 之前), - # field_count=1(不是0),field_count==0 静默返回不触发, - # AssignHandle 被注册为只有 _CurrentClass 字段(缺 Trans)。 - # 后续遍 existing is not None,不补字段 → attribute ptr is None: self.Trans - # - # 修复:declare_only==1 且父类未注册时,延迟注册到下一遍。 - # 多遍 PhaseA-pre 会在后续遍中重试(父类已注册后完整注册)。 - # Phase B(declare_only==0)不延迟,避免死锁。 - # ============================================================ - if trans._declare_only == 1 and parent_name is not None: - parent_check: HandlesStruct.StructEntry | t.CPtr = HandlesStruct.find_struct_by_module( - parent_name, trans.ModuleSha1) - if parent_check is None: - parent_check = HandlesStruct.find_struct(parent_name) - if parent_check is None: - return 0 - - # ============================================================ - # 1. 遍历 class body,收集字段信息 - # ============================================================ - # 用 CSizeT 数组存储指针值(64 位系统上 8 字节) - field_names_buf: t.CSizeT | t.CPtr = pool.alloc(8 * 64) - field_types_buf: t.CSizeT | t.CPtr = pool.alloc(8 * 64) - field_defaults_buf: t.CSizeT | t.CPtr = pool.alloc(8 * 64) - field_annot_buf: t.CSizeT | t.CPtr = pool.alloc(8 * 64) - if field_names_buf is None or field_types_buf is None or field_defaults_buf is None: - return 0 - if field_annot_buf is None: - return 0 - string.memset(field_names_buf, 0, 8 * 64) - string.memset(field_types_buf, 0, 8 * 64) - string.memset(field_defaults_buf, 0, 8 * 64) - string.memset(field_annot_buf, 0, 8 * 64) - - field_count: int = 0 - - # ============================================================ - # 1.5 继承父类字段(字段展平) - # ============================================================ - # - # 父类字段排在子类字段之前,结构体布局: - # [vtable_ptr?, parent_field1, ..., child_field1, ...] - # 跳过父类的 __vtable__ 字段(子类会有自己的 vtable 指针) - # ============================================================ - # 多继承字段展平:遍历所有父类(声明顺序),字段名去重(先声明优先) - if parents_count > 0 and parents_buf is not None: - for pi in range(parents_count): - pname_addr: t.CSizeT = parents_buf[pi] - if pname_addr == 0: - continue - pname: str = (str | t.CPtr)(t.CVoid(pname_addr, t.CPtr)) - if pname is None: - continue - # 用 SHA1 感知查找父类,规避跨模块同名找错 - parent_entry: HandlesStruct.StructEntry | t.CPtr = HandlesStruct.find_struct_by_module( - pname, trans.ModuleSha1) - if parent_entry is None: - # 父类可能定义在另一个模块(不同 SHA1,如 HandlesBase.Mixin), - # find_struct_by_module 不回退全局查找,此处手动回退到 find_struct, - # 否则子类无法继承父类字段 → field_count==0 → __sizeof__ 失败 - parent_entry = HandlesStruct.find_struct(pname) - if parent_entry is None: - continue - pfc: int = parent_entry.FieldCount - for pfi in range(pfc): - pfe: HandlesStruct.FieldEntry | t.CPtr = HandlesStruct._get_field_entry( - parent_entry, pfi) - if pfe is None: - continue - pfn: str = HandlesStruct.get_field_name_ptr(pfe) - if pfn is None: - continue - # 跳过父类的 vtable 指针字段 - if string.strcmp(pfn, "__vtable__") == 0: - continue - # 多继承去重:字段名已存在跳过(先声明父类优先) - if _field_name_exists(field_names_buf, field_count, pfn) != 0: - continue - if field_count < 64: - pft: llvmlite.LLVMType | t.CPtr = HandlesStruct.get_field_type_ptr(pfe) - pfd: ast.AST | t.CPtr = HandlesStruct.get_field_default_ptr(pfe) - pfa: str = HandlesStruct.get_field_annot_class_name(pfe) - field_names_buf[field_count] = t.CSizeT(pfn) - field_types_buf[field_count] = t.CSizeT(pft) - if pfd is not None: - field_defaults_buf[field_count] = t.CSizeT(pfd) - else: - field_defaults_buf[field_count] = 0 - if pfa is not None: - stored_val: t.CSizeT = t.CSizeT(pfa) - field_annot_buf[field_count] = stored_val - else: - field_annot_buf[field_count] = 0 - field_count += 1 - - children: list[ast.AST | t.CPtr] | t.CPtr = cd.children - if children is None: - return 0 - - cn: t.CSizeT = children.__len__() - for ci in range(cn): - stmt: ast.AST | t.CPtr = children.get(ci) - if stmt is None: - continue - sk: int = stmt.kind() - - if sk != ast.ASTKind.AnnAssign: continue - - # AnnAssign(target=Name(id), annotation=type, value=...) - aa: ast.AnnAssign | t.CPtr = (ast.AnnAssign | t.CPtr)(stmt) - if aa is None or aa.target is None: - continue - - # 获取字段名 - if aa.target.kind() != ast.ASTKind.Name: - continue - tgt: ast.Name | t.CPtr = (ast.Name | t.CPtr)(aa.target) - if tgt.id is None: - continue - - # 跳过编译期元数据字段(__provides__/__requires__/__require_must__) - # 这些字段只用于 with 上下文的静态可达性检查,不生成运行时代码 - # 避免类体中 list 字面量翻译失败(类体无 pool 变量上下文) - if string.strcmp(tgt.id, "__provides__") == 0: - continue - if string.strcmp(tgt.id, "__requires__") == 0: - continue - if string.strcmp(tgt.id, "__require_must__") == 0: - continue - - # 解析字段类型 - field_ty: llvmlite.LLVMType | t.CPtr = HandlesType.resolve_annotation_type( - pool, aa.annotation, trans._imported_modules, trans._from_imports, trans) - if field_ty is None: - # BUG 5 方案1修改点1:消除 i32 静默回退 - # Phase A-pre(declare_only=1):依赖的类可能尚未注册,延迟到下一遍 - # Phase B(declare_only=0):真正的类型解析错误,fast-fail 终止该类翻译 - # 不再用 i32 回退(会导致结构体布局错误 + GEP 索引错乱) - # 例外:泛型 Subscript(如 list[AST|t.CPtr])未特化时回退为 Ptr(i8), - # 因为泛型特化可能延迟到构造调用时。AnnotClassName 会携带 mangled name - # 供 translate_attribute 做后续 bitcast。 - is_generic_sub: int = 0 - if aa.annotation is not None and aa.annotation.kind() == ast.ASTKind.Subscript: - is_generic_sub = 1 - if is_generic_sub != 0: - # 泛型未特化:回退为 Ptr(i8),依赖 AnnotClassName 做后续类型恢复 - field_ty = llvmlite.Ptr(pool, llvmlite.Int8(pool)) - else: - # Phase A-pre(declare_only=1):依赖的类可能尚未注册, - # 静默 return 0 让多遍收敛机制生效(下一遍依赖类已注册即可成功) - if trans._declare_only == 1: - return 0 - # Phase B(declare_only=0):真正的类型解析错误,fast-fail 终止 - type_name2: str = HandlesType.annotation_to_str(aa.annotation) - HandlesType.fatal_error( - aa, - f"'{type_name2}' is not defined", - "NameError") - return 0 - - # 存储到数组(指针转 CSizeT) - if field_count < 64: - diag_name_val: t.CSizeT = t.CSizeT(tgt.id) - field_names_buf[field_count] = diag_name_val - field_types_buf[field_count] = t.CSizeT(field_ty) - # 存储默认值 AST 指针(None=无默认值) - if aa.value is not None: - field_defaults_buf[field_count] = t.CSizeT(aa.value) - else: - field_defaults_buf[field_count] = 0 - # 提取原始类型注解的类名(联合类型简化为 Ptr(i8) 时回退查找结构体) - # BUG 1 方案3:传 pool 使泛型 Subscript 返回 mangled name(如 "list[ast.AST|t.CPtr]") - if aa.annotation is not None: - annot_cn: str = HandlesType.extract_class_name_from_annotation( - aa.annotation, trans._imported_modules, pool) - if annot_cn is not None: - diag_cn_val: t.CSizeT = t.CSizeT(annot_cn) - field_annot_buf[field_count] = diag_cn_val - else: - field_annot_buf[field_count] = 0 - else: - field_annot_buf[field_count] = 0 - field_count += 1 - - if field_count == 0: - # PhaseA 预注册时,父类可能尚未注册(字母序单遍扫描), - # 导致子类无法继承父类字段 → field_count==0。 - # 静默返回,Phase2.py 的多遍 PhaseA-pre 会在后续遍中重试。 - if trans._declare_only == 1 and parent_name is not None: - return 0 - # 无字段类(接口/标记类):不能整体跳过——类可能只有方法 - # (如多继承中的 ShapeM/Vec2Extra),需注册类并翻译方法。 - # 空 struct 在 LLVM 中合法({});@t.CVTable 类由下方补 vtable 指针字段。 - fb_cf: t.CChar | t.CPtr = VLogger.fmt_buf() - if fb_cf is not None: - viperlib.snprintf(fb_cf, 1024, "%s has no fields", class_name) - VLogger.info(fb_cf, "CLASS") - - # ============================================================ - # 2. 创建 LLVM StructType - # ============================================================ - # 构建 ParamNode 链表 - first_node: llvmlite.ParamNode | t.CPtr = None - prev_node: llvmlite.ParamNode | t.CPtr = None - total_field_count: int = field_count - - # 如果有虚表,首字段添加 i8* vtable 指针 - if has_vtable == 1: - i8_ptr_ty: llvmlite.LLVMType | t.CPtr = llvmlite.Ptr(pool, llvmlite.Int8(pool)) - vtable_node: llvmlite.ParamNode | t.CPtr = pool.alloc(llvmlite.ParamNode.__sizeof__()) - if vtable_node is None: - fb_vn: t.CChar | t.CPtr = VLogger.fmt_buf() - if fb_vn is not None: - viperlib.snprintf(fb_vn, 1024, "failed to alloc vtable node for %s", class_name) - VLogger.error(fb_vn, "CLASS") - return 0 - string.memset(vtable_node, 0, llvmlite.ParamNode.__sizeof__()) - vtable_node.Ty = i8_ptr_ty - first_node = vtable_node - prev_node = vtable_node - total_field_count = field_count + 1 - - for fi in range(field_count): - fty_addr: t.CSizeT = field_types_buf[fi] - if fty_addr == 0: - continue - fty: llvmlite.LLVMType | t.CPtr = (llvmlite.LLVMType | t.CPtr)(t.CVoid(fty_addr, t.CPtr)) - - # 创建 ParamNode - pnode: llvmlite.ParamNode | t.CPtr = pool.alloc(llvmlite.ParamNode.__sizeof__()) - if pnode is None: - continue - string.memset(pnode, 0, llvmlite.ParamNode.__sizeof__()) - pnode.Ty = fty - - if first_node is None: - first_node = pnode - if prev_node is not None: - prev_node.Next = pnode - prev_node = pnode - - # 构造命名结构体类型名: "sha1.ClassName" 或 "ClassName" - # 注意: Phase 1b(declare_only=0)时 struct_ty 会注册到全局表并被后续 - # 文件翻译引用(vtable/self 参数类型打印),其 Name 必须跨 1b 每文件 - # reset_to(mark1) 存活 → 用 stdlib 深拷贝;Phase 1a 仍用 pool(无需跨文件)。 - type_name: str = class_name - if trans.ModuleSha1 is not None: - name_buf: t.CChar | t.CPtr = pool.alloc(64) - if name_buf is not None: - viperlib.snprintf(name_buf, 64, "%s.%s", trans.ModuleSha1, class_name) - type_name = name_buf - if trans._declare_only == 0 and type_name is not None: - tn_len: t.CSizeT = string.strlen(type_name) - tn_copy: t.CChar | t.CPtr = stdlib.malloc(tn_len + 1) - if tn_copy is not None: - string.strcpy(tn_copy, type_name) - type_name = tn_copy - - # 创建 StructType(命名结构体) - struct_ty: llvmlite.LLVMType | t.CPtr = llvmlite.Struct(pool, first_node, total_field_count, type_name) - if struct_ty is None: - fb_st: t.CChar | t.CPtr = VLogger.fmt_buf() - if fb_st is not None: - viperlib.snprintf(fb_st, 1024, "failed to create StructType for %s", class_name) - VLogger.error(fb_st, "CLASS") - return 0 - - # Phase 1b(declare_only=0)新注册的 struct_ty 会被注册到全局表并被后续文件 - # 翻译引用(vtable/self 参数类型打印/find_struct_by_type 指针匹配)。LLVMType - # 对象和 Fields 链是 pool 分配的,本文件 reset_to(mark1) 后悬空。深拷贝整棵树 - # 到 stdlib,并替换 struct_ty 指针,保证 entry.Ty 与调用方持有的 struct_ty - # 指向同一个 stdlib 拷贝(指针匹配不失效)且跨文件永久存活。 - if trans._declare_only == 0: - st_copy: llvmlite.LLVMType | t.CPtr = llvmlite.DeepCopyType(pool, struct_ty) - if st_copy is not None: - struct_ty = st_copy - type_name = llvmlite.get_struct_name(struct_ty) - - # 注册命名结构体到模块(输出 %"name" = type { ... } 定义行) - llvmlite.module_add_named_type(trans.Module, pool, struct_ty) - - # 扫描字段类型,为跨模块结构体引用添加 opaque 声明 - # 例如 list[int].__pool__ 引用 memhub.MemManager,需要在当前模块添加 %"sha1.MemManager" = type opaque - for fi in range(field_count): - fty_addr_op: t.CSizeT = field_types_buf[fi] - if fty_addr_op == 0: - continue - fty_op: llvmlite.LLVMType | t.CPtr = (llvmlite.LLVMType | t.CPtr)(t.CVoid(fty_addr_op, t.CPtr)) - llvmlite.module_ensure_opaque_for_type(trans.Module, pool, fty_op) - - # ============================================================ - # 3. 注册到 HandlesStruct - # ============================================================ - entry: HandlesStruct.StructEntry | t.CPtr = HandlesStruct.register_struct( - pool, class_name, struct_ty, trans.ModuleSha1) - if entry is None: - fb_re: t.CChar | t.CPtr = VLogger.fmt_buf() - if fb_re is not None: - viperlib.snprintf(fb_re, 1024, "failed to register %s", class_name) - VLogger.error(fb_re, "CLASS") - return 0 - - # 标记 VTable 状态(直接用 entry,规避跨模块同名 find_struct 找错) - if has_vtable == 1: - entry.HasVTable = 1 - if is_novtable_deco == 1: - entry.IsNoVTable = 1 - if parent_name is not None: - entry.ParentName = parent_name - # 多继承:设置父类数组(供 MRO/字段/vtable 查询,stdlib 深拷贝跨文件存活) - if parents_count > 0 and parents_buf is not None: - HandlesStruct.set_parent_names(class_name, parents_buf, parents_count) - - # 添加字段信息 - # 如果有虚表,先添加 __vtable__ 字段占位(索引 0),用户字段从索引 1 开始 - if has_vtable == 1: - i8_ptr_ty2: llvmlite.LLVMType | t.CPtr = llvmlite.Ptr(pool, llvmlite.Int8(pool)) - HandlesStruct.add_field(pool, entry, "__vtable__", i8_ptr_ty2, None, None) - - for fi in range(field_count): - fname_addr: t.CSizeT = field_names_buf[fi] - if fname_addr == 0: - continue - fname: str = (str | t.CPtr)(t.CVoid(fname_addr, t.CPtr)) - fty_addr2: t.CSizeT = field_types_buf[fi] - if fty_addr2 == 0: - continue - fty2: llvmlite.LLVMType | t.CPtr = (llvmlite.LLVMType | t.CPtr)(t.CVoid(fty_addr2, t.CPtr)) - # 恢复默认值 AST 指针 - fdef_addr: t.CSizeT = field_defaults_buf[fi] - fdef: ast.AST | t.CPtr = None - if fdef_addr != 0: - fdef = (ast.AST | t.CPtr)(t.CVoid(fdef_addr, t.CPtr)) - # 恢复注解类名指针 - fannot_addr: t.CSizeT = field_annot_buf[fi] - fannot: t.CChar | t.CPtr = None - if fannot_addr != 0: - fannot = (t.CChar | t.CPtr)(t.CVoid(fannot_addr, t.CPtr)) - if fname is not None and fty2 is not None: - HandlesStruct.add_field(pool, entry, fname, fty2, fdef, fannot) - - # Phase 1a 声明模式:只注册 struct + 设置 OOP 标志,不翻译方法体 - if trans._declare_only == 1: - _translate_oop_methods(trans, cd, struct_ty, class_name, 1) - return 0 - - # ============================================================ - # 4. OOP 方法处理:扫描 FunctionDef,标记 OOP,翻译方法,生成 __before_init__ - # ============================================================ - _translate_oop_methods(trans, cd, struct_ty, class_name) - + """翻译 class 定义,返回 0(委托到 gen.translate_class_def)""" + import lib.core.Gen.Generator as Generator + g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(_g_gen, t.CPtr)) + if g is not None: + return g.translate_class_def(trans, node) return 0 @@ -3032,31 +948,20 @@ VTBL_METHOD_MAX: t.CDefine = 32 # _vtable_strcat — 将 src 追加到 dst 末尾 def _vtable_strcat(dst: t.CChar | t.CPtr, dst_size: t.CSizeT, src: t.CChar | t.CPtr): - """将 src 追加到 dst 末尾""" - if dst is None or src is None: - return - dlen: t.CSizeT = string.strlen(dst) - slen: t.CSizeT = string.strlen(src) - remain: t.CSizeT = dst_size - dlen - if remain <= 0: - return - i: t.CSizeT = 0 - while i < slen and i + 1 < remain: - dst[dlen + i] = src[i] - i += 1 - dst[dlen + i] = '\0' + """将 src 追加到 dst 末尾(委托到 gen._vtable_strcat)""" + import lib.core.Gen.Generator as Generator + g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(_g_gen, t.CPtr)) + if g is not None: + g._vtable_strcat(dst, dst_size, src) # _vtable_name_needs_quote — 检查 LLVM 标识符是否需要引号 def _vtable_name_needs_quote(name: str) -> int: - """检查 LLVM 标识符是否需要引号(以数字开头或含 '.')""" - if name is None: - return 0 - if '0' <= name[0] <= '9': - return 1 - for i in name: - if i == '.': - return 1 + """检查 LLVM 标识符是否需要引号(以数字开头或含 '.')(委托到 gen._vtable_name_needs_quote)""" + import lib.core.Gen.Generator as Generator + g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(_g_gen, t.CPtr)) + if g is not None: + return g._vtable_name_needs_quote(name) return 0 @@ -3067,44 +972,17 @@ def _vtable_name_needs_quote(name: str) -> int: def _format_func_type_str(pool: memhub.MemBuddy | t.CPtr, buf: t.CChar | t.CPtr, buf_size: t.CSizeT, func: llvmlite.Function | t.CPtr) -> int: - """从 Function 对象生成函数类型字符串""" - if buf is None or func is None or buf_size == 0: - return 0 - buf[0] = '\0' - # 打印返回类型(使用访问器函数避免跨模块直接字段访问) - ret_ty: llvmlite.LLVMType | t.CPtr = llvmlite.function_get_ret_ty(func) - ret_buf: t.CChar | t.CPtr = pool.alloc(128) - if ret_buf is not None and ret_ty is not None: - ret_buf[0] = '\0' - llvmlite.TypePrint(ret_buf, 128, ret_ty, pool) - _vtable_strcat(buf, buf_size, ret_buf) - _vtable_strcat(buf, buf_size, " (") - - # 遍历参数(使用访问器函数避免跨模块直接字段访问) - cur: llvmlite.Param | t.CPtr = llvmlite.function_get_param_head(func) - first: int = 1 - param_buf: t.CChar | t.CPtr = pool.alloc(128) - _pc: int = 0 - while cur is not None: - _pc += 1 - if _pc > 100: - break - if first == 0: - _vtable_strcat(buf, buf_size, ", ") - if param_buf is not None: - param_buf[0] = '\0' - param_ty: llvmlite.LLVMType | t.CPtr = llvmlite.param_get_ty(cur) - if param_ty is not None: - llvmlite.TypePrint(param_buf, 128, param_ty, pool) - _vtable_strcat(buf, buf_size, param_buf) - cur = llvmlite.param_get_next(cur) - first = 0 - _vtable_strcat(buf, buf_size, ")") - return 1 + """从 Function 对象生成函数类型字符串(委托到 gen._format_func_type_str)""" + import lib.core.Gen.Generator as Generator + g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(_g_gen, t.CPtr)) + if g is not None: + return g._format_func_type_str(pool, buf, buf_size, func) + return 0 # ============================================================ -# vtable 收集暂存区(模块级) +# vtable 收集暂存区(已迁移为 ClassGenMixin.VtFullNames/ +# VtMethodNames/VtParentSha1s/VtMethodCount,P5-2 簇 D) # # _collect_vtable_methods 的收集结果,跨函数传递: # - _translate_oop_methods 在翻译方法体之前先收集一次, @@ -3113,10 +991,6 @@ def _format_func_type_str(pool: memhub.MemBuddy | t.CPtr, # method_names_buf 是 stdlib 分配,存入 StructEntry.VTableMethods # 后跨模块持久(不得迁入 mb 池 reset 区间)。 # ============================================================ -_g_vt_full_names: t.CSizeT | t.CPtr = None -_g_vt_method_names: t.CSizeT | t.CPtr = None -_g_vt_parent_sha1s: t.CSizeT | t.CPtr = None -_g_vt_method_count: int = 0 # ============================================================ @@ -3125,7 +999,8 @@ _g_vt_method_count: int = 0 # 1. 继承父类虚方法(父类方法排在子类方法之前,保持槽位顺序一致) # 2. 收集当前类虚方法(跳过已继承的) # -# 结果存入模块级暂存区(_g_vt_*),并设置 entry.VTableMethodCount / +# 结果存入 ClassGenMixin.VtFullNames/VtMethodNames/VtParentSha1s/ +# VtMethodCount(原模块级 _g_vt_*),并设置 entry.VTableMethodCount / # VTableMethods(stdlib 分配,供虚分派跨模块查询)。 # # 返回 1=有虚方法 / 0=无方法或失败 @@ -3133,206 +1008,12 @@ _g_vt_method_count: int = 0 def _collect_vtable_methods(trans: HT.Translator | t.CPtr, cd: ast.ClassDef | t.CPtr, class_name: str) -> int: - """收集虚方法信息,设置 entry.VTableMethods/VTableMethodCount""" - global _g_vt_full_names, _g_vt_method_names, _g_vt_parent_sha1s, _g_vt_method_count - if trans is None or cd is None or class_name is None: - return 0 - - pool: memhub.MemBuddy | t.CPtr = trans.Pool - mod: llvmlite.LLVMModule | t.CPtr = trans.Module - # 懒导入(find_func_global 探测方法实际定义类用) - import lib.core.Handles.HandlesExprCall as HandlesExprCall - - children: list[ast.AST | t.CPtr] | t.CPtr = cd.children - if children is None: - return 0 - cn: t.CSizeT = children.__len__() - - # 1. 收集虚方法信息 - # stdlib 分配:method_names_buf 存到 StructEntry.VTableMethods(跨文件永久存活), - # 必须迁出 mb 池 reset 区间,否则 1b 每文件 reset_to(mark1) 会回收导致悬空。 - full_names_buf: t.CSizeT | t.CPtr = stdlib.malloc(8 * VTBL_METHOD_MAX) - method_names_buf: t.CSizeT | t.CPtr = stdlib.malloc(8 * VTBL_METHOD_MAX) - # 记录每个方法的父类 SHA1(非 0=继承方法用父模块 SHA1 mangling,0=当前类方法) - method_parent_sha1s: t.CSizeT | t.CPtr = stdlib.malloc(8 * VTBL_METHOD_MAX) - if full_names_buf is None or method_names_buf is None or method_parent_sha1s is None: - return 0 - string.memset(full_names_buf, 0, 8 * VTBL_METHOD_MAX) - string.memset(method_names_buf, 0, 8 * VTBL_METHOD_MAX) - string.memset(method_parent_sha1s, 0, 8 * VTBL_METHOD_MAX) - - method_count: int = 0 - - # ============================================================ - # 1.5 继承父类虚方法 - # - # 父类虚方法排在子类虚方法之前,保持 vtable 槽位顺序一致。 - # 如果子类覆盖了方法,full_name 用子类的;否则用父类的。 - # 用 SHA1 感知查找,规避跨模块同名 find_struct 找错 - # ============================================================ - vt_self_entry: HandlesStruct.StructEntry | t.CPtr = HandlesStruct.find_struct_by_module( - class_name, trans.ModuleSha1) - # 多继承:遍历所有父类(声明顺序),vtable 方法合并(短名去重,先声明父类优先) - parent_count: int = HandlesStruct.get_parent_count(class_name) - if parent_count > 0: - for pi in range(parent_count): - pname: str = HandlesStruct.get_parent_name_at(class_name, pi) - if pname is None: - continue - # 查找父类 entry(优先同模块 SHA1 匹配) - vt_parent_entry: HandlesStruct.StructEntry | t.CPtr = HandlesStruct.find_struct_by_module( - pname, trans.ModuleSha1) - if vt_parent_entry is None: - # 跨模块继承: 父类在不同模块定义(SHA1 不同),回退到按类名查找 - vt_parent_entry = HandlesStruct.find_struct(pname) - parent_vt_count: int = 0 - if vt_parent_entry is not None: - parent_vt_count = vt_parent_entry.VTableMethodCount - if parent_vt_count > 0: - for pvi in range(parent_vt_count): - if method_count >= VTBL_METHOD_MAX: - break - pmethod_name: str = None - if vt_parent_entry is not None: - pmethod_name = HandlesStruct.get_vtable_method_name(pname, pvi) - if pmethod_name is None: - continue - # 多继承 vtable 去重:方法短名已存在跳过(先声明父类优先) - if _field_name_exists(method_names_buf, method_count, pmethod_name) != 0: - continue - # 检查子类是否覆盖了该方法,以及是否标记 @t.NoVTable - child_overrides: int = 0 - child_nvt: int = 0 - for ci2 in range(cn): - stmt2: ast.AST | t.CPtr = children.get(ci2) - if stmt2 is None: - continue - if stmt2.kind() != ast.ASTKind.FunctionDef: - continue - fd2: ast.FunctionDef | t.CPtr = (ast.FunctionDef | t.CPtr)(stmt2) - if fd2 is not None and fd2.name is not None: - if string.strcmp(fd2.name, pmethod_name) == 0: - child_overrides = 1 - # 检查子类覆盖方法是否标记 @t.NoVTable - if fd2.decorator_list is not None: - if _has_decorator(fd2.decorator_list, "NoVTable") == 1: - child_nvt = 1 - break - # 构造 full_name - # 子类覆盖且未标记 NoVTable → 用子类实现 - # 子类未覆盖 或 子类覆盖但标记 NoVTable → 用实际定义类实现(保持 vtable 槽位) - # - # 多层继承修复: 直接父类可能只是继承而非定义该方法 - # (如 ElectricCar 继承 Car 的 is_running 实际定义在 Vehicle), - # 沿父类链向上用 find_func_global("类名.方法名") 探测实际定义类, - # 避免生成 "Car.is_running" 这类找不到函数的 full_name → vtable 槽变 null。 - def_class: str = class_name - if child_overrides == 1 and child_nvt == 0: - def_class = class_name - else: - def_class = pname - # 多继承:沿 pname 的 MRO 祖先链探测实际定义类(跳过自身,先声明父类优先) - mro_ptr: t.CSizeT | t.CPtr = HandlesStruct.get_mro_chain(pool, pname) - mro_i: int = 1 - while mro_ptr is not None and mro_ptr[mro_i] != 0: - anc: str = (str | t.CPtr)(t.CVoid(mro_ptr[mro_i], t.CPtr)) - if anc is not None: - probe_buf: t.CChar | t.CPtr = pool.alloc(128) - if probe_buf is not None: - viperlib.snprintf(probe_buf, 128, "%s.%s", anc, pmethod_name) - if HandlesExprCall.find_func_global(probe_buf) is not None: - def_class = anc - break - mro_i += 1 - pfname_buf: t.CChar | t.CPtr = pool.alloc(128) - if pfname_buf is not None: - viperlib.snprintf(pfname_buf, 128, "%s.%s", def_class, pmethod_name) - full_names_buf[method_count] = t.CSizeT(pfname_buf) - # 复制方法名(短名) - pmname_len: t.CSizeT = string.strlen(pmethod_name) - pmname_buf: t.CChar | t.CPtr = stdlib.malloc(pmname_len + 1) - if pmname_buf is not None: - string.strcpy(pmname_buf, pmethod_name) - method_names_buf[method_count] = t.CSizeT(pmname_buf) - # 记录 mangling 用的 SHA1(继承未覆盖的方法用实际定义类的模块 SHA1) - if child_overrides == 1 and child_nvt == 0: - # 子类覆盖: 用当前模块 SHA1(保持 0) - method_parent_sha1s[method_count] = 0 - else: - # 继承未覆盖: 用实际定义类的模块 SHA1(跨模块继承时 mangling 正确) - def_entry2: HandlesStruct.StructEntry | t.CPtr = HandlesStruct.find_struct( - def_class) - if def_entry2 is not None and def_entry2.ModuleSha1 is not None: - method_parent_sha1s[method_count] = t.CSizeT(def_entry2.ModuleSha1) - else: - method_parent_sha1s[method_count] = 0 - method_count += 1 - - # 2. 收集当前类的虚方法(跳过已从父类继承的) - for ci in range(cn): - stmt: ast.AST | t.CPtr = children.get(ci) - if stmt is None: - continue - if stmt.kind() != ast.ASTKind.FunctionDef: - continue - fd: ast.FunctionDef | t.CPtr = (ast.FunctionDef | t.CPtr)(stmt) - if fd is None or fd.name is None: - continue - if method_count >= VTBL_METHOD_MAX: - break - - mname: str = fd.name - # 跳过构造函数和特殊方法(不应放入虚表) - if string.strcmp(mname, "__init__") == 0: - continue - if string.strcmp(mname, "__before_init__") == 0: - continue - if string.strcmp(mname, "__new__") == 0: - continue - # 函数级装饰器过滤:判断方法是否应该进入虚表 - if _should_method_be_virtual(cd, fd, trans) == 0: - continue - # 检查是否已从父类继承(避免重复) - already_in_vt: int = 0 - for mi in range(method_count): - exist_addr: t.CSizeT = method_names_buf[mi] - if exist_addr != 0: - exist_name: str = (str | t.CPtr)(t.CVoid(exist_addr, t.CPtr)) - if exist_name is not None and string.strcmp(exist_name, mname) == 0: - already_in_vt = 1 - break - if already_in_vt == 1: - continue - # 构造 full_name = "ClassName.method_name" - fname_buf: t.CChar | t.CPtr = pool.alloc(128) - if fname_buf is not None: - viperlib.snprintf(fname_buf, 128, "%s.%s", class_name, mname) - full_names_buf[method_count] = t.CSizeT(fname_buf) - - # 复制方法名 - mname_len: t.CSizeT = string.strlen(mname) - mname_buf: t.CChar | t.CPtr = stdlib.malloc(mname_len + 1) - if mname_buf is not None: - string.strcpy(mname_buf, mname) - method_names_buf[method_count] = t.CSizeT(mname_buf) - - method_count += 1 - - # 暂存结果(_generate_vtable 复用) - _g_vt_full_names = full_names_buf - _g_vt_method_names = method_names_buf - _g_vt_parent_sha1s = method_parent_sha1s - _g_vt_method_count = method_count - - # 设置 entry 元数据(虚分派查询用;必须在本类方法体翻译前就绪, - # 否则方法体内 self.虚方法 调用无法虚分派) - if vt_self_entry is not None and method_count > 0: - vt_self_entry.VTableMethodCount = method_count - vt_self_entry.VTableMethods = method_names_buf - - if method_count == 0: - return 0 - return 1 + """收集虚方法信息,设置 entry.VTableMethods/VTableMethodCount(委托到 gen._collect_vtable_methods)""" + import lib.core.Gen.Generator as Generator + g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(_g_gen, t.CPtr)) + if g is not None: + return g._collect_vtable_methods(trans, cd, class_name) + return 0 # _generate_vtable — 生成 VTable 全局变量 @@ -3345,162 +1026,11 @@ def _collect_vtable_methods(trans: HT.Translator | t.CPtr, def _generate_vtable(trans: HT.Translator | t.CPtr, cd: ast.ClassDef | t.CPtr, class_name: str) -> int: - """生成 VTable 全局变量""" - if trans is None or cd is None or class_name is None: - return 0 - - # 懒导入 - import lib.core.Handles.HandlesFunctions as HandlesFunctions - import lib.core.Handles.HandlesExprCall as HandlesExprCall - - pool: memhub.MemBuddy | t.CPtr = trans.Pool - mod: llvmlite.LLVMModule | t.CPtr = trans.Module - - # 收集虚方法信息(继承父类 + 自身,结果存模块级暂存区 _g_vt_*) - # 同时设置 entry.VTableMethodCount/VTableMethods(虚分派查询用) - if _collect_vtable_methods(trans, cd, class_name) == 0: - return 0 - full_names_buf: t.CSizeT | t.CPtr = _g_vt_full_names - method_names_buf: t.CSizeT | t.CPtr = _g_vt_method_names - method_parent_sha1s: t.CSizeT | t.CPtr = _g_vt_parent_sha1s - method_count: int = _g_vt_method_count - # 重新获取 entry(后续存储 VTableMethods 用) - vt_self_entry: HandlesStruct.StructEntry | t.CPtr = HandlesStruct.find_struct_by_module( - class_name, trans.ModuleSha1) - - # 2. 构造 VTable 类型: { i8*, i8*, ..., i8* } - i8_ty: llvmlite.LLVMType | t.CPtr = llvmlite.Int8(pool) - i8_ptr_ty: llvmlite.LLVMType | t.CPtr = llvmlite.Ptr(pool, i8_ty) - - first_node: llvmlite.ParamNode | t.CPtr = None - tail_node: llvmlite.ParamNode | t.CPtr = None - for i in range(method_count): - pnode: llvmlite.ParamNode | t.CPtr = llvmlite.new_param_node(pool, i8_ptr_ty) - if pnode is None: - continue - tail_node = llvmlite.param_list_append(first_node, tail_node, pnode) - if first_node is None: - first_node = tail_node - - vtable_ty: llvmlite.LLVMType | t.CPtr = llvmlite.Struct(pool, first_node, method_count, None) - if vtable_ty is None: - return 0 - - # 3. 构造初始化字符串 - # 大 vtable(如 MemBuddy 28+ 方法)每个方法 bitcast 约 100+ 字节, - # 4096 可能写满导致截断/strlen 越界,用 16384 预留足够空间。 - init_buf: t.CChar | t.CPtr = pool.alloc(16384) - if init_buf is None: - return 0 - init_buf[0] = '\0' - _vtable_strcat(init_buf, 16384, "{ ") - - for i in range(method_count): - if i > 0: - _vtable_strcat(init_buf, 16384, ", ") - - full_name_addr: t.CSizeT = full_names_buf[i] - if full_name_addr == 0: - _vtable_strcat(init_buf, 16384, "i8* null") - continue - - full_name: str = (str | t.CPtr)(t.CVoid(full_name_addr, t.CPtr)) - - # 检查是否是继承方法(method_parent_sha1s 非 0 表示用父模块 SHA1 mangling) - parent_sha1_addr: t.CSizeT = method_parent_sha1s[i] - if parent_sha1_addr != 0: - # 继承方法: 用父类模块 SHA1 做 mangling - parent_sha1: str = (str | t.CPtr)(t.CVoid(parent_sha1_addr, t.CPtr)) - mangled_name: str = HandlesFunctions._mangle_name_with_sha1(parent_sha1, full_name) - # 从全局函数表查找(跨模块函数不在当前模块表中) - func: llvmlite.Function | t.CPtr = HandlesExprCall.find_func_global(full_name) - else: - # 当前类方法: 用当前模块 SHA1 - mangled_name: str = HandlesFunctions._mangle_name(trans, full_name) - func: llvmlite.Function | t.CPtr = HandlesExprCall.find_func_in_table( - trans._funcs, trans._func_count, full_name) - # 当前模块表找不到时,回退到全局表 - if func is None: - func = HandlesExprCall.find_func_global(full_name) - - # func 可能已被 1b reset_to(mark1) 回收(跨模块继承方法在定义文件翻译后被 reset)。 - # 悬空指针非 NULL 但内容已被复用,_format_func_type_str 解引用会沿垃圾 Next 链 - # 指针追逐导致无限分配(TypePrint 每次 pool.alloc(512) → 单文件暴涨 900MB OOM)。 - # 因此 func 非 NULL 时也须用 _is_valid_ptr 校验,失败回退到 TypeStr。 - func_valid: int = 0 - if func is not None: - if trans.Pool is not None: - # 继承方法(parent_sha1_addr != 0):func 来自其他模块,该模块 1b 翻译 - # 后已被 reset_to(mark1) 回收,_is_valid_ptr 存在假阳性(块头复用后仍 - # 看似有效),直接判定无效走 TypeStr 回退,避免解引用悬空 func 崩溃。 - if parent_sha1_addr != 0: - func_valid = 0 - elif trans.Pool._is_valid_ptr(func) != 0: - func_valid = 1 - if func_valid == 0: - # 回退到全局表完整 entry 的 TypeStr(stdlib 深拷贝,跨文件永久存活)。 - ge: HandlesExprCall.FuncEntry | t.CPtr = HandlesExprCall.find_func_entry_global(full_name) - if ge is not None and ge.TypeStr is not None: - _vtable_strcat(init_buf, 16384, "i8* bitcast (") - _vtable_strcat(init_buf, 16384, ge.TypeStr) - _vtable_strcat(init_buf, 16384, "* @") - if _vtable_name_needs_quote(mangled_name) != 0: - _vtable_strcat(init_buf, 16384, "\"") - _vtable_strcat(init_buf, 16384, mangled_name) - _vtable_strcat(init_buf, 16384, "\"") - else: - _vtable_strcat(init_buf, 16384, mangled_name) - _vtable_strcat(init_buf, 16384, " to i8*)") - continue - _vtable_strcat(init_buf, 16384, "i8* null") - continue - - # 构造函数类型字符串 - func_ty_buf: t.CChar | t.CPtr = pool.alloc(512) - if func_ty_buf is None: - _vtable_strcat(init_buf, 16384, "i8* null") - continue - _format_func_type_str(pool, func_ty_buf, 512, func) - - # 构造 bitcast 字符串: i8* bitcast (func_ty* @mangled to i8*) - _vtable_strcat(init_buf, 16384, "i8* bitcast (") - _vtable_strcat(init_buf, 16384, func_ty_buf) - _vtable_strcat(init_buf, 16384, "* @") - - if _vtable_name_needs_quote(mangled_name) != 0: - _vtable_strcat(init_buf, 16384, "\"") - _vtable_strcat(init_buf, 16384, mangled_name) - _vtable_strcat(init_buf, 16384, "\"") - else: - _vtable_strcat(init_buf, 16384, mangled_name) - _vtable_strcat(init_buf, 16384, " to i8*)") - - _vtable_strcat(init_buf, 16384, " }") - - # 4. 构造 VTable 全局变量名 - vtable_name_buf: t.CChar | t.CPtr = pool.alloc(128) - if vtable_name_buf is None: - return 0 - viperlib.snprintf(vtable_name_buf, 128, "%s.vtable", class_name) - vtable_mangled: str = HandlesFunctions._mangle_name(trans, vtable_name_buf) - - # 5. 创建全局变量 - gv: llvmlite.GlobalVariable | t.CPtr = llvmlite.new_global_variable( - pool, vtable_mangled, vtable_ty) - if gv is None: - return 0 - gv.Initializer = init_buf - gv.IsConstant = 1 - gv.Linkage = "internal" - - # 添加到模块 - llvmlite.module_add_global(mod, gv) - - # 6. 存储虚方法名列表到 StructEntry(直接用 entry,规避跨模块同名 find_struct 找错) - if vt_self_entry is not None: - vt_self_entry.VTableMethods = method_names_buf - vt_self_entry.VTableMethodCount = method_count - + """生成 VTable 全局变量(委托到 gen._generate_vtable)""" + import lib.core.Gen.Generator as Generator + g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(_g_gen, t.CPtr)) + if g is not None: + return g._generate_vtable(trans, cd, class_name) return 0 @@ -3530,106 +1060,12 @@ def _translate_oop_methods(trans: HT.Translator | t.CPtr, """扫描 class body 中的方法并翻译,生成 __before_init__ mark_only: 0=全量翻译(默认),1=只设置 IsOOP/HasNew/HasInit 标志(不翻译方法体) + (委托到 gen._translate_oop_methods) """ - if trans is None or cd is None or struct_ty is None or class_name is None: - return 0 - - children: list[ast.AST | t.CPtr] | t.CPtr = cd.children - if children is None: - return 0 - - cn: t.CSizeT = children.__len__() - has_method: int = 0 - has_init: int = 0 - has_new: int = 0 - - # 提前用类型指针定位 entry(规避跨模块同名类 find_struct 找错) - oop_entry: HandlesStruct.StructEntry | t.CPtr = HandlesStruct.find_struct_by_type(struct_ty) - - # 第一遍:检测是否有方法,标记 OOP,并注册装饰器元数据 - for ci in range(cn): - stmt: ast.AST | t.CPtr = children.get(ci) - if stmt is None: - continue - if stmt.kind() == ast.ASTKind.FunctionDef: - has_method = 1 - fd_check: ast.FunctionDef | t.CPtr = (ast.FunctionDef | t.CPtr)(stmt) - if fd_check is not None and fd_check.name is not None: - if string.strcmp(fd_check.name, "__init__") == 0: - has_init = 1 - if string.strcmp(fd_check.name, "__new__") == 0: - has_new = 1 - # 注册装饰器元数据(@property/@staticmethod/@classmethod/@x.setter 等)。 - # 此处(含 mark_only=1 的 struct 预注册阶段)注册, - # 确保其他模块在 App 文件翻译时能识别属性访问。 - fd_meta: int = _extract_func_meta(fd_check.decorator_list) - if fd_meta != 0: - register_method_meta(class_name, fd_check.name, fd_meta) - - if has_method == 0: - # 子类没有自己的方法,但可能继承了父类的虚方法 - # 用 oop_entry 直接获取 ParentName,规避 find_struct 按名查找找错 - parent_name: str = None - if oop_entry is not None: - parent_name = oop_entry.ParentName - if parent_name is not None: - parent_vt_count: int = HandlesStruct.get_vtable_method_count(parent_name) - if parent_vt_count > 0: - has_method = 1 # 标记为有方法(继承的虚方法) - if has_method == 0: - return 0 - - # 标记为 OOP 结构体 - if oop_entry is not None: - oop_entry.IsOOP = 1 - if has_init != 0: - oop_entry.HasInit = 1 - if has_new != 0: - oop_entry.HasNew = 1 - - # mark_only 模式:只设置标志,不翻译方法体 - if mark_only != 0: - return 0 - - # 防重入:方法体翻译前先标记 MethodsEmitted=1。 - # 根因:若等全部方法译完再标记,翻译 __iter__(返回 list[T]|t.CPtr)时, - # 返回类型注解会再次触发 _specialize_generic_class,此时 MethodsEmitted - # 仍为 0,走补译分支把同一特化类方法全部重发 → invalid redefinition。 - if oop_entry is not None: - oop_entry.MethodsEmitted = 1 - - # 第二遍:翻译每个方法 - # 翻译方法体前先预注册 vtable 元数据(VTableMethods/VTableMethodCount)。 - # 根因:方法体翻译先于 _generate_vtable,若不预注册,方法体内的 - # self.虚方法 调用(如 MemManager.calloc 里的 self.alloc)读不到 - # VTableMethods,虚分派失败,被静态绑定到本类实现(基类 alloc 返回 - # None),导致 calloc 永远返回 NULL。 - oop_has_vt_pre: int = 0 - if oop_entry is not None: - oop_has_vt_pre = oop_entry.HasVTable - if oop_has_vt_pre == 1: - _collect_vtable_methods(trans, cd, class_name) - for ci in range(cn): - stmt: ast.AST | t.CPtr = children.get(ci) - if stmt is None: - continue - if stmt.kind() == ast.ASTKind.FunctionDef: - fd: ast.FunctionDef | t.CPtr = (ast.FunctionDef | t.CPtr)(stmt) - if fd is not None and fd.name is not None: - _translate_method(trans, fd, struct_ty, class_name) - - # 如果有虚表,先生成 VTable 全局变量(设置 VTableMethodCount) - # 必须在 __before_init__ 之前,否则 __before_init__ 读不到 VTableMethodCount - # 用 oop_entry 直接检查,规避跨模块同名 find_struct 找错 - has_vt_flag: int = 0 - if oop_entry is not None: - has_vt_flag = oop_entry.HasVTable - if has_vt_flag == 1: - _generate_vtable(trans, cd, class_name) - - # 生成 __before_init__ 函数(零值填充 + 默认值赋值 + vtable 指针设置) - _generate_before_init(trans, struct_ty, class_name) - + import lib.core.Gen.Generator as Generator + g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(_g_gen, t.CPtr)) + if g is not None: + return g._translate_oop_methods(trans, cd, struct_ty, class_name, mark_only) return 0 @@ -3646,315 +1082,11 @@ def _translate_method(trans: HT.Translator | t.CPtr, fd: ast.FunctionDef | t.CPtr, struct_ty: llvmlite.LLVMType | t.CPtr, class_name: str) -> int: - """翻译单个方法,返回 0""" - if trans is None or fd is None or struct_ty is None or class_name is None: - return 0 - - # 懒导入 - import lib.core.Handles.HandlesFunctions as HandlesFunctions - import lib.core.Handles.HandlesVar as HandlesVar - import lib.core.Handles.HandlesBody as HandlesBody - import lib.core.Handles.HandlesType as HandlesType - import lib.core.Handles.HandlesExprCall as HandlesExprCall - - pool: memhub.MemBuddy | t.CPtr = trans.Pool - mod: llvmlite.LLVMModule | t.CPtr = trans.Module - imported_modules: str = trans._imported_modules - from_imports: str = trans._from_imports - funcs_ptr: HandlesExprCall.FuncEntry | t.CPtr = trans._funcs - func_count: int = trans._func_count - - i32_ty: llvmlite.LLVMType | t.CPtr = llvmlite.Int32(pool) - self_ptr_ty: llvmlite.LLVMType | t.CPtr = llvmlite.Ptr(pool, struct_ty) - - method_name: str = fd.name - - # 提取装饰器元数据(@property/@staticmethod/@classmethod/@x.setter/@x.deleter) - func_meta: int = _extract_func_meta(fd.decorator_list) - # property setter/deleter 函数名带 $set/$del 后缀,避免与 getter 冲突 - method_name_buf: t.CChar | t.CPtr = pool.alloc(128) - if method_name_buf is None: - return 0 - viperlib.snprintf(method_name_buf, 128, "%s", fd.name) - if func_meta & META_PROP_SETTER != 0: - string.strcat(method_name_buf, "$set") - elif func_meta & META_PROP_DELETER != 0: - string.strcat(method_name_buf, "$del") - method_name = method_name_buf - - is_static_m: int = 0 - is_class_m: int = 0 - if func_meta & META_STATIC != 0: - is_static_m = 1 - if func_meta & META_CLASS != 0: - is_class_m = 1 - - # 构建方法全名: ClassName.method_name - full_name_buf: t.CChar | t.CPtr = pool.alloc(128) - if full_name_buf is None: - return 0 - viperlib.snprintf(full_name_buf, 128, "%s.%s", class_name, method_name) - full_name: str = full_name_buf - - # SHA1 命名空间混淆 - mangled_name: str = HandlesFunctions._mangle_name(trans, full_name) - - # 推断返回类型 - ret_ty: llvmlite.LLVMType | t.CPtr = None - if fd.returns is not None: - ret_ty = HandlesType.resolve_annotation_type( - pool, fd.returns, imported_modules, from_imports, trans) - if ret_ty is None and fd.returns is not None: - if HandlesType.has_decorator_marker(fd.returns, "State") != 0: - ret_ty = llvmlite.Void(pool) - if ret_ty is None: - # __init__ 和 __before_init__ 返回 void - if string.strcmp(method_name, "__init__") == 0: - ret_ty = llvmlite.Void(pool) - # __new__ 返回 Ptr(struct_ty)(结构体指针作为存储空间) - elif string.strcmp(method_name, "__new__") == 0: - ret_ty = llvmlite.Ptr(pool, struct_ty) - else: - param_types_str: str = HandlesType.build_param_types_str(pool, fd.args) - ret_ty = HandlesType.infer_return_type( - pool, fd.children, param_types_str) - - # 创建 LLVM 函数 - func: llvmlite.Function | t.CPtr = llvmlite.create_function( - pool, mod, mangled_name, ret_ty) - if func is None: - return 0 - - # 提取默认参数信息(普通方法 args[0] 是 self,不含在 param_count 中; - # @staticmethod 无 self,param_count 为完整参数数) - # 注意: 必须先把属性赋给显式类型为 list[...] | t.CPtr 的局部变量再调用 __len__(), - # 否则编译器无法识别属性返回的 list 类型,GEP base 会变成 i32 0 导致 llc 报错 - md_defaults: t.CVoid | t.CPtr = None - md_default_count: int = 0 - md_param_count: int = 0 - md_args_node: ast.Arguments | t.CPtr = fd.args - if md_args_node is not None: - md_ags: ast.Arguments | t.CPtr = (ast.Arguments | t.CPtr)(md_args_node) - if md_ags.args is not None: - md_alist: list[ast.AST | t.CPtr] | t.CPtr = md_ags.args - if is_static_m != 0: - md_param_count = md_alist.__len__() - else: - md_param_count = md_alist.__len__() - 1 - if md_ags.defaults is not None: - md_dlist: list[ast.AST | t.CPtr] | t.CPtr = md_ags.defaults - md_defaults = md_dlist - md_default_count = md_dlist.__len__() - - # 注册到函数表(用 ClassName.method_name 作为查找名,支持后缀匹配) - max_funcs: int = 256 - if HandlesExprCall.add_func_to_table(funcs_ptr, func_count, full_name, func, max_funcs, - md_defaults, md_default_count, md_param_count, - pool) == 0: - trans._func_count = func_count + 1 - - # 添加 self/cls 参数(Ptr(struct_ty));@staticmethod 无 self,跳过 - # @classmethod 的 cls 也用 Ptr(struct_ty),首参名取 args[0](如 cls) - if is_static_m == 0: - first_pname: str = "self" - if is_class_m != 0 and fd.args is not None: - fd_ags: ast.Arguments | t.CPtr = (ast.Arguments | t.CPtr)(fd.args) - if fd_ags.args is not None and fd_ags.args.__len__() > 0: - fd_first_arg: ast.Arg | t.CPtr = (ast.Arg | t.CPtr)(fd_ags.args.get(0)) - if fd_first_arg is not None and fd_first_arg.arg is not None: - first_pname = fd_first_arg.arg - first_pname_buf: t.CChar | t.CPtr = pool.alloc(32) - if first_pname_buf is not None: - viperlib.snprintf(first_pname_buf, 32, "%%%s", first_pname) - llvmlite.add_param(pool, func, self_ptr_ty, first_pname_buf) - - # 添加其他参数(支持类型注解;@staticmethod 从索引 0 开始,其余跳过索引 0 的 self/cls) - args_node: ast.Arguments | t.CPtr = fd.args - if args_node is not None: - ags: ast.Arguments | t.CPtr = (ast.Arguments | t.CPtr)(args_node) - if ags.args is not None: - alist: list[ast.AST | t.CPtr] | t.CPtr = ags.args - an: t.CSizeT = alist.__len__() - start_idx: int = 0 - if is_static_m == 0: - start_idx = 1 - for ai in range(start_idx, an): - arg: ast.Arg | t.CPtr = (ast.Arg | t.CPtr)(alist.get(ai)) - if arg is not None and arg.arg is not None: - param_ty: llvmlite.LLVMType | t.CPtr = i32_ty - if arg.annotation is not None: - resolved: llvmlite.LLVMType | t.CPtr = HandlesType.resolve_annotation_type( - pool, arg.annotation, imported_modules, from_imports, trans) - if resolved is not None: - # 裸类形参 → Ptr(struct):按"对象即指针"引用传参。 - # 若按 struct 值传参,self.Head = node 会取局部拷贝地址 - # (append 返回后悬垂,G5 Test4 head.Value 读到垃圾)。 - match resolved: - case llvmlite.LLVMType.Struct(_, _, _): - param_ty = llvmlite.Ptr(pool, resolved) - case _: - param_ty = resolved - pname: t.CChar | t.CPtr = pool.alloc(32) - if pname is not None: - viperlib.snprintf(pname, 32, "%%%s", arg.arg) - llvmlite.add_param(pool, func, param_ty, pname) - - # 参数添加完成,补全全局函数表的 TypeStr(供 vtable 在 func 被 reset 后使用) - HandlesExprCall.update_global_func_typestr(pool, full_name, func) - - # 创建 entry 块 - entry_blk: llvmlite.BasicBlock | t.CPtr = llvmlite.create_block(pool, func, "entry") - if entry_blk is None: - return 0 - - # 创建方法专属 builder - func_builder: llvmlite.IRBuilder | t.CPtr = llvmlite.new_builder(pool, func) - if func_builder is None: - return 0 - llvmlite.position_at_end(func_builder, entry_blk) - - # 进入函数作用域 - HandlesVar.enter_scope(trans.SymTab, SCOPE_FUNCTION) - - # 为 self/cls 创建 alloca 并 store(与其他参数一致);@staticmethod 无 self,跳过 - # 修复: 之前 self 注册为 SSA 值导致 translate_name_value 错误地 load 一次 - # 将 Ptr(struct_ty) 变成 struct 值,引发变参函数 ABI 不匹配崩溃 - if is_static_m == 0: - self_alloca: llvmlite.Value | t.CPtr = llvmlite.build_alloca(func_builder, self_ptr_ty) - if self_alloca is not None: - self_var_name: str = "self" - self_ssa_name: str = "%self" - if is_class_m != 0 and args_node is not None: - cags: ast.Arguments | t.CPtr = (ast.Arguments | t.CPtr)(args_node) - if cags.args is not None and cags.args.__len__() > 0: - cfirst: ast.Arg | t.CPtr = (ast.Arg | t.CPtr)(cags.args.get(0)) - if cfirst is not None and cfirst.arg is not None: - self_var_name = cfirst.arg - self_ssa_name_buf: t.CChar | t.CPtr = pool.alloc(32) - if self_ssa_name_buf is not None: - viperlib.snprintf(self_ssa_name_buf, 32, "%%%s", cfirst.arg) - self_ssa_name = self_ssa_name_buf - HandlesVar.define_var(trans.SymTab, self_var_name, self_alloca) - # 设置 self/cls 的类型注解类名(属性访问 lookup_field 回退查找用) - HandlesVar.set_var_annot_class_name(trans.SymTab, self_var_name, class_name) - self_val: llvmlite.Value | t.CPtr = llvmlite.SSAValue(pool, self_ptr_ty, self_ssa_name) - llvmlite.build_store(func_builder, self_val, self_alloca) - - # 为其他参数创建 alloca 并 store(与普通函数一致; - # @staticmethod 从索引 0 开始,其余跳过索引 0 的 self/cls 参数) - if args_node is not None: - ags2: ast.Arguments | t.CPtr = (ast.Arguments | t.CPtr)(args_node) - if ags2.args is not None: - alist2: list[ast.AST | t.CPtr] | t.CPtr = ags2.args - an2: t.CSizeT = alist2.__len__() - start_idx2: int = 0 - if is_static_m == 0: - start_idx2 = 1 - for ai2 in range(start_idx2, an2): - arg2: ast.Arg | t.CPtr = (ast.Arg | t.CPtr)(alist2.get(ai2)) - if arg2 is not None and arg2.arg is not None: - param_ty2: llvmlite.LLVMType | t.CPtr = i32_ty - if arg2.annotation is not None: - resolved2: llvmlite.LLVMType | t.CPtr = HandlesType.resolve_annotation_type( - pool, arg2.annotation, imported_modules, from_imports, trans) - if resolved2 is not None: - # 与 add_param 保持一致:裸类形参 → Ptr(struct)(对象即指针) - match resolved2: - case llvmlite.LLVMType.Struct(_, _, _): - param_ty2 = llvmlite.Ptr(pool, resolved2) - case _: - param_ty2 = resolved2 - alloca: llvmlite.Value | t.CPtr = llvmlite.build_alloca(func_builder, param_ty2) - if alloca is not None: - HandlesVar.define_var(trans.SymTab, arg2.arg, alloca) - # 存储原始类型注解的类名(方法调用检测时,Ptr(i8) 回退到类名查找结构体) - if arg2.annotation is not None: - cls_nm_oc: str = HandlesType.extract_class_name_from_annotation( - arg2.annotation, imported_modules) - if cls_nm_oc is not None: - HandlesVar.set_var_annot_class_name( - trans.SymTab, arg2.arg, cls_nm_oc) - pname2: t.CChar | t.CPtr = pool.alloc(32) - if pname2 is not None: - viperlib.snprintf(pname2, 32, "%%%s", arg2.arg) - param_val: llvmlite.Value | t.CPtr = llvmlite.SSAValue( - pool, param_ty2, pname2) - llvmlite.build_store(func_builder, param_val, alloca) - - # 保存模块级作用域状态 - old_func: llvmlite.Function | t.CPtr = trans._cur_func - old_builder: llvmlite.IRBuilder | t.CPtr = trans._cur_builder - old_global_count: int = trans._global_name_count - old_nonlocal_count: int = trans._nonlocal_name_count - old_env_count: int = trans._closure_env_count - - trans._cur_func = func - trans._cur_builder = func_builder - HT.clear_scope_names(trans) - - # 预扫描方法体:为局部变量提前创建 alloca - body: list[ast.AST | t.CPtr] | t.CPtr = fd.children - if body is not None: - bn: t.CSizeT = body.__len__() - for bi in range(bn): - stmt: ast.AST | t.CPtr = body.get(bi) - if stmt is not None: - HandlesBody.pre_scan_allocas(trans, stmt) - - # 翻译方法体 - if body is not None: - bn2: t.CSizeT = body.__len__() - for bi2 in range(bn2): - stmt2: ast.AST | t.CPtr = body.get(bi2) - if stmt2 is not None: - HandlesBody.translate_stmt(trans, stmt2) - - # 如果返回类型为 void,添加 ret void;否则添加隐式 ret 0 - is_void: int = 0 - if ret_ty is not None: - match ret_ty: - case llvmlite.LLVMType.Void(): - is_void = 1 - - if is_void != 0: - if llvmlite.builder_cur_block_is_terminated(func_builder) == 0: - llvmlite.build_ret_void(func_builder) - else: - last_is_return: int = 0 - if body is not None: - bn3: t.CSizeT = body.__len__() - if bn3 > 0: - last_stmt: ast.AST | t.CPtr = body.get(bn3 - 1) - if last_stmt is not None and last_stmt.kind() == ast.ASTKind.Return: - last_is_return = 1 - if last_is_return == 0: - if llvmlite.builder_cur_block_is_terminated(func_builder) == 0: - # 根据返回类型生成正确的零值返回 - _m_is_void: int = 0 - _m_is_ptr: int = 0 - if ret_ty is not None: - match ret_ty: - case llvmlite.LLVMType.Void(): - _m_is_void = 1 - case llvmlite.LLVMType.Ptr(_m_pe): - _m_is_ptr = 1 - if _m_is_void != 0: - llvmlite.build_ret_void(func_builder) - elif _m_is_ptr != 0: - _m_null_val: llvmlite.Value | t.CPtr = llvmlite.ConstNull(pool, ret_ty, "null") - llvmlite.build_ret(func_builder, _m_null_val) - else: - _m_zero_val: llvmlite.Value | t.CPtr = llvmlite.const_int32(pool, 0) - llvmlite.build_ret(func_builder, _m_zero_val) - - # 恢复模块级作用域 - HandlesVar.exit_scope(trans.SymTab) - trans._cur_func = old_func - trans._cur_builder = old_builder - trans._global_name_count = old_global_count - trans._nonlocal_name_count = old_nonlocal_count - trans._closure_env_count = old_env_count - + """翻译单个方法,返回 0(委托到 gen._translate_method)""" + import lib.core.Gen.Generator as Generator + g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(_g_gen, t.CPtr)) + if g is not None: + return g._translate_method(trans, fd, struct_ty, class_name) return 0 @@ -3971,156 +1103,9 @@ def _translate_method(trans: HT.Translator | t.CPtr, def _generate_before_init(trans: HT.Translator | t.CPtr, struct_ty: llvmlite.LLVMType | t.CPtr, class_name: str) -> int: - """生成 __before_init__ 函数,返回 0""" - if trans is None or struct_ty is None or class_name is None: - return 0 - - import lib.core.Handles.HandlesFunctions as HandlesFunctions - import lib.core.Handles.HandlesVar as HandlesVar - import lib.core.Handles.HandlesExpr as HandlesExpr - import lib.core.Handles.HandlesExprCall as HandlesExprCall - - pool: memhub.MemBuddy | t.CPtr = trans.Pool - mod: llvmlite.LLVMModule | t.CPtr = trans.Module - funcs_ptr: HandlesExprCall.FuncEntry | t.CPtr = trans._funcs - func_count: int = trans._func_count - - self_ptr_ty: llvmlite.LLVMType | t.CPtr = llvmlite.Ptr(pool, struct_ty) - void_ty: llvmlite.LLVMType | t.CPtr = llvmlite.Void(pool) - - # 构建函数名: ClassName.__before_init__ - full_name_buf: t.CChar | t.CPtr = pool.alloc(128) - if full_name_buf is None: - return 0 - viperlib.snprintf(full_name_buf, 128, "%s.__before_init__", class_name) - full_name: str = full_name_buf - - mangled_name: str = HandlesFunctions._mangle_name(trans, full_name) - - # 创建函数 - func: llvmlite.Function | t.CPtr = llvmlite.create_function( - pool, mod, mangled_name, void_ty) - if func is None: - return 0 - - # 注册到函数表 - max_funcs: int = 256 - rc_add: int = HandlesExprCall.add_func_to_table(funcs_ptr, func_count, full_name, func, max_funcs, None, 0, 0, pool) - if rc_add == 0: - trans._func_count = func_count + 1 - - # 添加 self 参数 - llvmlite.add_param(pool, func, self_ptr_ty, "%self") - - # 参数添加完成,补全全局函数表的 TypeStr - rc_ut: int = HandlesExprCall.update_global_func_typestr(pool, full_name, func) - - # 创建 entry 块 + builder - entry_blk: llvmlite.BasicBlock | t.CPtr = llvmlite.create_block(pool, func, "entry") - if entry_blk is None: - return 0 - func_builder: llvmlite.IRBuilder | t.CPtr = llvmlite.new_builder(pool, func) - if func_builder is None: - return 0 - llvmlite.position_at_end(func_builder, entry_blk) - - # 注册 self 为 SSA 值 - self_val: llvmlite.Value | t.CPtr = llvmlite.SSAValue(pool, self_ptr_ty, "%self") - - # 1. 零值填充: store zeroinitializer, Ptr(struct_ty)* %self - # 空 struct({})在 LLVM 中不允许 zeroinitializer(invalid type for null constant), - # 无字段类(接口/标记类,如多继承的 Vec2Extra)跳过零值填充; - # @t.CVTable 类必有 vtable 指针字段(非空),不受影响。 - struct_fcount_zi: int = llvmlite.get_struct_fcount(struct_ty) - if struct_fcount_zi > 0: - zero: llvmlite.Value | t.CPtr = llvmlite.ConstZero(pool, struct_ty) - if zero is not None: - llvmlite.build_store(func_builder, zero, self_val) - - # 1.5 如果有虚表,store vtable 全局地址到 __vtable__ 字段(索引 0) - # 用 find_struct_by_type 定位 entry,规避跨模块同名 find_struct 找错 - bi_entry: HandlesStruct.StructEntry | t.CPtr = HandlesStruct.find_struct_by_type(struct_ty) - bi_has_vt: int = 0 - if bi_entry is not None: - bi_has_vt = bi_entry.HasVTable - if bi_has_vt == 1: - vt_method_count: int = 0 - if bi_entry is not None: - vt_method_count = bi_entry.VTableMethodCount - if vt_method_count > 0: - # 构造 vtable 类型 { i8*, i8*, ..., i8* } - vt_i8_ty: llvmlite.LLVMType | t.CPtr = llvmlite.Int8(pool) - vt_i8_ptr_ty: llvmlite.LLVMType | t.CPtr = llvmlite.Ptr(pool, vt_i8_ty) - - vt_first_node: llvmlite.ParamNode | t.CPtr = None - vt_prev_node: llvmlite.ParamNode | t.CPtr = None - for vti in range(vt_method_count): - vtnode: llvmlite.ParamNode | t.CPtr = llvmlite.new_param_node(pool, vt_i8_ptr_ty) - if vtnode is None: - continue - if vt_first_node is None: - vt_first_node = vtnode - if vt_prev_node is not None: - llvmlite.paramnode_set_next(vt_prev_node, vtnode) - vt_prev_node = vtnode - - vt_ty: llvmlite.LLVMType | t.CPtr = llvmlite.Struct(pool, vt_first_node, vt_method_count, None) - vt_ptr_ty: llvmlite.LLVMType | t.CPtr = llvmlite.Ptr(pool, vt_ty) - - # 构造 vtable 全局变量名 - vt_name_buf: t.CChar | t.CPtr = pool.alloc(128) - if vt_name_buf is not None: - viperlib.snprintf(vt_name_buf, 128, "%s.vtable", class_name) - vt_full_name: str = vt_name_buf - vt_mangled: str = HandlesFunctions._mangle_name(trans, vt_full_name) - - # GEP 到 __vtable__ 字段(索引 0) - vt_slot: llvmlite.Value | t.CPtr = llvmlite.build_gep_struct( - func_builder, struct_ty, vt_i8_ptr_ty, self_val, 0) - if vt_slot is not None: - # 创建全局变量引用 Value - vt_ref: llvmlite.Value | t.CPtr = llvmlite.new_value(pool) - if vt_ref is not None: - llvmlite.value_set_ty(vt_ref, vt_ptr_ty) - llvmlite.value_set_isconst(vt_ref, 1) - # Name 格式: @"mangled" 或 @mangled - vt_ref_name: t.CChar | t.CPtr = pool.alloc(256) - if vt_ref_name is not None: - vt_ref_name[0] = '\0' - if _vtable_name_needs_quote(vt_mangled) != 0: - viperlib.snprintf(vt_ref_name, 256, "@\"%s\"", vt_mangled) - else: - viperlib.snprintf(vt_ref_name, 256, "@%s", vt_mangled) - llvmlite.value_set_name(vt_ref, vt_ref_name) - - # bitcast 到 i8* - vt_as_i8: llvmlite.Value | t.CPtr = llvmlite.build_bitcast( - func_builder, vt_ref, vt_i8_ptr_ty) - if vt_as_i8 is not None: - llvmlite.build_store(func_builder, vt_as_i8, vt_slot) - - # 2. 逐字段 store 默认值(用 bi_entry 直接访问,规避跨模块同名 find_struct 找错) - if bi_entry is not None: - for fi in range(bi_entry.FieldCount): - fe: HandlesStruct.FieldEntry | t.CPtr = HandlesStruct._get_field_entry( - bi_entry, fi) - if fe is None or fe.DefaultVal is None: - continue - # 翻译默认值表达式 - default_val: llvmlite.Value | t.CPtr = HandlesExpr.translate_value( - func_builder, pool, mod, fe.DefaultVal, None, 0, trans) - if default_val is None: - continue - # GEP 到字段 - field_ptr: llvmlite.Value | t.CPtr = llvmlite.build_gep_struct( - func_builder, struct_ty, fe.Ty, self_val, fe.Index) - if field_ptr is None: - continue - # 类型转换并 store - default_val = HandlesExpr.coerce_to_type(func_builder, default_val, fe.Ty, fe.DefaultVal) - llvmlite.build_store(func_builder, default_val, field_ptr) - - # 3. ret void - llvmlite.build_ret_void(func_builder) - + """生成 __before_init__ 函数,返回 0(委托到 gen._generate_before_init)""" + import lib.core.Gen.Generator as Generator + g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(_g_gen, t.CPtr)) + if g is not None: + return g._generate_before_init(trans, struct_ty, class_name) return 0 diff --git a/App/lib/core/Handles/HandlesFunctions.vp b/App/lib/core/Handles/HandlesFunctions.vp index 731c4c8..cfddff8 100644 --- a/App/lib/core/Handles/HandlesFunctions.vp +++ b/App/lib/core/Handles/HandlesFunctions.vp @@ -1,1116 +1,163 @@ -import t, c -from stdint import * -import ast -import llvmlite -import memhub -import string -import viperlib -import stdio -import stdlib -import lib.core.VLogger as VLogger -import lib.core.Handles.HandlesTranslator as HT -import lib.core.Handles.HandlesVar as HandlesVar -import lib.core.Handles.HandlesExprCall as HandlesExprCall -import lib.core.Handles.HandlesType as HandlesType -import lib.core.Handles.HandlesExpr as HandlesExpr -import lib.core.Handles.HandlesBody as HandlesBody -import lib.core.Handles.HandlesNonlocal as HandlesNonlocal -import lib.core.Handles.HandlesImports as HandlesImports - - -# 作用域类型常量(本地副本,避免旧编译器跨模块 CDefine 查找 bug) -SCOPE_FUNCTION: t.CDefine = 1 - - -# ============================================================ -# extract_func_attrs - 从 decorator_list 提取 c.Attribute 属性 -# -# 支持 @c.Attribute(t.attr.xxx()) 和 @c.Attribute(t.attr.xxx) 形式 -# 也支持 @c.Attribute(t.attr.llvm.xxx) 形式 -# -# 返回 LLVM IR 属性字符串(如 "alwaysinline nounwind"),无属性返回 None -# ============================================================ -def extract_func_attrs(pool: memhub.MemBuddy | t.CPtr, - decorator_list: list[ast.AST | t.CPtr] | t.CPtr, - imported_modules: str) -> t.CChar | t.CPtr: - """从 decorator_list 提取 c.Attribute 属性,返回 LLVM IR 属性字符串""" - if decorator_list is None: - return None - dn: t.CSizeT = decorator_list.__len__() - if dn == 0: - return None - - attrs_buf: t.CChar | t.CPtr = pool.alloc(256) - if attrs_buf is None: - return None - attrs_buf[0] = '\0' - found_any: int = 0 - - for di in range(dn): - deco: ast.AST | t.CPtr = decorator_list.get(di) - if deco is None or deco.kind() != ast.ASTKind.Call: - continue - call_node: ast.Call | t.CPtr = (ast.Call | t.CPtr)(deco) - if call_node.func is None or call_node.func.kind() != ast.ASTKind.Attribute: - continue - - # 检测 c.Attribute - func_attr: ast.Attribute | t.CPtr = (ast.Attribute | t.CPtr)(call_node.func) - if func_attr.attr is None or string.strcmp(func_attr.attr, "Attribute") != 0: - continue - if func_attr.value is None or func_attr.value.kind() != ast.ASTKind.Name: - continue - c_name: ast.Name | t.CPtr = (ast.Name | t.CPtr)(func_attr.value) - if c_name.id is None or string.strcmp(c_name.id, "c") != 0: - continue - if HandlesImports.is_module_imported(imported_modules, "c") == 0: - continue - - # 遍历参数提取属性 - if call_node.args is None: - continue - args_list: list[ast.AST | t.CPtr] | t.CPtr = call_node.args - an: t.CSizeT = args_list.__len__() - for ai in range(an): - arg_node: ast.AST | t.CPtr = args_list.get(ai) - if arg_node is None: - continue - - # 提取属性名(t.attr.xxx / t.attr.xxx() / t.attr.llvm.xxx) - attr_name: str = _get_attr_name_from_node(arg_node) - if attr_name is None: - continue - - # 映射到 LLVM 属性名并追加 - if _append_llvm_attr(attrs_buf, attr_name) != 0: - found_any = 1 - # 追加成功后,如果不是最后一个属性,添加空格分隔 - # 在下一次追加前由 _append_str 处理 - - if found_any == 0: - return None - return attrs_buf - - -def _get_attr_name_from_node(node: ast.AST | t.CPtr) -> str: - """从 AST 节点提取属性名 - - 支持: - - Call(func=Attribute(...)): t.attr.always_inline() -> "always_inline" - - Attribute: t.attr.packed -> "packed" - - Attribute(t.attr.llvm.xxx): t.attr.llvm.nounwind -> "nounwind" - """ - if node is None: - return None - k: int = node.kind() - - # Call 节点: t.attr.always_inline() - if k == ast.ASTKind.Call: - call: ast.Call | t.CPtr = (ast.Call | t.CPtr)(node) - if call.func is None or call.func.kind() != ast.ASTKind.Attribute: - return None - at: ast.Attribute | t.CPtr = (ast.Attribute | t.CPtr)(call.func) - return at.attr - - # Attribute 节点: t.attr.packed 或 t.attr.llvm.nounwind - if k == ast.ASTKind.Attribute: - at2: ast.Attribute | t.CPtr = (ast.Attribute | t.CPtr)(node) - return at2.attr - - return None - - -def _append_llvm_attr(attrs_buf: t.CChar | t.CPtr, attr_name: str) -> int: - """将属性名映射到 LLVM 属性名并追加到缓冲区 - - 返回 1 表示已追加,0 表示不支持该属性 - """ - if attrs_buf is None or attr_name is None: - return 0 - - # 先确定映射的 LLVM 属性名 - llvm_name: str = None - if string.strcmp(attr_name, "always_inline") == 0: - llvm_name = "alwaysinline" - elif string.strcmp(attr_name, "noinline") == 0: - llvm_name = "noinline" - elif string.strcmp(attr_name, "noreturn") == 0: - llvm_name = "noreturn" - elif string.strcmp(attr_name, "pure") == 0: - llvm_name = "readonly" - elif string.strcmp(attr_name, "const") == 0: - llvm_name = "readnone" - elif string.strcmp(attr_name, "nounwind") == 0: - llvm_name = "nounwind" - elif string.strcmp(attr_name, "noredzone") == 0: - llvm_name = "noredzone" - elif string.strcmp(attr_name, "willreturn") == 0: - llvm_name = "willreturn" - elif string.strcmp(attr_name, "mustprogress") == 0: - llvm_name = "mustprogress" - else: - # packed/aligned/section/visibility/weak 等不支持作为函数内联属性 - return 0 - - # 支持的属性:如果缓冲区非空,先追加空格分隔 - if attrs_buf[0] != '\0': - _append_str(attrs_buf, " ") - _append_str(attrs_buf, llvm_name) - return 1 - - -def _append_str(buf: t.CChar | t.CPtr, s: str) -> None: - """将字符串追加到 buf 末尾(用 strlen+strcpy 模拟 strcat)""" - if buf is None or s is None: - return - cur_len: t.CSizeT = string.strlen(buf) - string.strcpy(buf + cur_len, s) - - -# ============================================================ -# HandlesFunctions - 函数定义处理(trans 单参模式) -# -# 参考 Python 版 TransPyC FunctionHandle -# -# 函数有自己的局部作用域,通过 HandlesVar.enter_scope/exit_scope -# 管理嵌套作用域链,翻译函数体前进入函数作用域,翻译完退出。 -# ============================================================ - - -# ============================================================ -# _mangle_name - 为名称添加 SHA1 前缀 -# -# 返回 "sha1.name" 格式的混淆名。若 ModuleSha1 为 None 或名称已带 -# SHA1 前缀(16 hex + '.'),则原样返回。 -# ============================================================ -def _mangle_name(trans: HT.Translator | t.CPtr, name: str) -> str: - """为任意名称添加 SHA1 前缀(不做 main/export 检查)""" - if trans is None or name is None: - return name - if trans.ModuleSha1 is None: - return name - name_len: t.CSizeT = string.strlen(name) - # 已带 SHA1 前缀(16 hex + '.')则跳过 - if name_len > 17: - is_sha1: int = 1 - for i in range(16): - c: t.CChar = name[i] - if not (('0' <= c <= '9') or ('a' <= c <= 'f')): - is_sha1 = 0 - break - if is_sha1 != 0 and name[16] == '.': - return name - sha1: str = trans.ModuleSha1 - sha1_len: t.CSizeT = string.strlen(sha1) - mangled: str = stdlib.malloc(sha1_len + name_len + 2) - if mangled is None: - return name - string.strcpy(mangled, sha1) - mangled[sha1_len] = '.' - string.strcpy(mangled + sha1_len + 1, name) - return mangled - - -# ============================================================ -# _mangle_name_with_sha1 — 用指定 SHA1 为名称添加前缀 -# -# 用于跨模块 vtable 继承: 继承方法需要用父模块的 SHA1 做 mangling, -# 而非当前模块的 SHA1。 -# ============================================================ -def _mangle_name_with_sha1(sha1: str, name: str) -> str: - """用指定 SHA1 为名称添加前缀(不做 main/export 检查)""" - if sha1 is None or name is None: - return name - name_len: t.CSizeT = string.strlen(name) - # 已带 SHA1 前缀(16 hex + '.')则跳过 - if name_len > 17: - is_sha1: int = 1 - for i in range(16): - c2: t.CChar = name[i] - if not (('0' <= c2 <= '9') or ('a' <= c2 <= 'f')): - is_sha1 = 0 - break - if is_sha1 != 0 and name[16] == '.': - return name - sha1_len: t.CSizeT = string.strlen(sha1) - mangled: str = stdlib.malloc(sha1_len + name_len + 2) - if mangled is None: - return name - string.strcpy(mangled, sha1) - mangled[sha1_len] = '.' - string.strcpy(mangled + sha1_len + 1, name) - return mangled - - -# ============================================================ -# _mangle_func_name - 为函数名添加 SHA1 前缀(含 main/export 检查) -# -# 规则: -# - main 函数不加前缀(程序入口点) -# - has_export 非 0 时不加前缀(t.CExport 导出函数) -# - 已带 SHA1 前缀的不再加 -# - ModuleSha1 为 None 时不加前缀 -# ============================================================ -def _mangle_func_name(trans: HT.Translator | t.CPtr, name: str, - has_export: int) -> str: - """为函数名添加 SHA1 前缀(检查 main/export)""" - if trans is None or name is None: - return name - if has_export != 0: - return name - if string.strcmp(name, "main") == 0: - return name - return _mangle_name(trans, name) - - -# ============================================================ -# forward_declare_functions - 预扫描所有顶层 FunctionDef,创建前向声明 -# -# 解决同模块内前向引用问题:如 viperlib.py 中 sprintf(行15) 调用 -# vsnprintf(行41),但 vsnprintf 定义在后面。 -# -# 对每个顶层 FunctionDef: -# 1. 推断返回类型和参数类型 -# 2. 计算 mangled name(含 SHA1 前缀) -# 3. 创建 declare(IsDeclared=1) -# 4. 添加参数 -# 5. 注册到函数表 -# -# 后续 translate_function_def 会通过 find_func_in_module 找到已有的 declare, -# 复用之(清除 IsDeclared,跳过参数创建,直接添加函数体)。 -# ============================================================ -def forward_declare_functions(trans: HT.Translator | t.CPtr, - tree: ast.AST | t.CPtr) -> int: - """预扫描所有顶层 FunctionDef,创建前向声明""" - if trans is None or tree is None: - return 0 - pool: memhub.MemBuddy | t.CPtr = trans.Pool - mod: llvmlite.LLVMModule | t.CPtr = trans.Module - if pool is None or mod is None: - return 0 - - imported_modules: str = trans._imported_modules - from_imports: str = trans._from_imports - funcs_ptr: HandlesExprCall.FuncEntry | t.CPtr = trans._funcs - - i32_ty: llvmlite.LLVMType | t.CPtr = llvmlite.Int32(pool) - i8_ty: llvmlite.LLVMType | t.CPtr = llvmlite.Int8(pool) - i8_ptr_ty: llvmlite.LLVMType | t.CPtr = llvmlite.Ptr(pool, i8_ty) - - ch: list[ast.AST | t.CPtr] | t.CPtr = tree.children - if ch is None: - return 0 - - # 解析函数签名期间临时切换到"仅声明"模式: - # 签名里的泛型类注解(如 _empty_like(a: ndarray[t.CDouble]))会触发泛型特化, - # 若此时特化立即翻译方法体,方法体前向引用同模块后续函数(如 _empty_like 自身) - # 会因 declare 尚未创建而报"裸名调用未定义且未导入"。 - # 临时 declare_only=1 使特化只注册结构体(mark_only 不译方法体), - # 方法体由后续 resolve_annotation_type 命中已注册结构体时补译 - # (_specialize_generic_class 的 Phase B 补译分支)。 - saved_declare_only: int = trans._declare_only - trans._declare_only = 1 - cn_count: t.CSizeT = ch.__len__() - - for ci in range(cn_count): - child: ast.AST | t.CPtr = ch.get(ci) - if child is None: - continue - if child.kind() != ast.ASTKind.FunctionDef: - continue - fd: ast.FunctionDef | t.CPtr = (ast.FunctionDef | t.CPtr)(child) - if fd is None or fd.name is None: - continue - - # 推断返回类型 - ret_ty: llvmlite.LLVMType | t.CPtr = None - if fd.returns is not None: - ret_ty = HandlesType.resolve_annotation_type( - pool, fd.returns, imported_modules, from_imports, trans) - if ret_ty is None and fd.returns is not None: - if HandlesType.has_decorator_marker(fd.returns, "State") != 0: - ret_ty = llvmlite.Void(pool) - if ret_ty is None: - ret_ty = i32_ty - - # 检测 CExtern/State/CExport - has_extern: int = 0 - has_state: int = 0 - has_export: int = 0 - if fd.returns is not None: - has_extern = HandlesType.has_decorator_marker(fd.returns, "CExtern") - has_state = HandlesType.has_decorator_marker(fd.returns, "State") - has_export = HandlesType.has_decorator_marker(fd.returns, "CExport") - is_extern_decl: int = 0 - if has_extern != 0 or has_state != 0: - is_extern_decl = 1 - - # 计算 mangled name - if has_extern != 0 or has_state != 0 or has_export != 0 or string.strcmp(fd.name, "main") == 0: - mangled_name: str = fd.name - else: - mangled_name = _mangle_func_name(trans, fd.name, 0) - - # 如果函数已存在(如重复定义),跳过 - existing: llvmlite.Function | t.CPtr = HandlesExprCall.find_func_in_module(mod, mangled_name) - if existing is not None: - continue - - # 创建 declare - func: llvmlite.Function | t.CPtr = llvmlite.create_declare( - pool, mod, mangled_name, ret_ty) - if func is None: - continue - - # 提取默认参数信息 - # 注意: 必须先把属性赋给显式类型为 list[...] | t.CPtr 的局部变量再调用 __len__(), - # 否则编译器无法识别属性返回的 list 类型,GEP base 会变成 i32 0 导致 llc 报错 - fd_args_node: ast.Arguments | t.CPtr = fd.args - fd_defaults: t.CVoid | t.CPtr = None - fd_default_count: int = 0 - fd_param_count: int = 0 - if fd_args_node is not None: - fd_ags: ast.Arguments | t.CPtr = (ast.Arguments | t.CPtr)(fd_args_node) - if fd_ags.args is not None: - fd_alist: list[ast.AST | t.CPtr] | t.CPtr = fd_ags.args - fd_param_count = fd_alist.__len__() - if fd_ags.defaults is not None: - fd_dlist: list[ast.AST | t.CPtr] | t.CPtr = fd_ags.defaults - fd_defaults = fd_dlist - fd_default_count = fd_dlist.__len__() - - # 注册到函数表(用裸名 fd.name,不是 mangled_name) - max_funcs: int = 256 - cur_count: int = trans._func_count - if HandlesExprCall.add_func_to_table(funcs_ptr, cur_count, fd.name, func, max_funcs, - fd_defaults, fd_default_count, fd_param_count, - trans.Pool) == 0: - trans._func_count = cur_count + 1 - - # 注册 CExport 函数到全局表 - if (has_export != 0 or has_state != 0) and trans.ModuleSha1 is not None: - HandlesExprCall.register_cexport_func(trans.ModuleSha1, fd.name) - - # 添加参数 - args_node: ast.Arguments | t.CPtr = fd.args - if args_node is not None: - ags: ast.Arguments | t.CPtr = (ast.Arguments | t.CPtr)(args_node) - if ags.args is not None: - alist: list[ast.AST | t.CPtr] | t.CPtr = ags.args - an: t.CSizeT = alist.__len__() - for ai in range(an): - arg: ast.Arg | t.CPtr = (ast.Arg | t.CPtr)(alist.get(ai)) - if arg is None or arg.arg is None: - continue - # t.CVoid 表示空参:跳过 - if arg.annotation is not None: - if HandlesType._is_t_attr(arg.annotation, "CVoid", imported_modules) != 0: - continue - param_ty: llvmlite.LLVMType | t.CPtr = i32_ty - if arg.annotation is not None: - resolved: llvmlite.LLVMType | t.CPtr = HandlesType.resolve_annotation_type( - pool, arg.annotation, imported_modules, from_imports, trans) - if resolved is not None: - # 裸类形参 → Ptr(struct)(对象即指针,与方法形参一致) - match resolved: - case llvmlite.LLVMType.Struct(_, _, _): - param_ty = llvmlite.Ptr(pool, resolved) - case _: - param_ty = resolved - pname: t.CChar | t.CPtr = pool.alloc(32) - if pname is not None: - viperlib.snprintf(pname, 32, "%%%s", arg.arg) - llvmlite.add_param(pool, func, param_ty, pname) - - # *args 变长参数:设置 IsVarArg=1,生成 ... 后缀 - if ags.vararg is not None: - func.IsVarArg = 1 - - # 参数添加完成,补全全局函数表的 TypeStr(供 vtable 在 func 被 reset 后使用) - HandlesExprCall.update_global_func_typestr(trans.Pool, fd.name, func) - - # 恢复原始声明模式 - trans._declare_only = saved_declare_only - return 0 - - -# ============================================================ -# 翻译函数定义 FunctionDef(name, args, body, ...) -# -# trans 单参模式:所有共享状态从 trans 获取 -# 函数局部作用域通过 enter_scope/exit_scope 管理 -# ============================================================ -def translate_function_def(trans: HT.Translator | t.CPtr, - node: ast.AST | t.CPtr) -> int: - """翻译函数定义,返回新增的变量数(通常为 0,函数定义不增加当前作用域变量)""" - fd: ast.FunctionDef | t.CPtr = (ast.FunctionDef | t.CPtr)(node) - if fd is None or fd.name is None: - return 0 - - pool: memhub.MemBuddy | t.CPtr = trans.Pool - mod: llvmlite.LLVMModule | t.CPtr = trans.Module - imported_modules: str = trans._imported_modules - from_imports: str = trans._from_imports - funcs_ptr: HandlesExprCall.FuncEntry | t.CPtr = trans._funcs - func_count: int = trans._func_count - - i32_ty: llvmlite.LLVMType | t.CPtr = llvmlite.Int32(pool) - - # 推断返回类型:优先使用返回类型注解 - ret_ty: llvmlite.LLVMType | t.CPtr = None - if fd.returns is not None: - ret_ty = HandlesType.resolve_annotation_type( - pool, fd.returns, imported_modules, from_imports, trans) - - # 如果返回类型注解纯装饰器标记(如 t.State,无实际类型),使用 void - # 注意:必须在 infer_return_type 之前检测,因为 infer_return_type 至少返回 i32 - if ret_ty is None and fd.returns is not None: - if HandlesType.has_decorator_marker(fd.returns, "State") != 0: - ret_ty = llvmlite.Void(pool) - - # 如果仍然为 None,扫描 return 语句推断(至少返回 i32) - if ret_ty is None: - param_types_str: str = HandlesType.build_param_types_str(pool, fd.args) - ret_ty = HandlesType.infer_return_type( - pool, fd.children, param_types_str) - # 检测是否为外部声明函数(t.CExtern 或 t.State) - # 语义:t.CExtern 忽略 body 体,仅生成 declare(由链接器解析符号) - # t.State = t.CExtern + t.CExport(既是声明又是导出) - # t.CExport 导出函数不加 SHA1 前缀 - # t.CExtern/t.State/t.CExport 都不加 SHA1 前缀,直接映射到 C 标准库函数名 - is_extern_decl: int = 0 - has_export: int = 0 - has_extern: int = 0 - has_state: int = 0 - if fd.returns is not None: - has_extern = HandlesType.has_decorator_marker(fd.returns, "CExtern") - has_state = HandlesType.has_decorator_marker(fd.returns, "State") - has_export = HandlesType.has_decorator_marker(fd.returns, "CExport") - # t.CExtern/t.State 忽略 body 体,仅声明(无论 body 是否为 pass) - if has_extern != 0 or has_state != 0: - is_extern_decl = 1 - - # SHA1 命名空间:t.CExtern/t.State/t.CExport 不加前缀,直接用裸名 - # (裸名映射到 C 标准库符号,带 sha1 前缀会导致 undefined reference) - # main 函数也不加前缀(程序入口点) - if has_extern != 0 or has_state != 0 or has_export != 0 or string.strcmp(fd.name, "main") == 0: - mangled_name: str = fd.name - else: - mangled_name: str = _mangle_func_name(trans, fd.name, 0) - - # 注册 CExport 函数到全局表(供跨模块调用查表) - # t.CExport 函数定义用裸名(@strlen),跨模块调用需查表确认用裸名而非 @{sha1}.func - if (has_export != 0 or has_state != 0) and trans.ModuleSha1 is not None: - HandlesExprCall.register_cexport_func(trans.ModuleSha1, fd.name) - - if is_extern_decl != 0: - # 外部声明函数:生成 declare(仅声明,不定义) - # 先检查是否已由 forward_declare_functions 创建,避免重复 declare - existing_extern: llvmlite.Function | t.CPtr = HandlesExprCall.find_func_in_module(mod, mangled_name) - if existing_extern is not None: - # 已存在前向声明,复用之,不再重复创建 - return 0 - - func: llvmlite.Function | t.CPtr = llvmlite.create_declare( - pool, mod, mangled_name, ret_ty) - if func is None: - return 0 - - # 注册到函数表 - max_funcs_extern: int = 256 - if HandlesExprCall.add_func_to_table(funcs_ptr, func_count, fd.name, func, max_funcs_extern, None, 0, 0, pool) == 0: - trans._func_count = func_count + 1 - - # 添加参数(支持类型注解) - args_node_extern: ast.Arguments | t.CPtr = fd.args - if args_node_extern is not None: - ags_e: ast.Arguments | t.CPtr = (ast.Arguments | t.CPtr)(args_node_extern) - if ags_e.args is not None: - alist_e: list[ast.AST | t.CPtr] | t.CPtr = ags_e.args - an_e: t.CSizeT = alist_e.__len__() - for ai_e in range(an_e): - arg_e: ast.Arg | t.CPtr = (ast.Arg | t.CPtr)(alist_e.get(ai_e)) - if arg_e is not None and arg_e.arg is not None: - # t.CVoid 表示空参:跳过,不添加到函数签名 - if arg_e.annotation is not None: - if HandlesType._is_t_attr(arg_e.annotation, "CVoid", imported_modules) != 0: - continue - param_ty_e: llvmlite.LLVMType | t.CPtr = i32_ty - if arg_e.annotation is not None: - resolved_e: llvmlite.LLVMType | t.CPtr = HandlesType.resolve_annotation_type( - pool, arg_e.annotation, imported_modules, from_imports, trans) - if resolved_e is not None: - # 裸类形参 → Ptr(struct)(对象即指针,与方法形参一致) - match resolved_e: - case llvmlite.LLVMType.Struct(_, _, _): - param_ty_e = llvmlite.Ptr(pool, resolved_e) - case _: - param_ty_e = resolved_e - pname_e: t.CChar | t.CPtr = pool.alloc(32) - if pname_e is not None: - viperlib.snprintf(pname_e, 32, "%%%s", arg_e.arg) - llvmlite.add_param(pool, func, param_ty_e, pname_e) - - # 提取 @c.Attribute 装饰器属性并设置到函数 - func_attrs_e: t.CChar | t.CPtr = extract_func_attrs(pool, fd.decorator_list, imported_modules) - if func_attrs_e is not None: - llvmlite.function_set_attrs(func, func_attrs_e) - - # 参数添加完成,补全全局函数表的 TypeStr - HandlesExprCall.update_global_func_typestr(pool, fd.name, func) - - return 0 - - # args_node 用于后续 alloca 创建,提前赋值 - args_node: ast.Arguments | t.CPtr = fd.args - - # 检查是否已有前向声明(由 forward_declare_functions 创建) - func: llvmlite.Function | t.CPtr = HandlesExprCall.find_func_in_module(mod, mangled_name) - if func is not None and llvmlite.function_is_declared(func) != 0: - # 复用前向声明:清除 IsDeclared 标记,转为 define - func.IsDeclared = 0 - # 装饰器属性设置(前向声明时未设置) - func_attrs_reuse: t.CChar | t.CPtr = extract_func_attrs(pool, fd.decorator_list, imported_modules) - if func_attrs_reuse is not None: - llvmlite.function_set_attrs(func, func_attrs_reuse) - else: - # 创建新的 LLVM 函数(使用 SHA1 混淆名) - func = llvmlite.create_function(pool, mod, mangled_name, ret_ty) - if func is None: - fb_cf: t.CChar | t.CPtr = VLogger.fmt_buf() - if fb_cf is not None: - viperlib.snprintf(fb_cf, 1024, "create_function %s failed", fd.name) - VLogger.error(fb_cf, "FUNC") - return 0 - - # 提取 @c.Attribute 装饰器属性并设置到函数 - func_attrs: t.CChar | t.CPtr = extract_func_attrs(pool, fd.decorator_list, imported_modules) - if func_attrs is not None: - llvmlite.function_set_attrs(func, func_attrs) - - # 提取默认参数信息 - tfd_defaults: t.CVoid | t.CPtr = None - tfd_default_count: int = 0 - tfd_param_count: int = 0 - if args_node is not None: - tfd_ags: ast.Arguments | t.CPtr = (ast.Arguments | t.CPtr)(args_node) - if tfd_ags.args is not None: - tfd_alist: list[ast.AST | t.CPtr] | t.CPtr = tfd_ags.args - tfd_param_count = tfd_alist.__len__() - if tfd_ags.defaults is not None: - tfd_dlist: list[ast.AST | t.CPtr] | t.CPtr = tfd_ags.defaults - tfd_defaults = tfd_dlist - tfd_default_count = tfd_dlist.__len__() - - # 注册到函数表 - max_funcs: int = 256 - if HandlesExprCall.add_func_to_table(funcs_ptr, func_count, fd.name, func, max_funcs, - tfd_defaults, tfd_default_count, tfd_param_count, - trans.Pool) == 0: - trans._func_count = func_count + 1 - - # 添加参数(支持类型注解) - if args_node is not None: - ags: ast.Arguments | t.CPtr = (ast.Arguments | t.CPtr)(args_node) - if ags.args is not None: - alist: list[ast.AST | t.CPtr] | t.CPtr = ags.args - an: t.CSizeT = alist.__len__() - for ai in range(an): - arg: ast.Arg | t.CPtr = (ast.Arg | t.CPtr)(alist.get(ai)) - if arg is not None and arg.arg is not None: - # t.CVoid 表示空参:跳过,不添加到函数签名 - if arg.annotation is not None: - if HandlesType._is_t_attr(arg.annotation, "CVoid", imported_modules) != 0: - continue - param_ty: llvmlite.LLVMType | t.CPtr = i32_ty - if arg.annotation is not None: - resolved: llvmlite.LLVMType | t.CPtr = HandlesType.resolve_annotation_type( - pool, arg.annotation, imported_modules, from_imports, trans) - if resolved is not None: - # 裸类形参 → Ptr(struct)(对象即指针,与方法形参一致) - match resolved: - case llvmlite.LLVMType.Struct(_, _, _): - param_ty = llvmlite.Ptr(pool, resolved) - case _: - param_ty = resolved - pname: t.CChar | t.CPtr = pool.alloc(32) - if pname is not None: - viperlib.snprintf(pname, 32, "%%%s", arg.arg) - llvmlite.add_param(pool, func, param_ty, pname) - - # *args 变长参数:设置 IsVarArg=1,生成 ... 后缀 - if ags.vararg is not None: - func.IsVarArg = 1 - - # 参数添加完成,补全全局函数表的 TypeStr - HandlesExprCall.update_global_func_typestr(trans.Pool, fd.name, func) - - # 创建 entry 块 - entry_blk: llvmlite.BasicBlock | t.CPtr = llvmlite.create_block(pool, func, "entry") - if entry_blk is None: - return 0 - - # 创建函数专属 builder - func_builder: llvmlite.IRBuilder | t.CPtr = llvmlite.new_builder(pool, func) - if func_builder is None: - return 0 - llvmlite.position_at_end(func_builder, entry_blk) - - # 进入函数作用域(嵌套符号表) - HandlesVar.enter_scope(trans.SymTab, SCOPE_FUNCTION) - - # PEP 695 泛型函数: def f[T](...) — 设置泛型上下文,类型参数映射到 "int" 兜底。 - # TPV 无泛型函数特化机制(类泛型走 _specialize_generic_class),泛型函数按普通 - # 函数编译;设置上下文使参数注解 T / 方法体中的 T(x) 转换可解析为 int。 - # (注意与类特化的 set_generic_context 一样是全局状态,需在退出作用域前清除。) - tp_names_fn: list[str] | t.CPtr = None - if fd.type_params is not None: - tp_names_fn = fd.type_params - tp_args_fn: list[str] | t.CPtr = list[str](pool, 8) - if tp_args_fn is not None: - tpn_fn: t.CSizeT = fd.type_params.__len__() - tpi_fn: t.CSizeT = 0 - for tpi_fn in range(tpn_fn): - tp_args_fn.append("int") - HandlesType.set_generic_context(tp_names_fn, tp_args_fn) - - # 为参数创建 alloca - if args_node is not None: - ags2: ast.Arguments | t.CPtr = (ast.Arguments | t.CPtr)(args_node) - if ags2.args is not None: - alist2: list[ast.AST | t.CPtr] | t.CPtr = ags2.args - an2: t.CSizeT = alist2.__len__() - for ai2 in range(an2): - arg2: ast.Arg | t.CPtr = (ast.Arg | t.CPtr)(alist2.get(ai2)) - if arg2 is not None and arg2.arg is not None: - # t.CVoid 表示空参:跳过,不创建 alloca - if arg2.annotation is not None: - if HandlesType._is_t_attr(arg2.annotation, "CVoid", imported_modules) != 0: - continue - param_ty2: llvmlite.LLVMType | t.CPtr = i32_ty - if arg2.annotation is not None: - resolved2: llvmlite.LLVMType | t.CPtr = HandlesType.resolve_annotation_type( - pool, arg2.annotation, imported_modules, from_imports, trans) - if resolved2 is not None: - # 与 add_param 保持一致:裸类形参 → Ptr(struct)(对象即指针) - match resolved2: - case llvmlite.LLVMType.Struct(_, _, _): - param_ty2 = llvmlite.Ptr(pool, resolved2) - case _: - param_ty2 = resolved2 - alloca: llvmlite.Value | t.CPtr = llvmlite.build_alloca(func_builder, param_ty2) - if alloca is not None: - HandlesVar.define_var(trans.SymTab, arg2.arg, alloca) - # 存储原始类型注解的类名(方法调用检测时,Ptr(i8) 回退到类名查找结构体) - if arg2.annotation is not None: - cls_nm: str = HandlesType.extract_class_name_from_annotation( - arg2.annotation, imported_modules) - if cls_nm is not None: - HandlesVar.set_var_annot_class_name( - trans.SymTab, arg2.arg, cls_nm) - pname2: t.CChar | t.CPtr = pool.alloc(32) - if pname2 is not None: - viperlib.snprintf(pname2, 32, "%%%s", arg2.arg) - param_val: llvmlite.Value | t.CPtr = llvmlite.SSAValue( - pool, param_ty2, pname2) - llvmlite.build_store(func_builder, param_val, alloca) - - # *args 变长参数:创建 va_list 缓冲区 + 调用 va_start + 注册到符号表 - # 生成 IR: - # %args_va = alloca [24 x i8], align 16 ; va_list 缓冲区(Win64 __va_list_tag) - # %args = bitcast [24 x i8]* %args_va to i8* - # call void @llvm.va_start(i8* %args) ; 初始化 va_list - # 用户函数体内可通过 args 名字读取 va_list 地址(i8*),或用 arg(type) 糖函数 - if ags2.vararg is not None: - vararg_node: ast.Arg | t.CPtr = (ast.Arg | t.CPtr)(ags2.vararg) - if vararg_node is not None and vararg_node.arg is not None: - vararg_name_str: str = vararg_node.arg - # va_list 缓冲区 24 字节(Win64 的 __va_list_tag = {i32,i32,i8*,i8*})+ 16 对齐 - # (对齐 TPC HandlesFunctions.py:1739-1741) - i8_ty_va: llvmlite.LLVMType | t.CPtr = llvmlite.Int8(pool) - i8_ptr_ty_va: llvmlite.LLVMType | t.CPtr = llvmlite.Ptr(pool, i8_ty_va) - va_buf_ty: llvmlite.LLVMType | t.CPtr = llvmlite.Array(pool, i8_ty_va, 24) - va_list_alloca: llvmlite.Value | t.CPtr = llvmlite.build_alloca_aligned( - func_builder, va_buf_ty, 16) - if va_list_alloca is not None: - # i8* 地址(指向 24 字节 va_list 缓冲区)——vararg 名的值语义 - va_list_addr: llvmlite.Value | t.CPtr = llvmlite.build_bitcast( - func_builder, va_list_alloca, i8_ptr_ty_va) - if va_list_addr is not None: - # 注册到符号表(translate_name_value 对 vararg 名特殊处理返回地址) - HandlesVar.define_var(trans.SymTab, vararg_name_str, va_list_alloca) - # 调用 @llvm.va_start(i8* %va_list_addr) - void_ty_va: llvmlite.LLVMType | t.CPtr = llvmlite.Void(pool) - llvmlite.build_call(func_builder, "llvm.va_start", - va_list_addr, 1, void_ty_va, 0) - # 保存到 trans 供 arg(type) 糖函数与 vararg 名翻译使用 - trans._va_list_ptr = va_list_addr - trans._vararg_name = vararg_name_str - - # 保存模块级作用域状态(仅非变量表相关) - old_func: llvmlite.Function | t.CPtr = trans._cur_func - old_builder: llvmlite.IRBuilder | t.CPtr = trans._cur_builder - old_global_count: int = trans._global_name_count - old_nonlocal_count: int = trans._nonlocal_name_count - old_env_count: int = trans._closure_env_count - old_va_list_ptr: llvmlite.Value | t.CPtr = trans._va_list_ptr - old_vararg_name: str = trans._vararg_name - - trans._cur_func = func - trans._cur_builder = func_builder - # 清空 global/nonlocal 名称集合(新函数作用域) - HT.clear_scope_names(trans) - - # 预扫描函数体: - # 1. 先预扫描 Global/Nonlocal 声明(Python 语义:global/nonlocal - # 对整个函数作用域生效,与声明位置无关,故须在任何赋值前注册) - # 2. 再预扫描 AnnAssign 为局部变量提前创建 alloca - body: list[ast.AST | t.CPtr] | t.CPtr = fd.children - if body is not None: - bn: t.CSizeT = body.__len__() - for bi in range(bn): - stmt: ast.AST | t.CPtr = body.get(bi) - if stmt is not None: - HandlesBody.pre_scan_scope_decls(trans, stmt) - for bi in range(bn): - stmt: ast.AST | t.CPtr = body.get(bi) - if stmt is not None: - HandlesBody.pre_scan_allocas(trans, stmt) - - # 翻译函数体 - if body is not None: - bn2: t.CSizeT = body.__len__() - for bi2 in range(bn2): - stmt2: ast.AST | t.CPtr = body.get(bi2) - if stmt2 is not None: - HandlesBody.translate_stmt(trans, stmt2) - - # 如果函数体最后一条语句不是 Return,添加隐式 ret - last_is_return: int = 0 - if body is not None: - bn3: t.CSizeT = body.__len__() - if bn3 > 0: - last_stmt: ast.AST | t.CPtr = body.get(bn3 - 1) - if last_stmt is not None and last_stmt.kind() == ast.ASTKind.Return: - last_is_return = 1 - if last_is_return == 0: - if llvmlite.builder_cur_block_is_terminated(func_builder) == 0: - # 根据返回类型生成正确的零值返回 - # 必须覆盖浮点返回类型:double/float 函数生成 ConstFloat(0.0), - # 否则默认 ret i32 0 类型不匹配(llc: value doesn't match function result type) - _is_void: int = 0 - _is_ptr: int = 0 - _is_float: int = 0 - if ret_ty is not None: - match ret_ty: - case llvmlite.LLVMType.Void(): - _is_void = 1 - case llvmlite.LLVMType.Ptr(_pe): - _is_ptr = 1 - case llvmlite.LLVMType.Float(_fb): - _is_float = 1 - if _is_void != 0: - llvmlite.build_ret_void(func_builder) - elif _is_ptr != 0: - _null_val: llvmlite.Value | t.CPtr = llvmlite.ConstNull(pool, ret_ty, "null") - llvmlite.build_ret(func_builder, _null_val) - elif _is_float != 0: - _zero_f: llvmlite.Value | t.CPtr = llvmlite.ConstFloat(pool, ret_ty, 0.0) - llvmlite.build_ret(func_builder, _zero_f) - else: - _zero_val: llvmlite.Value | t.CPtr = llvmlite.const_int32(pool, 0) - llvmlite.build_ret(func_builder, _zero_val) - - # 恢复模块级作用域(退出函数作用域) - if tp_names_fn is not None: - HandlesType.clear_generic_context() - HandlesVar.exit_scope(trans.SymTab) - trans._cur_func = old_func - trans._cur_builder = old_builder - trans._global_name_count = old_global_count - trans._nonlocal_name_count = old_nonlocal_count - trans._closure_env_count = old_env_count - trans._va_list_ptr = old_va_list_ptr - trans._vararg_name = old_vararg_name - - return 0 - - -# ============================================================ -# translate_nested_function_def - 嵌套函数提升 + 闭包创建 -# -# 将嵌套函数提升为顶层函数 @__closure_{name}(i8* %env) -> i32, -# 在父函数中创建闭包对象 {i8* fn_ptr, i8* env_ptr} 并存储到 -# 以函数名命名的局部变量中。 -# -# 闭包结构: {i8* fn_ptr, i8* env_ptr} (16 字节, malloc 分配) -# Env 结构: {i8* ptr0, i8* ptr1, ...} (每个 nonlocal 变量 8 字节,指向父函数 alloca) -# ============================================================ -def translate_nested_function_def(trans: HT.Translator | t.CPtr, - node: ast.AST | t.CPtr) -> int: - """翻译嵌套函数定义:提升为顶层函数 + 创建闭包""" - fd: ast.FunctionDef | t.CPtr = (ast.FunctionDef | t.CPtr)(node) - if fd is None or fd.name is None: - return 0 - - pool: memhub.MemBuddy | t.CPtr = trans.Pool - mod: llvmlite.LLVMModule | t.CPtr = trans.Module - func_name: str = fd.name - - i32_ty: llvmlite.LLVMType | t.CPtr = llvmlite.Int32(pool) - i8_ty: llvmlite.LLVMType | t.CPtr = llvmlite.Int8(pool) - i8_ptr_ty: llvmlite.LLVMType | t.CPtr = llvmlite.Ptr(pool, i8_ty) - - # 1. 构建提升后的函数名: __closure_{name}(加 SHA1 前缀避免跨模块冲突) - promoted_name: t.CChar | t.CPtr = pool.alloc(64) - if promoted_name is not None: - viperlib.snprintf(promoted_name, 64, "__closure_%s", func_name) - mangled_promoted: str = _mangle_name(trans, promoted_name) - - # 2. 创建提升后的函数: define i32 @__closure_{name}(i8* %env) - func: llvmlite.Function | t.CPtr = llvmlite.create_function( - pool, mod, mangled_promoted, i32_ty) - if func is None: - return 0 - llvmlite.add_param(pool, func, i8_ptr_ty, "%env") - - # 3. 创建 entry 块 + builder - entry_blk: llvmlite.BasicBlock | t.CPtr = llvmlite.create_block(pool, func, "entry") - if entry_blk is None: - return 0 - func_builder: llvmlite.IRBuilder | t.CPtr = llvmlite.new_builder(pool, func) - if func_builder is None: - return 0 - llvmlite.position_at_end(func_builder, entry_blk) - - # 4. 进入嵌套函数作用域(嵌套符号表) - HandlesVar.enter_scope(trans.SymTab, SCOPE_FUNCTION) - - # 5. 创建 _env_ptr alloca 并存储 %env 参数 - env_alloca: llvmlite.Value | t.CPtr = llvmlite.build_alloca(func_builder, i8_ptr_ty) - if env_alloca is not None: - HandlesVar.define_var(trans.SymTab, "_env_ptr", env_alloca) - env_param_val: llvmlite.Value | t.CPtr = llvmlite.SSAValue(pool, i8_ptr_ty, "%env") - llvmlite.build_store(func_builder, env_param_val, env_alloca) - - # 6. 保存父函数作用域状态(仅非变量表相关) - old_func: llvmlite.Function | t.CPtr = trans._cur_func - old_builder: llvmlite.IRBuilder | t.CPtr = trans._cur_builder - old_func_name: str = trans._cur_func_name - old_global_count: int = trans._global_name_count - old_nonlocal_count: int = trans._nonlocal_name_count - old_env_count: int = trans._closure_env_count - - # 7. 切换到嵌套函数作用域 + 清空 scope names - trans._cur_func = func - trans._cur_builder = func_builder - trans._cur_func_name = func_name - HT.clear_scope_names(trans) - - # 8. 预扫描函数体: - # a. 先预扫描 Global/Nonlocal 声明(Python 语义:对整个函数作用域生效) - # b. 再预扫描 AnnAssign 为局部变量提前创建 alloca - body: list[ast.AST | t.CPtr] | t.CPtr = fd.children - if body is not None: - bn: t.CSizeT = body.__len__() - for bi in range(bn): - stmt: ast.AST | t.CPtr = body.get(bi) - if stmt is not None: - HandlesBody.pre_scan_scope_decls(trans, stmt) - for bi in range(bn): - stmt: ast.AST | t.CPtr = body.get(bi) - if stmt is not None: - HandlesBody.pre_scan_allocas(trans, stmt) - - # 9. 翻译函数体(Nonlocal 语句会填充 _nonlocal_names) - if body is not None: - bn2: t.CSizeT = body.__len__() - for bi2 in range(bn2): - stmt2: ast.AST | t.CPtr = body.get(bi2) - if stmt2 is not None: - HandlesBody.translate_stmt(trans, stmt2) - - # 10. 隐式 ret - last_is_return: int = 0 - if body is not None: - bn3: t.CSizeT = body.__len__() - if bn3 > 0: - last_stmt: ast.AST | t.CPtr = body.get(bn3 - 1) - if last_stmt is not None and last_stmt.kind() == ast.ASTKind.Return: - last_is_return = 1 - if last_is_return == 0: - zero_val: llvmlite.Value | t.CPtr = llvmlite.const_int32(pool, 0) - llvmlite.build_ret(func_builder, zero_val) - - # 11. 保存嵌套函数的 nonlocal 信息 - nested_nonlocal_count: int = trans._nonlocal_name_count - - # 12. 退出嵌套函数作用域,回到父函数作用域(保留 _nonlocal_names 用于 env 创建) - HandlesVar.exit_scope(trans.SymTab) - trans._cur_func = old_func - trans._cur_builder = old_builder - # NOTE: _nonlocal_names 和 _nonlocal_name_count 仍为嵌套函数的值 - - # 13. 在父函数中创建闭包对象 - parent_builder: llvmlite.IRBuilder | t.CPtr = old_builder - if parent_builder is None: - # 无 builder(模块级嵌套函数?)→ 无法创建闭包,仅恢复状态 - trans._cur_func_name = old_func_name - trans._global_name_count = old_global_count - trans._nonlocal_name_count = old_nonlocal_count - trans._closure_env_count = old_env_count - return 0 - - # 13a. 创建 env: malloc(8 * nested_nonlocal_count) — env 存储指针数组 - # 每个 nonlocal 变量占 8 字节(i8*),指向父函数的 alloca(共享存储) - env_ptr: llvmlite.Value | t.CPtr = None - if nested_nonlocal_count > 0: - env_size: t.CInt64T = nested_nonlocal_count * 8 - env_size_val: llvmlite.Value | t.CPtr = llvmlite.const_int64(pool, env_size) - if env_size_val is not None: - env_size_val.Next = None - env_ptr = llvmlite.build_call( - parent_builder, "malloc", env_size_val, 1, i8_ptr_ty, 0) - - # 为每个 nonlocal 变量存储 alloca 指针到 env(共享存储,修改互相可见) - if env_ptr is not None: - i8_ptr_ptr_ty: llvmlite.LLVMType | t.CPtr = llvmlite.Ptr(pool, i8_ptr_ty) - for ni in range(nested_nonlocal_count): - # 从 _nonlocal_names 缓冲区读取名称 - name_addr: t.CUInt64T = t.CUInt64T(trans._nonlocal_names) + ni * 8 - nl_slot: str | t.CPtr = (t.CVoid | t.CPtr)(name_addr) - nl_name: str = nl_slot[0] - if nl_name is not None: - # 在父函数作用域中查找(Current 已回到父作用域) - var_alloca: llvmlite.Value | t.CPtr = HandlesVar.lookup_var( - trans.SymTab, nl_name) - if var_alloca is not None: - # bitcast alloca 指针为 i8*(擦除类型信息) - alloca_as_i8: llvmlite.Value | t.CPtr = llvmlite.build_bitcast( - parent_builder, var_alloca, i8_ptr_ty) - if alloca_as_i8 is not None: - # GEP to env[ni*8] - offset_val: llvmlite.Value | t.CPtr = llvmlite.const_int32(pool, ni * 8) - slot: llvmlite.Value | t.CPtr = llvmlite.build_gep( - parent_builder, i8_ty, env_ptr, offset_val) - if slot is not None: - # bitcast to i8** and store alloca pointer - slot_typed: llvmlite.Value | t.CPtr = llvmlite.build_bitcast( - parent_builder, slot, i8_ptr_ptr_ty) - if slot_typed is not None: - llvmlite.build_store(parent_builder, alloca_as_i8, slot_typed) - - # 13b. 创建闭包结构: malloc(16) - closure_size_val: llvmlite.Value | t.CPtr = llvmlite.const_int64(pool, 16) - if closure_size_val is not None: - closure_size_val.Next = None - closure_ptr: llvmlite.Value | t.CPtr = llvmlite.build_call( - parent_builder, "malloc", closure_size_val, 1, i8_ptr_ty, 0) - if closure_ptr is None: - # malloc 失败,恢复状态 - trans._cur_func_name = old_func_name - trans._global_name_count = old_global_count - trans._nonlocal_name_count = old_nonlocal_count - trans._closure_env_count = old_env_count - return 0 - - # 13c. 存储 fn_ptr 到 offset 0 - # 创建函数指针类型 i32(i8*)* - fn_param_node: llvmlite.ParamNode | t.CPtr = llvmlite.new_param_node(pool, i8_ptr_ty) - fn_func_ty: llvmlite.LLVMType | t.CPtr = llvmlite.Func(pool, i32_ty, fn_param_node, 1) - fn_func_ptr_ty: llvmlite.LLVMType | t.CPtr = llvmlite.Ptr(pool, fn_func_ty) - - # 创建函数引用 Value(类型为 i32(i8*)*,使用 SHA1 混淆名) - fn_ptr_name: t.CChar | t.CPtr = pool.alloc(64) - if fn_ptr_name is not None: - # SHA1 前缀名含 '.' 需要加引号(如 @"sha1.__closure_func") - if string.strchr(mangled_promoted, '.') is not None: - viperlib.snprintf(fn_ptr_name, 64, "@\"%s\"", mangled_promoted) - else: - viperlib.snprintf(fn_ptr_name, 64, "@%s", mangled_promoted) - fn_ptr_val: llvmlite.Value | t.CPtr = llvmlite.SSAValue(pool, fn_func_ptr_ty, fn_ptr_name) - - # bitcast 函数指针到 i8*(闭包存储 i8* 类型) - fn_as_i8ptr: llvmlite.Value | t.CPtr = llvmlite.build_bitcast( - parent_builder, fn_ptr_val, i8_ptr_ty) - fn_slot: llvmlite.Value | t.CPtr = llvmlite.build_bitcast( - parent_builder, closure_ptr, llvmlite.Ptr(pool, i8_ptr_ty)) - if fn_slot is not None and fn_as_i8ptr is not None: - llvmlite.build_store(parent_builder, fn_as_i8ptr, fn_slot) - - # 13d. 存储 env_ptr 到 offset 8 - eight_val: llvmlite.Value | t.CPtr = llvmlite.const_int32(pool, 8) - env_slot_addr: llvmlite.Value | t.CPtr = llvmlite.build_gep( - parent_builder, i8_ty, closure_ptr, eight_val) - if env_slot_addr is not None: - env_slot: llvmlite.Value | t.CPtr = llvmlite.build_bitcast( - parent_builder, env_slot_addr, llvmlite.Ptr(pool, i8_ptr_ty)) - if env_slot is not None: - if env_ptr is not None: - llvmlite.build_store(parent_builder, env_ptr, env_slot) - else: - # 无 nonlocal 变量,存储 null - null_val: llvmlite.Value | t.CPtr = llvmlite.SSAValue(pool, i8_ptr_ty, "null") - llvmlite.build_store(parent_builder, null_val, env_slot) - - # 13e. 将闭包指针存储到父函数的局部变量 {func_name} - closure_alloca: llvmlite.Value | t.CPtr = llvmlite.build_alloca(parent_builder, i8_ptr_ty) - if closure_alloca is not None: - llvmlite.build_store(parent_builder, closure_ptr, closure_alloca) - HandlesVar.define_var(trans.SymTab, func_name, closure_alloca) - # 注册闭包变量名(供调用时区分闭包 vs 函数指针变量, - # 两者 alloca 类型同为 i8**,_is_func_ptr_alloca 无法区分) - HandlesExprCall.register_closure_name(func_name) - - # 14. 恢复 scope names - trans._cur_func_name = old_func_name - trans._global_name_count = old_global_count - trans._nonlocal_name_count = old_nonlocal_count - trans._closure_env_count = old_env_count - - return 1 - - -# ============================================================ -# 创建 LLVM 函数(简单版本,仅声明) -# ============================================================ -def create_function(pool: memhub.MemBuddy | t.CPtr, - mod: llvmlite.LLVMModule | t.CPtr, - name: str, - args_node: ast.AST | t.CPtr, - ret_ty: llvmlite.LLVMType | t.CPtr) -> llvmlite.Function | t.CPtr: - """创建 LLVM 函数并添加参数""" - if name is None or mod is None: - return None - - func: llvmlite.Function | t.CPtr = llvmlite.create_function(pool, mod, name, ret_ty) - if func is None: - return None - - if args_node is not None: - ags: ast.Arguments | t.CPtr = (ast.Arguments | t.CPtr)(args_node) - if ags.args is not None: - alist: list[ast.AST | t.CPtr] | t.CPtr = ags.args - an: t.CSizeT = alist.__len__() - i32_ty: llvmlite.LLVMType | t.CPtr = llvmlite.Int32(pool) - for ai in range(an): - arg: ast.Arg | t.CPtr = (ast.Arg | t.CPtr)(alist.get(ai)) - if arg is not None and arg.arg is not None: - # t.CVoid 表示空参:跳过 - if arg.annotation is not None: - if arg.annotation.kind() == ast.ASTKind.Attribute: - at_cf: ast.Attribute | t.CPtr = (ast.Attribute | t.CPtr)(arg.annotation) - if at_cf.attr is not None and string.strcmp(at_cf.attr, "CVoid") == 0: - continue - param_ty: llvmlite.LLVMType | t.CPtr = i32_ty - if arg.annotation is not None: - resolved: llvmlite.LLVMType | t.CPtr = HandlesType.resolve_annotation_type( - pool, arg.annotation, None, None, None) - if resolved is not None: - param_ty = resolved - pname: t.CChar | t.CPtr = pool.alloc(32) - if pname is not None: - viperlib.snprintf(pname, 32, "%%%s", arg.arg) - llvmlite.add_param(pool, func, param_ty, pname) - - return func +import t, c +from stdint import * +import ast +import llvmlite +import memhub +import string +import viperlib +import stdio +import stdlib +import lib.core.VLogger as VLogger +import lib.core.Handles.HandlesTranslator as HT +import lib.core.Handles.HandlesVar as HandlesVar +import lib.core.Handles.HandlesExprCall as HandlesExprCall +import lib.core.Handles.HandlesType as HandlesType +import lib.core.Handles.HandlesExpr as HandlesExpr +import lib.core.Handles.HandlesBody as HandlesBody +import lib.core.Handles.HandlesNonlocal as HandlesNonlocal +import lib.core.Handles.HandlesImports as HandlesImports + + +# ============================================================ +# HandlesFunctions - 函数定义处理(P5-1 对象化后的委托层) +# +# P5-1 对象化重构(wiki/14-oo-refactor.md): +# 全部函数已迁移为 lib.core.Gen.FuncGenMixin 的方法,本模块保留 +# 同名模块级函数作为"一行委托":延迟 import Gen 取全局单例 +# (BuildPipeline/main 创建后 set_global_gen 注册),再调用 gen +# 的对应方法。签名与旧函数完全一致,调用方零改动。 +# ============================================================ + + +# ============================================================ +# 全局 gen 单例(模块级镜像) +# +# 由 BuildPipeline/main 在 gen 创建后调用 set_global_gen 注入。 +# 委托函数用本地 _g_gen(cast 成 Generator 类型),避免函数体 +# import 包模块(TPC 不注册包短名)与 Generator 类/模块名歧义。 +# ============================================================ +_g_gen: t.CVoid | t.CPtr = None + + +def set_global_gen(gen: t.CVoid | t.CPtr) -> None: + """注入全局 gen 单例(BuildPipeline/main 调用)""" + global _g_gen + _g_gen = gen + + +# 作用域类型常量(本地副本,避免旧编译器跨模块 CDefine 查找 bug) +SCOPE_FUNCTION: t.CDefine = 1 + + +# ============================================================ +# 委托函数:延迟 import Gen 取全局单例 → 调 gen 方法 +# (gen 未注册时正常流程不会发生;有返回值函数返回默认值) +# ============================================================ + + +def extract_func_attrs(pool: memhub.MemBuddy | t.CPtr, + decorator_list: list[ast.AST | t.CPtr] | t.CPtr, + imported_modules: str) -> t.CChar | t.CPtr: + """从 decorator_list 提取 c.Attribute 属性,返回 LLVM IR 属性字符串(委托到 gen.extract_func_attrs)""" + import lib.core.Gen.Generator as Generator + g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(_g_gen, t.CPtr)) + if g is not None: + return g.extract_func_attrs(pool, decorator_list, imported_modules) + return None + + +def _get_attr_name_from_node(node: ast.AST | t.CPtr) -> str: + """从 AST 节点提取属性名(委托到 gen._get_attr_name_from_node)""" + import lib.core.Gen.Generator as Generator + g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(_g_gen, t.CPtr)) + if g is not None: + return g._get_attr_name_from_node(node) + return None + + +def _append_llvm_attr(attrs_buf: t.CChar | t.CPtr, attr_name: str) -> int: + """将属性名映射到 LLVM 属性名并追加到缓冲区(委托到 gen._append_llvm_attr)""" + import lib.core.Gen.Generator as Generator + g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(_g_gen, t.CPtr)) + if g is not None: + return g._append_llvm_attr(attrs_buf, attr_name) + return 0 + + +def _append_str(buf: t.CChar | t.CPtr, s: str) -> None: + """将字符串追加到 buf 末尾(用 strlen+strcpy 模拟 strcat)(委托到 gen._append_str)""" + import lib.core.Gen.Generator as Generator + g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(_g_gen, t.CPtr)) + if g is not None: + g._append_str(buf, s) + + +def _mangle_name(trans: HT.Translator | t.CPtr, name: str) -> str: + """为任意名称添加 SHA1 前缀(不做 main/export 检查)(委托到 gen._mangle_name)""" + import lib.core.Gen.Generator as Generator + g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(_g_gen, t.CPtr)) + if g is not None: + return g._mangle_name(trans, name) + return None + + +def _mangle_name_with_sha1(sha1: str, name: str) -> str: + """用指定 SHA1 为名称添加前缀(不做 main/export 检查)(委托到 gen._mangle_name_with_sha1)""" + import lib.core.Gen.Generator as Generator + g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(_g_gen, t.CPtr)) + if g is not None: + return g._mangle_name_with_sha1(sha1, name) + return None + + +def _mangle_func_name(trans: HT.Translator | t.CPtr, name: str, + has_export: int) -> str: + """为函数名添加 SHA1 前缀(检查 main/export)(委托到 gen._mangle_func_name)""" + import lib.core.Gen.Generator as Generator + g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(_g_gen, t.CPtr)) + if g is not None: + return g._mangle_func_name(trans, name, has_export) + return None + + +def forward_declare_functions(trans: HT.Translator | t.CPtr, + tree: ast.AST | t.CPtr) -> int: + """预扫描所有顶层 FunctionDef,创建前向声明(委托到 gen.forward_declare_functions)""" + import lib.core.Gen.Generator as Generator + g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(_g_gen, t.CPtr)) + if g is not None: + return g.forward_declare_functions(trans, tree) + return 0 + + +def translate_function_def(trans: HT.Translator | t.CPtr, + node: ast.AST | t.CPtr) -> int: + """翻译函数定义,返回新增的变量数(通常为 0,函数定义不增加当前作用域变量)(委托到 gen.translate_function_def)""" + import lib.core.Gen.Generator as Generator + g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(_g_gen, t.CPtr)) + if g is not None: + return g.translate_function_def(trans, node) + return 0 + + +def translate_nested_function_def(trans: HT.Translator | t.CPtr, + node: ast.AST | t.CPtr) -> int: + """翻译嵌套函数定义:提升为顶层函数 + 创建闭包(委托到 gen.translate_nested_function_def)""" + import lib.core.Gen.Generator as Generator + g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(_g_gen, t.CPtr)) + if g is not None: + return g.translate_nested_function_def(trans, node) + return 0 + + +def create_function(pool: memhub.MemBuddy | t.CPtr, + mod: llvmlite.LLVMModule | t.CPtr, + name: str, + args_node: ast.AST | t.CPtr, + ret_ty: llvmlite.LLVMType | t.CPtr) -> llvmlite.Function | t.CPtr: + """创建 LLVM 函数并添加参数(委托到 gen.create_function)""" + import lib.core.Gen.Generator as Generator + g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(_g_gen, t.CPtr)) + if g is not None: + return g.create_function(pool, mod, name, args_node, ret_ty) + return None diff --git a/App/lib/core/Handles/HandlesMatch.vp b/App/lib/core/Handles/HandlesMatch.vp index edaf517..60ee318 100644 --- a/App/lib/core/Handles/HandlesMatch.vp +++ b/App/lib/core/Handles/HandlesMatch.vp @@ -172,20 +172,14 @@ class MatchHandle(HandlesBase.Mixin): # ============================================================ # _find_renum_class_for_variant - 从变体名反查 REnum 类名 + # + # P5-2 后 REnum 变体表迁入 gen 字段(RenumClassNames/RenumClassCount), + # 模块级 _renum_class_* 已失效,统一委托到 gen._lookup_renum_variant。 # ============================================================ def _find_renum_class_for_variant(self, variant_name: str) -> str: if variant_name is None: return None - i: int = 0 - while i < HandlesClassDef._renum_class_count: - cls_nm: str = HandlesClassDef._renum_class_names[i] - if cls_nm is not None: - tag: int = HandlesClassDef._lookup_renum_variant_in_class( - cls_nm, variant_name) - if tag >= 0: - return cls_nm - i = i + 1 - return None + return HandlesClassDef._lookup_renum_variant(variant_name) # ============================================================ # _has_no_break - 检测 case body 是否含 c.NoBreak() 调用 diff --git a/App/main.vp b/App/main.vp index 5918184..faaa249 100644 --- a/App/main.vp +++ b/App/main.vp @@ -18,6 +18,8 @@ import lib.core.Handles.HandlesStruct as HandlesStruct import lib.core.Handles.HandlesExpr as HandlesExpr import lib.core.Handles.HandlesExprOps as HandlesExprOps import lib.core.Handles.HandlesExprCall as HandlesExprCall +import lib.core.Handles.HandlesFunctions as HandlesFunctions +import lib.core.Handles.HandlesClassDef as HandlesClassDef import lib.core.Handles.HandlesType as HandlesType import lib.core.BuildPipeline as BuildPipeline import lib.core.IncludesScanner as IncludesScanner @@ -89,13 +91,14 @@ def main() -> int: gen.__before_init__() gen.__init__(mb) GenGenerator.set_global_gen(gen) - # P2/P3/P4: 注入 HandlesType/HandlesStruct/HandlesExpr/HandlesExprOps/HandlesExprCall - # 模块级单例(Phase1 阶段即调用其状态函数) + # P2-P5: 注入各 Handles 模块级单例(Phase1 阶段即调用其状态函数) HandlesType.set_global_gen(gen) HandlesStruct.set_global_gen(gen) HandlesExpr.set_global_gen(gen) HandlesExprOps.set_global_gen(gen) HandlesExprCall.set_global_gen(gen) + HandlesFunctions.set_global_gen(gen) + HandlesClassDef.set_global_gen(gen) # 初始化 VLogger 并打印启动日志 log: VLogger.Logger | t.CPtr = VLogger.get_logger()