From 65cf71ff7eb9caac09c69771dc5cdfdbbfe954ba Mon Sep 17 00:00:00 2001 From: TermiNexus Date: Mon, 17 Aug 2026 07:17:03 +0800 Subject: [PATCH] =?UTF-8?q?refactor(gen):=20FuncGenMixin=20=E6=8B=86=20Bas?= =?UTF-8?q?e/Def=EF=BC=882683=E2=86=921178=20=E8=A1=8C=EF=BC=89=EF=BC=8C?= =?UTF-8?q?=E8=A1=A5=205=20=E4=B8=AA=E8=B7=A8=20Mixin=20=E5=A7=94=E6=89=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- App/lib/core/Gen/FuncGenBase.vp | 333 +++++ App/lib/core/Gen/FuncGenDef.vp | 1236 ++++++++++++++++++ App/lib/core/Gen/FuncGenMixin.vp | 1515 +---------------------- App/lib/core/Gen/Generator.vp | 3 + App/lib/core/Handles/HandlesExprCall.vp | 58 + 5 files changed, 1635 insertions(+), 1510 deletions(-) create mode 100644 App/lib/core/Gen/FuncGenBase.vp create mode 100644 App/lib/core/Gen/FuncGenDef.vp diff --git a/App/lib/core/Gen/FuncGenBase.vp b/App/lib/core/Gen/FuncGenBase.vp new file mode 100644 index 0000000..8b2e4a6 --- /dev/null +++ b/App/lib/core/Gen/FuncGenBase.vp @@ -0,0 +1,333 @@ +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.HandlesExpr as HandlesExpr +import lib.core.Handles.HandlesExprCall as HandlesExprCall +import lib.core.Handles.HandlesNonlocal as HandlesNonlocal +import lib.core.Handles.HandlesType as HandlesType +import lib.core.Handles.HandlesBody as HandlesBody +import lib.core.Handles.HandlesImports as HandlesImports +import lib.core.Handles.HandlesClassDef as HandlesClassDef + + +# ============================================================ +# FuncGenBase - FuncGenMixin 拆分(阶段 D):函数属性 / 命名 / mangle / create_function 基础工具 +# +# 继承 CallGenBase(1 级,TPV self 调用仅支持 1 级父类)。 +# 跨 Mixin 调用统一走 HandlesExprCall 委托(经 _g_gen)。 +# @t.NoVTable:静态绑定。 +# ============================================================ +@t.NoVTable +class FuncGenBase(CallGenBase.CallGenBase): + """函数属性 / 命名 / mangle / create_function 基础工具""" + + # ============================================================ + # 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) -> str: + """从 decorator_list 提取 c.Attribute 属性,返回 LLVM IR 属性字符串""" + if decorator_list is None: + return None + dn: t.CSizeT = len(decorator_list) + if dn == 0: + return None + + attrs_buf: str = 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 = len(args_list) + 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: str, 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: str, s: str, + max_len: t.CSizeT = 256) -> None: + """将字符串追加到 buf 末尾(有界,防 strcpy 越界写穿定长缓冲)""" + if buf is None or s is None: + return + cur_len: t.CSizeT = string.strlen(buf) + s_len: t.CSizeT = string.strlen(s) + if cur_len + s_len + 1 > max_len: + return # 无剩余容量:丢弃本次追加,避免越界写 + 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) + # ============================================================ + # _body_has_raise - 函数体是否含 raise(非 StopIteration) + # + # 对齐 TPC HandlesFunctions.py L216-243 _body_contains_raise:函数签名 + # 追加 __eh_msg_out__/__eh_code_out__ 输出参数的条件。v1 只扫函数体 + # 顶层 raise(嵌套 if/for/try 内的 raise 未覆盖,后续扩展)。 + # ============================================================ + def _body_has_raise(self, fd: ast.FunctionDef | t.CPtr) -> int: + """函数体顶层是否含 raise(非 StopIteration),1=是 / 0=否""" + if fd is None or fd.children is None: + return 0 + body_f: list[ast.AST | t.CPtr] | t.CPtr = fd.children + bn_f: t.CSizeT = len(body_f) + for bi_f in range(bn_f): + stmt_f: ast.AST | t.CPtr = body_f.get(bi_f) + if stmt_f is None: + continue + if stmt_f.kind() != ast.ASTKind.Raise: + continue + rn_f: ast.Raise | t.CPtr = (ast.Raise | t.CPtr)(stmt_f) + if rn_f is None or rn_f.exc is None: + continue + ek_f: int = rn_f.exc.kind() + is_stop_f: int = 0 + if ek_f == ast.ASTKind.Name: + enm_f: ast.Name | t.CPtr = (ast.Name | t.CPtr)(rn_f.exc) + if enm_f.id is not None and string.strcmp(enm_f.id, "StopIteration") == 0: + is_stop_f = 1 + elif ek_f == ast.ASTKind.Call: + ecl_f: ast.Call | t.CPtr = (ast.Call | t.CPtr)(rn_f.exc) + if ecl_f.func is not None and ecl_f.func.kind() == ast.ASTKind.Name: + ecn_f: ast.Name | t.CPtr = (ast.Name | t.CPtr)(ecl_f.func) + if ecn_f.id is not None and string.strcmp(ecn_f.id, "StopIteration") == 0: + is_stop_f = 1 + if is_stop_f == 0: + return 1 + return 0 + # ============================================================ + # 创建 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 = len(alist) + 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: str = 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 \ No newline at end of file diff --git a/App/lib/core/Gen/FuncGenDef.vp b/App/lib/core/Gen/FuncGenDef.vp new file mode 100644 index 0000000..31aaa85 --- /dev/null +++ b/App/lib/core/Gen/FuncGenDef.vp @@ -0,0 +1,1236 @@ +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.HandlesExpr as HandlesExpr +import lib.core.Handles.HandlesExprCall as HandlesExprCall +import lib.core.Handles.HandlesNonlocal as HandlesNonlocal +import lib.core.Handles.HandlesType as HandlesType +import lib.core.Handles.HandlesBody as HandlesBody +import lib.core.Handles.HandlesImports as HandlesImports +import lib.core.Handles.HandlesClassDef as HandlesClassDef + + +# ============================================================ +# FuncGenDef - FuncGenMixin 拆分(阶段 D):函数声明 / translate_function_def / decorator wrapper +# +# 继承 CallGenBase(1 级,TPV self 调用仅支持 1 级父类)。 +# 跨 Mixin 调用统一走 HandlesExprCall 委托(经 _g_gen)。 +# @t.NoVTable:静态绑定。 +# ============================================================ +@t.NoVTable +class FuncGenDef(CallGenBase.CallGenBase): + """函数声明 / translate_function_def / decorator wrapper""" + + # ============================================================ + # 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 = len(ch) + + 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") + # 装饰器形式存储类标记(@t.CExport/@t.CExtern/@t.State/@t.CStatic) + # 对齐 TPC HandlesFunctions._extract_decorator_storage_flags; + # CExport/CExtern/State 影响函数名(导出裸名),CStatic 仅标记。 + # 注意: 用 HandlesClassDef._has_decorator 委托而非 self._has_decorator + # (Mixin 是 @t.NoVTable 静态绑定,跨 Mixin 方法经 MRO 调用会生成 + # 不存在的 FuncGenMixin._has_decorator → 链接 undefined symbol) + if fd.decorator_list is not None: + if has_extern == 0 and HandlesClassDef._has_decorator(fd.decorator_list, "CExtern") == 1: + has_extern = 1 + if has_state == 0 and HandlesClassDef._has_decorator(fd.decorator_list, "State") == 1: + has_state = 1 + if has_export == 0 and HandlesClassDef._has_decorator(fd.decorator_list, "CExport") == 1: + has_export = 1 + 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 = HandlesExprCall._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 = len(fd_alist) + 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 = len(fd_dlist) + + # 注册到函数表(用裸名 fd.name,不是 mangled_name) + max_funcs: int = 1024 + 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 = len(alist) + 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)(对象即指针,与方法形参一致) + # CArray 形参 → 元素指针 ty*(C 数组衰减,与 add_param 一致) + match resolved: + case llvmlite.LLVMType.Struct(_, _, _): + param_ty = llvmlite.Ptr(pool, resolved) + case llvmlite.LLVMType.Array(aelem_ty, _): + param_ty = llvmlite.Ptr(pool, aelem_ty) + case _: + param_ty = resolved + pname: str = 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 + # 装饰器形式存储类标记(@t.CExport/@t.CExtern/@t.State/@t.CStatic), + # 对齐 TPC HandlesFunctions._extract_decorator_storage_flags(与 + # forward_declare_functions 一致,保证 declare 与 define 同名同语义)。 + # 用 HandlesClassDef._has_decorator 委托(Mixin 静态绑定不能 self. 跨类调) + if fd.decorator_list is not None: + if has_extern == 0 and HandlesClassDef._has_decorator(fd.decorator_list, "CExtern") == 1: + has_extern = 1 + if has_state == 0 and HandlesClassDef._has_decorator(fd.decorator_list, "State") == 1: + has_state = 1 + if has_export == 0 and HandlesClassDef._has_decorator(fd.decorator_list, "CExport") == 1: + has_export = 1 + if (has_extern != 0 or has_state != 0) and is_extern_decl == 0: + is_extern_decl = 1 + # @t.TLS 一次性初始化标记(对齐 TPC HandlesFunctions.py L1223-1231) + has_tls: int = 0 + if fd.decorator_list is not None: + has_tls = HandlesClassDef._has_decorator(fd.decorator_list, "TLS") + + # 自定义行为装饰器检测(@log/@skip/@repeat(3) 等):非 t 存储标记、 + # 非内置(staticmethod/property/classmethod)的 Name/Name(args) 装饰器。 + # 对齐 TPC HandlesFunctions.py L1161-1189 + DecoratorPass.py。首版取 + # decorator_list 中第一个自定义装饰器(Python 最外层),链式嵌套后续扩展。 + has_custom_decor: int = 0 + decor_handler: str = None + decor_arg0: t.CInt64T = 0 + if fd.decorator_list is not None: + ddn: t.CSizeT = len(fd.decorator_list) + for ddi in range(ddn): + deco: ast.AST | t.CPtr = fd.decorator_list.get(ddi) + if deco is None: + continue + dk: int = deco.kind() + dname: str = None + if dk == ast.ASTKind.Name: + dnm: ast.Name | t.CPtr = (ast.Name | t.CPtr)(deco) + dname = dnm.id + elif dk == ast.ASTKind.Call: + dcl: ast.Call | t.CPtr = (ast.Call | t.CPtr)(deco) + if dcl.func is not None and dcl.func.kind() == ast.ASTKind.Name: + dnm2: ast.Name | t.CPtr = (ast.Name | t.CPtr)(dcl.func) + dname = dnm2.id + # @repeat(3):取首个常量 int 参数(对齐 TPC L1182-1184) + if dcl.args is not None and len(dcl.args) >= 1: + da0: ast.AST | t.CPtr = dcl.args.get(0) + if da0 is not None and da0.kind() == ast.ASTKind.Constant: + dc0: ast.Constant | t.CPtr = (ast.Constant | t.CPtr)(da0) + if dc0.const_kind == ast.CONST_INT: + decor_arg0 = dc0.int_val + if dname is None: + continue + # 跳过内置装饰器 + if string.strcmp(dname, "staticmethod") == 0 \ + or string.strcmp(dname, "property") == 0 \ + or string.strcmp(dname, "classmethod") == 0: + continue + # 跳过 t 模块存储类标记(@t.CExport/@t.CExtern/@t.State/@t.TLS/ + # @t.CStatic/@t.CInline/@t.CVTable/@t.NoVTable/@t.Object/@t.CEnum + # /@t.CUnion/@t.REnum/@t.CDefine 等裸名形式——Attribute 形式 + # @t.xxx 的 kind 是 Attribute,不进入本检测) + if string.strcmp(dname, "CExport") == 0 \ + or string.strcmp(dname, "CExtern") == 0 \ + or string.strcmp(dname, "State") == 0 \ + or string.strcmp(dname, "TLS") == 0 \ + or string.strcmp(dname, "CStatic") == 0 \ + or string.strcmp(dname, "CInline") == 0 \ + or string.strcmp(dname, "CVTable") == 0 \ + or string.strcmp(dname, "NoVTable") == 0 \ + or string.strcmp(dname, "Object") == 0 \ + or string.strcmp(dname, "CEnum") == 0 \ + or string.strcmp(dname, "CUnion") == 0 \ + or string.strcmp(dname, "REnum") == 0 \ + or string.strcmp(dname, "CDefine") == 0: + continue + has_custom_decor = 1 + decor_handler = dname + break + + # 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 = HandlesExprCall._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 = len(alist_e) + 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 \ + and 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 None: + # fail-fast:外部声明函数参数有注解但类型解析失败, + # 不再静默保持 i32(声明签名错误会在 ABI 层暴露) + HandlesType.fatal_error( + arg_e, f"参数 '{arg_e.arg}' 类型解析失败: {HandlesType.annotation_to_str(arg_e.annotation)}", + "NameError") + resolved_e = i32_ty # 不可达(fatal_error 已退出) + if resolved_e is not None: + # 裸类形参 → Ptr(struct)(对象即指针,与方法形参一致) + # CArray 形参 → 元素指针 ty*(C 数组衰减) + match resolved_e: + case llvmlite.LLVMType.Struct(_, _, _): + param_ty_e = llvmlite.Ptr(pool, resolved_e) + case llvmlite.LLVMType.Array(aelem_ty_e, _): + param_ty_e = llvmlite.Ptr(pool, aelem_ty_e) + case _: + param_ty_e = resolved_e + pname_e: str = 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: str = HandlesExprCall.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: str = HandlesExprCall.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: str = 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: str = HandlesExprCall.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 = len(tfd_alist) + 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 = len(tfd_dlist) + + # 注册到函数表 + max_funcs: int = 1024 + 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 = len(alist) + 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 \ + and 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)(对象即指针,与方法形参一致) + # CArray 形参 → 元素指针 ty*(C 数组衰减:final(out: t.CArray[..., N]) + # 的 out 指向调用方数组首元素;传 Ptr(数组) 会使 out[i] 的 + # GEP 以整个数组为步长错位,摘要垃圾根因) + match resolved: + case llvmlite.LLVMType.Struct(_, _, _): + param_ty = llvmlite.Ptr(pool, resolved) + case llvmlite.LLVMType.Array(aelem_ty, _): + param_ty = llvmlite.Ptr(pool, aelem_ty) + case _: + param_ty = resolved + pname: str = 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 + + # try-except:函数体含 raise → 追加 __eh_msg_out__(i8**)/ + # __eh_code_out__(i32*)输出参数(对齐 TPC HandlesFunctions.py + # L706-711;main 除外)。被调函数把异常编码/消息写入调用方传入 + # 的指针,调用方 _check_eh_return 检测。 + # 注意:必须在参数添加块(if args_node is not None:)外——无参函数 + # (def f())的 args_node 为 None,若放在其内会被跳过,导致函数体 + # store %__eh_code_out__ 但签名无此参数(llc: use of undefined value)。 + if string.strcmp(fd.name, "main") != 0: + if HandlesExprCall._body_has_raise(fd) != 0: + i8_ty_eh: llvmlite.LLVMType | t.CPtr = llvmlite.Int8(pool) + i8_ptr_ty_eh: llvmlite.LLVMType | t.CPtr = llvmlite.Ptr(pool, i8_ty_eh) + i8_ptr_ptr_ty_eh: llvmlite.LLVMType | t.CPtr = llvmlite.Ptr(pool, i8_ptr_ty_eh) + i32_ty_eh: llvmlite.LLVMType | t.CPtr = llvmlite.Int32(pool) + i32_ptr_ty_eh: llvmlite.LLVMType | t.CPtr = llvmlite.Ptr(pool, i32_ty_eh) + if i8_ptr_ptr_ty_eh is not None and i32_ptr_ty_eh is not None: + llvmlite.add_param(pool, func, i8_ptr_ptr_ty_eh, "%__eh_msg_out__") + llvmlite.add_param(pool, func, i32_ptr_ty_eh, "%__eh_code_out__") + + # 参数添加完成,补全全局函数表的 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) + + # @t.TLS 一次性初始化守卫(对齐 TPC HandlesFunctions.py L1763-1792): + # 首次调用执行函数体并置全局标志 __tls_init_done_{name}=1,后续调用 + # 直接返回默认值。TPV 此前未实现 @t.TLS,_init_tls 每次 TlsAlloc 导致 + # provider 栈跨调用丢失(FakeDuckTest Test 9 注入失败根因)。 + if has_tls != 0: + tls_flag_name: str = pool.alloc(128) + if tls_flag_name is not None: + viperlib.snprintf(tls_flag_name, 128, "__tls_init_done_%s", fd.name) + tls_flag_gv: llvmlite.GlobalVariable | t.CPtr = llvmlite.create_global_int( + pool, mod, tls_flag_name, 1, 0) + if tls_flag_gv is not None: + i1_ty_t: llvmlite.LLVMType | t.CPtr = llvmlite.Int1(pool) + if i1_ty_t is not None: + # GlobalVariable 不是 Value 子类(字段布局不同),build_load/store + # 按 Value 读 ptr.Ty/ptr.Name 会错位(Ty 读到 Name → void,Name 为空)。 + # 与 create_global_string 一致:构造 Value 视图(Ty=Ptr(i1), Name="@name")。 + tls_gv_ptr_ty: llvmlite.LLVMType | t.CPtr = llvmlite.Ptr(pool, i1_ty_t) + tls_ref_name: str = pool.alloc(64) + if tls_ref_name is not None: + viperlib.snprintf(tls_ref_name, 64, "@%s", tls_flag_name) + tls_flag_ref: llvmlite.Value | t.CPtr = llvmlite.SSAValue( + pool, tls_gv_ptr_ty, tls_ref_name) + if tls_flag_ref is not None: + tls_flag_ld: llvmlite.Value | t.CPtr = llvmlite.build_load( + func_builder, i1_ty_t, tls_flag_ref) + # 块名唯一化(create_block 不自动编号,同函数同名 label 冲突) + lc_t: int = trans._label_counter + trans._label_counter = lc_t + 1 + tls_bb_buf: str = pool.alloc(64) + if tls_bb_buf is not None: + viperlib.snprintf(tls_bb_buf, 64, "tls.skip.%d", lc_t) + tls_skip_bb: llvmlite.BasicBlock | t.CPtr = llvmlite.create_block( + pool, func, tls_bb_buf) + viperlib.snprintf(tls_bb_buf, 64, "tls.cont.%d", lc_t) + tls_cont_bb: llvmlite.BasicBlock | t.CPtr = llvmlite.create_block( + pool, func, tls_bb_buf) + if tls_skip_bb is not None and tls_cont_bb is not None: + llvmlite.build_cond_br( + func_builder, tls_flag_ld, tls_skip_bb, tls_cont_bb) + # skip 块:按返回类型生成默认值直接返回 + llvmlite.position_at_end(func_builder, tls_skip_bb) + match ret_ty: + case llvmlite.LLVMType.Void(): + llvmlite.build_ret_void(func_builder) + case llvmlite.LLVMType.Int(_): + tlz0: llvmlite.Value | t.CPtr = llvmlite.ConstInt( + pool, ret_ty, 0, "0") + if tlz0 is not None: + llvmlite.build_ret(func_builder, tlz0) + case llvmlite.LLVMType.Float(_): + tlf0: llvmlite.Value | t.CPtr = llvmlite.ConstFloat( + pool, ret_ty, 0.0) + if tlf0 is not None: + llvmlite.build_ret(func_builder, tlf0) + case _: + tln0: llvmlite.Value | t.CPtr = llvmlite.ConstNull( + pool, ret_ty, "null") + if tln0 is not None: + llvmlite.build_ret(func_builder, tln0) + # cont 块:置标志=1,继续函数体 + llvmlite.position_at_end(func_builder, tls_cont_bb) + tlone: llvmlite.Value | t.CPtr = llvmlite.ConstInt( + pool, i1_ty_t, 1, "1") + if tlone is not None: + llvmlite.build_store(func_builder, tlone, tls_flag_ref) + + # 进入函数作用域(嵌套符号表) + 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 = len(fd.type_params) + 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 = len(alist2) + 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 None: + # fail-fast:参数有注解但类型解析失败,不再静默保持 i32 + HandlesType.fatal_error( + arg2, f"参数 '{arg2.arg}' 类型解析失败: {HandlesType.annotation_to_str(arg2.annotation)}", + "NameError") + resolved2 = i32_ty # 不可达(fatal_error 已退出) + if resolved2 is not None: + # 与 add_param 保持一致:裸类形参 → Ptr(struct)(对象即指针); + # CArray 形参 → 元素指针 ty*(数组衰减,alloca 类型须与形参一致, + # 否则 store ty* 到 [N x ty]* 容器类型不匹配) + match resolved2: + case llvmlite.LLVMType.Struct(_, _, _): + param_ty2 = llvmlite.Ptr(pool, resolved2) + case llvmlite.LLVMType.Array(aelem_ty2, _): + param_ty2 = llvmlite.Ptr(pool, aelem_ty2) + 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) 回退到类名查找结构体) + # 传 pool:泛型 Subscript 返回 mangled name(对齐 HandlesAnnAssign 修复) + cls_nm: str = None + if arg2.annotation is not None: + cls_nm = HandlesType.extract_class_name_from_annotation( + arg2.annotation, imported_modules, pool) + if cls_nm is not None: + HandlesVar.set_var_annot_class_name( + trans.SymTab, arg2.arg, cls_nm) + pname2: str = 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) 糖函数 + # 注意:必须在参数 alloca 段(if args_node is not None:)内但 EH 块外—— + # 无 raise 的函数(viperlib.sprintf 等)同样有 *args,若放在 EH 块内 + # 会被跳过,args 未注册到符号表 → NameError: 未定义名称 'args'。 + 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 + + # try-except:新函数作用域 EH 状态从零开始。必须先保存外层函数 + # (调用方/包围函数)的 EH 输出参数,翻译完本函数后再恢复——否则 + # 下方设置本函数 EH 参数会覆盖外层值,恢复时 old_eh_* 拿到的是 + # 本函数自身参数(嵌套函数/多函数链 EH 状态错乱)。 + old_eh_msg_out: llvmlite.Value | t.CPtr = trans._eh_msg_out_param + old_eh_code_out: llvmlite.Value | t.CPtr = trans._eh_code_out_param + old_cur_func_has_eh: int = trans._cur_func_has_eh + trans._eh_msg_out_param = None + trans._eh_code_out_param = None + trans._cur_func_has_eh = 0 + + # try-except:保存当前函数的 EH 输出参数(__eh_msg_out__/__eh_code_out__) + # 供 translate_raise / UnhandledBB 写入并向上传播。无 EH 参数的函数置空。 + if string.strcmp(fd.name, "main") != 0 and HandlesExprCall._body_has_raise(fd) != 0: + i8_ty_eh2: llvmlite.LLVMType | t.CPtr = llvmlite.Int8(pool) + i8_ptr_ty_eh2: llvmlite.LLVMType | t.CPtr = llvmlite.Ptr(pool, i8_ty_eh2) + i8_ptr_ptr_ty_eh2: llvmlite.LLVMType | t.CPtr = llvmlite.Ptr(pool, i8_ptr_ty_eh2) + i32_ty_eh2: llvmlite.LLVMType | t.CPtr = llvmlite.Int32(pool) + i32_ptr_ty_eh2: llvmlite.LLVMType | t.CPtr = llvmlite.Ptr(pool, i32_ty_eh2) + if i8_ptr_ptr_ty_eh2 is not None and i32_ptr_ty_eh2 is not None: + msg_out_ref: llvmlite.Value | t.CPtr = llvmlite.SSAValue( + pool, i8_ptr_ptr_ty_eh2, "%__eh_msg_out__") + code_out_ref: llvmlite.Value | t.CPtr = llvmlite.SSAValue( + pool, i32_ptr_ty_eh2, "%__eh_code_out__") + trans._eh_msg_out_param = msg_out_ref + trans._eh_code_out_param = code_out_ref + trans._cur_func_has_eh = 1 + + # 保存模块级作用域状态(仅非变量表相关) + 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) + # 重置链内 nonlocal 堆预建标志(每函数只建一次;多嵌套函数定义 + # 共享同一堆,防重复 malloc + 二次重定向 VarEntry) + trans._nl_chain_done = 0 + + # 预扫描函数体: + # 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 = len(body) + 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 = len(body) + for bi2 in range(bn2): + stmt2: ast.AST | t.CPtr = body.get(bi2) + if stmt2 is not None: + # 嵌套函数定义前:预扫描其链内 nonlocal 并建堆 + # (不同层捕获不同变量的场景,见 _prepare_chain_nonlocals) + if stmt2.kind() == ast.ASTKind.FunctionDef: + HandlesExprCall._prepare_chain_nonlocals( + trans, stmt2, pool, func_builder, mod, + llvmlite.Int8(pool), llvmlite.Ptr(pool, llvmlite.Int8(pool))) + HandlesBody.translate_stmt(trans, stmt2) + + # 如果函数体最后一条语句不是 Return,添加隐式 ret + last_is_return: int = 0 + # 追加89:bn3 提前初始化,避免 body is None 时下方 fail-fast 分支 + # 引用未定义的 bn3(追加81 同款 NameError 风险) + bn3: t.CSizeT = 0 + if body is not None: + bn3 = len(body) + 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: + # 追加89:编译器不替代码发明返回值——函数流程真实掉出末尾而 + # 未显式 return 时 fail-fast(要求补 return,Python traceback + # 风格定位到函数)。三种合法收尾: + # ① void 函数掉出末尾 → ret void(无值可发明,Python 语义) + # ② 末句是控制流语句(match/if 全分支 return)且当前块 + # 未 terminated → merge 块结构性不可达 → unreachable + # ③ 无返回类型注解的函数(fd.returns is None,如 + # ast/base.vp _set_pos 过程风格赋值函数)→ 视为无返回值 + # 函数,默认生成零值返回(用户决策:没有返回值默认不用 + # return;ConstZero 按推断出的 ret_ty 构造,类型匹配) + # 有 -> 注解且末句是普通语句掉出末尾 → fail-fast(不得替代码 + # 发明返回值,也不做 noreturn 函数名白名单——错误终止路径 + # 也必须在源码层面保证块收尾,如显式 return 样板) + # 末句是否为控制流语句(If/Match/While/For/Try/With): + # 控制流语句翻译后当前块未 terminated 表示 merge 块结构性 + # 不可达(所有分支均已 return/terminated)——对非 void 函数 + # 生成 unreachable 而非 fail-fast(GCC/Clang 对 fall-through + # 视为 UB 同语义;追加89 修正 get_struct_name 全 case return + # 被错判"不可能抵达") + last_is_ctrl: int = 0 + if bn3 > 0: + last_stmt3: ast.AST | t.CPtr = body.get(bn3 - 1) + if last_stmt3 is not None: + k3: int = last_stmt3.kind() + if k3 == ast.ASTKind.If or k3 == ast.ASTKind.While or \ + k3 == ast.ASTKind.For or k3 == ast.ASTKind.Try or \ + k3 == ast.ASTKind.With or k3 == ast.ASTKind.Match: + last_is_ctrl = 1 + _is_void: int = 0 + if ret_ty is not None: + match ret_ty: + case llvmlite.LLVMType.Void(): + _is_void = 1 + case _: + pass + if _is_void != 0: + llvmlite.build_ret_void(func_builder) + elif last_is_ctrl != 0 and trans._ctrl_merge_reachable == 0: + # 追加90:非 void 函数末句是控制流且 merge 块结构性不可达 + # (全分支 return,无 br 到 merge)→ LLVM 语义 unreachable。 + # 注意:merge 可达(分支 br 到 merge,如 testcheck.check 的 + # if/else 无 return)时不是结构性不可达,需正常收尾(下方 + # ConstZero / fail-fast)。原实现无条件 unreachable 使 llc + # O2 把 br-to-unreachable 优化为 fall-through → 双分支执行 + # 崩溃(FuncTest check PASS+FAIL 双打印) + llvmlite.build_unreachable(func_builder) + elif fd.returns is None: + # 无返回类型注解 → 无返回值过程函数,默认零值返回 + if ret_ty is not None: + zero_val: llvmlite.Value | t.CPtr = llvmlite.ConstZero(pool, ret_ty) + if zero_val is not None: + llvmlite.build_ret(func_builder, zero_val) + else: + HandlesType.fatal_error(node, "函数流程掉出末尾但未显式 return", "TypeError") + else: + HandlesType.fatal_error(node, "函数流程掉出末尾但未显式 return", "TypeError") + else: + # fail-fast:有 -> 注解但流程真实掉出末尾(定位到函数定义 + # 节点,fatal_error 输出 traceback 风格错误) + if ret_ty is not None: + # llvmlite 无 type_get_name API,类型序列化用真实接口 + # TypePrint(buf, size, ty, pool)(追加89 修正) + rt_name: str = pool.alloc(64) + if rt_name is not None: + llvmlite.TypePrint(rt_name, 64, ret_ty, pool) + if rt_name[0] == '\0': + rt_name = "?" + err_fn: str = pool.alloc(256) + if err_fn is not None: + viperlib.snprintf( + err_fn, 256, + "函数 '%s' 流程掉出函数末尾但未显式 return(返回类型 %s)," + "请补显式 return(如 return 0 / return null)", fd.name, rt_name) + HandlesType.fatal_error(node, err_fn, "TypeError") + HandlesType.fatal_error(node, "函数流程掉出末尾但未显式 return", "TypeError") + else: + HandlesType.fatal_error(node, "函数流程掉出末尾但未显式 return", "TypeError") + + # 恢复模块级作用域(退出函数作用域) + 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 + # 恢复外层函数(调用方)的 EH 输出参数——本函数体内的 raise 传播 + # 使用本函数参数,翻译结束必须交还外层作用域,否则嵌套函数/链式 + # 调用后 EH 状态残留导致 raise 写入错误的 out 指针。 + trans._eh_msg_out_param = old_eh_msg_out + trans._eh_code_out_param = old_eh_code_out + trans._cur_func_has_eh = old_cur_func_has_eh + + # 自定义装饰器:注册 + 生成 wrapper(对齐 TPC DecoratorPass.run)。 + # 仅模块级函数(fd 是顶层定义);wrapper 名 __decor_wrap_{裸函数名}。 + # 调用点重写经 lookup_decor_wrapper(translate_call 拦截原函数名)。 + if has_custom_decor != 0: + wb_name: str = pool.alloc(128) + if wb_name is not None: + viperlib.snprintf(wb_name, 128, "__decor_wrap_%s", fd.name) + HandlesClassDef.register_decorator(pool, fd.name, wb_name, decor_arg0) + self._gen_decor_wrapper( + trans, pool, mod, func, fd.name, wb_name, + decor_handler, decor_arg0) + + return 0 + # ============================================================ + # _gen_decor_wrapper - 生成装饰器 wrapper 函数(对齐 TPC DecoratorPass.py + # _generate_single_wrapper v4) + # + # v4 Wrapper 结构(最外层含递归保护): + # entry → 递归保护检查(最外层) + # recursive_call → 递归时直接调用原函数,跳过所有装饰 + # decorated_entry → 置递归标志,分配 ctx/args/ret,调用 handler 前置 + # loop_header → 计数器 i < n_calls(TPV 用 alloca 计数器替代 phi) + # loop.body → 从 args_struct 读回参数,调用原函数 + # post → 调用 handler 后置,清递归标志,返回结果 + # + # handler 调用约定:i32 decor(i8* ctx, i8* func_name, i32 phase, + # i8* args_ptr, i8* ret_ptr, i8* decor_args_ptr) + # 前置返回:0=跳过原函数,1=调用一次,N=循环 N 次 + # ============================================================ + def _gen_decor_wrapper(self, trans: HT.Translator | t.CPtr, + pool: memhub.MemBuddy | t.CPtr, + mod: llvmlite.LLVMModule | t.CPtr, + func: llvmlite.Function | t.CPtr, + func_name: str, + wrapper_name: str, + handler_name: str, + decor_arg0: t.CInt64T) -> llvmlite.Function | t.CPtr: + """生成装饰器 wrapper 函数,返回 wrapper 或 None""" + if trans is None or pool is None or mod is None or func is None: + return None + if func_name is None or wrapper_name is None or handler_name is None: + return None + ret_ty: llvmlite.LLVMType | t.CPtr = llvmlite.function_get_ret_ty(func) + if ret_ty is None: + return None + orig_call_name: str = llvmlite.function_get_name(func) + if orig_call_name is None: + return None + + 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) + + # ---- 收集原函数参数类型(按位置,最多 16 个)---- + n_params: int = 0 + param_tys: t.CSizeT | t.CPtr = pool.alloc(16 * 8) + if param_tys is None: + return None + string.memset(param_tys, 0, 16 * 8) + pp: llvmlite.Param | t.CPtr = llvmlite.function_get_param_head(func) + while pp is not None: + pty: llvmlite.LLVMType | t.CPtr = llvmlite.param_get_ty(pp) + if pty is not None and n_params < 16: + param_tys[n_params] = t.CSizeT(pty) + n_params += 1 + pp = llvmlite.param_get_next(pp) + + # ---- 创建 wrapper 函数并添加参数(名字 %a0..%aN)---- + wrapper: llvmlite.Function | t.CPtr = llvmlite.create_function( + pool, mod, wrapper_name, ret_ty) + if wrapper is None: + return None + pi: int = 0 + for pi in range(n_params): + pname_w: str = pool.alloc(16) + if pname_w is not None: + viperlib.snprintf(pname_w, 16, "%%a%d", pi) + llvmlite.add_param(pool, wrapper, (llvmlite.LLVMType | t.CPtr)( + t.CVoid(param_tys[pi], t.CPtr)), pname_w) + + # ---- 创建块 ---- + entry_bb: llvmlite.BasicBlock | t.CPtr = llvmlite.create_block(pool, wrapper, "entry") + loop_h_bb: llvmlite.BasicBlock | t.CPtr = llvmlite.create_block(pool, wrapper, "loop.header") + loop_b_bb: llvmlite.BasicBlock | t.CPtr = llvmlite.create_block(pool, wrapper, "loop.body") + post_bb: llvmlite.BasicBlock | t.CPtr = llvmlite.create_block(pool, wrapper, "post") + if entry_bb is None or loop_h_bb is None or loop_b_bb is None or post_bb is None: + return None + + # 递归保护标志(最外层):@__decor_rec_{wrapper} = global i8 0 + rec_flag_ref: llvmlite.Value | t.CPtr = None + rec_flag_name: str = pool.alloc(128) + if rec_flag_name is not None: + viperlib.snprintf(rec_flag_name, 128, "__decor_rec_%s", wrapper_name) + llvmlite.create_global_int(pool, mod, rec_flag_name, 8, 0) + rec_ref_nm: str = pool.alloc(96) + if rec_ref_nm is not None: + viperlib.snprintf(rec_ref_nm, 96, "@%s", rec_flag_name) + rec_flag_ref = llvmlite.SSAValue(pool, llvmlite.Ptr(pool, i8_ty), rec_ref_nm) + + wb: llvmlite.IRBuilder | t.CPtr = llvmlite.new_builder(pool, wrapper) + if wb is None: + return None + + # 返回类型分类 + ret_is_void: int = 0 + match ret_ty: + case llvmlite.LLVMType.Void(): + ret_is_void = 1 + case _: + pass + + # ---- entry:递归保护检查(最外层)---- + llvmlite.position_at_end(wb, entry_bb) + loop_pred_bb: llvmlite.BasicBlock | t.CPtr = entry_bb + if rec_flag_ref is not None: + rec_bb: llvmlite.BasicBlock | t.CPtr = llvmlite.create_block(pool, wrapper, "recursive_call") + dec_bb: llvmlite.BasicBlock | t.CPtr = llvmlite.create_block(pool, wrapper, "decorated_entry") + if rec_bb is None or dec_bb is None: + return None + rec_val: llvmlite.Value | t.CPtr = llvmlite.build_load(wb, i8_ty, rec_flag_ref) + rec_zero: llvmlite.Value | t.CPtr = llvmlite.ConstInt(pool, i8_ty, 0, "0") + rec_is: llvmlite.Value | t.CPtr = llvmlite.build_icmp( + wb, llvmlite.ICMP_NE, rec_val, rec_zero) + llvmlite.build_cond_br(wb, rec_is, rec_bb, dec_bb) + # recursive_call:直接调用原函数返回(跳过所有装饰逻辑) + llvmlite.position_at_end(wb, rec_bb) + rec_args: llvmlite.Value | t.CPtr = None + ri: int = 0 + for ri in range(n_params): + an_r: str = pool.alloc(16) + if an_r is None: + continue + viperlib.snprintf(an_r, 16, "%%a%d", ri) + av_r: llvmlite.Value | t.CPtr = llvmlite.SSAValue( + pool, (llvmlite.LLVMType | t.CPtr)(t.CVoid(param_tys[ri], t.CPtr)), an_r) + if av_r is not None: + llvmlite.value_set_next(av_r, None) + if rec_args is None: + rec_args = av_r + else: + # 链尾追加 + rt: llvmlite.Value | t.CPtr = rec_args + while rt.Next is not None: + rt = rt.Next + llvmlite.value_set_next(rt, av_r) + if ret_is_void != 0: + llvmlite.build_call(wb, orig_call_name, rec_args, n_params, ret_ty, 0) + llvmlite.build_ret_void(wb) + else: + rc_res: llvmlite.Value | t.CPtr = llvmlite.build_call( + wb, orig_call_name, rec_args, n_params, ret_ty, 0) + if rc_res is not None: + llvmlite.build_ret(wb, rc_res) + else: + llvmlite.build_ret_void(wb) + # decorated_entry:置递归标志,继续装饰路径 + llvmlite.position_at_end(wb, dec_bb) + rec_one: llvmlite.Value | t.CPtr = llvmlite.ConstInt(pool, i8_ty, 1, "1") + if rec_one is not None: + llvmlite.build_store(wb, rec_one, rec_flag_ref) + loop_pred_bb = dec_bb + + # ---- 公共装饰路径(entry 或 decorated_entry)---- + # 1. ctx = alloca [32 x i8]; ctx_ptr = bitcast i8* + ctx_ty: llvmlite.LLVMType | t.CPtr = llvmlite.Array(pool, i8_ty, 32) + ctx_alloca: llvmlite.Value | t.CPtr = llvmlite.build_alloca(wb, ctx_ty) + ctx_ptr: llvmlite.Value | t.CPtr = llvmlite.build_bitcast(wb, ctx_alloca, i8_ptr_ty) + + # 2. 打包函数参数到结构体 {param_types}(装饰器可读写 args_ptr) + args_alloca: llvmlite.Value | t.CPtr = None + args_ptr: llvmlite.Value | t.CPtr = None + if n_params > 0: + fields_head: llvmlite.ParamNode | t.CPtr = None + fk: int = 0 + for fk in range(n_params - 1, -1, -1): + pn_n: llvmlite.ParamNode | t.CPtr = llvmlite.new_param_node( + pool, (llvmlite.LLVMType | t.CPtr)(t.CVoid(param_tys[fk], t.CPtr))) + if pn_n is not None: + pn_n.Next = fields_head + fields_head = pn_n + args_ty: llvmlite.LLVMType | t.CPtr = llvmlite.Struct( + pool, fields_head, n_params, None) + if args_ty is not None: + args_alloca = llvmlite.build_alloca(wb, args_ty) + fi2: int = 0 + for fi2 in range(n_params): + fld_ty: llvmlite.LLVMType | t.CPtr = (llvmlite.LLVMType | t.CPtr)( + t.CVoid(param_tys[fi2], t.CPtr)) + fld_ptr: llvmlite.Value | t.CPtr = llvmlite.build_gep_struct( + wb, args_ty, fld_ty, args_alloca, fi2) + if fld_ptr is not None: + fld_nm: str = pool.alloc(16) + if fld_nm is not None: + viperlib.snprintf(fld_nm, 16, "%%a%d", fi2) + fld_v: llvmlite.Value | t.CPtr = llvmlite.SSAValue( + pool, fld_ty, fld_nm) + if fld_v is not None: + llvmlite.build_store(wb, fld_v, fld_ptr) + args_ptr = llvmlite.build_bitcast(wb, args_alloca, i8_ptr_ty) + else: + args_ptr = llvmlite.ConstNull(pool, i8_ptr_ty, "null") + + # 3. 返回值存储(零初始化;跳过原函数时返回安全默认值) + ret_alloca: llvmlite.Value | t.CPtr = None + if ret_is_void == 0: + ret_alloca = llvmlite.build_alloca(wb, ret_ty) + ret_zero: llvmlite.Value | t.CPtr = None + match ret_ty: + case llvmlite.LLVMType.Int(_): + ret_zero = llvmlite.ConstInt(pool, ret_ty, 0, "0") + case llvmlite.LLVMType.Float(_): + ret_zero = llvmlite.ConstFloat(pool, ret_ty, 0.0) + case _: + ret_zero = llvmlite.ConstNull(pool, ret_ty, "null") + if ret_zero is not None and ret_alloca is not None: + llvmlite.build_store(wb, ret_zero, ret_alloca) + + # 4. 函数名字符串常量 + fn_str: llvmlite.Value | t.CPtr = HandlesExpr.create_global_string( + wb, pool, mod, func_name, trans) + if fn_str is None: + fn_str = llvmlite.ConstNull(pool, i8_ptr_ty, "null") + + # 5. handler 声明(未翻译时 declare,固定签名 i32 (i8*,i8*,i32,i8*,i8*,i8*)) + if HandlesExprCall.find_func_in_module(mod, handler_name) is None: + handler_d: llvmlite.Function | t.CPtr = llvmlite.create_declare( + pool, mod, handler_name, i32_ty) + if handler_d is not None: + llvmlite.add_param(pool, handler_d, i8_ptr_ty, "ctx") + llvmlite.add_param(pool, handler_d, i8_ptr_ty, "func_name") + llvmlite.add_param(pool, handler_d, i32_ty, "phase") + llvmlite.add_param(pool, handler_d, i8_ptr_ty, "args_ptr") + llvmlite.add_param(pool, handler_d, i8_ptr_ty, "ret_ptr") + llvmlite.add_param(pool, handler_d, i8_ptr_ty, "decor_args_ptr") + + # 6. 前置阶段:handler 返回调用次数 n_calls + ph0: llvmlite.Value | t.CPtr = llvmlite.ConstInt(pool, i32_ty, 0, "0") + null_ret: llvmlite.Value | t.CPtr = llvmlite.ConstNull(pool, i8_ptr_ty, "null") + null_dec: llvmlite.Value | t.CPtr = llvmlite.ConstNull(pool, i8_ptr_ty, "null") + # 参数链表(6 个独立值):ctx_ptr → fn_str → 0 → args_ptr → null → null + # 注意:不能 self 链接(null.Next = null 会让 build_call 遍历死循环) + if ctx_ptr is not None: + llvmlite.value_set_next(ctx_ptr, fn_str) + if fn_str is not None: + llvmlite.value_set_next(fn_str, ph0) + if ph0 is not None: + llvmlite.value_set_next(ph0, args_ptr) + if args_ptr is not None: + llvmlite.value_set_next(args_ptr, null_ret) + if null_ret is not None: + llvmlite.value_set_next(null_ret, null_dec) + n_calls: llvmlite.Value | t.CPtr = llvmlite.build_call( + wb, handler_name, ctx_ptr, 6, i32_ty, 0) + + # 7. 计数器 alloca(TPV 用 alloca 计数器替代 phi) + cnt_alloca: llvmlite.Value | t.CPtr = llvmlite.build_alloca(wb, i32_ty) + cnt_zero: llvmlite.Value | t.CPtr = llvmlite.ConstInt(pool, i32_ty, 0, "0") + if cnt_alloca is not None and cnt_zero is not None: + llvmlite.build_store(wb, cnt_zero, cnt_alloca) + llvmlite.build_br(wb, loop_h_bb) + + # 8. loop.header:cur = load cnt; cur < n_calls → body / post + llvmlite.position_at_end(wb, loop_h_bb) + cur_i: llvmlite.Value | t.CPtr = llvmlite.build_load(wb, i32_ty, cnt_alloca) + loop_cond: llvmlite.Value | t.CPtr = llvmlite.build_icmp( + wb, llvmlite.ICMP_SLT, cur_i, n_calls) + llvmlite.build_cond_br(wb, loop_cond, loop_b_bb, post_bb) + + # 9. loop.body:读回参数(装饰器可能已修改)→ 调用原函数 → store ret + llvmlite.position_at_end(wb, loop_b_bb) + call_args: llvmlite.Value | t.CPtr = None + if n_params > 0: + k: int = 0 + for k in range(n_params): + fld_ty_k: llvmlite.LLVMType | t.CPtr = (llvmlite.LLVMType | t.CPtr)( + t.CVoid(param_tys[k], t.CPtr)) + fld_pk: llvmlite.Value | t.CPtr = llvmlite.build_gep_struct( + wb, args_ty, fld_ty_k, args_alloca, k) + if fld_pk is None: + continue + fld_vk: llvmlite.Value | t.CPtr = llvmlite.build_load(wb, fld_ty_k, fld_pk) + if fld_vk is not None: + llvmlite.value_set_next(fld_vk, None) + if call_args is None: + call_args = fld_vk + else: + ct: llvmlite.Value | t.CPtr = call_args + while ct.Next is not None: + ct = ct.Next + llvmlite.value_set_next(ct, fld_vk) + res_v: llvmlite.Value | t.CPtr = llvmlite.build_call( + wb, orig_call_name, call_args, n_params, ret_ty, 0) + if ret_alloca is not None and res_v is not None: + llvmlite.build_store(wb, res_v, ret_alloca) + nxt_i: llvmlite.Value | t.CPtr = llvmlite.build_add( + wb, cur_i, llvmlite.ConstInt(pool, i32_ty, 1, "1")) + if nxt_i is not None and cnt_alloca is not None: + llvmlite.build_store(wb, nxt_i, cnt_alloca) + llvmlite.build_br(wb, loop_h_bb) + + # 10. post:handler 后置 → 清递归标志 → 返回结果 + llvmlite.position_at_end(wb, post_bb) + ret_ptr: llvmlite.Value | t.CPtr = null_ret + if ret_alloca is not None: + ret_ptr = llvmlite.build_bitcast(wb, ret_alloca, i8_ptr_ty) + ph1: llvmlite.Value | t.CPtr = llvmlite.ConstInt(pool, i32_ty, 1, "1") + # 后置参数链:ctx_ptr → fn_str → 1 → args_ptr → ret_ptr → null + if ctx_ptr is not None: + llvmlite.value_set_next(ctx_ptr, fn_str) + if fn_str is not None: + llvmlite.value_set_next(fn_str, ph1) + if ph1 is not None: + llvmlite.value_set_next(ph1, args_ptr) + if args_ptr is not None: + llvmlite.value_set_next(args_ptr, ret_ptr) + if ret_ptr is not None: + llvmlite.value_set_next(ret_ptr, null_dec) + llvmlite.build_call(wb, handler_name, ctx_ptr, 6, i32_ty, 0) + if rec_flag_ref is not None: + rec_zero2: llvmlite.Value | t.CPtr = llvmlite.ConstInt(pool, i8_ty, 0, "0") + if rec_zero2 is not None: + llvmlite.build_store(wb, rec_zero2, rec_flag_ref) + if ret_is_void != 0: + llvmlite.build_ret_void(wb) + else: + final_v: llvmlite.Value | t.CPtr = llvmlite.build_load(wb, ret_ty, ret_alloca) + if final_v is not None: + llvmlite.build_ret(wb, final_v) + else: + llvmlite.build_ret_void(wb) + + return wrapper \ No newline at end of file diff --git a/App/lib/core/Gen/FuncGenMixin.vp b/App/lib/core/Gen/FuncGenMixin.vp index 65ca968..666ee6d 100644 --- a/App/lib/core/Gen/FuncGenMixin.vp +++ b/App/lib/core/Gen/FuncGenMixin.vp @@ -17,6 +17,7 @@ import lib.core.Handles.HandlesType as HandlesType import lib.core.Handles.HandlesBody as HandlesBody import lib.core.Handles.HandlesImports as HandlesImports import lib.core.Handles.HandlesClassDef as HandlesClassDef +import lib.core.Gen.CallGenBase as CallGenBase # ============================================================ @@ -54,1481 +55,19 @@ SCOPE_FUNCTION: t.CDefine = 1 # FuncGenMixin - 函数属性/命名/声明/翻译 # ============================================================ @t.NoVTable -class FuncGenMixin: +class FuncGenMixin(CallGenBase.CallGenBase): """函数/方法翻译 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) -> str: - """从 decorator_list 提取 c.Attribute 属性,返回 LLVM IR 属性字符串""" - if decorator_list is None: - return None - dn: t.CSizeT = len(decorator_list) - if dn == 0: - return None - attrs_buf: str = 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 = len(args_list) - 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: str, 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: str, s: str, - max_len: t.CSizeT = 256) -> None: - """将字符串追加到 buf 末尾(有界,防 strcpy 越界写穿定长缓冲)""" - if buf is None or s is None: - return - cur_len: t.CSizeT = string.strlen(buf) - s_len: t.CSizeT = string.strlen(s) - if cur_len + s_len + 1 > max_len: - return # 无剩余容量:丢弃本次追加,避免越界写 - 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) - - # ============================================================ - # _body_has_raise - 函数体是否含 raise(非 StopIteration) - # - # 对齐 TPC HandlesFunctions.py L216-243 _body_contains_raise:函数签名 - # 追加 __eh_msg_out__/__eh_code_out__ 输出参数的条件。v1 只扫函数体 - # 顶层 raise(嵌套 if/for/try 内的 raise 未覆盖,后续扩展)。 - # ============================================================ - def _body_has_raise(self, fd: ast.FunctionDef | t.CPtr) -> int: - """函数体顶层是否含 raise(非 StopIteration),1=是 / 0=否""" - if fd is None or fd.children is None: - return 0 - body_f: list[ast.AST | t.CPtr] | t.CPtr = fd.children - bn_f: t.CSizeT = len(body_f) - for bi_f in range(bn_f): - stmt_f: ast.AST | t.CPtr = body_f.get(bi_f) - if stmt_f is None: - continue - if stmt_f.kind() != ast.ASTKind.Raise: - continue - rn_f: ast.Raise | t.CPtr = (ast.Raise | t.CPtr)(stmt_f) - if rn_f is None or rn_f.exc is None: - continue - ek_f: int = rn_f.exc.kind() - is_stop_f: int = 0 - if ek_f == ast.ASTKind.Name: - enm_f: ast.Name | t.CPtr = (ast.Name | t.CPtr)(rn_f.exc) - if enm_f.id is not None and string.strcmp(enm_f.id, "StopIteration") == 0: - is_stop_f = 1 - elif ek_f == ast.ASTKind.Call: - ecl_f: ast.Call | t.CPtr = (ast.Call | t.CPtr)(rn_f.exc) - if ecl_f.func is not None and ecl_f.func.kind() == ast.ASTKind.Name: - ecn_f: ast.Name | t.CPtr = (ast.Name | t.CPtr)(ecl_f.func) - if ecn_f.id is not None and string.strcmp(ecn_f.id, "StopIteration") == 0: - is_stop_f = 1 - if is_stop_f == 0: - return 1 - return 0 - - # ============================================================ - # 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 = len(ch) - - 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") - # 装饰器形式存储类标记(@t.CExport/@t.CExtern/@t.State/@t.CStatic) - # 对齐 TPC HandlesFunctions._extract_decorator_storage_flags; - # CExport/CExtern/State 影响函数名(导出裸名),CStatic 仅标记。 - # 注意: 用 HandlesClassDef._has_decorator 委托而非 self._has_decorator - # (Mixin 是 @t.NoVTable 静态绑定,跨 Mixin 方法经 MRO 调用会生成 - # 不存在的 FuncGenMixin._has_decorator → 链接 undefined symbol) - if fd.decorator_list is not None: - if has_extern == 0 and HandlesClassDef._has_decorator(fd.decorator_list, "CExtern") == 1: - has_extern = 1 - if has_state == 0 and HandlesClassDef._has_decorator(fd.decorator_list, "State") == 1: - has_state = 1 - if has_export == 0 and HandlesClassDef._has_decorator(fd.decorator_list, "CExport") == 1: - has_export = 1 - 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 = len(fd_alist) - 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 = len(fd_dlist) - - # 注册到函数表(用裸名 fd.name,不是 mangled_name) - max_funcs: int = 1024 - 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 = len(alist) - 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)(对象即指针,与方法形参一致) - # CArray 形参 → 元素指针 ty*(C 数组衰减,与 add_param 一致) - match resolved: - case llvmlite.LLVMType.Struct(_, _, _): - param_ty = llvmlite.Ptr(pool, resolved) - case llvmlite.LLVMType.Array(aelem_ty, _): - param_ty = llvmlite.Ptr(pool, aelem_ty) - case _: - param_ty = resolved - pname: str = 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 - # 装饰器形式存储类标记(@t.CExport/@t.CExtern/@t.State/@t.CStatic), - # 对齐 TPC HandlesFunctions._extract_decorator_storage_flags(与 - # forward_declare_functions 一致,保证 declare 与 define 同名同语义)。 - # 用 HandlesClassDef._has_decorator 委托(Mixin 静态绑定不能 self. 跨类调) - if fd.decorator_list is not None: - if has_extern == 0 and HandlesClassDef._has_decorator(fd.decorator_list, "CExtern") == 1: - has_extern = 1 - if has_state == 0 and HandlesClassDef._has_decorator(fd.decorator_list, "State") == 1: - has_state = 1 - if has_export == 0 and HandlesClassDef._has_decorator(fd.decorator_list, "CExport") == 1: - has_export = 1 - if (has_extern != 0 or has_state != 0) and is_extern_decl == 0: - is_extern_decl = 1 - # @t.TLS 一次性初始化标记(对齐 TPC HandlesFunctions.py L1223-1231) - has_tls: int = 0 - if fd.decorator_list is not None: - has_tls = HandlesClassDef._has_decorator(fd.decorator_list, "TLS") - - # 自定义行为装饰器检测(@log/@skip/@repeat(3) 等):非 t 存储标记、 - # 非内置(staticmethod/property/classmethod)的 Name/Name(args) 装饰器。 - # 对齐 TPC HandlesFunctions.py L1161-1189 + DecoratorPass.py。首版取 - # decorator_list 中第一个自定义装饰器(Python 最外层),链式嵌套后续扩展。 - has_custom_decor: int = 0 - decor_handler: str = None - decor_arg0: t.CInt64T = 0 - if fd.decorator_list is not None: - ddn: t.CSizeT = len(fd.decorator_list) - for ddi in range(ddn): - deco: ast.AST | t.CPtr = fd.decorator_list.get(ddi) - if deco is None: - continue - dk: int = deco.kind() - dname: str = None - if dk == ast.ASTKind.Name: - dnm: ast.Name | t.CPtr = (ast.Name | t.CPtr)(deco) - dname = dnm.id - elif dk == ast.ASTKind.Call: - dcl: ast.Call | t.CPtr = (ast.Call | t.CPtr)(deco) - if dcl.func is not None and dcl.func.kind() == ast.ASTKind.Name: - dnm2: ast.Name | t.CPtr = (ast.Name | t.CPtr)(dcl.func) - dname = dnm2.id - # @repeat(3):取首个常量 int 参数(对齐 TPC L1182-1184) - if dcl.args is not None and len(dcl.args) >= 1: - da0: ast.AST | t.CPtr = dcl.args.get(0) - if da0 is not None and da0.kind() == ast.ASTKind.Constant: - dc0: ast.Constant | t.CPtr = (ast.Constant | t.CPtr)(da0) - if dc0.const_kind == ast.CONST_INT: - decor_arg0 = dc0.int_val - if dname is None: - continue - # 跳过内置装饰器 - if string.strcmp(dname, "staticmethod") == 0 \ - or string.strcmp(dname, "property") == 0 \ - or string.strcmp(dname, "classmethod") == 0: - continue - # 跳过 t 模块存储类标记(@t.CExport/@t.CExtern/@t.State/@t.TLS/ - # @t.CStatic/@t.CInline/@t.CVTable/@t.NoVTable/@t.Object/@t.CEnum - # /@t.CUnion/@t.REnum/@t.CDefine 等裸名形式——Attribute 形式 - # @t.xxx 的 kind 是 Attribute,不进入本检测) - if string.strcmp(dname, "CExport") == 0 \ - or string.strcmp(dname, "CExtern") == 0 \ - or string.strcmp(dname, "State") == 0 \ - or string.strcmp(dname, "TLS") == 0 \ - or string.strcmp(dname, "CStatic") == 0 \ - or string.strcmp(dname, "CInline") == 0 \ - or string.strcmp(dname, "CVTable") == 0 \ - or string.strcmp(dname, "NoVTable") == 0 \ - or string.strcmp(dname, "Object") == 0 \ - or string.strcmp(dname, "CEnum") == 0 \ - or string.strcmp(dname, "CUnion") == 0 \ - or string.strcmp(dname, "REnum") == 0 \ - or string.strcmp(dname, "CDefine") == 0: - continue - has_custom_decor = 1 - decor_handler = dname - break - - # 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 = len(alist_e) - 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 \ - and 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 None: - # fail-fast:外部声明函数参数有注解但类型解析失败, - # 不再静默保持 i32(声明签名错误会在 ABI 层暴露) - HandlesType.fatal_error( - arg_e, f"参数 '{arg_e.arg}' 类型解析失败: {HandlesType.annotation_to_str(arg_e.annotation)}", - "NameError") - resolved_e = i32_ty # 不可达(fatal_error 已退出) - if resolved_e is not None: - # 裸类形参 → Ptr(struct)(对象即指针,与方法形参一致) - # CArray 形参 → 元素指针 ty*(C 数组衰减) - match resolved_e: - case llvmlite.LLVMType.Struct(_, _, _): - param_ty_e = llvmlite.Ptr(pool, resolved_e) - case llvmlite.LLVMType.Array(aelem_ty_e, _): - param_ty_e = llvmlite.Ptr(pool, aelem_ty_e) - case _: - param_ty_e = resolved_e - pname_e: str = 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: str = 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: str = 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: str = 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: str = 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 = len(tfd_alist) - 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 = len(tfd_dlist) - - # 注册到函数表 - max_funcs: int = 1024 - 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 = len(alist) - 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 \ - and 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)(对象即指针,与方法形参一致) - # CArray 形参 → 元素指针 ty*(C 数组衰减:final(out: t.CArray[..., N]) - # 的 out 指向调用方数组首元素;传 Ptr(数组) 会使 out[i] 的 - # GEP 以整个数组为步长错位,摘要垃圾根因) - match resolved: - case llvmlite.LLVMType.Struct(_, _, _): - param_ty = llvmlite.Ptr(pool, resolved) - case llvmlite.LLVMType.Array(aelem_ty, _): - param_ty = llvmlite.Ptr(pool, aelem_ty) - case _: - param_ty = resolved - pname: str = 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 - - # try-except:函数体含 raise → 追加 __eh_msg_out__(i8**)/ - # __eh_code_out__(i32*)输出参数(对齐 TPC HandlesFunctions.py - # L706-711;main 除外)。被调函数把异常编码/消息写入调用方传入 - # 的指针,调用方 _check_eh_return 检测。 - # 注意:必须在参数添加块(if args_node is not None:)外——无参函数 - # (def f())的 args_node 为 None,若放在其内会被跳过,导致函数体 - # store %__eh_code_out__ 但签名无此参数(llc: use of undefined value)。 - if string.strcmp(fd.name, "main") != 0: - if self._body_has_raise(fd) != 0: - i8_ty_eh: llvmlite.LLVMType | t.CPtr = llvmlite.Int8(pool) - i8_ptr_ty_eh: llvmlite.LLVMType | t.CPtr = llvmlite.Ptr(pool, i8_ty_eh) - i8_ptr_ptr_ty_eh: llvmlite.LLVMType | t.CPtr = llvmlite.Ptr(pool, i8_ptr_ty_eh) - i32_ty_eh: llvmlite.LLVMType | t.CPtr = llvmlite.Int32(pool) - i32_ptr_ty_eh: llvmlite.LLVMType | t.CPtr = llvmlite.Ptr(pool, i32_ty_eh) - if i8_ptr_ptr_ty_eh is not None and i32_ptr_ty_eh is not None: - llvmlite.add_param(pool, func, i8_ptr_ptr_ty_eh, "%__eh_msg_out__") - llvmlite.add_param(pool, func, i32_ptr_ty_eh, "%__eh_code_out__") - - # 参数添加完成,补全全局函数表的 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) - - # @t.TLS 一次性初始化守卫(对齐 TPC HandlesFunctions.py L1763-1792): - # 首次调用执行函数体并置全局标志 __tls_init_done_{name}=1,后续调用 - # 直接返回默认值。TPV 此前未实现 @t.TLS,_init_tls 每次 TlsAlloc 导致 - # provider 栈跨调用丢失(FakeDuckTest Test 9 注入失败根因)。 - if has_tls != 0: - tls_flag_name: str = pool.alloc(128) - if tls_flag_name is not None: - viperlib.snprintf(tls_flag_name, 128, "__tls_init_done_%s", fd.name) - tls_flag_gv: llvmlite.GlobalVariable | t.CPtr = llvmlite.create_global_int( - pool, mod, tls_flag_name, 1, 0) - if tls_flag_gv is not None: - i1_ty_t: llvmlite.LLVMType | t.CPtr = llvmlite.Int1(pool) - if i1_ty_t is not None: - # GlobalVariable 不是 Value 子类(字段布局不同),build_load/store - # 按 Value 读 ptr.Ty/ptr.Name 会错位(Ty 读到 Name → void,Name 为空)。 - # 与 create_global_string 一致:构造 Value 视图(Ty=Ptr(i1), Name="@name")。 - tls_gv_ptr_ty: llvmlite.LLVMType | t.CPtr = llvmlite.Ptr(pool, i1_ty_t) - tls_ref_name: str = pool.alloc(64) - if tls_ref_name is not None: - viperlib.snprintf(tls_ref_name, 64, "@%s", tls_flag_name) - tls_flag_ref: llvmlite.Value | t.CPtr = llvmlite.SSAValue( - pool, tls_gv_ptr_ty, tls_ref_name) - if tls_flag_ref is not None: - tls_flag_ld: llvmlite.Value | t.CPtr = llvmlite.build_load( - func_builder, i1_ty_t, tls_flag_ref) - # 块名唯一化(create_block 不自动编号,同函数同名 label 冲突) - lc_t: int = trans._label_counter - trans._label_counter = lc_t + 1 - tls_bb_buf: str = pool.alloc(64) - if tls_bb_buf is not None: - viperlib.snprintf(tls_bb_buf, 64, "tls.skip.%d", lc_t) - tls_skip_bb: llvmlite.BasicBlock | t.CPtr = llvmlite.create_block( - pool, func, tls_bb_buf) - viperlib.snprintf(tls_bb_buf, 64, "tls.cont.%d", lc_t) - tls_cont_bb: llvmlite.BasicBlock | t.CPtr = llvmlite.create_block( - pool, func, tls_bb_buf) - if tls_skip_bb is not None and tls_cont_bb is not None: - llvmlite.build_cond_br( - func_builder, tls_flag_ld, tls_skip_bb, tls_cont_bb) - # skip 块:按返回类型生成默认值直接返回 - llvmlite.position_at_end(func_builder, tls_skip_bb) - match ret_ty: - case llvmlite.LLVMType.Void(): - llvmlite.build_ret_void(func_builder) - case llvmlite.LLVMType.Int(_): - tlz0: llvmlite.Value | t.CPtr = llvmlite.ConstInt( - pool, ret_ty, 0, "0") - if tlz0 is not None: - llvmlite.build_ret(func_builder, tlz0) - case llvmlite.LLVMType.Float(_): - tlf0: llvmlite.Value | t.CPtr = llvmlite.ConstFloat( - pool, ret_ty, 0.0) - if tlf0 is not None: - llvmlite.build_ret(func_builder, tlf0) - case _: - tln0: llvmlite.Value | t.CPtr = llvmlite.ConstNull( - pool, ret_ty, "null") - if tln0 is not None: - llvmlite.build_ret(func_builder, tln0) - # cont 块:置标志=1,继续函数体 - llvmlite.position_at_end(func_builder, tls_cont_bb) - tlone: llvmlite.Value | t.CPtr = llvmlite.ConstInt( - pool, i1_ty_t, 1, "1") - if tlone is not None: - llvmlite.build_store(func_builder, tlone, tls_flag_ref) - - # 进入函数作用域(嵌套符号表) - 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 = len(fd.type_params) - 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 = len(alist2) - 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 None: - # fail-fast:参数有注解但类型解析失败,不再静默保持 i32 - HandlesType.fatal_error( - arg2, f"参数 '{arg2.arg}' 类型解析失败: {HandlesType.annotation_to_str(arg2.annotation)}", - "NameError") - resolved2 = i32_ty # 不可达(fatal_error 已退出) - if resolved2 is not None: - # 与 add_param 保持一致:裸类形参 → Ptr(struct)(对象即指针); - # CArray 形参 → 元素指针 ty*(数组衰减,alloca 类型须与形参一致, - # 否则 store ty* 到 [N x ty]* 容器类型不匹配) - match resolved2: - case llvmlite.LLVMType.Struct(_, _, _): - param_ty2 = llvmlite.Ptr(pool, resolved2) - case llvmlite.LLVMType.Array(aelem_ty2, _): - param_ty2 = llvmlite.Ptr(pool, aelem_ty2) - 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) 回退到类名查找结构体) - # 传 pool:泛型 Subscript 返回 mangled name(对齐 HandlesAnnAssign 修复) - cls_nm: str = None - if arg2.annotation is not None: - cls_nm = HandlesType.extract_class_name_from_annotation( - arg2.annotation, imported_modules, pool) - if cls_nm is not None: - HandlesVar.set_var_annot_class_name( - trans.SymTab, arg2.arg, cls_nm) - pname2: str = 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) 糖函数 - # 注意:必须在参数 alloca 段(if args_node is not None:)内但 EH 块外—— - # 无 raise 的函数(viperlib.sprintf 等)同样有 *args,若放在 EH 块内 - # 会被跳过,args 未注册到符号表 → NameError: 未定义名称 'args'。 - 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 - - # try-except:新函数作用域 EH 状态从零开始。必须先保存外层函数 - # (调用方/包围函数)的 EH 输出参数,翻译完本函数后再恢复——否则 - # 下方设置本函数 EH 参数会覆盖外层值,恢复时 old_eh_* 拿到的是 - # 本函数自身参数(嵌套函数/多函数链 EH 状态错乱)。 - old_eh_msg_out: llvmlite.Value | t.CPtr = trans._eh_msg_out_param - old_eh_code_out: llvmlite.Value | t.CPtr = trans._eh_code_out_param - old_cur_func_has_eh: int = trans._cur_func_has_eh - trans._eh_msg_out_param = None - trans._eh_code_out_param = None - trans._cur_func_has_eh = 0 - - # try-except:保存当前函数的 EH 输出参数(__eh_msg_out__/__eh_code_out__) - # 供 translate_raise / UnhandledBB 写入并向上传播。无 EH 参数的函数置空。 - if string.strcmp(fd.name, "main") != 0 and self._body_has_raise(fd) != 0: - i8_ty_eh2: llvmlite.LLVMType | t.CPtr = llvmlite.Int8(pool) - i8_ptr_ty_eh2: llvmlite.LLVMType | t.CPtr = llvmlite.Ptr(pool, i8_ty_eh2) - i8_ptr_ptr_ty_eh2: llvmlite.LLVMType | t.CPtr = llvmlite.Ptr(pool, i8_ptr_ty_eh2) - i32_ty_eh2: llvmlite.LLVMType | t.CPtr = llvmlite.Int32(pool) - i32_ptr_ty_eh2: llvmlite.LLVMType | t.CPtr = llvmlite.Ptr(pool, i32_ty_eh2) - if i8_ptr_ptr_ty_eh2 is not None and i32_ptr_ty_eh2 is not None: - msg_out_ref: llvmlite.Value | t.CPtr = llvmlite.SSAValue( - pool, i8_ptr_ptr_ty_eh2, "%__eh_msg_out__") - code_out_ref: llvmlite.Value | t.CPtr = llvmlite.SSAValue( - pool, i32_ptr_ty_eh2, "%__eh_code_out__") - trans._eh_msg_out_param = msg_out_ref - trans._eh_code_out_param = code_out_ref - trans._cur_func_has_eh = 1 - - # 保存模块级作用域状态(仅非变量表相关) - 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) - # 重置链内 nonlocal 堆预建标志(每函数只建一次;多嵌套函数定义 - # 共享同一堆,防重复 malloc + 二次重定向 VarEntry) - trans._nl_chain_done = 0 - - # 预扫描函数体: - # 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 = len(body) - 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 = len(body) - for bi2 in range(bn2): - stmt2: ast.AST | t.CPtr = body.get(bi2) - if stmt2 is not None: - # 嵌套函数定义前:预扫描其链内 nonlocal 并建堆 - # (不同层捕获不同变量的场景,见 _prepare_chain_nonlocals) - if stmt2.kind() == ast.ASTKind.FunctionDef: - self._prepare_chain_nonlocals( - trans, stmt2, pool, func_builder, mod, - llvmlite.Int8(pool), llvmlite.Ptr(pool, llvmlite.Int8(pool))) - HandlesBody.translate_stmt(trans, stmt2) - - # 如果函数体最后一条语句不是 Return,添加隐式 ret - last_is_return: int = 0 - # 追加89:bn3 提前初始化,避免 body is None 时下方 fail-fast 分支 - # 引用未定义的 bn3(追加81 同款 NameError 风险) - bn3: t.CSizeT = 0 - if body is not None: - bn3 = len(body) - 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: - # 追加89:编译器不替代码发明返回值——函数流程真实掉出末尾而 - # 未显式 return 时 fail-fast(要求补 return,Python traceback - # 风格定位到函数)。三种合法收尾: - # ① void 函数掉出末尾 → ret void(无值可发明,Python 语义) - # ② 末句是控制流语句(match/if 全分支 return)且当前块 - # 未 terminated → merge 块结构性不可达 → unreachable - # ③ 无返回类型注解的函数(fd.returns is None,如 - # ast/base.vp _set_pos 过程风格赋值函数)→ 视为无返回值 - # 函数,默认生成零值返回(用户决策:没有返回值默认不用 - # return;ConstZero 按推断出的 ret_ty 构造,类型匹配) - # 有 -> 注解且末句是普通语句掉出末尾 → fail-fast(不得替代码 - # 发明返回值,也不做 noreturn 函数名白名单——错误终止路径 - # 也必须在源码层面保证块收尾,如显式 return 样板) - # 末句是否为控制流语句(If/Match/While/For/Try/With): - # 控制流语句翻译后当前块未 terminated 表示 merge 块结构性 - # 不可达(所有分支均已 return/terminated)——对非 void 函数 - # 生成 unreachable 而非 fail-fast(GCC/Clang 对 fall-through - # 视为 UB 同语义;追加89 修正 get_struct_name 全 case return - # 被错判"不可能抵达") - last_is_ctrl: int = 0 - if bn3 > 0: - last_stmt3: ast.AST | t.CPtr = body.get(bn3 - 1) - if last_stmt3 is not None: - k3: int = last_stmt3.kind() - if k3 == ast.ASTKind.If or k3 == ast.ASTKind.While or \ - k3 == ast.ASTKind.For or k3 == ast.ASTKind.Try or \ - k3 == ast.ASTKind.With or k3 == ast.ASTKind.Match: - last_is_ctrl = 1 - _is_void: int = 0 - if ret_ty is not None: - match ret_ty: - case llvmlite.LLVMType.Void(): - _is_void = 1 - case _: - pass - if _is_void != 0: - llvmlite.build_ret_void(func_builder) - elif last_is_ctrl != 0 and trans._ctrl_merge_reachable == 0: - # 追加90:非 void 函数末句是控制流且 merge 块结构性不可达 - # (全分支 return,无 br 到 merge)→ LLVM 语义 unreachable。 - # 注意:merge 可达(分支 br 到 merge,如 testcheck.check 的 - # if/else 无 return)时不是结构性不可达,需正常收尾(下方 - # ConstZero / fail-fast)。原实现无条件 unreachable 使 llc - # O2 把 br-to-unreachable 优化为 fall-through → 双分支执行 - # 崩溃(FuncTest check PASS+FAIL 双打印) - llvmlite.build_unreachable(func_builder) - elif fd.returns is None: - # 无返回类型注解 → 无返回值过程函数,默认零值返回 - if ret_ty is not None: - zero_val: llvmlite.Value | t.CPtr = llvmlite.ConstZero(pool, ret_ty) - if zero_val is not None: - llvmlite.build_ret(func_builder, zero_val) - else: - HandlesType.fatal_error(node, "函数流程掉出末尾但未显式 return", "TypeError") - else: - HandlesType.fatal_error(node, "函数流程掉出末尾但未显式 return", "TypeError") - else: - # fail-fast:有 -> 注解但流程真实掉出末尾(定位到函数定义 - # 节点,fatal_error 输出 traceback 风格错误) - if ret_ty is not None: - # llvmlite 无 type_get_name API,类型序列化用真实接口 - # TypePrint(buf, size, ty, pool)(追加89 修正) - rt_name: str = pool.alloc(64) - if rt_name is not None: - llvmlite.TypePrint(rt_name, 64, ret_ty, pool) - if rt_name[0] == '\0': - rt_name = "?" - err_fn: str = pool.alloc(256) - if err_fn is not None: - viperlib.snprintf( - err_fn, 256, - "函数 '%s' 流程掉出函数末尾但未显式 return(返回类型 %s)," - "请补显式 return(如 return 0 / return null)", fd.name, rt_name) - HandlesType.fatal_error(node, err_fn, "TypeError") - HandlesType.fatal_error(node, "函数流程掉出末尾但未显式 return", "TypeError") - else: - HandlesType.fatal_error(node, "函数流程掉出末尾但未显式 return", "TypeError") - - # 恢复模块级作用域(退出函数作用域) - 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 - # 恢复外层函数(调用方)的 EH 输出参数——本函数体内的 raise 传播 - # 使用本函数参数,翻译结束必须交还外层作用域,否则嵌套函数/链式 - # 调用后 EH 状态残留导致 raise 写入错误的 out 指针。 - trans._eh_msg_out_param = old_eh_msg_out - trans._eh_code_out_param = old_eh_code_out - trans._cur_func_has_eh = old_cur_func_has_eh - - # 自定义装饰器:注册 + 生成 wrapper(对齐 TPC DecoratorPass.run)。 - # 仅模块级函数(fd 是顶层定义);wrapper 名 __decor_wrap_{裸函数名}。 - # 调用点重写经 lookup_decor_wrapper(translate_call 拦截原函数名)。 - if has_custom_decor != 0: - wb_name: str = pool.alloc(128) - if wb_name is not None: - viperlib.snprintf(wb_name, 128, "__decor_wrap_%s", fd.name) - HandlesClassDef.register_decorator(pool, fd.name, wb_name, decor_arg0) - self._gen_decor_wrapper( - trans, pool, mod, func, fd.name, wb_name, - decor_handler, decor_arg0) - - return 0 - - # ============================================================ - # _gen_decor_wrapper - 生成装饰器 wrapper 函数(对齐 TPC DecoratorPass.py - # _generate_single_wrapper v4) - # - # v4 Wrapper 结构(最外层含递归保护): - # entry → 递归保护检查(最外层) - # recursive_call → 递归时直接调用原函数,跳过所有装饰 - # decorated_entry → 置递归标志,分配 ctx/args/ret,调用 handler 前置 - # loop_header → 计数器 i < n_calls(TPV 用 alloca 计数器替代 phi) - # loop.body → 从 args_struct 读回参数,调用原函数 - # post → 调用 handler 后置,清递归标志,返回结果 - # - # handler 调用约定:i32 decor(i8* ctx, i8* func_name, i32 phase, - # i8* args_ptr, i8* ret_ptr, i8* decor_args_ptr) - # 前置返回:0=跳过原函数,1=调用一次,N=循环 N 次 - # ============================================================ - def _gen_decor_wrapper(self, trans: HT.Translator | t.CPtr, - pool: memhub.MemBuddy | t.CPtr, - mod: llvmlite.LLVMModule | t.CPtr, - func: llvmlite.Function | t.CPtr, - func_name: str, - wrapper_name: str, - handler_name: str, - decor_arg0: t.CInt64T) -> llvmlite.Function | t.CPtr: - """生成装饰器 wrapper 函数,返回 wrapper 或 None""" - if trans is None or pool is None or mod is None or func is None: - return None - if func_name is None or wrapper_name is None or handler_name is None: - return None - ret_ty: llvmlite.LLVMType | t.CPtr = llvmlite.function_get_ret_ty(func) - if ret_ty is None: - return None - orig_call_name: str = llvmlite.function_get_name(func) - if orig_call_name is None: - return None - - 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) - - # ---- 收集原函数参数类型(按位置,最多 16 个)---- - n_params: int = 0 - param_tys: t.CSizeT | t.CPtr = pool.alloc(16 * 8) - if param_tys is None: - return None - string.memset(param_tys, 0, 16 * 8) - pp: llvmlite.Param | t.CPtr = llvmlite.function_get_param_head(func) - while pp is not None: - pty: llvmlite.LLVMType | t.CPtr = llvmlite.param_get_ty(pp) - if pty is not None and n_params < 16: - param_tys[n_params] = t.CSizeT(pty) - n_params += 1 - pp = llvmlite.param_get_next(pp) - - # ---- 创建 wrapper 函数并添加参数(名字 %a0..%aN)---- - wrapper: llvmlite.Function | t.CPtr = llvmlite.create_function( - pool, mod, wrapper_name, ret_ty) - if wrapper is None: - return None - pi: int = 0 - for pi in range(n_params): - pname_w: str = pool.alloc(16) - if pname_w is not None: - viperlib.snprintf(pname_w, 16, "%%a%d", pi) - llvmlite.add_param(pool, wrapper, (llvmlite.LLVMType | t.CPtr)( - t.CVoid(param_tys[pi], t.CPtr)), pname_w) - - # ---- 创建块 ---- - entry_bb: llvmlite.BasicBlock | t.CPtr = llvmlite.create_block(pool, wrapper, "entry") - loop_h_bb: llvmlite.BasicBlock | t.CPtr = llvmlite.create_block(pool, wrapper, "loop.header") - loop_b_bb: llvmlite.BasicBlock | t.CPtr = llvmlite.create_block(pool, wrapper, "loop.body") - post_bb: llvmlite.BasicBlock | t.CPtr = llvmlite.create_block(pool, wrapper, "post") - if entry_bb is None or loop_h_bb is None or loop_b_bb is None or post_bb is None: - return None - - # 递归保护标志(最外层):@__decor_rec_{wrapper} = global i8 0 - rec_flag_ref: llvmlite.Value | t.CPtr = None - rec_flag_name: str = pool.alloc(128) - if rec_flag_name is not None: - viperlib.snprintf(rec_flag_name, 128, "__decor_rec_%s", wrapper_name) - llvmlite.create_global_int(pool, mod, rec_flag_name, 8, 0) - rec_ref_nm: str = pool.alloc(96) - if rec_ref_nm is not None: - viperlib.snprintf(rec_ref_nm, 96, "@%s", rec_flag_name) - rec_flag_ref = llvmlite.SSAValue(pool, llvmlite.Ptr(pool, i8_ty), rec_ref_nm) - - wb: llvmlite.IRBuilder | t.CPtr = llvmlite.new_builder(pool, wrapper) - if wb is None: - return None - - # 返回类型分类 - ret_is_void: int = 0 - match ret_ty: - case llvmlite.LLVMType.Void(): - ret_is_void = 1 - case _: - pass - - # ---- entry:递归保护检查(最外层)---- - llvmlite.position_at_end(wb, entry_bb) - loop_pred_bb: llvmlite.BasicBlock | t.CPtr = entry_bb - if rec_flag_ref is not None: - rec_bb: llvmlite.BasicBlock | t.CPtr = llvmlite.create_block(pool, wrapper, "recursive_call") - dec_bb: llvmlite.BasicBlock | t.CPtr = llvmlite.create_block(pool, wrapper, "decorated_entry") - if rec_bb is None or dec_bb is None: - return None - rec_val: llvmlite.Value | t.CPtr = llvmlite.build_load(wb, i8_ty, rec_flag_ref) - rec_zero: llvmlite.Value | t.CPtr = llvmlite.ConstInt(pool, i8_ty, 0, "0") - rec_is: llvmlite.Value | t.CPtr = llvmlite.build_icmp( - wb, llvmlite.ICMP_NE, rec_val, rec_zero) - llvmlite.build_cond_br(wb, rec_is, rec_bb, dec_bb) - # recursive_call:直接调用原函数返回(跳过所有装饰逻辑) - llvmlite.position_at_end(wb, rec_bb) - rec_args: llvmlite.Value | t.CPtr = None - ri: int = 0 - for ri in range(n_params): - an_r: str = pool.alloc(16) - if an_r is None: - continue - viperlib.snprintf(an_r, 16, "%%a%d", ri) - av_r: llvmlite.Value | t.CPtr = llvmlite.SSAValue( - pool, (llvmlite.LLVMType | t.CPtr)(t.CVoid(param_tys[ri], t.CPtr)), an_r) - if av_r is not None: - llvmlite.value_set_next(av_r, None) - if rec_args is None: - rec_args = av_r - else: - # 链尾追加 - rt: llvmlite.Value | t.CPtr = rec_args - while rt.Next is not None: - rt = rt.Next - llvmlite.value_set_next(rt, av_r) - if ret_is_void != 0: - llvmlite.build_call(wb, orig_call_name, rec_args, n_params, ret_ty, 0) - llvmlite.build_ret_void(wb) - else: - rc_res: llvmlite.Value | t.CPtr = llvmlite.build_call( - wb, orig_call_name, rec_args, n_params, ret_ty, 0) - if rc_res is not None: - llvmlite.build_ret(wb, rc_res) - else: - llvmlite.build_ret_void(wb) - # decorated_entry:置递归标志,继续装饰路径 - llvmlite.position_at_end(wb, dec_bb) - rec_one: llvmlite.Value | t.CPtr = llvmlite.ConstInt(pool, i8_ty, 1, "1") - if rec_one is not None: - llvmlite.build_store(wb, rec_one, rec_flag_ref) - loop_pred_bb = dec_bb - - # ---- 公共装饰路径(entry 或 decorated_entry)---- - # 1. ctx = alloca [32 x i8]; ctx_ptr = bitcast i8* - ctx_ty: llvmlite.LLVMType | t.CPtr = llvmlite.Array(pool, i8_ty, 32) - ctx_alloca: llvmlite.Value | t.CPtr = llvmlite.build_alloca(wb, ctx_ty) - ctx_ptr: llvmlite.Value | t.CPtr = llvmlite.build_bitcast(wb, ctx_alloca, i8_ptr_ty) - - # 2. 打包函数参数到结构体 {param_types}(装饰器可读写 args_ptr) - args_alloca: llvmlite.Value | t.CPtr = None - args_ptr: llvmlite.Value | t.CPtr = None - if n_params > 0: - fields_head: llvmlite.ParamNode | t.CPtr = None - fk: int = 0 - for fk in range(n_params - 1, -1, -1): - pn_n: llvmlite.ParamNode | t.CPtr = llvmlite.new_param_node( - pool, (llvmlite.LLVMType | t.CPtr)(t.CVoid(param_tys[fk], t.CPtr))) - if pn_n is not None: - pn_n.Next = fields_head - fields_head = pn_n - args_ty: llvmlite.LLVMType | t.CPtr = llvmlite.Struct( - pool, fields_head, n_params, None) - if args_ty is not None: - args_alloca = llvmlite.build_alloca(wb, args_ty) - fi2: int = 0 - for fi2 in range(n_params): - fld_ty: llvmlite.LLVMType | t.CPtr = (llvmlite.LLVMType | t.CPtr)( - t.CVoid(param_tys[fi2], t.CPtr)) - fld_ptr: llvmlite.Value | t.CPtr = llvmlite.build_gep_struct( - wb, args_ty, fld_ty, args_alloca, fi2) - if fld_ptr is not None: - fld_nm: str = pool.alloc(16) - if fld_nm is not None: - viperlib.snprintf(fld_nm, 16, "%%a%d", fi2) - fld_v: llvmlite.Value | t.CPtr = llvmlite.SSAValue( - pool, fld_ty, fld_nm) - if fld_v is not None: - llvmlite.build_store(wb, fld_v, fld_ptr) - args_ptr = llvmlite.build_bitcast(wb, args_alloca, i8_ptr_ty) - else: - args_ptr = llvmlite.ConstNull(pool, i8_ptr_ty, "null") - - # 3. 返回值存储(零初始化;跳过原函数时返回安全默认值) - ret_alloca: llvmlite.Value | t.CPtr = None - if ret_is_void == 0: - ret_alloca = llvmlite.build_alloca(wb, ret_ty) - ret_zero: llvmlite.Value | t.CPtr = None - match ret_ty: - case llvmlite.LLVMType.Int(_): - ret_zero = llvmlite.ConstInt(pool, ret_ty, 0, "0") - case llvmlite.LLVMType.Float(_): - ret_zero = llvmlite.ConstFloat(pool, ret_ty, 0.0) - case _: - ret_zero = llvmlite.ConstNull(pool, ret_ty, "null") - if ret_zero is not None and ret_alloca is not None: - llvmlite.build_store(wb, ret_zero, ret_alloca) - - # 4. 函数名字符串常量 - fn_str: llvmlite.Value | t.CPtr = HandlesExpr.create_global_string( - wb, pool, mod, func_name, trans) - if fn_str is None: - fn_str = llvmlite.ConstNull(pool, i8_ptr_ty, "null") - - # 5. handler 声明(未翻译时 declare,固定签名 i32 (i8*,i8*,i32,i8*,i8*,i8*)) - if HandlesExprCall.find_func_in_module(mod, handler_name) is None: - handler_d: llvmlite.Function | t.CPtr = llvmlite.create_declare( - pool, mod, handler_name, i32_ty) - if handler_d is not None: - llvmlite.add_param(pool, handler_d, i8_ptr_ty, "ctx") - llvmlite.add_param(pool, handler_d, i8_ptr_ty, "func_name") - llvmlite.add_param(pool, handler_d, i32_ty, "phase") - llvmlite.add_param(pool, handler_d, i8_ptr_ty, "args_ptr") - llvmlite.add_param(pool, handler_d, i8_ptr_ty, "ret_ptr") - llvmlite.add_param(pool, handler_d, i8_ptr_ty, "decor_args_ptr") - - # 6. 前置阶段:handler 返回调用次数 n_calls - ph0: llvmlite.Value | t.CPtr = llvmlite.ConstInt(pool, i32_ty, 0, "0") - null_ret: llvmlite.Value | t.CPtr = llvmlite.ConstNull(pool, i8_ptr_ty, "null") - null_dec: llvmlite.Value | t.CPtr = llvmlite.ConstNull(pool, i8_ptr_ty, "null") - # 参数链表(6 个独立值):ctx_ptr → fn_str → 0 → args_ptr → null → null - # 注意:不能 self 链接(null.Next = null 会让 build_call 遍历死循环) - if ctx_ptr is not None: - llvmlite.value_set_next(ctx_ptr, fn_str) - if fn_str is not None: - llvmlite.value_set_next(fn_str, ph0) - if ph0 is not None: - llvmlite.value_set_next(ph0, args_ptr) - if args_ptr is not None: - llvmlite.value_set_next(args_ptr, null_ret) - if null_ret is not None: - llvmlite.value_set_next(null_ret, null_dec) - n_calls: llvmlite.Value | t.CPtr = llvmlite.build_call( - wb, handler_name, ctx_ptr, 6, i32_ty, 0) - - # 7. 计数器 alloca(TPV 用 alloca 计数器替代 phi) - cnt_alloca: llvmlite.Value | t.CPtr = llvmlite.build_alloca(wb, i32_ty) - cnt_zero: llvmlite.Value | t.CPtr = llvmlite.ConstInt(pool, i32_ty, 0, "0") - if cnt_alloca is not None and cnt_zero is not None: - llvmlite.build_store(wb, cnt_zero, cnt_alloca) - llvmlite.build_br(wb, loop_h_bb) - - # 8. loop.header:cur = load cnt; cur < n_calls → body / post - llvmlite.position_at_end(wb, loop_h_bb) - cur_i: llvmlite.Value | t.CPtr = llvmlite.build_load(wb, i32_ty, cnt_alloca) - loop_cond: llvmlite.Value | t.CPtr = llvmlite.build_icmp( - wb, llvmlite.ICMP_SLT, cur_i, n_calls) - llvmlite.build_cond_br(wb, loop_cond, loop_b_bb, post_bb) - - # 9. loop.body:读回参数(装饰器可能已修改)→ 调用原函数 → store ret - llvmlite.position_at_end(wb, loop_b_bb) - call_args: llvmlite.Value | t.CPtr = None - if n_params > 0: - k: int = 0 - for k in range(n_params): - fld_ty_k: llvmlite.LLVMType | t.CPtr = (llvmlite.LLVMType | t.CPtr)( - t.CVoid(param_tys[k], t.CPtr)) - fld_pk: llvmlite.Value | t.CPtr = llvmlite.build_gep_struct( - wb, args_ty, fld_ty_k, args_alloca, k) - if fld_pk is None: - continue - fld_vk: llvmlite.Value | t.CPtr = llvmlite.build_load(wb, fld_ty_k, fld_pk) - if fld_vk is not None: - llvmlite.value_set_next(fld_vk, None) - if call_args is None: - call_args = fld_vk - else: - ct: llvmlite.Value | t.CPtr = call_args - while ct.Next is not None: - ct = ct.Next - llvmlite.value_set_next(ct, fld_vk) - res_v: llvmlite.Value | t.CPtr = llvmlite.build_call( - wb, orig_call_name, call_args, n_params, ret_ty, 0) - if ret_alloca is not None and res_v is not None: - llvmlite.build_store(wb, res_v, ret_alloca) - nxt_i: llvmlite.Value | t.CPtr = llvmlite.build_add( - wb, cur_i, llvmlite.ConstInt(pool, i32_ty, 1, "1")) - if nxt_i is not None and cnt_alloca is not None: - llvmlite.build_store(wb, nxt_i, cnt_alloca) - llvmlite.build_br(wb, loop_h_bb) - - # 10. post:handler 后置 → 清递归标志 → 返回结果 - llvmlite.position_at_end(wb, post_bb) - ret_ptr: llvmlite.Value | t.CPtr = null_ret - if ret_alloca is not None: - ret_ptr = llvmlite.build_bitcast(wb, ret_alloca, i8_ptr_ty) - ph1: llvmlite.Value | t.CPtr = llvmlite.ConstInt(pool, i32_ty, 1, "1") - # 后置参数链:ctx_ptr → fn_str → 1 → args_ptr → ret_ptr → null - if ctx_ptr is not None: - llvmlite.value_set_next(ctx_ptr, fn_str) - if fn_str is not None: - llvmlite.value_set_next(fn_str, ph1) - if ph1 is not None: - llvmlite.value_set_next(ph1, args_ptr) - if args_ptr is not None: - llvmlite.value_set_next(args_ptr, ret_ptr) - if ret_ptr is not None: - llvmlite.value_set_next(ret_ptr, null_dec) - llvmlite.build_call(wb, handler_name, ctx_ptr, 6, i32_ty, 0) - if rec_flag_ref is not None: - rec_zero2: llvmlite.Value | t.CPtr = llvmlite.ConstInt(pool, i8_ty, 0, "0") - if rec_zero2 is not None: - llvmlite.build_store(wb, rec_zero2, rec_flag_ref) - if ret_is_void != 0: - llvmlite.build_ret_void(wb) - else: - final_v: llvmlite.Value | t.CPtr = llvmlite.build_load(wb, ret_ty, ret_alloca) - if final_v is not None: - llvmlite.build_ret(wb, final_v) - else: - llvmlite.build_ret_void(wb) - - return wrapper # ============================================================ @@ -1560,7 +99,7 @@ class FuncGenMixin: promoted_name: str = 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) + mangled_promoted: str = HandlesExprCall._mangle_name(trans, promoted_name) # 2. 创建提升后的函数: define i32 @__closure_{name}(i8* %env, args...) func: llvmlite.Function | t.CPtr = llvmlite.create_function( @@ -1976,7 +515,7 @@ class FuncGenMixin: """构造 nonlocal 堆地址全局映射变量名 nlheap_{sha1}.{name}""" if pool is None or trans is None or name is None: return None - mangled: str = self._mangle_name(trans, name) + mangled: str = HandlesExprCall._mangle_name(trans, name) buf: str = pool.alloc(160) if buf is not None: viperlib.snprintf(buf, 160, "nlheap_%s", mangled) @@ -2206,7 +745,7 @@ class FuncGenMixin: if pname_buf is None: return None viperlib.snprintf(pname_buf, 64, "__lambda_%d", lambda_id) - mangled_promoted: str = self._mangle_name(trans, pname_buf) + mangled_promoted: str = HandlesExprCall._mangle_name(trans, pname_buf) # 2. 解析参数(名称 + 类型,类型默认 i32,有注解则解析) param_names: str = pool.alloc(32 * 64) # 64 参数 × 32 字节名 @@ -2637,47 +1176,3 @@ class FuncGenMixin: return self._lambda_scan_body(trans, lam2.body, param_names, param_count, cap_names, cap_allocas, cap_tys, cap_count) return cap_count - - # ============================================================ - # 创建 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 = len(alist) - 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: str = 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 ff3d16f..dcfb9fb 100644 --- a/App/lib/core/Gen/Generator.vp +++ b/App/lib/core/Gen/Generator.vp @@ -18,6 +18,8 @@ import lib.core.Gen.CallGenVt as CallGenVt import lib.core.Gen.CallGenVa as CallGenVa import lib.core.Gen.CallGenLib as CallGenLib import lib.core.Gen.CallGenDispatch as CallGenDispatch +import lib.core.Gen.FuncGenBase as FuncGenBase +import lib.core.Gen.FuncGenDef as FuncGenDef import lib.core.Gen.FuncGenMixin as FuncGenMixin import lib.core.Gen.ClassGenMixin as ClassGenMixin import lib.core.Gen.ImportsGenMixin as ImportsGenMixin @@ -50,6 +52,7 @@ class Generator(BaseGenMixin.BaseGenMixin, TypeGenMixin.TypeGenMixin, CallGenProp.CallGenProp, CallGenFd.CallGenFd, CallGenVt.CallGenVt, CallGenVa.CallGenVa, CallGenLib.CallGenLib, CallGenDispatch.CallGenDispatch, + FuncGenBase.FuncGenBase, FuncGenDef.FuncGenDef, FuncGenMixin.FuncGenMixin, ClassGenMixin.ClassGenMixin, ImportsGenMixin.ImportsGenMixin, StmtGenMixin.StmtGenMixin, AssignGenMixin.AssignGenMixin, diff --git a/App/lib/core/Handles/HandlesExprCall.vp b/App/lib/core/Handles/HandlesExprCall.vp index 25d596c..dfb5f92 100644 --- a/App/lib/core/Handles/HandlesExprCall.vp +++ b/App/lib/core/Handles/HandlesExprCall.vp @@ -1981,3 +1981,61 @@ def _tc_h6_method_dispatch(pool: memhub.MemBuddy | t.CPtr, if g is not None: return g._tc_h6_method_dispatch(pool, builder, mod, cl, funcs_ptr, func_count, trans, func_name, cargs, can) return None + + +# ============================================================ +# FuncGen 跨 Mixin 委托(阶段 D:FuncGenMixin 拆 Base/Def 后顶层经 +# 此调用这些方法。参数与目标方法一致,去 self) +# ============================================================ +def extract_func_attrs(pool: memhub.MemBuddy | t.CPtr, + decorator_list: list[ast.AST | t.CPtr] | t.CPtr, + imported_modules: str) -> str: + """从 decorator_list 提取 c.Attribute 属性(委托到 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 _mangle_name(trans: HT.Translator | t.CPtr, name: str) -> str: + """为任意名称添加 SHA1 前缀(委托到 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 name + + +def _mangle_func_name(trans: HT.Translator | t.CPtr, name: str, + has_export: int) -> str: + """为函数名添加 SHA1 前缀(委托到 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 name + + +def _body_has_raise(fd: ast.FunctionDef | t.CPtr) -> int: + """函数体顶层是否含 raise(委托到 gen._body_has_raise)""" + 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._body_has_raise(fd) + return 0 + + +def _prepare_chain_nonlocals(trans: HT.Translator | t.CPtr, + node: ast.AST | t.CPtr, + pool: memhub.MemBuddy | t.CPtr, + builder: llvmlite.IRBuilder | t.CPtr, + mod: llvmlite.LLVMModule | t.CPtr, + i8_ty: llvmlite.LLVMType | t.CPtr, + i8_ptr_ty: llvmlite.LLVMType | t.CPtr) -> int: + """准备嵌套函数 nonlocals 链(委托到 gen._prepare_chain_nonlocals)""" + 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._prepare_chain_nonlocals(trans, node, pool, builder, mod, i8_ty, i8_ptr_ty) + return 0