- Gen 内部 1742 处 HandlesX.func() 改 self.Gen.Y.method() 链式调用 - 数据类/常量迁移 GenTypes.vp(10 类 + CLASS_META_*/META_*/SEQ_KIND_*/FIELD_MAX 等) - 管线/保留文件经 GenApi.vp 模块级入口(48 函数带类型注解,从 Gen 方法签名自动生成) - 删除 26 个纯委托 Handles 文件,仅留 5 个实体文件(Base/Translator/Expr/ExprCall/ExprCallTable) - 修复字段分裂:TypeGenErr CurrentFile/TraceCount 链式化;CallGenBase TempDir/Cexport 真源化
1232 lines
72 KiB
Plaintext
1232 lines
72 KiB
Plaintext
import lib.core.Gen.GenTypes as GenTypes
|
||
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.HandlesExpr as HandlesExpr
|
||
import lib.core.Handles.HandlesExprCall as HandlesExprCall
|
||
import lib.core.Handles.ExprCallTable as ExprCallTable
|
||
|
||
|
||
# ============================================================
|
||
# 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: GenTypes.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 = self.Gen.TypeGenResolve.resolve_annotation_type(
|
||
pool, fd.returns, imported_modules, from_imports, trans)
|
||
if ret_ty is None and fd.returns is not None:
|
||
if self.Gen.TypeGenErr.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 = self.Gen.TypeGenErr.has_decorator_marker(fd.returns, "CExtern")
|
||
has_state = self.Gen.TypeGenErr.has_decorator_marker(fd.returns, "State")
|
||
has_export = self.Gen.TypeGenErr.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 self.Gen.ClassGenBase._has_decorator(fd.decorator_list, "CExtern") == 1:
|
||
has_extern = 1
|
||
if has_state == 0 and self.Gen.ClassGenBase._has_decorator(fd.decorator_list, "State") == 1:
|
||
has_state = 1
|
||
if has_export == 0 and self.Gen.ClassGenBase._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.Gen.FuncGenBase._mangle_func_name(trans, fd.name, 0)
|
||
|
||
# 如果函数已存在(如重复定义),跳过
|
||
existing: llvmlite.Function | t.CPtr = self.Gen.CallGenBase.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 self.Gen.CallGenLeafKit.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:
|
||
self.Gen.CallGenBase.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 self.Gen.TypeGenResolve._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 = self.Gen.TypeGenResolve.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 后使用)
|
||
self.Gen.CallGenLeafKit.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: GenTypes.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 = self.Gen.TypeGenResolve.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 self.Gen.TypeGenErr.has_decorator_marker(fd.returns, "State") != 0:
|
||
ret_ty = llvmlite.Void(pool)
|
||
|
||
# 如果仍然为 None,扫描 return 语句推断(至少返回 i32)
|
||
if ret_ty is None:
|
||
param_types_str: str = self.Gen.TypeGenErr.build_param_types_str(pool, fd.args)
|
||
ret_ty = self.Gen.TypeGenErr.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 = self.Gen.TypeGenErr.has_decorator_marker(fd.returns, "CExtern")
|
||
has_state = self.Gen.TypeGenErr.has_decorator_marker(fd.returns, "State")
|
||
has_export = self.Gen.TypeGenErr.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 self.Gen.ClassGenBase._has_decorator(fd.decorator_list, "CExtern") == 1:
|
||
has_extern = 1
|
||
if has_state == 0 and self.Gen.ClassGenBase._has_decorator(fd.decorator_list, "State") == 1:
|
||
has_state = 1
|
||
if has_export == 0 and self.Gen.ClassGenBase._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 = self.Gen.ClassGenBase._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.Gen.FuncGenBase._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:
|
||
self.Gen.CallGenBase.register_cexport_func(trans.ModuleSha1, fd.name)
|
||
|
||
if is_extern_decl != 0:
|
||
# 外部声明函数:生成 declare(仅声明,不定义)
|
||
# 先检查是否已由 forward_declare_functions 创建,避免重复 declare
|
||
existing_extern: llvmlite.Function | t.CPtr = self.Gen.CallGenBase.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 self.Gen.CallGenLeafKit.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 self.Gen.TypeGenResolve._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 = self.Gen.TypeGenResolve.resolve_annotation_type(
|
||
pool, arg_e.annotation, imported_modules, from_imports, trans)
|
||
if resolved_e is None:
|
||
# fail-fast:外部声明函数参数有注解但类型解析失败,
|
||
# 不再静默保持 i32(声明签名错误会在 ABI 层暴露)
|
||
self.Gen.TypeGenErr.fatal_error(
|
||
arg_e, f"参数 '{arg_e.arg}' 类型解析失败: {self.Gen.TypeGenResolve.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.Gen.FuncGenBase.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
|
||
self.Gen.CallGenLeafKit.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 = self.Gen.CallGenBase.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.Gen.FuncGenBase.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.Gen.FuncGenBase.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 self.Gen.CallGenLeafKit.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 self.Gen.TypeGenResolve._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 = self.Gen.TypeGenResolve.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.Gen.FuncGenBase._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
|
||
self.Gen.CallGenLeafKit.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)
|
||
|
||
# 进入函数作用域(嵌套符号表)
|
||
self.Gen.VarGen.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")
|
||
self.Gen.TypeGenBase.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 self.Gen.TypeGenResolve._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 = self.Gen.TypeGenResolve.resolve_annotation_type(
|
||
pool, arg2.annotation, imported_modules, from_imports, trans)
|
||
if resolved2 is None:
|
||
# fail-fast:参数有注解但类型解析失败,不再静默保持 i32
|
||
self.Gen.TypeGenErr.fatal_error(
|
||
arg2, f"参数 '{arg2.arg}' 类型解析失败: {self.Gen.TypeGenResolve.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:
|
||
self.Gen.VarGen.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 = self.Gen.TypeGenResolve.extract_class_name_from_annotation(
|
||
arg2.annotation, imported_modules, pool)
|
||
if cls_nm is not None:
|
||
self.Gen.VarGen.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 名特殊处理返回地址)
|
||
self.Gen.VarGen.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.Gen.FuncGenBase._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:
|
||
self.Gen.StmtGenDecl.pre_scan_scope_decls(trans, stmt)
|
||
for bi in range(bn):
|
||
stmt: ast.AST | t.CPtr = body.get(bi)
|
||
if stmt is not None:
|
||
self.Gen.StmtGenDecl.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.Gen.FuncGen._prepare_chain_nonlocals(
|
||
trans, stmt2, pool, func_builder, mod,
|
||
llvmlite.Int8(pool), llvmlite.Ptr(pool, llvmlite.Int8(pool)))
|
||
self.Gen.StmtGen.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:
|
||
self.Gen.TypeGenErr.fatal_error(node, "函数流程掉出末尾但未显式 return", "TypeError")
|
||
else:
|
||
self.Gen.TypeGenErr.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)
|
||
self.Gen.TypeGenErr.fatal_error(node, err_fn, "TypeError")
|
||
self.Gen.TypeGenErr.fatal_error(node, "函数流程掉出末尾但未显式 return", "TypeError")
|
||
else:
|
||
self.Gen.TypeGenErr.fatal_error(node, "函数流程掉出末尾但未显式 return", "TypeError")
|
||
|
||
# 恢复模块级作用域(退出函数作用域)
|
||
if tp_names_fn is not None:
|
||
self.Gen.TypeGenBase.clear_generic_context()
|
||
self.Gen.VarGen.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)
|
||
self.Gen.ClassGenBase.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 = self.Gen.ExprGenConst.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 self.Gen.CallGenBase.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 |