void 只允许用于 void* 与 typedef 不透明结构体别名(用户 2026-10-01 定)。 此前 def f(p: void) / class C: x: void 不走 translate_annassign,会按 LLVM void 直接建形参/字段槽,生成非法 IR 拖到 llc 阶段才暴露。现补 6 处形参落点 (FuncGenDef 前向声明/外部声明/函数体/alloca 各一、ClassGenVTable 签名/alloca 各一) 与 1 处字段落点(ClassGenDef),统一编译期 TypeError。 void* 已在上游归并为 i8*,不受影响。
1388 lines
88 KiB
Plaintext
1388 lines
88 KiB
Plaintext
import lib.core.Gen.GenTypes as GenTypes
|
||
import lib.core.Gen.Func.FuncGenMixin as FuncGenMixin
|
||
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.Gen.Translator as HT
|
||
import lib.core.Gen.Call.CallGenBase as CallGenBase
|
||
import lib.core.Gen.GenApi as GenApi
|
||
import lib.core.Gen.DebugInfoGen as DebugInfoGen
|
||
|
||
|
||
# ============================================================
|
||
# FuncGenDef - 函数声明 / translate_function_def / decorator wrapper
|
||
# ============================================================
|
||
novirtual class FuncGenDef(CallGenBase.CallGenBase):
|
||
"""函数声明 / translate_function_def / decorator wrapper"""
|
||
|
||
# forward_declare_functions - 预扫描所有顶层 FunctionDef,创建前向声明
|
||
# 解决同模块内前向引用问题(如 sprintf 调用定义在后面的 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*,
|
||
tree: ast.AST*) -> int:
|
||
"""预扫描所有顶层 FunctionDef,创建前向声明"""
|
||
if trans is None or tree is None: return 0
|
||
pool: memhub.MemBuddy* = trans.Pool
|
||
mod: llvmlite.LLVMModule* = 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* = trans._funcs
|
||
|
||
i32_ty: llvmlite.LLVMType* = llvmlite.Int32(pool)
|
||
i8_ty: llvmlite.LLVMType* = llvmlite.Int8(pool)
|
||
i8_ptr_ty: llvmlite.LLVMType* = llvmlite.Ptr(pool, i8_ty)
|
||
|
||
ch: list[ast.AST*]* = 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: sizet = len(ch)
|
||
|
||
# ============================================================
|
||
# 预注册当前模块 ClassDef(declare_only 模式,仅 struct+字段+方法声明,
|
||
# 不译方法体)。背景:1a 阶段(declare_only=1)不注入 vpi、不处理
|
||
# import,依赖模块的 CTypedef(stdint 的 u16/u32/UINT 等)查表失败,
|
||
# 含此类字段的类(socket.vp SocketAddr: u16/u32/u64)1a 注册整体中止;
|
||
# 1b 此处 vpi 注入已完成、typedef 可解析,若不预注册,forward_declare
|
||
# 解析返回/参数注解(如 _MakeAddr -> SocketAddr)时类未注册 →
|
||
# "函数返回类型解析失败:注解不可解析"(WebTest socket.vp 根因)。
|
||
# 按 AST 序预注册保证同文件类间依赖(class A 引用 class B,B 在后)
|
||
# 也能先注册。已完整注册的类(1a 成功 / 依赖方 stub 注入含字段)跳过,
|
||
# 交由 translate_children 走 existing 路径,无重复处理副作用。
|
||
pre_i: sizet
|
||
for pre_i in range(cn_count):
|
||
pre_child: ast.AST* = ch.get(pre_i)
|
||
if pre_child is None: continue
|
||
if pre_child.kind() != ast.ASTKind.ClassDef: continue
|
||
pre_cd: ast.ClassDef* = ast.ClassDef*(pre_child)
|
||
if pre_cd is None or pre_cd.name is None: continue
|
||
pre_ex: GenTypes.StructEntry* = self.Gen.StructGen.find_struct_by_module(pre_cd.name, trans.ModuleSha1)
|
||
if pre_ex is not None and pre_ex.FieldCount > 0: continue
|
||
self.Gen.ClassGenDef.translate_class_def(trans, pre_child)
|
||
|
||
for ci in range(cn_count):
|
||
child: ast.AST* = ch.get(ci)
|
||
if child is None: continue
|
||
if child.kind() != ast.ASTKind.FunctionDef: continue
|
||
fd: ast.FunctionDef* = ast.FunctionDef*(child)
|
||
if fd is None or fd.name is None: continue
|
||
|
||
# PEP 695 泛型函数(def f[T](...) -> T)按普通函数编译(TPV 无泛型
|
||
# 函数特化机制,与 translate_function_def L678-691 一致):此处先设置
|
||
# 类型参数上下文(T→"int"),使返回/参数注解中的 T 可解析,否则
|
||
# forward_declare 阶段 "函数返回类型解析失败:注解不可解析"
|
||
# (ExpandKeywordsTest fn ident[T] 根因)。所有退出路径(continue /
|
||
# 循环末尾)必须 clear_generic_context,避免污染后续函数注解解析。
|
||
tp_names_fd: list[str]* = None
|
||
if fd.type_params is not None:
|
||
tp_names_fd = fd.type_params
|
||
tp_args_fd: list[str]* = list[str](pool, 8)
|
||
if tp_args_fd is not None:
|
||
tpn_fd: sizet = len(fd.type_params)
|
||
tpi_fd: sizet = 0
|
||
for tpi_fd in range(tpn_fd):
|
||
tp_args_fd.append("int")
|
||
self.Gen.TypeGenBase.set_generic_context(tp_names_fd, tp_args_fd)
|
||
|
||
# 推断返回类型
|
||
ret_ty: llvmlite.LLVMType* = None
|
||
if fd.returns is not None:
|
||
ret_ty = self.Gen.TypeGenResolve.resolve_annotation_type(pool, fd.returns, imported_modules, from_imports, trans, 0)
|
||
# 单独 t.CExport 返回注解(def free(...) -> t.CExport:)=
|
||
# 导出修饰符,无实际返回类型 → Void(根因:CExport 被 map_t_type
|
||
# 回退为 i32 → 掉尾检查强制 return i32,mm.vp free 根因)。
|
||
# CExport 混用实际类型(-> t.CExport | int)时保持解析结果。
|
||
if fd.returns.kind() == ast.ASTKind.Attribute:
|
||
ce_at: ast.Attribute* = ast.Attribute*(fd.returns)
|
||
if ce_at.attr is not None and string.strcmp(ce_at.attr, "CExport") == 0:
|
||
if ce_at.value is not None and ce_at.value.kind() == ast.ASTKind.Name:
|
||
ce_nm: ast.Name* = ast.Name*(ce_at.value)
|
||
if ce_nm.id is not None and string.strcmp(ce_nm.id, "t") == 0:
|
||
ret_ty = llvmlite.Void(pool)
|
||
if ret_ty is None and fd.returns is not None:
|
||
if self.Gen.TypeGenErr.has_decorator_marker(fd.returns, "State", 0) != 0:
|
||
ret_ty = llvmlite.Void(pool)
|
||
# @c.CReturn 装饰器已移除:遇到即编译期报错(多返回值改用 -> tuple[...])
|
||
if ret_ty is None:
|
||
self.Gen.FuncGenBase.RejectCReturnDecorator(fd, fd.decorator_list)
|
||
if ret_ty is None and fd.returns is not None:
|
||
# 有返回注解但解析失败:编译期报错,不静默回退 i32。
|
||
# (i32 回退曾导致掉尾检查强制 return i32 / 跨模块调用返回类型错位,
|
||
# mm.vp free / GetMemoryStats 根因。)无返回注解函数(def foo():)
|
||
# 保留 i32 默认,不在此报错。
|
||
self.Gen.TypeGenErr.fatal_error(fd, "函数返回类型解析失败:注解不可解析", "TypeError")
|
||
return 0
|
||
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", 0)
|
||
has_state = self.Gen.TypeGenErr.has_decorator_marker(fd.returns, "State", 0)
|
||
has_export = self.Gen.TypeGenErr.has_decorator_marker(fd.returns, "CExport", 0)
|
||
# 装饰器形式存储类标记(@t.CExport/@t.CExtern/@t.State/@t.CStatic)
|
||
# 对齐 TPC HandlesFunctions._extract_decorator_storage_flags;
|
||
# CExport/CExtern/State 影响函数名(导出裸名),CStatic 不影响函数名,
|
||
# 但登记到 static 符号表(禁止跨模块使用,见下方 RegisterStaticSymbol)。
|
||
# 注意: 用 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
|
||
|
||
# static(禁止跨模块使用):注解形态(`def f() -> t.CVoid | t.CStatic:`)
|
||
# 与装饰器形态(`@t.CStatic`;裸 `static def f(...)` 已由解析层归一为
|
||
# 装饰器)同源识别并登记。逻辑收敛在 _RegisterStaticFunc 内(不内联——
|
||
# 本函数含多分支,内联新增分支会干扰其类型推断,与 ExprGenAttr /
|
||
# CallGenMixin / TranslatorGenMixin 同款处理)。
|
||
self._RegisterStaticFunc(trans, fd)
|
||
|
||
# 计算 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* = self.Gen.CallGenBase.find_func_in_module(mod, mangled_name)
|
||
if existing is not None:
|
||
if tp_names_fd is not None:
|
||
self.Gen.TypeGenBase.clear_generic_context()
|
||
continue
|
||
|
||
# 创建 declare
|
||
func: llvmlite.Function* = llvmlite.create_declare(pool, mod, mangled_name, ret_ty)
|
||
if func is None:
|
||
if tp_names_fd is not None:
|
||
self.Gen.TypeGenBase.clear_generic_context()
|
||
continue
|
||
|
||
# 提取默认参数信息
|
||
# 注意: 必须先把属性赋给显式类型为 list[...] | t.CPtr 的局部变量再调用 __len__(),
|
||
# 否则编译器无法识别属性返回的 list 类型,GEP base 会变成 i32 0 导致 llc 报错
|
||
fd_args_node: ast.Arguments* = fd.args
|
||
fd_defaults: t.CPtr = None
|
||
fd_default_count: int = 0
|
||
fd_param_count: int = 0
|
||
if fd_args_node is not None:
|
||
fd_ags: ast.Arguments* = ast.Arguments*(fd_args_node)
|
||
if fd_ags.args is not None:
|
||
fd_alist: list[ast.AST*]* = fd_ags.args
|
||
fd_param_count = len(fd_alist)
|
||
if fd_ags.defaults is not None:
|
||
fd_dlist: list[ast.AST*]* = 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* = fd.args
|
||
if args_node is not None:
|
||
ags: ast.Arguments* = ast.Arguments*(args_node)
|
||
if ags.args is not None:
|
||
alist: list[ast.AST*]* = ags.args
|
||
an: sizet = len(alist)
|
||
for ai in range(an):
|
||
arg: ast.Arg* = ast.Arg*(alist.get(ai))
|
||
if arg is None or arg.arg is None: continue
|
||
# 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* = i32_ty
|
||
if arg.annotation is not None:
|
||
resolved: llvmlite.LLVMType* = self.Gen.TypeGenResolve.resolve_annotation_type(pool, arg.annotation, imported_modules, from_imports, trans, 0)
|
||
if resolved is None:
|
||
# [S4 fail-fast] 有注解但解析失败:不再静默用 i32
|
||
# (declare 与 define 签名不一致 → ABI 错位,运行期读栈垃圾)
|
||
self.Gen.TypeGenErr.fatal_error(arg, f"前向声明形参 '{arg.arg}' 类型注解解析失败", "NameError")
|
||
return 0
|
||
# 裸类形参 → Ptr(struct)(对象即指针,与方法形参一致)
|
||
# CArray 形参 → 元素指针 ty*(C 数组衰减,与 add_param 一致)
|
||
# 例外(三处必须同步:本处 / translate_function_def 的 extern
|
||
# 声明分支 / VpiReader 注入侧 _AggregateParamTy):
|
||
# C ABI 外部声明(t.CExtern/t.State,本模块无 define 侧)的
|
||
# 裸结构体形参按值 %Struct —— 真实被调方在 DLL/CRT,形参 ABI
|
||
# 由 C 头决定。TPC 定义侧同为按值(TransPyC/lib/core/Handles/
|
||
# HandlesTypeMerge.py L940-946「仅 IsStruct 吸收 1 层 CPtr」
|
||
# + LLVMCG/TypeConvert.py L137-143「CStruct → 具名结构体值」)。
|
||
# 值参数要求具名类型有**完整定义**(llvm-as 实测:opaque/未定义
|
||
# 具名类型作值参数 ⇒ "invalid type for function argument"),
|
||
# 故判据 = 该结构体在注册表可查(find_struct_by_type 命中,
|
||
# 先例 VpiReader._ensure_full_value_types L2633),命中则先
|
||
# 注册完整定义再按值(ensure_struct_def_in_module,先例
|
||
# CallGenCtor.vp L478);不命中(真 opaque)保持 Ptr(struct)。
|
||
match resolved:
|
||
case llvmlite.LLVMType.Void():
|
||
# void 不是合法形参类型(用户 2026-10-01:void 只能用于
|
||
# `void*` 与 `typedef 不透明结构体 = void`)。放任会按
|
||
# LLVM void 建形参 ⇒ 非法 IR 拖到 llc 才暴露,改编译期 fail-fast。
|
||
# 注意 `void*` 已在上游归并为 i8*,不会命中此分支。
|
||
self.Gen.TypeGenErr.fatal_error(arg, f"形参 '{arg.arg}' 不能是 void 类型(void 只能用于 void* 与 typedef 别名)", "TypeError")
|
||
return 0
|
||
case llvmlite.LLVMType.Struct(_, _, _):
|
||
if is_extern_decl != 0 and self.Gen.StructGen.find_struct_by_type(resolved) is not None:
|
||
self.Gen.StructGen.ensure_struct_def_in_module(pool, mod, resolved)
|
||
param_ty = resolved
|
||
else:
|
||
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
|
||
|
||
# 参数添加完成,补全全局函数表的 Spec(供 vtable 在 func 被 reset 后派生类型文本)
|
||
self.Gen.CallGenLeafKit.update_global_func_spec(fd.name, func)
|
||
|
||
# 泛型函数上下文用完即清(防泄漏到后续函数的注解解析)
|
||
if tp_names_fd is not None:
|
||
self.Gen.TypeGenBase.clear_generic_context()
|
||
|
||
# 恢复原始声明模式
|
||
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*,
|
||
node: ast.AST*) -> int:
|
||
"""翻译函数定义,返回新增的变量数(通常为 0,函数定义不增加当前作用域变量)"""
|
||
fd: ast.FunctionDef* = ast.FunctionDef*(node)
|
||
if fd is None or fd.name is None:
|
||
return 0
|
||
|
||
# async def(TPV-M1 协程):FLAG_IS_ASYNC=1(includes/ast/stmts.vp L342-345,
|
||
# 解析器把 async def 存为 FunctionDef 且 flags & 1)。
|
||
# → 走 AsyncGenMixin 状态机翻译(create_<name>/resume_<name>),
|
||
# 早返回不进普通函数路径(普通路径生成 ret 型普通函数,无法挂起/恢复)。
|
||
if fd.flags is not None and (fd.flags & 1) != 0:
|
||
return self.Gen.AsyncGen.translate_async_function(trans, node)
|
||
|
||
pool: memhub.MemBuddy* = trans.Pool
|
||
mod: llvmlite.LLVMModule* = trans.Module
|
||
imported_modules: str = trans._imported_modules
|
||
from_imports: str = trans._from_imports
|
||
funcs_ptr: GenTypes.FuncEntry* = trans._funcs
|
||
func_count: int = trans._func_count
|
||
|
||
i32_ty: llvmlite.LLVMType* = llvmlite.Int32(pool)
|
||
|
||
# 推断返回类型:优先使用返回类型注解
|
||
ret_ty: llvmlite.LLVMType* = None
|
||
if fd.returns is not None:
|
||
ret_ty = self.Gen.TypeGenResolve.resolve_annotation_type(pool, fd.returns, imported_modules, from_imports, trans, 0)
|
||
# 单独 t.CExport 返回注解(def free(...) -> t.CExport:)= 导出
|
||
# 修饰符,无实际返回类型 → Void(根因:CExport 被 map_t_type 回退
|
||
# 为 i32 → 掉尾检查强制 return i32,mm.vp free 根因)。
|
||
# 混合实际类型(-> t.CExport | int)时保持解析结果。
|
||
if fd.returns.kind() == ast.ASTKind.Attribute:
|
||
ce_at2: ast.Attribute* = ast.Attribute*(fd.returns)
|
||
if ce_at2.attr is not None and string.strcmp(ce_at2.attr, "CExport") == 0:
|
||
if ce_at2.value is not None and ce_at2.value.kind() == ast.ASTKind.Name:
|
||
ce_nm2: ast.Name* = ast.Name*(ce_at2.value)
|
||
if ce_nm2.id is not None and string.strcmp(ce_nm2.id, "t") == 0:
|
||
ret_ty = llvmlite.Void(pool)
|
||
|
||
# 如果返回类型注解纯装饰器标记(如 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) != 0:
|
||
ret_ty = llvmlite.Void(pool)
|
||
|
||
# @c.CReturn 装饰器已移除:遇到即编译期报错(多返回值改用 -> tuple[...])
|
||
if ret_ty is None:
|
||
self.Gen.FuncGenBase.RejectCReturnDecorator(fd, fd.decorator_list)
|
||
|
||
# 如果仍然为 None,扫描 return 语句推断(至少返回 i32)
|
||
if ret_ty is None:
|
||
# fail-fast:无返回类型注解(fd.returns is None)但函数体返回了
|
||
# 非 None 值 → 报错,不静默推断。返回具体值必须有显式 -> 注解,
|
||
# 编译器不替用户推断返回类型(推断位宽会掩盖返回契约,且让
|
||
# __doc__ 等依赖精确返回类型的检查静默出错)。无注解函数只允许
|
||
# 过程形态:无 return / 裸 return / return None(掉尾默认零值返回)。
|
||
if fd.returns is None:
|
||
if self.Gen.TypeGenErr.body_has_value_return(pool, fd.children) != 0:
|
||
rtn_err: str = pool.alloc(256)
|
||
if rtn_err is not None:
|
||
viperlib.snprintf(rtn_err, 256, "函数 '%s' 无返回类型注解却返回了非 None 值,请添加显式返回类型注解(如 -> int)", fd.name)
|
||
self.Gen.TypeGenErr.fatal_error(fd, rtn_err, "TypeError")
|
||
return 0
|
||
self.Gen.TypeGenErr.fatal_error(fd, "函数无返回类型注解却返回了非 None 值", "TypeError")
|
||
return 0
|
||
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", 0)
|
||
has_state = self.Gen.TypeGenErr.has_decorator_marker(fd.returns, "State", 0)
|
||
has_export = self.Gen.TypeGenErr.has_decorator_marker(fd.returns, "CExport", 0)
|
||
# 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: int64 = 0
|
||
if fd.decorator_list is not None:
|
||
ddn: sizet = len(fd.decorator_list)
|
||
for ddi in range(ddn):
|
||
deco: ast.AST* = 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* = ast.Name*(deco)
|
||
dname = dnm.id
|
||
elif dk == ast.ASTKind.Call:
|
||
dcl: ast.Call* = ast.Call*(deco)
|
||
if dcl.func is not None and dcl.func.kind() == ast.ASTKind.Name:
|
||
dnm2: ast.Name* = ast.Name*(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* = dcl.args.get(0)
|
||
if da0 is not None and da0.kind() == ast.ASTKind.Constant:
|
||
dc0: ast.Constant* = ast.Constant*(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* = self.Gen.CallGenBase.find_func_in_module(mod, mangled_name)
|
||
if existing_extern is not None: return 0
|
||
|
||
func: llvmlite.Function* = 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* = fd.args
|
||
if args_node_extern is not None:
|
||
ags_e: ast.Arguments* = ast.Arguments*(args_node_extern)
|
||
if ags_e.args is not None:
|
||
alist_e: list[ast.AST*]* = ags_e.args
|
||
an_e: sizet = len(alist_e)
|
||
for ai_e in range(an_e):
|
||
arg_e: ast.Arg* = ast.Arg*(alist_e.get(ai_e))
|
||
if arg_e is not None and arg_e.arg is not None:
|
||
# 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* = i32_ty
|
||
if arg_e.annotation is not None:
|
||
resolved_e: llvmlite.LLVMType* = self.Gen.TypeGenResolve.resolve_annotation_type(pool, arg_e.annotation, imported_modules, from_imports, trans, 0)
|
||
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 数组衰减)
|
||
# 本分支恒为 C ABI 外部声明(is_extern_decl != 0,见
|
||
# 上方 if):裸结构体形参按值 %Struct(判据与降级
|
||
# 同 forward_declare_functions / VpiReader
|
||
# _AggregateParamTy,三处必须同步)。
|
||
match resolved_e:
|
||
case llvmlite.LLVMType.Void():
|
||
# void 不是合法形参类型(用户 2026-10-01,见上方同款判据)
|
||
self.Gen.TypeGenErr.fatal_error(arg_e, f"形参 '{arg_e.arg}' 不能是 void 类型(void 只能用于 void* 与 typedef 别名)", "TypeError")
|
||
case llvmlite.LLVMType.Struct(_, _, _):
|
||
if self.Gen.StructGen.find_struct_by_type(resolved_e) is not None:
|
||
self.Gen.StructGen.ensure_struct_def_in_module(pool, mod, resolved_e)
|
||
param_ty_e = resolved_e
|
||
else:
|
||
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)
|
||
# B5:section 字符串属性走属性组 #N
|
||
func_section_e: str = self.Gen.FuncGenBase.extract_func_section(pool, fd.decorator_list, imported_modules)
|
||
if func_section_e is not None:
|
||
llvmlite.function_set_attr_group(func, func_section_e)
|
||
|
||
# 参数添加完成,补全全局函数表的 Spec
|
||
self.Gen.CallGenLeafKit.update_global_func_spec(fd.name, func)
|
||
|
||
return 0
|
||
|
||
# args_node 用于后续 alloca 创建,提前赋值
|
||
args_node: ast.Arguments* = fd.args
|
||
|
||
# 检查是否已有前向声明(由 forward_declare_functions 创建)
|
||
func: llvmlite.Function* = 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)
|
||
# B5:section 字符串属性走属性组 #N
|
||
func_section_reuse: str = self.Gen.FuncGenBase.extract_func_section(pool, fd.decorator_list, imported_modules)
|
||
if func_section_reuse is not None:
|
||
llvmlite.function_set_attr_group(func, func_section_reuse)
|
||
else:
|
||
# 创建新的 LLVM 函数(使用 SHA1 混淆名)
|
||
func = llvmlite.create_function(pool, mod, mangled_name, ret_ty)
|
||
if func is None:
|
||
VLogger.error(f"create_function {fd.name} failed", "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)
|
||
# B5:section 字符串属性走属性组 #N(LLVM 不接受内联 section="...")
|
||
func_section: str = self.Gen.FuncGenBase.extract_func_section(pool, fd.decorator_list, imported_modules)
|
||
if func_section is not None:
|
||
llvmlite.function_set_attr_group(func, func_section)
|
||
|
||
# 提取默认参数信息
|
||
tfd_defaults: t.CPtr = None
|
||
tfd_default_count: int = 0
|
||
tfd_param_count: int = 0
|
||
if args_node is not None:
|
||
tfd_ags: ast.Arguments* = ast.Arguments*(args_node)
|
||
if tfd_ags.args is not None:
|
||
tfd_alist: list[ast.AST*]* = tfd_ags.args
|
||
tfd_param_count = len(tfd_alist)
|
||
if tfd_ags.defaults is not None:
|
||
tfd_dlist: list[ast.AST*]* = 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* = ast.Arguments*(args_node)
|
||
if ags.args is not None:
|
||
alist: list[ast.AST*]* = ags.args
|
||
an: sizet = len(alist)
|
||
for ai in range(an):
|
||
arg: ast.Arg* = ast.Arg*(alist.get(ai))
|
||
if arg is not None and arg.arg is not None:
|
||
# 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* = i32_ty
|
||
if arg.annotation is not None:
|
||
resolved: llvmlite.LLVMType* = self.Gen.TypeGenResolve.resolve_annotation_type(pool, arg.annotation, imported_modules, from_imports, trans, 0)
|
||
if resolved is None:
|
||
# [S4 fail-fast] 有注解但解析失败:不再静默用 i32
|
||
# (形参类型错 → ABI 错位/字段访问错)
|
||
self.Gen.TypeGenErr.fatal_error(arg, f"形参 '{arg.arg}' 类型注解解析失败", "NameError")
|
||
return 0
|
||
# 裸类形参 → Ptr(struct)(对象即指针,与方法形参一致)
|
||
# CArray 形参 → 元素指针 ty*(C 数组衰减:final(out: t.CArray[..., N])
|
||
# 的 out 指向调用方数组首元素;传 Ptr(数组) 会使 out[i] 的
|
||
# GEP 以整个数组为步长错位,摘要垃圾根因)
|
||
match resolved:
|
||
case llvmlite.LLVMType.Void():
|
||
# void 不是合法形参类型(用户 2026-10-01,见上方同款判据)
|
||
self.Gen.TypeGenErr.fatal_error(arg, f"形参 '{arg.arg}' 不能是 void 类型(void 只能用于 void* 与 typedef 别名)", "TypeError")
|
||
return 0
|
||
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* = llvmlite.Int8(pool)
|
||
i8_ptr_ty_eh: llvmlite.LLVMType* = llvmlite.Ptr(pool, i8_ty_eh)
|
||
i8_ptr_ptr_ty_eh: llvmlite.LLVMType* = llvmlite.Ptr(pool, i8_ptr_ty_eh)
|
||
i32_ty_eh: llvmlite.LLVMType* = llvmlite.Int32(pool)
|
||
i32_ptr_ty_eh: llvmlite.LLVMType* = 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__")
|
||
|
||
# 参数添加完成,补全全局函数表的 Spec
|
||
self.Gen.CallGenLeafKit.update_global_func_spec(fd.name, func)
|
||
|
||
# 创建 entry 块
|
||
entry_blk: rawptr[llvmlite.BasicBlock] = llvmlite.create_block(pool, func, "entry")
|
||
if entry_blk is None:
|
||
return 0
|
||
|
||
# 创建函数专属 builder
|
||
func_builder: llvmlite.IRBuilder* = llvmlite.new_builder(pool, func)
|
||
if func_builder is None:
|
||
return 0
|
||
llvmlite.position_at_end(func_builder, entry_blk)
|
||
|
||
# --traceback: attach a DISubprogram to this define and set every
|
||
# instruction in the body to the entry DILocation (the statement hook
|
||
# refines it per statement). No-op when DI is disabled.
|
||
dbg_pushed: int = DebugInfoGen.PushFunction(pool, func_builder, func,
|
||
fd.lineno, fd.col_offset + 1)
|
||
|
||
# @t.TLS 一次性初始化守卫(对齐 TPC HandlesFunctions.py):首次调用执行函数体并置
|
||
# 全局标志 __tls_init_done_{name}=1,后续调用直接返回默认值。不实现则每次调用都
|
||
# TlsAlloc,provider 栈跨调用丢失。
|
||
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* = llvmlite.create_global_int(pool, mod, tls_flag_name, 1, 0)
|
||
if tls_flag_gv is not None:
|
||
i1_ty_t: llvmlite.LLVMType* = 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* = 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* = llvmlite.SSAValue(pool, tls_gv_ptr_ty, tls_ref_name)
|
||
if tls_flag_ref is not None:
|
||
tls_flag_ld: llvmlite.Value* = 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: rawptr[llvmlite.BasicBlock] = llvmlite.create_block(pool, func, tls_bb_buf)
|
||
viperlib.snprintf(tls_bb_buf, 64, "tls.cont.%d", lc_t)
|
||
tls_cont_bb: rawptr[llvmlite.BasicBlock] = 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* = 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* = llvmlite.ConstFloat(pool, ret_ty, 0.0)
|
||
if tlf0 is not None:
|
||
llvmlite.build_ret(func_builder, tlf0)
|
||
case _:
|
||
tln0: llvmlite.Value* = 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* = 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, FuncGenMixin.SCOPE_FUNCTION)
|
||
|
||
# PEP 695 泛型函数: def f[T](...) — 设置泛型上下文,类型参数映射到 "int" 兜底。
|
||
# TPV 无泛型函数特化机制(类泛型走 _specialize_generic_class),泛型函数按普通
|
||
# 函数编译;设置上下文使参数注解 T / 方法体中的 T(x) 转换可解析为 int。
|
||
# (注意与类特化的 set_generic_context 一样是全局状态,需在退出作用域前清除。)
|
||
tp_names_fn: list[str]* = None
|
||
if fd.type_params is not None:
|
||
tp_names_fn = fd.type_params
|
||
tp_args_fn: list[str]* = list[str](pool, 8)
|
||
if tp_args_fn is not None:
|
||
tpn_fn: sizet = len(fd.type_params)
|
||
tpi_fn: sizet = 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* = ast.Arguments*(args_node)
|
||
if ags2.args is not None:
|
||
alist2: list[ast.AST*]* = ags2.args
|
||
an2: sizet = len(alist2)
|
||
for ai2 in range(an2):
|
||
arg2: ast.Arg* = ast.Arg*(alist2.get(ai2))
|
||
if arg2 is not None and arg2.arg is not None:
|
||
# 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* = i32_ty
|
||
if arg2.annotation is not None:
|
||
resolved2: llvmlite.LLVMType* = self.Gen.TypeGenResolve.resolve_annotation_type(pool, arg2.annotation, imported_modules, from_imports, trans, 0)
|
||
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.Void():
|
||
# void 不是合法形参类型(用户 2026-10-01,见上方同款判据)
|
||
self.Gen.TypeGenErr.fatal_error(arg2, f"形参 '{arg2.arg}' 不能是 void 类型(void 只能用于 void* 与 typedef 别名)", "TypeError")
|
||
return 0
|
||
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* = 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, trans._from_imports)
|
||
if cls_nm is not None:
|
||
self.Gen.VarGen.set_var_annot_class_name(trans.SymTab, arg2.arg, cls_nm)
|
||
# t.CVolatile 形参:声明期标记,函数体内该参数名的
|
||
# load/store 带 volatile(volatile 参数对象的读改写不得
|
||
# 被优化器提升/合并,如自旋等待入参)。
|
||
if arg2.annotation is not None:
|
||
# const 形参:**沿用 TPC 形参的历史判据**(只看注解
|
||
# 是否含 t.CConst,不看指针层数)——TPC 形参登记点
|
||
# HandlesFunctions 的 IsParam=True 用同一条件,两侧逐条
|
||
# 对齐(见 Debugger/type-descriptors.md 已知差异)。
|
||
if self.Gen.TypeGenErr.has_decorator_marker(arg2.annotation, "CConst", 0) != 0:
|
||
self.Gen.VarGen.set_var_const(trans.SymTab, arg2.arg)
|
||
if self.Gen.TypeGenErr.has_decorator_marker(arg2.annotation, "CVolatile", 0) != 0:
|
||
self.Gen.VarGen.set_var_volatile(trans.SymTab, arg2.arg)
|
||
# rawptr[t.CVolatile | T] 形参(volatile 指针指向物):
|
||
# 函数体内该参数解引用(p[i]/p.field/c.Deref(p))带 volatile。
|
||
if self.Gen.TypeGenErr.has_pointee_volatile_marker(arg2.annotation) != 0:
|
||
self.Gen.VarGen.set_var_pointee_volatile(trans.SymTab, arg2.arg)
|
||
pname2: str = pool.alloc(32)
|
||
if pname2 is not None:
|
||
viperlib.snprintf(pname2, 32, "%%%s", arg2.arg)
|
||
param_val: llvmlite.Value* = llvmlite.SSAValue(pool, param_ty2, pname2)
|
||
vol_p2: int = self.Gen.VarGen.var_is_volatile(self.Gen.VarGen.lookup_var_entry(trans.SymTab, arg2.arg))
|
||
llvmlite.build_store(func_builder, param_val, alloca, vol_p2)
|
||
|
||
# *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* = ast.Arg*(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* = llvmlite.Int8(pool)
|
||
i8_ptr_ty_va: llvmlite.LLVMType* = llvmlite.Ptr(pool, i8_ty_va)
|
||
va_buf_ty: llvmlite.LLVMType* = llvmlite.Array(pool, i8_ty_va, 24)
|
||
va_list_alloca: llvmlite.Value* = 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* = 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* = 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* = trans._eh_msg_out_param
|
||
old_eh_code_out: llvmlite.Value* = 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* = llvmlite.Int8(pool)
|
||
i8_ptr_ty_eh2: llvmlite.LLVMType* = llvmlite.Ptr(pool, i8_ty_eh2)
|
||
i8_ptr_ptr_ty_eh2: llvmlite.LLVMType* = llvmlite.Ptr(pool, i8_ptr_ty_eh2)
|
||
i32_ty_eh2: llvmlite.LLVMType* = llvmlite.Int32(pool)
|
||
i32_ptr_ty_eh2: llvmlite.LLVMType* = 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* = llvmlite.SSAValue(pool, i8_ptr_ptr_ty_eh2, "%__eh_msg_out__")
|
||
code_out_ref: llvmlite.Value* = 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* = trans._cur_func
|
||
old_builder: llvmlite.IRBuilder* = 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* = trans._va_list_ptr
|
||
old_vararg_name: str = trans._vararg_name
|
||
# 返回注解上下文([C①] 裸名泛型构造的类型实参回退来源之一):
|
||
# 进入函数体前记录本函数返回注解,退出时恢复外层函数的值
|
||
old_ret_annot: ast.AST* = trans.CurFuncRetAnnot
|
||
|
||
trans._cur_func = func
|
||
trans._cur_builder = func_builder
|
||
trans.CurFuncRetAnnot = fd.returns
|
||
# 清空 global/nonlocal 名称集合(新函数作用域)
|
||
GenApi.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*]* = fd.children
|
||
if body is not None:
|
||
bn: sizet = len(body)
|
||
for bi in range(bn):
|
||
stmt: ast.AST* = 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* = body.get(bi)
|
||
if stmt is not None:
|
||
self.Gen.StmtGenDecl.pre_scan_allocas(trans, stmt)
|
||
|
||
# 翻译函数体
|
||
if body is not None:
|
||
bn2: sizet = len(body)
|
||
for bi2 in range(bn2):
|
||
stmt2: ast.AST* = 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: sizet = 0
|
||
if body is not None:
|
||
bn3 = len(body)
|
||
if bn3 > 0:
|
||
last_stmt: ast.AST* = 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:
|
||
# 编译器不替代码发明返回值——函数流程真实掉出末尾而未显式 return 时 fail-fast
|
||
# (要求补 return,定位到函数)。三种合法收尾:
|
||
# ① void 函数掉出末尾 → ret void(无值可发明,Python 语义)
|
||
# ② 末句是控制流语句(match/if 全分支 return)且当前块未 terminated →
|
||
# merge 块结构性不可达 → unreachable
|
||
# ③ 无返回类型注解的函数(fd.returns is None,过程风格函数)→ 视为无返回值
|
||
# 函数,默认生成零值返回(ConstZero 按推断出的 ret_ty 构造,类型匹配)
|
||
# 有 -> 注解且末句是普通语句掉出末尾 → fail-fast(不得替代码发明返回值,也不做
|
||
# noreturn 函数名白名单——错误终止路径也必须在源码层面保证块收尾)。
|
||
# 末句是否为控制流语句(If/Match/While/For/Try/With):翻译后当前块未 terminated
|
||
# 表示 merge 块结构性不可达(所有分支均已 return/terminated)——对非 void 函数
|
||
# 生成 unreachable 而非 fail-fast(GCC/Clang 对 fall-through 视为 UB 同语义)。
|
||
last_is_ctrl: int = 0
|
||
if bn3 > 0:
|
||
last_stmt3: ast.AST* = 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
|
||
# 返回注解层面的"无返回值"判据(与上面的 ret_ty 类型判定互为双保险,
|
||
# 不改变任何非 void 分支):LLVMType 的 REnum class-pattern match 一旦退化
|
||
# (变体表/类名失配 → _handle_simple_match 不产出 case 值),_is_void 恒 0,
|
||
# 会把 c.Asm 收尾的 void 函数(流程真实掉出末尾)误报成"缺显式 return";
|
||
# 报文的"(返回类型 void)"不能作为判据(TypePrint 的 `case _` 兜底同样打印
|
||
# void,任何未命中类型都显示 void)。故按注解判据补足,与注解→类型解析同口径
|
||
# (注解声明无返回值 ⇔ 解析为 LLVMType.Void):① t\.CVoid(Attribute 形式)
|
||
# ② 裸名 CVoid(from t import CVoid)③ -> None(CONST_NONE);
|
||
# ①②统一经既有判据 TypeGenResolve._is_cvoid_marker 判定(不新增名字白名单)。
|
||
if _is_void == 0 and fd.returns is not None:
|
||
if self.Gen.TypeGenResolve._is_cvoid_marker(fd.returns, imported_modules) != 0:
|
||
_is_void = 1
|
||
elif fd.returns.kind() == ast.ASTKind.Constant:
|
||
ret_none_cn: ast.Constant* = (ast.Constant*)(fd.returns)
|
||
if ret_none_cn.const_kind == ast.CONST_NONE:
|
||
_is_void = 1
|
||
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 是 UB,llc 不生成任何指令 ⇒ 执行掉进布局紧随其后的块。
|
||
# ★ 可达性判据**只用 `_ctrl_merge_reachable`**(MatchGenMixin 逐臂真正
|
||
# `br end_bb` 时才置 1,并由"用本 match 自身的 br 记录覆盖"写回):
|
||
# 实测反面教材 —— includes/llvmlite/__types.vp::_TypePrintDepth 末句
|
||
# `match ty:` 带 `case _:`,各臂只 snprintf 后 br 到 merge;旧判据(追加92
|
||
# 的 MatchHasWildcardArm 子句)按"穷尽 ⇒ 流程不可能掉出末尾"推断,给这个
|
||
# 可达 merge 生成了 unreachable ⇒ 打印完 "i32" 后掉进同一 switch 的跳转表,
|
||
# 用上一条 snprintf 的返回值("i%d" → 3)当 tag 取 table[3] = Array 臂,
|
||
# 把 Int 的 Bits(32) 当指针递归解引用 ⇒ AV at 0x20。
|
||
# 穷尽性 ≠ 各臂都终止:只有"有没有 br 到 merge"才是可达性。
|
||
llvmlite.build_unreachable(func_builder)
|
||
elif fd.returns is None:
|
||
# 无返回类型注解 → 无返回值过程函数,默认零值返回
|
||
if ret_ty is not None:
|
||
zero_val: llvmlite.Value* = 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
|
||
# 交还外层函数的返回注解([C①] 见上方 old_ret_annot)
|
||
trans.CurFuncRetAnnot = old_ret_annot
|
||
# 恢复外层函数(调用方)的 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)
|
||
|
||
if dbg_pushed != 0:
|
||
DebugInfoGen.PopFunction(func_builder)
|
||
|
||
return 0
|
||
|
||
# ============================================================
|
||
# _RegisterStaticFunc - static 函数登记(禁止跨模块使用)
|
||
#
|
||
# 两种书写形态同源识别(解析层已归一):
|
||
# 1) 注解形态:`def f() -> t.CVoid | t.CStatic:`(CStatic 标记在 returns 里)
|
||
# 2) 装饰器形态:`@t.CStatic` / 裸 `static def f(...)`(解析层合成装饰器)
|
||
# 命中即登记 (函数名, 定义模块 SHA1) 到 static 符号表;跨模块引用侧
|
||
# (_CheckStaticCallCrossModule / _CheckStaticFromImport / _CheckStaticCrossModule)
|
||
# 据此 fail-fast。独立成方法:translate_function_def 含多分支,内联新增分支
|
||
# 会干扰其类型推断(同 ExprGenAttr / CallGenMixin / TranslatorGenMixin 处理)。
|
||
# ============================================================
|
||
def _RegisterStaticFunc(self, trans: HT.Translator*,
|
||
fd: ast.FunctionDef*) -> int:
|
||
"""static 函数登记:returns 注解或 @t.CStatic 装饰器命中即登记;1=已登记 / 0=未命中"""
|
||
if trans is None or fd is None or fd.name is None:
|
||
return 0
|
||
if trans.ModuleSha1 is None:
|
||
return 0
|
||
has: int = 0
|
||
if fd.returns is not None:
|
||
has = self.Gen.TypeGenErr.has_decorator_marker(fd.returns, "CStatic", 0)
|
||
if has == 0 and fd.decorator_list is not None:
|
||
if self.Gen.ClassGenBase._has_decorator(fd.decorator_list, "CStatic") == 1:
|
||
has = 1
|
||
if has == 0:
|
||
return 0
|
||
return self.Gen.CallGenBase.RegisterStaticSymbol(trans.ModuleSha1, fd.name)
|
||
|
||
# ============================================================
|
||
# _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*,
|
||
pool: memhub.MemBuddy*,
|
||
mod: llvmlite.LLVMModule*,
|
||
func: llvmlite.Function*,
|
||
func_name: str,
|
||
wrapper_name: str,
|
||
handler_name: str,
|
||
decor_arg0: int64) -> llvmlite.Function*:
|
||
"""生成装饰器 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* = 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* = llvmlite.Int32(pool)
|
||
i8_ty: llvmlite.LLVMType* = llvmlite.Int8(pool)
|
||
i8_ptr_ty: llvmlite.LLVMType* = llvmlite.Ptr(pool, i8_ty)
|
||
|
||
# ---- 收集原函数参数类型(按位置,最多 16 个)----
|
||
n_params: int = 0
|
||
param_tys: sizet* = pool.alloc(16 * 8)
|
||
if param_tys is None:
|
||
return None
|
||
string.memset(param_tys, 0, 16 * 8)
|
||
pp: llvmlite.Param* = llvmlite.function_get_param_head(func)
|
||
while pp is not None:
|
||
pty: llvmlite.LLVMType* = llvmlite.param_get_ty(pp)
|
||
if pty is not None and n_params < 16:
|
||
param_tys[n_params] = sizet(pty)
|
||
n_params += 1
|
||
pp = llvmlite.param_get_next(pp)
|
||
|
||
# ---- 创建 wrapper 函数并添加参数(名字 %a0..%aN)----
|
||
wrapper: llvmlite.Function* = 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*)(param_tys[pi]), pname_w)
|
||
|
||
# ---- 创建块 ----
|
||
entry_bb: rawptr[llvmlite.BasicBlock] = llvmlite.create_block(pool, wrapper, "entry")
|
||
loop_h_bb: rawptr[llvmlite.BasicBlock] = llvmlite.create_block(pool, wrapper, "loop.header")
|
||
loop_b_bb: rawptr[llvmlite.BasicBlock] = llvmlite.create_block(pool, wrapper, "loop.body")
|
||
post_bb: rawptr[llvmlite.BasicBlock] = 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* = 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* = 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: rawptr[llvmlite.BasicBlock] = entry_bb
|
||
if rec_flag_ref is not None:
|
||
rec_bb: rawptr[llvmlite.BasicBlock] = llvmlite.create_block(pool, wrapper, "recursive_call")
|
||
dec_bb: rawptr[llvmlite.BasicBlock] = llvmlite.create_block(pool, wrapper, "decorated_entry")
|
||
if rec_bb is None or dec_bb is None:
|
||
return None
|
||
rec_val: llvmlite.Value* = llvmlite.build_load(wb, i8_ty, rec_flag_ref)
|
||
rec_zero: llvmlite.Value* = llvmlite.ConstInt(pool, i8_ty, 0, "0")
|
||
rec_is: llvmlite.Value* = 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* = 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* = llvmlite.SSAValue(pool, (llvmlite.LLVMType*)(param_tys[ri]), 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* = 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* = 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* = 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* = llvmlite.Array(pool, i8_ty, 32)
|
||
ctx_alloca: llvmlite.Value* = llvmlite.build_alloca(wb, ctx_ty)
|
||
ctx_ptr: llvmlite.Value* = llvmlite.build_bitcast(wb, ctx_alloca, i8_ptr_ty)
|
||
|
||
# 2. 打包函数参数到结构体 {param_types}(装饰器可读写 args_ptr)
|
||
args_alloca: llvmlite.Value* = None
|
||
args_ptr: llvmlite.Value* = None
|
||
if n_params > 0:
|
||
fields_head: llvmlite.ParamNode* = None
|
||
fk: int = 0
|
||
for fk in range(n_params - 1, -1, -1):
|
||
pn_n: llvmlite.ParamNode* = llvmlite.new_param_node(pool, (llvmlite.LLVMType*)(param_tys[fk]))
|
||
if pn_n is not None:
|
||
pn_n.Next = fields_head
|
||
fields_head = pn_n
|
||
args_ty: llvmlite.LLVMType* = 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* = (llvmlite.LLVMType*)(param_tys[fi2])
|
||
fld_ptr: llvmlite.Value* = 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* = 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* = None
|
||
if ret_is_void == 0:
|
||
ret_alloca = llvmlite.build_alloca(wb, ret_ty)
|
||
ret_zero: llvmlite.Value* = 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* = 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* = 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* = llvmlite.ConstInt(pool, i32_ty, 0, "0")
|
||
null_ret: llvmlite.Value* = llvmlite.ConstNull(pool, i8_ptr_ty, "null")
|
||
null_dec: llvmlite.Value* = 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* = llvmlite.build_call(wb, handler_name, ctx_ptr, 6, i32_ty, 0)
|
||
|
||
# 7. 计数器 alloca(TPV 用 alloca 计数器替代 phi)
|
||
cnt_alloca: llvmlite.Value* = llvmlite.build_alloca(wb, i32_ty)
|
||
cnt_zero: llvmlite.Value* = 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* = llvmlite.build_load(wb, i32_ty, cnt_alloca)
|
||
loop_cond: llvmlite.Value* = 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* = None
|
||
if n_params > 0:
|
||
k: int = 0
|
||
for k in range(n_params):
|
||
fld_ty_k: llvmlite.LLVMType* = (llvmlite.LLVMType*)(param_tys[k])
|
||
fld_pk: llvmlite.Value* = llvmlite.build_gep_struct(wb, args_ty, fld_ty_k, args_alloca, k)
|
||
if fld_pk is None: continue
|
||
fld_vk: llvmlite.Value* = 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* = call_args
|
||
while ct.Next is not None:
|
||
ct = ct.Next
|
||
llvmlite.value_set_next(ct, fld_vk)
|
||
res_v: llvmlite.Value* = 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* = 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* = null_ret
|
||
if ret_alloca is not None:
|
||
ret_ptr = llvmlite.build_bitcast(wb, ret_alloca, i8_ptr_ty)
|
||
ph1: llvmlite.Value* = 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* = 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* = 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 |