方法(method)预扫描只调 pre_scan_allocas,漏调 pre_scan_scope_decls(模块级 函数路径 FuncGenDef 是先 scope_decls 再 allocas)。导致 global BootInfo 未 注册时 prescan 把 BootInfo 当局部创建 alloca(define_var 注册局部),后续翻译 is_global_name 为真又写全局 → 局部 alloca 永不写入 → 读全 0(main.vp __init__ BootInfo memmap 全 0 根因)。 修复:方法预扫描先 pre_scan_scope_decls 注册 global/nonlocal,再 pre_scan_allocas, 与 FuncGenDef/FuncGenMixin 路径对齐。
1305 lines
71 KiB
Plaintext
1305 lines
71 KiB
Plaintext
import lib.core.Gen.GenTypes as GenTypes
|
||
import t, c
|
||
from stdint import *
|
||
import ast
|
||
import llvmlite
|
||
import memhub
|
||
import string
|
||
import stdio
|
||
import stdlib
|
||
import viperlib
|
||
import lib.core.VLogger as VLogger
|
||
import lib.core.Handles.HandlesTranslator as HT
|
||
import lib.Stub.StubMerger as StubMerger
|
||
import lib.core.CompilerFactory as CompilerFactory
|
||
|
||
import lib.core.Gen.ClassGenBase as ClassGenBase
|
||
import lib.core.Handles.ExprCallTable as ExprCallTable
|
||
|
||
|
||
# 方法元数据 flag:TLS(@t.TLS 装饰器,对齐 ClassGenBase 本地常量;本地副本避免跨模块 CDefine 查找)
|
||
META_TLS: t.CDefine = 32
|
||
# 虚表方法数上限(原 HandlesClassDef.VTBL_METHOD_MAX,阶段 D 拆分遗漏)
|
||
VTBL_METHOD_MAX: t.CDefine = 32
|
||
|
||
SCOPE_FUNCTION: t.CDefine = 1
|
||
|
||
# ============================================================
|
||
# ClassGenVTable - ClassGenMixin 拆分(阶段 D):vtable 收集/生成/方法翻译
|
||
#
|
||
# 继承 ClassGenBase(1 级,TPV self 调用仅支持 1 级父类)。
|
||
# 跨 Mixin 调用统一走 HandlesClassDef 委托(经 _g_gen)。
|
||
# @t.NoVTable:静态绑定。
|
||
# ============================================================
|
||
@t.NoVTable
|
||
class ClassGenVTable(ClassGenBase.ClassGenBase):
|
||
"""vtable 收集/生成/方法翻译"""
|
||
|
||
# ============================================================
|
||
# _vtable_strcat — 将 src 追加到 dst 末尾
|
||
# ============================================================
|
||
def _vtable_strcat(self, dst: str, dst_size: t.CSizeT,
|
||
src: str):
|
||
"""将 src 追加到 dst 末尾"""
|
||
if dst is None or src is None:
|
||
return
|
||
dlen: t.CSizeT = string.strlen(dst)
|
||
slen: t.CSizeT = string.strlen(src)
|
||
remain: t.CSizeT = dst_size - dlen
|
||
if remain <= 0:
|
||
return
|
||
i: t.CSizeT = 0
|
||
while i < slen and i + 1 < remain:
|
||
dst[dlen + i] = src[i]
|
||
i += 1
|
||
dst[dlen + i] = '\0'
|
||
# ============================================================
|
||
# _vtable_name_needs_quote — 检查 LLVM 标识符是否需要引号
|
||
# ============================================================
|
||
def _vtable_name_needs_quote(self, name: str) -> int:
|
||
"""检查 LLVM 标识符是否需要引号(以数字开头或含 '.')"""
|
||
if name is None:
|
||
return 0
|
||
if '0' <= name[0] <= '9':
|
||
return 1
|
||
for i in name:
|
||
if i == '.':
|
||
return 1
|
||
return 0
|
||
# ============================================================
|
||
# _format_func_type_str — 从 Function 对象生成函数类型字符串
|
||
#
|
||
# 格式: ret_ty (param1_ty, param2_ty, ...)
|
||
# 例如: void ({i32, i32}*, i32)
|
||
# ============================================================
|
||
def _format_func_type_str(self, pool: memhub.MemBuddy | t.CPtr,
|
||
buf: str, buf_size: t.CSizeT,
|
||
func: llvmlite.Function | t.CPtr) -> int:
|
||
"""从 Function 对象生成函数类型字符串"""
|
||
if buf is None or func is None or buf_size == 0:
|
||
return 0
|
||
buf[0] = '\0'
|
||
# 打印返回类型(使用访问器函数避免跨模块直接字段访问)
|
||
ret_ty: llvmlite.LLVMType | t.CPtr = llvmlite.function_get_ret_ty(func)
|
||
ret_buf: str = pool.alloc(128)
|
||
if ret_buf is not None and ret_ty is not None:
|
||
ret_buf[0] = '\0'
|
||
llvmlite.TypePrint(ret_buf, 128, ret_ty, pool)
|
||
self._vtable_strcat(buf, buf_size, ret_buf)
|
||
self._vtable_strcat(buf, buf_size, " (")
|
||
|
||
# 遍历参数(使用访问器函数避免跨模块直接字段访问)
|
||
cur: llvmlite.Param | t.CPtr = llvmlite.function_get_param_head(func)
|
||
first: int = 1
|
||
param_buf: str = pool.alloc(128)
|
||
_pc: int = 0
|
||
while cur is not None:
|
||
_pc += 1
|
||
if _pc > 100:
|
||
break
|
||
if first == 0:
|
||
self._vtable_strcat(buf, buf_size, ", ")
|
||
if param_buf is not None:
|
||
param_buf[0] = '\0'
|
||
param_ty: llvmlite.LLVMType | t.CPtr = llvmlite.param_get_ty(cur)
|
||
if param_ty is not None:
|
||
llvmlite.TypePrint(param_buf, 128, param_ty, pool)
|
||
self._vtable_strcat(buf, buf_size, param_buf)
|
||
cur = llvmlite.param_get_next(cur)
|
||
first = 0
|
||
self._vtable_strcat(buf, buf_size, ")")
|
||
return 1
|
||
# ============================================================
|
||
# _collect_vtable_methods — 收集类的虚方法信息
|
||
#
|
||
# 1. 继承父类虚方法(父类方法排在子类方法之前,保持槽位顺序一致)
|
||
# 2. 收集当前类虚方法(跳过已继承的)
|
||
#
|
||
# 结果存入 self.VtFullNames/VtMethodNames/VtParentSha1s/VtMethodCount
|
||
# (原模块级 _g_vt_*),并设置 entry.VTableMethodCount /
|
||
# VTableMethods(stdlib 分配,供虚分派跨模块查询)。
|
||
#
|
||
# 返回 1=有虚方法 / 0=无方法或失败
|
||
# ============================================================
|
||
def _collect_vtable_methods(self, trans: HT.Translator | t.CPtr,
|
||
cd: ast.ClassDef | t.CPtr,
|
||
class_name: str) -> int:
|
||
"""收集虚方法信息,设置 entry.VTableMethods/VTableMethodCount"""
|
||
if trans is None or cd is None or class_name is None:
|
||
return 0
|
||
|
||
pool: memhub.MemBuddy | t.CPtr = trans.Pool
|
||
mod: llvmlite.LLVMModule | t.CPtr = trans.Module
|
||
|
||
children: list[ast.AST | t.CPtr] | t.CPtr = cd.children
|
||
if children is None:
|
||
return 0
|
||
cn: t.CSizeT = len(children)
|
||
|
||
# 1. 收集虚方法信息
|
||
# stdlib 分配:method_names_buf 存到 StructEntry.VTableMethods(跨文件永久存活),
|
||
# 必须迁出 mb 池 reset 区间,否则 1b 每文件 reset_to(mark1) 会回收导致悬空。
|
||
full_names_buf: t.CSizeT | t.CPtr = CompilerFactory.get_perm_pool().alloc(8 * VTBL_METHOD_MAX)
|
||
method_names_buf: t.CSizeT | t.CPtr = CompilerFactory.get_perm_pool().alloc(8 * VTBL_METHOD_MAX)
|
||
# 记录每个方法的父类 SHA1(非 0=继承方法用父模块 SHA1 mangling,0=当前类方法)
|
||
method_parent_sha1s: t.CSizeT | t.CPtr = CompilerFactory.get_perm_pool().alloc(8 * VTBL_METHOD_MAX)
|
||
if full_names_buf is None or method_names_buf is None or method_parent_sha1s is None:
|
||
return 0
|
||
string.memset(full_names_buf, 0, 8 * VTBL_METHOD_MAX)
|
||
string.memset(method_names_buf, 0, 8 * VTBL_METHOD_MAX)
|
||
string.memset(method_parent_sha1s, 0, 8 * VTBL_METHOD_MAX)
|
||
|
||
method_count: int = 0
|
||
|
||
# ============================================================
|
||
# 1.5 继承父类虚方法
|
||
#
|
||
# 父类虚方法排在子类虚方法之前,保持 vtable 槽位顺序一致。
|
||
# 如果子类覆盖了方法,full_name 用子类的;否则用父类的。
|
||
# 用 SHA1 感知查找,规避跨模块同名 find_struct 找错
|
||
# ============================================================
|
||
vt_self_entry: GenTypes.StructEntry | t.CPtr = self.Gen.StructGen.find_struct_by_module(
|
||
class_name, trans.ModuleSha1)
|
||
# 多继承:遍历所有父类(声明顺序),vtable 方法合并(短名去重,先声明父类优先)
|
||
parent_count: int = self.Gen.StructGen.get_parent_count(class_name)
|
||
if parent_count > 0:
|
||
for pi in range(parent_count):
|
||
pname: str = self.Gen.StructGen.get_parent_name_at(class_name, pi)
|
||
if pname is None:
|
||
continue
|
||
# 查找父类 entry(优先同模块 SHA1 匹配)
|
||
vt_parent_entry: GenTypes.StructEntry | t.CPtr = self.Gen.StructGen.find_struct_by_module(
|
||
pname, trans.ModuleSha1)
|
||
if vt_parent_entry is None:
|
||
# 跨模块继承: 父类在不同模块定义(SHA1 不同),回退到按类名查找
|
||
vt_parent_entry = self.Gen.StructGen.find_struct(pname)
|
||
parent_vt_count: int = 0
|
||
if vt_parent_entry is not None:
|
||
parent_vt_count = vt_parent_entry.VTableMethodCount
|
||
if parent_vt_count > 0:
|
||
for pvi in range(parent_vt_count):
|
||
if method_count >= VTBL_METHOD_MAX:
|
||
break
|
||
pmethod_name: str = None
|
||
if vt_parent_entry is not None:
|
||
pmethod_name = self.Gen.StructGen.get_vtable_method_name(pname, pvi)
|
||
if pmethod_name is None:
|
||
continue
|
||
# 多继承 vtable 去重:方法短名已存在跳过(先声明父类优先)
|
||
if self.Gen.ClassGenBase._field_name_exists(method_names_buf, method_count, pmethod_name) != 0:
|
||
continue
|
||
# 检查子类是否覆盖了该方法,以及是否标记 @t.NoVTable
|
||
child_overrides: int = 0
|
||
child_nvt: int = 0
|
||
for ci2 in range(cn):
|
||
stmt2: ast.AST | t.CPtr = children.get(ci2)
|
||
if stmt2 is None:
|
||
continue
|
||
if stmt2.kind() != ast.ASTKind.FunctionDef:
|
||
continue
|
||
fd2: ast.FunctionDef | t.CPtr = (ast.FunctionDef | t.CPtr)(stmt2)
|
||
if fd2 is not None and fd2.name is not None:
|
||
if string.strcmp(fd2.name, pmethod_name) == 0:
|
||
child_overrides = 1
|
||
# 检查子类覆盖方法是否标记 @t.NoVTable
|
||
if fd2.decorator_list is not None:
|
||
if self.Gen.ClassGenBase._has_decorator(fd2.decorator_list, "NoVTable") == 1:
|
||
child_nvt = 1
|
||
break
|
||
# 构造 full_name
|
||
# 子类覆盖且未标记 NoVTable → 用子类实现
|
||
# 子类未覆盖 或 子类覆盖但标记 NoVTable → 用实际定义类实现(保持 vtable 槽位)
|
||
#
|
||
# 多层继承修复: 直接父类可能只是继承而非定义该方法
|
||
# (如 ElectricCar 继承 Car 的 is_running 实际定义在 Vehicle),
|
||
# 沿父类链向上用 find_func_global("类名.方法名") 探测实际定义类,
|
||
# 避免生成 "Car.is_running" 这类找不到函数的 full_name → vtable 槽变 null。
|
||
def_class: str = class_name
|
||
if child_overrides == 1 and child_nvt == 0:
|
||
def_class = class_name
|
||
else:
|
||
def_class = pname
|
||
# 多继承:沿 pname 的 MRO 祖先链探测实际定义类(跳过自身,先声明父类优先)
|
||
mro_ptr: t.CSizeT | t.CPtr = self.Gen.StructGen.get_mro_chain(pool, pname)
|
||
mro_i: int = 1
|
||
while mro_ptr is not None and mro_ptr[mro_i] != 0:
|
||
anc: str = (str | t.CPtr)(t.CVoid(mro_ptr[mro_i], t.CPtr))
|
||
if anc is not None:
|
||
probe_buf: str = pool.alloc(128)
|
||
if probe_buf is not None:
|
||
viperlib.snprintf(probe_buf, 128, "%s.%s", anc, pmethod_name)
|
||
if self.Gen.CallGenLeafKit.find_func_global(probe_buf) is not None:
|
||
def_class = anc
|
||
break
|
||
mro_i += 1
|
||
pfname_buf: str = CompilerFactory.get_perm_pool().alloc(128)
|
||
if pfname_buf is not None:
|
||
viperlib.snprintf(pfname_buf, 128, "%s.%s", def_class, pmethod_name)
|
||
full_names_buf[method_count] = t.CSizeT(pfname_buf)
|
||
# 复制方法名(短名)
|
||
pmname_len: t.CSizeT = string.strlen(pmethod_name)
|
||
pmname_buf: str = CompilerFactory.get_perm_pool().alloc(pmname_len + 1)
|
||
if pmname_buf is not None:
|
||
string.strcpy(pmname_buf, pmethod_name)
|
||
method_names_buf[method_count] = t.CSizeT(pmname_buf)
|
||
# 记录 mangling 用的 SHA1(继承未覆盖的方法用实际定义类的模块 SHA1)
|
||
if child_overrides == 1 and child_nvt == 0:
|
||
# 子类覆盖: 用当前模块 SHA1(保持 0)
|
||
method_parent_sha1s[method_count] = 0
|
||
else:
|
||
# 继承未覆盖: 用实际定义类的模块 SHA1(跨模块继承时 mangling 正确)
|
||
def_entry2: GenTypes.StructEntry | t.CPtr = self.Gen.StructGen.find_struct(
|
||
def_class)
|
||
if def_entry2 is not None and def_entry2.ModuleSha1 is not None:
|
||
method_parent_sha1s[method_count] = t.CSizeT(def_entry2.ModuleSha1)
|
||
else:
|
||
method_parent_sha1s[method_count] = 0
|
||
method_count += 1
|
||
|
||
# 2. 收集当前类的虚方法(跳过已从父类继承的)
|
||
for ci in range(cn):
|
||
stmt: ast.AST | t.CPtr = children.get(ci)
|
||
if stmt is None:
|
||
continue
|
||
if stmt.kind() != ast.ASTKind.FunctionDef:
|
||
continue
|
||
fd: ast.FunctionDef | t.CPtr = (ast.FunctionDef | t.CPtr)(stmt)
|
||
if fd is None or fd.name is None:
|
||
continue
|
||
if method_count >= VTBL_METHOD_MAX:
|
||
break
|
||
|
||
mname: str = fd.name
|
||
# 跳过构造函数和特殊方法(不应放入虚表)
|
||
if string.strcmp(mname, "__init__") == 0:
|
||
continue
|
||
if string.strcmp(mname, "__before_init__") == 0:
|
||
continue
|
||
if string.strcmp(mname, "__new__") == 0:
|
||
continue
|
||
# 函数级装饰器过滤:判断方法是否应该进入虚表
|
||
if self.Gen.ClassGenBase._should_method_be_virtual(cd, fd, trans) == 0:
|
||
continue
|
||
# 检查是否已从父类继承(避免重复)
|
||
already_in_vt: int = 0
|
||
for mi in range(method_count):
|
||
exist_addr: t.CSizeT = method_names_buf[mi]
|
||
if exist_addr != 0:
|
||
exist_name: str = (str | t.CPtr)(t.CVoid(exist_addr, t.CPtr))
|
||
if exist_name is not None and string.strcmp(exist_name, mname) == 0:
|
||
already_in_vt = 1
|
||
break
|
||
if already_in_vt == 1:
|
||
continue
|
||
# 构造 full_name = "ClassName.method_name"
|
||
# 内容必须落在 perm_pool:1a(mark_only=1)收集的 VTableMethods 被
|
||
# Phase 1b 依赖模块翻译跨文件读取,1a 每文件 reset 后 pool 裸字符串悬空
|
||
fname_buf: str = CompilerFactory.get_perm_pool().alloc(128)
|
||
if fname_buf is not None:
|
||
viperlib.snprintf(fname_buf, 128, "%s.%s", class_name, mname)
|
||
full_names_buf[method_count] = t.CSizeT(fname_buf)
|
||
|
||
# 复制方法名
|
||
mname_len: t.CSizeT = string.strlen(mname)
|
||
mname_buf: str = CompilerFactory.get_perm_pool().alloc(mname_len + 1)
|
||
if mname_buf is not None:
|
||
string.strcpy(mname_buf, mname)
|
||
method_names_buf[method_count] = t.CSizeT(mname_buf)
|
||
|
||
method_count += 1
|
||
|
||
# 暂存结果(_generate_vtable 复用)
|
||
self.VtFullNames = full_names_buf
|
||
self.VtMethodNames = method_names_buf
|
||
self.VtParentSha1s = method_parent_sha1s
|
||
self.VtMethodCount = method_count
|
||
|
||
# 设置 entry 元数据(虚分派查询用;必须在本类方法体翻译前就绪,
|
||
# 否则方法体内 self.虚方法 调用无法虚分派)
|
||
if vt_self_entry is not None and method_count > 0:
|
||
vt_self_entry.VTableMethodCount = method_count
|
||
vt_self_entry.VTableMethods = method_names_buf
|
||
|
||
if method_count == 0:
|
||
return 0
|
||
return 1
|
||
# ============================================================
|
||
# _generate_vtable — 生成 VTable 全局变量
|
||
#
|
||
# 1. 收集 class body 中所有 FunctionDef 作为虚方法
|
||
# 2. 构造 VTable 类型 { i8*, i8*, ... }
|
||
# 3. 构造初始化字符串 { i8* bitcast (...), ... }
|
||
# 4. 创建全局变量 @"SHA1.ClassName.vtable"
|
||
# 5. 存储虚方法名列表到 StructEntry
|
||
# ============================================================
|
||
def _generate_vtable(self, trans: HT.Translator | t.CPtr,
|
||
cd: ast.ClassDef | t.CPtr,
|
||
class_name: str) -> int:
|
||
"""生成 VTable 全局变量"""
|
||
if trans is None or cd is None or class_name is None:
|
||
return 0
|
||
|
||
|
||
pool: memhub.MemBuddy | t.CPtr = trans.Pool
|
||
mod: llvmlite.LLVMModule | t.CPtr = trans.Module
|
||
|
||
# 收集虚方法信息(继承父类 + 自身,结果存 self.VtFullNames 等暂存区)
|
||
# 同时设置 entry.VTableMethodCount/VTableMethods(虚分派查询用)
|
||
if self._collect_vtable_methods(trans, cd, class_name) == 0:
|
||
return 0
|
||
full_names_buf: t.CSizeT | t.CPtr = self.VtFullNames
|
||
method_names_buf: t.CSizeT | t.CPtr = self.VtMethodNames
|
||
method_parent_sha1s: t.CSizeT | t.CPtr = self.VtParentSha1s
|
||
method_count: int = self.VtMethodCount
|
||
# 重新获取 entry(后续存储 VTableMethods 用)
|
||
vt_self_entry: GenTypes.StructEntry | t.CPtr = self.Gen.StructGen.find_struct_by_module(
|
||
class_name, trans.ModuleSha1)
|
||
|
||
# 2. 构造 VTable 类型: { i8*, i8*, ..., i8* }
|
||
i8_ty: llvmlite.LLVMType | t.CPtr = llvmlite.Int8(pool)
|
||
i8_ptr_ty: llvmlite.LLVMType | t.CPtr = llvmlite.Ptr(pool, i8_ty)
|
||
|
||
first_node: llvmlite.ParamNode | t.CPtr = None
|
||
tail_node: llvmlite.ParamNode | t.CPtr = None
|
||
for i in range(method_count):
|
||
pnode: llvmlite.ParamNode | t.CPtr = llvmlite.new_param_node(pool, i8_ptr_ty)
|
||
if pnode is None:
|
||
continue
|
||
tail_node = llvmlite.param_list_append(first_node, tail_node, pnode)
|
||
if first_node is None:
|
||
first_node = tail_node
|
||
|
||
vtable_ty: llvmlite.LLVMType | t.CPtr = llvmlite.Struct(pool, first_node, method_count, None)
|
||
if vtable_ty is None:
|
||
return 0
|
||
|
||
# 3. 构造初始化字符串
|
||
# 大 vtable(如 MemBuddy 28+ 方法)每个方法 bitcast 约 100+ 字节,
|
||
# 4096 可能写满导致截断/strlen 越界,用 16384 预留足够空间。
|
||
init_buf: str = pool.alloc(16384)
|
||
if init_buf is None:
|
||
return 0
|
||
init_buf[0] = '\0'
|
||
self._vtable_strcat(init_buf, 16384, "{ ")
|
||
|
||
for i in range(method_count):
|
||
if i > 0:
|
||
self._vtable_strcat(init_buf, 16384, ", ")
|
||
|
||
full_name_addr: t.CSizeT = full_names_buf[i]
|
||
if full_name_addr == 0:
|
||
self._vtable_strcat(init_buf, 16384, "i8* null")
|
||
continue
|
||
|
||
full_name: str = (str | t.CPtr)(t.CVoid(full_name_addr, t.CPtr))
|
||
|
||
# 检查是否是继承方法(method_parent_sha1s 非 0 表示用父模块 SHA1 mangling)
|
||
parent_sha1_addr: t.CSizeT = method_parent_sha1s[i]
|
||
if parent_sha1_addr != 0:
|
||
# 继承方法: 用父类模块 SHA1 做 mangling
|
||
parent_sha1: str = (str | t.CPtr)(t.CVoid(parent_sha1_addr, t.CPtr))
|
||
mangled_name: str = self.Gen.FuncGenBase._mangle_name_with_sha1(parent_sha1, full_name)
|
||
# 从全局函数表查找(跨模块函数不在当前模块表中)
|
||
func: llvmlite.Function | t.CPtr = self.Gen.CallGenLeafKit.find_func_global(full_name)
|
||
else:
|
||
# 当前类方法: 用当前模块 SHA1
|
||
mangled_name: str = self._mangle_name(trans, full_name)
|
||
func: llvmlite.Function | t.CPtr = self.Gen.CallGenLeafKit.find_func_in_table(
|
||
trans._funcs, trans._func_count, full_name)
|
||
# 当前模块表找不到时,回退到全局表
|
||
if func is None:
|
||
func = self.Gen.CallGenLeafKit.find_func_global(full_name)
|
||
|
||
# func 可能已被 1b reset_to(mark1) 回收(跨模块继承方法在定义文件翻译后被 reset)。
|
||
# 悬空指针非 NULL 但内容已被复用,_format_func_type_str 解引用会沿垃圾 Next 链
|
||
# 指针追逐导致无限分配(TypePrint 每次 pool.alloc(512) → 单文件暴涨 900MB OOM)。
|
||
# 因此 func 非 NULL 时也须用 _is_valid_ptr 校验,失败回退到 TypeStr。
|
||
func_valid: int = 0
|
||
if func is not None:
|
||
if trans.Pool is not None:
|
||
# 继承方法(parent_sha1_addr != 0):func 来自其他模块,该模块 1b 翻译
|
||
# 后已被 reset_to(mark1) 回收,_is_valid_ptr 存在假阳性(块头复用后仍
|
||
# 看似有效),直接判定无效走 TypeStr 回退,避免解引用悬空 func 崩溃。
|
||
if parent_sha1_addr != 0:
|
||
func_valid = 0
|
||
elif trans.Pool._is_valid_ptr(func) != 0:
|
||
func_valid = 1
|
||
if func_valid == 0:
|
||
# 回退到全局表完整 entry 的 TypeStr(stdlib 深拷贝,跨文件永久存活)。
|
||
ge: GenTypes.FuncEntry | t.CPtr = self.Gen.CallGenLeafKit.find_func_entry_global(full_name)
|
||
if ge is not None and ge.TypeStr is not None:
|
||
self._vtable_strcat(init_buf, 16384, "i8* bitcast (")
|
||
self._vtable_strcat(init_buf, 16384, ge.TypeStr)
|
||
self._vtable_strcat(init_buf, 16384, "* @")
|
||
if self._vtable_name_needs_quote(mangled_name) != 0:
|
||
self._vtable_strcat(init_buf, 16384, "\"")
|
||
self._vtable_strcat(init_buf, 16384, mangled_name)
|
||
self._vtable_strcat(init_buf, 16384, "\"")
|
||
else:
|
||
self._vtable_strcat(init_buf, 16384, mangled_name)
|
||
self._vtable_strcat(init_buf, 16384, " to i8*)")
|
||
continue
|
||
# fail-fast:func 无效且全局表 TypeStr 回退也失败,
|
||
# 不再写 "i8* null" 静默掩盖缺失实现。
|
||
self.Gen.TypeGenErr.fatal_error(
|
||
cd, f"vtable 方法 '{full_name}' 找不到函数实现", "InternalCompilerError")
|
||
continue
|
||
|
||
# 构造函数类型字符串
|
||
func_ty_buf: str = pool.alloc(512)
|
||
if func_ty_buf is None:
|
||
self._vtable_strcat(init_buf, 16384, "i8* null")
|
||
continue
|
||
self._format_func_type_str(pool, func_ty_buf, 512, func)
|
||
|
||
# 构造 bitcast 字符串: i8* bitcast (func_ty* @mangled to i8*)
|
||
self._vtable_strcat(init_buf, 16384, "i8* bitcast (")
|
||
self._vtable_strcat(init_buf, 16384, func_ty_buf)
|
||
self._vtable_strcat(init_buf, 16384, "* @")
|
||
|
||
if self._vtable_name_needs_quote(mangled_name) != 0:
|
||
self._vtable_strcat(init_buf, 16384, "\"")
|
||
self._vtable_strcat(init_buf, 16384, mangled_name)
|
||
self._vtable_strcat(init_buf, 16384, "\"")
|
||
else:
|
||
self._vtable_strcat(init_buf, 16384, mangled_name)
|
||
self._vtable_strcat(init_buf, 16384, " to i8*)")
|
||
|
||
self._vtable_strcat(init_buf, 16384, " }")
|
||
|
||
# 4. 构造 VTable 全局变量名
|
||
vtable_name_buf: str = pool.alloc(128)
|
||
if vtable_name_buf is None:
|
||
return 0
|
||
viperlib.snprintf(vtable_name_buf, 128, "%s.vtable", class_name)
|
||
vtable_mangled: str = self._mangle_name(trans, vtable_name_buf)
|
||
|
||
# 5. 创建全局变量
|
||
gv: llvmlite.GlobalVariable | t.CPtr = llvmlite.new_global_variable(
|
||
pool, vtable_mangled, vtable_ty)
|
||
if gv is None:
|
||
return 0
|
||
gv.Initializer = init_buf
|
||
gv.IsConstant = 1
|
||
# 默认 linkage(external,2026-08-10):isinstance 内建函数需要跨模块
|
||
# 引用其他模块类的 vtable 符号({模块sha1}.Class.vtable),internal 不对外
|
||
# 导出会导致链接失败。vtable 名含模块 sha1 前缀全局唯一,外部可见不冲突。
|
||
# llvmlite 打印规则:Initializer 非空 + external 时不打印 external 关键字,
|
||
# 输出 @name = constant {...}(合法外部强定义)。
|
||
|
||
# 添加到模块
|
||
llvmlite.module_add_global(mod, gv)
|
||
|
||
# 6. 存储虚方法名列表到 StructEntry(直接用 entry,规避跨模块同名 find_struct 找错)
|
||
if vt_self_entry is not None:
|
||
vt_self_entry.VTableMethods = method_names_buf
|
||
vt_self_entry.VTableMethodCount = method_count
|
||
|
||
return 0
|
||
# ============================================================
|
||
# _translate_oop_methods — 扫描 class body 中的方法并翻译
|
||
#
|
||
# 遍历 ClassDef.children,对每个 FunctionDef:
|
||
# - 标记 OOP(mark_as_oop)
|
||
# - 如果是 __init__,标记 has_init
|
||
# - 翻译方法(生成 SHA1.ClassName.method_name 函数)
|
||
# 翻译完所有方法后,生成 __before_init__ 函数
|
||
# ============================================================
|
||
def _translate_oop_methods(self, trans: HT.Translator | t.CPtr,
|
||
cd: ast.ClassDef | t.CPtr,
|
||
struct_ty: llvmlite.LLVMType | t.CPtr,
|
||
class_name: str,
|
||
mark_only: int = 0,
|
||
reemit: int = 0) -> int:
|
||
"""扫描 class body 中的方法并翻译,生成 __before_init__
|
||
|
||
mark_only: 0=全量翻译(默认),1=只设置 IsOOP/HasNew/HasInit 标志(不翻译方法体)
|
||
reemit: 1=补译模式(_specialize_generic_class Phase B 补译分支调用)。
|
||
补译分支为防重入已提前置 MethodsEmitted=1,但方法体尚未发射,
|
||
必须跳过下方 MethodsEmitted==1 的防重复检查强制发射,否则补译
|
||
被自身拦截 → 特化方法只有 call 无 define → 链接 undefined symbol。
|
||
"""
|
||
if trans is None or cd is None or struct_ty is None or class_name is None:
|
||
return 0
|
||
|
||
children: list[ast.AST | t.CPtr] | t.CPtr = cd.children
|
||
if children is None:
|
||
return 0
|
||
|
||
cn: t.CSizeT = len(children)
|
||
has_method: int = 0
|
||
has_init: int = 0
|
||
has_new: int = 0
|
||
|
||
# 提前用类型指针定位 entry(规避跨模块同名类 find_struct 找错)
|
||
oop_entry: GenTypes.StructEntry | t.CPtr = self.Gen.StructGen.find_struct_by_type(struct_ty)
|
||
|
||
# 第一遍:检测是否有方法,标记 OOP,并注册装饰器元数据
|
||
for ci in range(cn):
|
||
stmt: ast.AST | t.CPtr = children.get(ci)
|
||
if stmt is None:
|
||
continue
|
||
if stmt.kind() == ast.ASTKind.FunctionDef:
|
||
has_method = 1
|
||
fd_check: ast.FunctionDef | t.CPtr = (ast.FunctionDef | t.CPtr)(stmt)
|
||
if fd_check is not None and fd_check.name is not None:
|
||
if string.strcmp(fd_check.name, "__init__") == 0:
|
||
has_init = 1
|
||
if string.strcmp(fd_check.name, "__new__") == 0:
|
||
has_new = 1
|
||
# 注册装饰器元数据(@property/@staticmethod/@classmethod/@x.setter 等)。
|
||
# 此处(含 mark_only=1 的 struct 预注册阶段)注册,
|
||
# 确保其他模块在 App 文件翻译时能识别属性访问。
|
||
fd_meta: int = self.Gen.ClassGenBase._extract_func_meta(fd_check.decorator_list)
|
||
if fd_meta != 0:
|
||
self.Gen.ClassGenBase.register_method_meta(class_name, fd_check.name, fd_meta)
|
||
|
||
if has_method == 0:
|
||
# 子类没有自己的方法,但可能继承了父类的虚方法
|
||
# 用 oop_entry 直接获取 ParentName,规避 find_struct 按名查找找错
|
||
parent_name: str = None
|
||
if oop_entry is not None:
|
||
parent_name = oop_entry.ParentName
|
||
if parent_name is not None:
|
||
parent_vt_count: int = self.Gen.StructGen.get_vtable_method_count(parent_name)
|
||
if parent_vt_count > 0:
|
||
has_method = 1 # 标记为有方法(继承的虚方法)
|
||
if has_method == 0:
|
||
return 0
|
||
|
||
# 标记为 OOP 结构体
|
||
if oop_entry is not None:
|
||
oop_entry.IsOOP = 1
|
||
if has_init != 0:
|
||
oop_entry.HasInit = 1
|
||
if has_new != 0:
|
||
oop_entry.HasNew = 1
|
||
|
||
# mark_only 模式:只设置标志,不翻译方法体
|
||
if mark_only != 0:
|
||
# Phase 1a 预注册也收集 vtable 元数据(VTableMethods/VTableMethodCount)。
|
||
# 根因:Phase 1b 中依赖模块可能先于其依赖类全量翻译(如 tokens.vp 先于
|
||
# memhub 生成 text.ll),此时调用方查到 entry 有 HasVTable=1 但
|
||
# VTableMethods=None → _translate_method_call 虚分派条件
|
||
# (VTableMethods is not None)不成立 → pool.alloc 被静态绑定到
|
||
# MemManager.alloc(默认返回 None)→ KwEntry.__new__ 返回 null →
|
||
# __before_init__ 写 null 崩溃。
|
||
# 短名顺序与 Phase 1b 全量收集一致(父类方法在前 + 本类方法,确定性),
|
||
# 多遍扫描重复收集时用新缓冲区覆盖(stdlib 泄漏可忽略,Phase 1b 重译幂等)。
|
||
mk_has_vt: int = 0
|
||
if oop_entry is not None:
|
||
mk_has_vt = oop_entry.HasVTable
|
||
if mk_has_vt == 1:
|
||
self._collect_vtable_methods(trans, cd, class_name)
|
||
return 0
|
||
|
||
# 防重复生成:MethodsEmitted==1 说明方法体/__before_init__ 已生成过。
|
||
# 场景:_specialize_generic_class 的 Phase B 补译分支(MethodsEmitted==0
|
||
# 时补译方法体并置 1)之后,同一特化类又经 translate_class_def 全量
|
||
# 翻译进入本方法 → 重复生成 __before_init__ → ld.lld duplicate symbol。
|
||
# 已生成过则直接跳过(方法+__before_init__ 都产出过,跳过安全)。
|
||
# reemit=1(补译模式)时跳过本检查:补译分支为防重入已提前置
|
||
# MethodsEmitted=1,但方法体尚未发射,必须强制发射。
|
||
if oop_entry is not None and oop_entry.MethodsEmitted == 1 and reemit == 0:
|
||
return 0
|
||
|
||
# 防重入:方法体翻译前先标记 MethodsEmitted=1。
|
||
# 根因:若等全部方法译完再标记,翻译 __iter__(返回 list[T]|t.CPtr)时,
|
||
# 返回类型注解会再次触发 _specialize_generic_class,此时 MethodsEmitted
|
||
# 仍为 0,走补译分支把同一特化类方法全部重发 → invalid redefinition。
|
||
if oop_entry is not None:
|
||
oop_entry.MethodsEmitted = 1
|
||
|
||
# 第二遍:翻译每个方法
|
||
# 翻译方法体前先预注册 vtable 元数据(VTableMethods/VTableMethodCount)。
|
||
# 根因:方法体翻译先于 _generate_vtable,若不预注册,方法体内的
|
||
# self.虚方法 调用(如 MemManager.calloc 里的 self.alloc)读不到
|
||
# VTableMethods,虚分派失败,被静态绑定到本类实现(基类 alloc 返回
|
||
# None),导致 calloc 永远返回 NULL。
|
||
oop_has_vt_pre: int = 0
|
||
if oop_entry is not None:
|
||
oop_has_vt_pre = oop_entry.HasVTable
|
||
if oop_has_vt_pre == 1:
|
||
self._collect_vtable_methods(trans, cd, class_name)
|
||
for ci in range(cn):
|
||
stmt: ast.AST | t.CPtr = children.get(ci)
|
||
if stmt is None:
|
||
continue
|
||
if stmt.kind() == ast.ASTKind.FunctionDef:
|
||
fd: ast.FunctionDef | t.CPtr = (ast.FunctionDef | t.CPtr)(stmt)
|
||
if fd is not None and fd.name is not None:
|
||
self._translate_method(trans, fd, struct_ty, class_name)
|
||
|
||
# 如果有虚表,先生成 VTable 全局变量(设置 VTableMethodCount)
|
||
# 必须在 __before_init__ 之前,否则 __before_init__ 读不到 VTableMethodCount
|
||
# 用 oop_entry 直接检查,规避跨模块同名 find_struct 找错
|
||
has_vt_flag: int = 0
|
||
if oop_entry is not None:
|
||
has_vt_flag = oop_entry.HasVTable
|
||
if has_vt_flag == 1:
|
||
self._generate_vtable(trans, cd, class_name)
|
||
|
||
# 生成 __before_init__ 函数(零值填充 + 默认值赋值 + vtable 指针设置)
|
||
self._generate_before_init(trans, struct_ty, class_name)
|
||
|
||
return 0
|
||
# ============================================================
|
||
# _translate_method — 翻译单个方法
|
||
#
|
||
# 生成: define <ret_ty> @SHA1.ClassName.method_name(Ptr(StructTy) %self, ...)
|
||
#
|
||
# self 参数处理:
|
||
# - 类型 Ptr(struct_ty),直接注册为 SSA 值(不创建 alloca)
|
||
# - 使 self.field 能通过 GEP 直接访问原始结构体
|
||
# ============================================================
|
||
def _translate_method(self, trans: HT.Translator | t.CPtr,
|
||
fd: ast.FunctionDef | t.CPtr,
|
||
struct_ty: llvmlite.LLVMType | t.CPtr,
|
||
class_name: str) -> int:
|
||
"""翻译单个方法,返回 0"""
|
||
if trans is None or fd is None or struct_ty is None or class_name is None:
|
||
return 0
|
||
|
||
|
||
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)
|
||
self_ptr_ty: llvmlite.LLVMType | t.CPtr = llvmlite.Ptr(pool, struct_ty)
|
||
|
||
method_name: str = fd.name
|
||
if method_name is None:
|
||
# fail-fast:方法名缺失(解析器不可能产出无名 def)——静默打印
|
||
VLogger.error("方法名缺失(fd.name is None)", "OOP")
|
||
self.Gen.TypeGenErr.fatal_error(fd, "方法名缺失(fd.name is None)", "TypeError")
|
||
|
||
# 提取装饰器元数据(@property/@staticmethod/@classmethod/@x.setter/@x.deleter)
|
||
func_meta: int = self.Gen.ClassGenBase._extract_func_meta(fd.decorator_list)
|
||
# property setter/deleter 函数名带 $set/$del 后缀,避免与 getter 冲突
|
||
method_name_buf: str = pool.alloc(128)
|
||
if method_name_buf is None:
|
||
return 0
|
||
viperlib.snprintf(method_name_buf, 128, "%s", fd.name)
|
||
if func_meta & GenTypes.META_PROP_SETTER != 0:
|
||
# 128 字节缓冲:追加 "$set" 前检查剩余容量,防 strcat 无界写穿
|
||
mn_len2: t.CSizeT = string.strlen(method_name_buf)
|
||
if mn_len2 + 5 < 128:
|
||
string.strcat(method_name_buf, "$set")
|
||
elif func_meta & GenTypes.META_PROP_DELETER != 0:
|
||
mn_len2: t.CSizeT = string.strlen(method_name_buf)
|
||
if mn_len2 + 5 < 128:
|
||
string.strcat(method_name_buf, "$del")
|
||
method_name = method_name_buf
|
||
|
||
is_static_m: int = 0
|
||
is_class_m: int = 0
|
||
is_tls_m: int = 0
|
||
if func_meta & GenTypes.META_STATIC != 0:
|
||
is_static_m = 1
|
||
if func_meta & GenTypes.META_CLASS != 0:
|
||
is_class_m = 1
|
||
if func_meta & META_TLS != 0:
|
||
is_tls_m = 1
|
||
|
||
# 构建方法全名: ClassName.method_name
|
||
full_name_buf: str = pool.alloc(128)
|
||
if full_name_buf is None:
|
||
return 0
|
||
viperlib.snprintf(full_name_buf, 128, "%s.%s", class_name, method_name)
|
||
full_name: str = full_name_buf
|
||
|
||
# SHA1 命名空间混淆
|
||
mangled_name: str = self._mangle_name(trans, full_name)
|
||
|
||
# 推断返回类型
|
||
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, 0)
|
||
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)
|
||
if ret_ty is None:
|
||
# __init__ 和 __before_init__ 返回 void
|
||
if string.strcmp(method_name, "__init__") == 0:
|
||
ret_ty = llvmlite.Void(pool)
|
||
# __new__ 返回 Ptr(struct_ty)(结构体指针作为存储空间)
|
||
elif string.strcmp(method_name, "__new__") == 0:
|
||
ret_ty = llvmlite.Ptr(pool, struct_ty)
|
||
else:
|
||
param_types_str: str = self.Gen.TypeGenErr.build_param_types_str(pool, fd.args)
|
||
ret_ty = self.Gen.TypeGenErr.infer_return_type(
|
||
pool, fd.children, param_types_str)
|
||
|
||
# 创建 LLVM 函数
|
||
func: llvmlite.Function | t.CPtr = llvmlite.create_function(
|
||
pool, mod, mangled_name, ret_ty)
|
||
if func is None:
|
||
return 0
|
||
|
||
# 提取默认参数信息(普通方法 args[0] 是 self,不含在 param_count 中;
|
||
# @staticmethod 无 self,param_count 为完整参数数)
|
||
# 注意: 必须先把属性赋给显式类型为 list[...] | t.CPtr 的局部变量再调用 __len__(),
|
||
# 否则编译器无法识别属性返回的 list 类型,GEP base 会变成 i32 0 导致 llc 报错
|
||
md_defaults: t.CVoid | t.CPtr = None
|
||
md_default_count: int = 0
|
||
md_param_count: int = 0
|
||
md_args_node: ast.Arguments | t.CPtr = fd.args
|
||
if md_args_node is not None:
|
||
md_ags: ast.Arguments | t.CPtr = (ast.Arguments | t.CPtr)(md_args_node)
|
||
if md_ags.args is not None:
|
||
md_alist: list[ast.AST | t.CPtr] | t.CPtr = md_ags.args
|
||
if is_static_m != 0:
|
||
md_param_count = len(md_alist)
|
||
else:
|
||
md_param_count = len(md_alist) - 1
|
||
if md_ags.defaults is not None:
|
||
md_dlist: list[ast.AST | t.CPtr] | t.CPtr = md_ags.defaults
|
||
md_defaults = md_dlist
|
||
md_default_count = len(md_dlist)
|
||
|
||
# 注册到函数表(用 ClassName.method_name 作为查找名,支持后缀匹配)
|
||
max_funcs: int = 1024
|
||
if self.Gen.CallGenLeafKit.add_func_to_table(funcs_ptr, func_count, full_name, func, max_funcs,
|
||
md_defaults, md_default_count, md_param_count,
|
||
pool) == 0:
|
||
trans._func_count = func_count + 1
|
||
|
||
# 添加 self/cls 参数(Ptr(struct_ty));@staticmethod 无 self,跳过
|
||
# @classmethod 的 cls 也用 Ptr(struct_ty),首参名取 args[0](如 cls)
|
||
if is_static_m == 0:
|
||
first_pname: str = "self"
|
||
if is_class_m != 0 and fd.args is not None:
|
||
fd_ags: ast.Arguments | t.CPtr = (ast.Arguments | t.CPtr)(fd.args)
|
||
if fd_ags.args is not None and len(fd_ags.args) > 0:
|
||
fd_first_arg: ast.Arg | t.CPtr = (ast.Arg | t.CPtr)(fd_ags.args.get(0))
|
||
if fd_first_arg is not None and fd_first_arg.arg is not None:
|
||
first_pname = fd_first_arg.arg
|
||
first_pname_buf: str = pool.alloc(32)
|
||
if first_pname_buf is not None:
|
||
viperlib.snprintf(first_pname_buf, 32, "%%%s", first_pname)
|
||
llvmlite.add_param(pool, func, self_ptr_ty, first_pname_buf)
|
||
|
||
# 添加其他参数(支持类型注解;@staticmethod 从索引 0 开始,其余跳过索引 0 的 self/cls)
|
||
args_node: ast.Arguments | t.CPtr = fd.args
|
||
if args_node is not None:
|
||
ags: ast.Arguments | t.CPtr = (ast.Arguments | t.CPtr)(args_node)
|
||
if ags.args is not None:
|
||
alist: list[ast.AST | t.CPtr] | t.CPtr = ags.args
|
||
an: t.CSizeT = len(alist)
|
||
start_idx: int = 0
|
||
if is_static_m == 0:
|
||
start_idx = 1
|
||
for ai in range(start_idx, an):
|
||
arg: ast.Arg | t.CPtr = (ast.Arg | t.CPtr)(alist.get(ai))
|
||
if arg is not None and arg.arg is not None:
|
||
param_ty: llvmlite.LLVMType | t.CPtr = i32_ty
|
||
if arg.annotation is not None:
|
||
resolved: llvmlite.LLVMType | t.CPtr = self.Gen.TypeGenResolve.resolve_annotation_type(
|
||
pool, arg.annotation, imported_modules, from_imports, trans, 0)
|
||
if resolved is not None:
|
||
# 裸类形参 → Ptr(struct):按"对象即指针"引用传参。
|
||
# 若按 struct 值传参,self.Head = node 会取局部拷贝地址
|
||
# (append 返回后悬垂,G5 Test4 head.Value 读到垃圾)。
|
||
# CArray 形参 → 元素指针 ty*(数组衰减,C 语义,与函数形参一致)。
|
||
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)
|
||
|
||
# OOP iter 协议:__next__ 方法注入隐藏参数 __stop_iter_flag__(i1*)。
|
||
# raise StopIteration 时置 1(对齐 TPC HandlesFunctions.py L703-705)。
|
||
# 该参数不计入 md_param_count(逻辑参数),调用侧(for 循环)显式传。
|
||
if string.strcmp(method_name, "__next__") == 0:
|
||
i1_ty_si: llvmlite.LLVMType | t.CPtr = llvmlite.Int1(pool)
|
||
if i1_ty_si is not None:
|
||
i1_ptr_ty_si: llvmlite.LLVMType | t.CPtr = llvmlite.Ptr(pool, i1_ty_si)
|
||
if i1_ptr_ty_si is not None:
|
||
llvmlite.add_param(pool, func, i1_ptr_ty_si, "%__stop_iter_flag__")
|
||
|
||
# 参数添加完成,补全全局函数表的 TypeStr(供 vtable 在 func 被 reset 后使用)
|
||
self.Gen.CallGenLeafKit.update_global_func_typestr(pool, full_name, func)
|
||
|
||
# 创建 entry 块
|
||
entry_blk: llvmlite.BasicBlock | t.CPtr = llvmlite.create_block(pool, func, "entry")
|
||
if entry_blk is None:
|
||
return 0
|
||
|
||
# 创建方法专属 builder
|
||
func_builder: llvmlite.IRBuilder | t.CPtr = llvmlite.new_builder(pool, func)
|
||
if func_builder is None:
|
||
return 0
|
||
llvmlite.position_at_end(func_builder, entry_blk)
|
||
|
||
# @t.TLS 一次性初始化守卫(对齐 TPC HandlesFunctions.py L1763-1792;
|
||
# 与 FuncGenMixin.translate_function_def 同一实现,类方法同样支持)
|
||
if is_tls_m != 0:
|
||
tls_m_flag_name: str = pool.alloc(128)
|
||
if tls_m_flag_name is not None:
|
||
viperlib.snprintf(tls_m_flag_name, 128, "__tls_init_done_%s", method_name)
|
||
tls_m_gv: llvmlite.GlobalVariable | t.CPtr = llvmlite.create_global_int(
|
||
pool, mod, tls_m_flag_name, 1, 0)
|
||
if tls_m_gv is not None:
|
||
i1_ty_m: llvmlite.LLVMType | t.CPtr = llvmlite.Int1(pool)
|
||
if i1_ty_m is not None:
|
||
# GlobalVariable 非 Value 子类:构造 Value 视图后再 load/store
|
||
tls_m_ptr_ty: llvmlite.LLVMType | t.CPtr = llvmlite.Ptr(pool, i1_ty_m)
|
||
tls_m_rn: str = pool.alloc(64)
|
||
if tls_m_rn is not None:
|
||
viperlib.snprintf(tls_m_rn, 64, "@%s", tls_m_flag_name)
|
||
tls_m_ref: llvmlite.Value | t.CPtr = llvmlite.SSAValue(
|
||
pool, tls_m_ptr_ty, tls_m_rn)
|
||
if tls_m_ref is not None:
|
||
tls_m_ld: llvmlite.Value | t.CPtr = llvmlite.build_load(
|
||
func_builder, i1_ty_m, tls_m_ref)
|
||
lc_m: int = trans._label_counter
|
||
trans._label_counter = lc_m + 1
|
||
tls_m_buf: str = pool.alloc(64)
|
||
if tls_m_buf is not None:
|
||
viperlib.snprintf(tls_m_buf, 64, "tls.skip.%d", lc_m)
|
||
tls_m_skip: llvmlite.BasicBlock | t.CPtr = llvmlite.create_block(
|
||
pool, func, tls_m_buf)
|
||
viperlib.snprintf(tls_m_buf, 64, "tls.cont.%d", lc_m)
|
||
tls_m_cont: llvmlite.BasicBlock | t.CPtr = llvmlite.create_block(
|
||
pool, func, tls_m_buf)
|
||
if tls_m_skip is not None and tls_m_cont is not None:
|
||
llvmlite.build_cond_br(
|
||
func_builder, tls_m_ld, tls_m_skip, tls_m_cont)
|
||
llvmlite.position_at_end(func_builder, tls_m_skip)
|
||
match ret_ty:
|
||
case llvmlite.LLVMType.Void():
|
||
llvmlite.build_ret_void(func_builder)
|
||
case llvmlite.LLVMType.Int(_):
|
||
tlm0: llvmlite.Value | t.CPtr = llvmlite.ConstInt(
|
||
pool, ret_ty, 0, "0")
|
||
if tlm0 is not None:
|
||
llvmlite.build_ret(func_builder, tlm0)
|
||
case llvmlite.LLVMType.Float(_):
|
||
tlmf: llvmlite.Value | t.CPtr = llvmlite.ConstFloat(
|
||
pool, ret_ty, 0.0)
|
||
if tlmf is not None:
|
||
llvmlite.build_ret(func_builder, tlmf)
|
||
case _:
|
||
tlmn: llvmlite.Value | t.CPtr = llvmlite.ConstNull(
|
||
pool, ret_ty, "null")
|
||
if tlmn is not None:
|
||
llvmlite.build_ret(func_builder, tlmn)
|
||
llvmlite.position_at_end(func_builder, tls_m_cont)
|
||
tlmo: llvmlite.Value | t.CPtr = llvmlite.ConstInt(
|
||
pool, i1_ty_m, 1, "1")
|
||
if tlmo is not None:
|
||
llvmlite.build_store(func_builder, tlmo, tls_m_ref)
|
||
|
||
# 进入函数作用域
|
||
self.Gen.VarGen.enter_scope(trans.SymTab, SCOPE_FUNCTION)
|
||
|
||
# 为 self/cls 创建 alloca 并 store(与其他参数一致);@staticmethod 无 self,跳过
|
||
# 修复: 之前 self 注册为 SSA 值导致 translate_name_value 错误地 load 一次
|
||
# 将 Ptr(struct_ty) 变成 struct 值,引发变参函数 ABI 不匹配崩溃
|
||
if is_static_m == 0:
|
||
self_alloca: llvmlite.Value | t.CPtr = llvmlite.build_alloca(func_builder, self_ptr_ty)
|
||
if self_alloca is not None:
|
||
self_var_name: str = "self"
|
||
self_ssa_name: str = "%self"
|
||
if is_class_m != 0 and args_node is not None:
|
||
cags: ast.Arguments | t.CPtr = (ast.Arguments | t.CPtr)(args_node)
|
||
if cags.args is not None and len(cags.args) > 0:
|
||
cfirst: ast.Arg | t.CPtr = (ast.Arg | t.CPtr)(cags.args.get(0))
|
||
if cfirst is not None and cfirst.arg is not None:
|
||
self_var_name = cfirst.arg
|
||
self_ssa_name_buf: str = pool.alloc(32)
|
||
if self_ssa_name_buf is not None:
|
||
viperlib.snprintf(self_ssa_name_buf, 32, "%%%s", cfirst.arg)
|
||
self_ssa_name = self_ssa_name_buf
|
||
self.Gen.VarGen.define_var(trans.SymTab, self_var_name, self_alloca)
|
||
# 设置 self/cls 的类型注解类名(属性访问 lookup_field 回退查找用)
|
||
self.Gen.VarGen.set_var_annot_class_name(trans.SymTab, self_var_name, class_name)
|
||
self_val: llvmlite.Value | t.CPtr = llvmlite.SSAValue(pool, self_ptr_ty, self_ssa_name)
|
||
llvmlite.build_store(func_builder, self_val, self_alloca)
|
||
|
||
# 为其他参数创建 alloca 并 store(与普通函数一致;
|
||
# @staticmethod 从索引 0 开始,其余跳过索引 0 的 self/cls 参数)
|
||
if args_node is not None:
|
||
ags2: ast.Arguments | t.CPtr = (ast.Arguments | t.CPtr)(args_node)
|
||
if ags2.args is not None:
|
||
alist2: list[ast.AST | t.CPtr] | t.CPtr = ags2.args
|
||
an2: t.CSizeT = len(alist2)
|
||
start_idx2: int = 0
|
||
if is_static_m == 0:
|
||
start_idx2 = 1
|
||
for ai2 in range(start_idx2, an2):
|
||
arg2: ast.Arg | t.CPtr = (ast.Arg | t.CPtr)(alist2.get(ai2))
|
||
if arg2 is not None and arg2.arg is not None:
|
||
param_ty2: llvmlite.LLVMType | t.CPtr = i32_ty
|
||
if arg2.annotation is not None:
|
||
resolved2: llvmlite.LLVMType | t.CPtr = 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"方法 '{class_name}.{method_name}' 参数 '{arg2.arg}' 类型解析失败",
|
||
"NameError")
|
||
resolved2 = i32_ty # 不可达(fatal_error 已退出)
|
||
if resolved2 is not None:
|
||
# 与 add_param 保持一致:裸类形参 → Ptr(struct)(对象即指针)
|
||
# CArray 形参 → 元素指针 ty*(数组衰减,与 add_param 一致)
|
||
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 修复)
|
||
if arg2.annotation is not None:
|
||
cls_nm_oc: str = self.Gen.TypeGenResolve.extract_class_name_from_annotation(
|
||
arg2.annotation, imported_modules, pool, trans._from_imports)
|
||
if cls_nm_oc is not None:
|
||
self.Gen.VarGen.set_var_annot_class_name(
|
||
trans.SymTab, arg2.arg, cls_nm_oc)
|
||
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)
|
||
|
||
# OOP iter 协议:__next__ 的 stop-flag 参数初始化(store 0)并保存
|
||
# 指针到 trans,供 translate_raise 的 raise StopIteration 写 1。
|
||
# 参数名必须与上面 add_param 的 "%__stop_iter_flag__" 一致。
|
||
if string.strcmp(method_name, "__next__") == 0:
|
||
i1_ty_sf: llvmlite.LLVMType | t.CPtr = llvmlite.Int1(pool)
|
||
if i1_ty_sf is not None:
|
||
i1_ptr_ty_sf: llvmlite.LLVMType | t.CPtr = llvmlite.Ptr(pool, i1_ty_sf)
|
||
if i1_ptr_ty_sf is not None:
|
||
flag_ref_sf: llvmlite.Value | t.CPtr = llvmlite.SSAValue(
|
||
pool, i1_ptr_ty_sf, "%__stop_iter_flag__")
|
||
if flag_ref_sf is not None:
|
||
trans._stop_iter_flag_ptr = flag_ref_sf
|
||
zero_i1_sf: llvmlite.Value | t.CPtr = llvmlite.ConstInt(
|
||
pool, i1_ty_sf, 0, "0")
|
||
if zero_i1_sf is not None:
|
||
llvmlite.build_store(func_builder, zero_i1_sf, flag_ref_sf)
|
||
|
||
# 保存模块级作用域状态
|
||
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_stop_iter_flag: llvmlite.Value | t.CPtr = trans._stop_iter_flag_ptr
|
||
|
||
trans._cur_func = func
|
||
trans._cur_builder = func_builder
|
||
HT.clear_scope_names(trans)
|
||
|
||
# 预扫描方法体:为局部变量提前创建 alloca
|
||
# 必须先预扫描 Global/Nonlocal 声明(对齐 FuncGenDef 模块级函数路径),
|
||
# 否则 `global BootInfo` 未注册时 prescan 把 BootInfo 当局部创建 alloca,
|
||
# 后续翻译 is_global_name 为真又写全局 → 局部 alloca 永不写入 → 读全 0
|
||
# (main.vp __init__ BootInfo memmap 全 0 根因)。
|
||
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:
|
||
self.Gen.StmtGen.translate_stmt(trans, stmt2)
|
||
|
||
# 追加89:方法末尾收尾与模块级函数(FuncGenMixin.translate_function_def)
|
||
# 同语义——编译器不替代码发明返回值,三种合法收尾:
|
||
# ① void 方法掉出末尾 → ret void(无值可发明,Python 语义)
|
||
# ② 末句是控制流语句(match/if 全分支 return)→ merge 块结构性
|
||
# 不可达 → build_unreachable(不可能抵达,GCC/Clang fall-through
|
||
# 视为 UB 同语义)
|
||
# ③ 无返回类型注解的方法 → 视为无返回值过程,ConstZero 兜底
|
||
# 有 -> 注解且末句普通语句掉出末尾 → fail-fast。
|
||
# 不做 noreturn 函数名白名单:错误终止路径(fatal_error 等)也必须在
|
||
# 源码层面保证块收尾(如显式 return 样板),每个函数都符合块设计。
|
||
# 原实现 L4529 const_int32 硬编码 ret i32 0,对 i64 返回方法报 llc
|
||
# "value doesn't match function result type 'i64'"(追加88 只修了
|
||
# FuncGenMixin 模块级函数路径,方法路径此处追加89 一并同步)
|
||
last_is_return: int = 0
|
||
# 追加89:bn3 提前初始化,避免 body is None 时下方引用未定义变量
|
||
bn3: t.CSizeT = 0
|
||
if body is not None:
|
||
bn3 = len(body)
|
||
if bn3 > 0:
|
||
last_stmt_m: ast.AST | t.CPtr = body.get(bn3 - 1)
|
||
if last_stmt_m is not None and last_stmt_m.kind() == ast.ASTKind.Return:
|
||
last_is_return = 1
|
||
if last_is_return == 0:
|
||
if llvmlite.builder_cur_block_is_terminated(func_builder) == 0:
|
||
last_is_ctrl: int = 0
|
||
if bn3 > 0:
|
||
last_stmt3_m: ast.AST | t.CPtr = body.get(bn3 - 1)
|
||
if last_stmt3_m is not None:
|
||
k3m: int = last_stmt3_m.kind()
|
||
if k3m == ast.ASTKind.If or k3m == ast.ASTKind.While or \
|
||
k3m == ast.ASTKind.For or k3m == ast.ASTKind.Try or \
|
||
k3m == ast.ASTKind.With or k3m == 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(与 FuncGenMixin 同步):非 void 方法末句是控制流
|
||
# 且 merge 块结构性不可达(全分支 return,无 br 到 merge)
|
||
# → LLVM 语义 unreachable。merge 可达(分支 br 到 merge)时
|
||
# 不是结构性不可达,需正常收尾(下方 ConstZero / fail-fast)。
|
||
# 原无条件 unreachable 使 llc O2 优化 br-to-unreachable 为
|
||
# fall-through → 双分支执行崩溃(FuncTest check)
|
||
llvmlite.build_unreachable(func_builder)
|
||
elif fd.returns is None:
|
||
# 无返回类型注解 → 无返回值过程方法,默认零值返回
|
||
if ret_ty is not None:
|
||
_m_zero_val: llvmlite.Value | t.CPtr = llvmlite.ConstZero(pool, ret_ty)
|
||
if _m_zero_val is not None:
|
||
llvmlite.build_ret(func_builder, _m_zero_val)
|
||
else:
|
||
self.Gen.TypeGenErr.fatal_error(fd, "方法流程掉出末尾但未显式 return", "TypeError")
|
||
else:
|
||
self.Gen.TypeGenErr.fatal_error(fd, "方法流程掉出末尾但未显式 return", "TypeError")
|
||
else:
|
||
# fail-fast:有 -> 注解但流程真实掉出末尾(traceback 风格)
|
||
if ret_ty is not None:
|
||
rt_name_m: str = pool.alloc(64)
|
||
if rt_name_m is not None:
|
||
llvmlite.TypePrint(rt_name_m, 64, ret_ty, pool)
|
||
if rt_name_m[0] == '\0':
|
||
rt_name_m = "?"
|
||
err_fn_m: str = pool.alloc(256)
|
||
if err_fn_m is not None:
|
||
viperlib.snprintf(
|
||
err_fn_m, 256,
|
||
"方法 '%s' 流程掉出末尾但未显式 return(返回类型 %s),"
|
||
"请补显式 return(如 return 0 / return null)", method_name, rt_name_m)
|
||
self.Gen.TypeGenErr.fatal_error(fd, err_fn_m, "TypeError")
|
||
self.Gen.TypeGenErr.fatal_error(fd, "方法流程掉出末尾但未显式 return", "TypeError")
|
||
else:
|
||
self.Gen.TypeGenErr.fatal_error(fd, "方法流程掉出末尾但未显式 return", "TypeError")
|
||
|
||
# 恢复模块级作用域
|
||
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._stop_iter_flag_ptr = old_stop_iter_flag
|
||
|
||
return 0
|
||
# ============================================================
|
||
# _generate_before_init — 生成 __before_init__ 函数
|
||
#
|
||
# 生成: define void @SHA1.ClassName.__before_init__(Ptr(StructTy) %self)
|
||
#
|
||
# 执行:
|
||
# 1. store zeroinitializer 到 %self(零值填充)
|
||
# 2. 逐字段 store 默认值(如有)
|
||
# 3. ret void
|
||
# ============================================================
|
||
def _generate_before_init(self, trans: HT.Translator | t.CPtr,
|
||
struct_ty: llvmlite.LLVMType | t.CPtr,
|
||
class_name: str) -> int:
|
||
"""生成 __before_init__ 函数,返回 0"""
|
||
if trans is None or struct_ty is None or class_name is None:
|
||
return 0
|
||
|
||
|
||
pool: memhub.MemBuddy | t.CPtr = trans.Pool
|
||
mod: llvmlite.LLVMModule | t.CPtr = trans.Module
|
||
funcs_ptr: GenTypes.FuncEntry | t.CPtr = trans._funcs
|
||
func_count: int = trans._func_count
|
||
|
||
self_ptr_ty: llvmlite.LLVMType | t.CPtr = llvmlite.Ptr(pool, struct_ty)
|
||
void_ty: llvmlite.LLVMType | t.CPtr = llvmlite.Void(pool)
|
||
|
||
# 构建函数名: ClassName.__before_init__
|
||
full_name_buf: str = pool.alloc(128)
|
||
if full_name_buf is None:
|
||
return 0
|
||
viperlib.snprintf(full_name_buf, 128, "%s.__before_init__", class_name)
|
||
full_name: str = full_name_buf
|
||
|
||
mangled_name: str = self._mangle_name(trans, full_name)
|
||
|
||
# 创建函数
|
||
func: llvmlite.Function | t.CPtr = llvmlite.create_function(
|
||
pool, mod, mangled_name, void_ty)
|
||
if func is None:
|
||
return 0
|
||
|
||
# 注册到函数表
|
||
max_funcs: int = 1024
|
||
rc_add: int = self.Gen.CallGenLeafKit.add_func_to_table(funcs_ptr, func_count, full_name, func, max_funcs, None, 0, 0, pool)
|
||
if rc_add == 0:
|
||
trans._func_count = func_count + 1
|
||
|
||
# 添加 self 参数
|
||
llvmlite.add_param(pool, func, self_ptr_ty, "%self")
|
||
|
||
# 参数添加完成,补全全局函数表的 TypeStr
|
||
rc_ut: int = self.Gen.CallGenLeafKit.update_global_func_typestr(pool, full_name, func)
|
||
|
||
# 创建 entry 块 + builder
|
||
entry_blk: llvmlite.BasicBlock | t.CPtr = llvmlite.create_block(pool, func, "entry")
|
||
if entry_blk is None:
|
||
return 0
|
||
func_builder: llvmlite.IRBuilder | t.CPtr = llvmlite.new_builder(pool, func)
|
||
if func_builder is None:
|
||
return 0
|
||
llvmlite.position_at_end(func_builder, entry_blk)
|
||
|
||
# 注册 self 为 SSA 值
|
||
self_val: llvmlite.Value | t.CPtr = llvmlite.SSAValue(pool, self_ptr_ty, "%self")
|
||
|
||
# 1. 零值填充: store zeroinitializer, Ptr(struct_ty)* %self
|
||
# 空 struct({})在 LLVM 中不允许 zeroinitializer(invalid type for null constant),
|
||
# 无字段类(接口/标记类,如多继承的 Vec2Extra)跳过零值填充;
|
||
# @t.CVTable 类必有 vtable 指针字段(非空),不受影响。
|
||
struct_fcount_zi: int = llvmlite.get_struct_fcount(struct_ty)
|
||
if struct_fcount_zi > 0:
|
||
zero: llvmlite.Value | t.CPtr = llvmlite.ConstZero(pool, struct_ty)
|
||
if zero is not None:
|
||
llvmlite.build_store(func_builder, zero, self_val)
|
||
|
||
# 1.5 如果有虚表,store vtable 全局地址到 __vtable__ 字段(索引 0)
|
||
# 用 find_struct_by_type 定位 entry,规避跨模块同名 find_struct 找错
|
||
bi_entry: GenTypes.StructEntry | t.CPtr = self.Gen.StructGen.find_struct_by_type(struct_ty)
|
||
bi_has_vt: int = 0
|
||
if bi_entry is not None:
|
||
bi_has_vt = bi_entry.HasVTable
|
||
if bi_has_vt == 1:
|
||
vt_method_count: int = 0
|
||
if bi_entry is not None:
|
||
vt_method_count = bi_entry.VTableMethodCount
|
||
if vt_method_count > 0:
|
||
# 构造 vtable 类型 { i8*, i8*, ..., i8* }
|
||
vt_i8_ty: llvmlite.LLVMType | t.CPtr = llvmlite.Int8(pool)
|
||
vt_i8_ptr_ty: llvmlite.LLVMType | t.CPtr = llvmlite.Ptr(pool, vt_i8_ty)
|
||
|
||
vt_first_node: llvmlite.ParamNode | t.CPtr = None
|
||
vt_prev_node: llvmlite.ParamNode | t.CPtr = None
|
||
for vti in range(vt_method_count):
|
||
vtnode: llvmlite.ParamNode | t.CPtr = llvmlite.new_param_node(pool, vt_i8_ptr_ty)
|
||
if vtnode is None:
|
||
continue
|
||
if vt_first_node is None:
|
||
vt_first_node = vtnode
|
||
if vt_prev_node is not None:
|
||
llvmlite.paramnode_set_next(vt_prev_node, vtnode)
|
||
vt_prev_node = vtnode
|
||
|
||
vt_ty: llvmlite.LLVMType | t.CPtr = llvmlite.Struct(pool, vt_first_node, vt_method_count, None)
|
||
vt_ptr_ty: llvmlite.LLVMType | t.CPtr = llvmlite.Ptr(pool, vt_ty)
|
||
|
||
# 构造 vtable 全局变量名
|
||
vt_name_buf: str = pool.alloc(128)
|
||
if vt_name_buf is not None:
|
||
viperlib.snprintf(vt_name_buf, 128, "%s.vtable", class_name)
|
||
vt_full_name: str = vt_name_buf
|
||
vt_mangled: str = self._mangle_name(trans, vt_full_name)
|
||
|
||
# GEP 到 __vtable__ 字段(索引 0)
|
||
vt_slot: llvmlite.Value | t.CPtr = llvmlite.build_gep_struct(
|
||
func_builder, struct_ty, vt_i8_ptr_ty, self_val, 0)
|
||
if vt_slot is not None:
|
||
# 创建全局变量引用 Value
|
||
vt_ref: llvmlite.Value | t.CPtr = llvmlite.new_value(pool)
|
||
if vt_ref is not None:
|
||
llvmlite.value_set_ty(vt_ref, vt_ptr_ty)
|
||
llvmlite.value_set_isconst(vt_ref, 1)
|
||
# Name 格式: @"mangled" 或 @mangled
|
||
vt_ref_name: str = pool.alloc(256)
|
||
if vt_ref_name is not None:
|
||
vt_ref_name[0] = '\0'
|
||
if self._vtable_name_needs_quote(vt_mangled) != 0:
|
||
viperlib.snprintf(vt_ref_name, 256, "@\"%s\"", vt_mangled)
|
||
else:
|
||
viperlib.snprintf(vt_ref_name, 256, "@%s", vt_mangled)
|
||
llvmlite.value_set_name(vt_ref, vt_ref_name)
|
||
|
||
# bitcast 到 i8*
|
||
vt_as_i8: llvmlite.Value | t.CPtr = llvmlite.build_bitcast(
|
||
func_builder, vt_ref, vt_i8_ptr_ty)
|
||
if vt_as_i8 is not None:
|
||
llvmlite.build_store(func_builder, vt_as_i8, vt_slot)
|
||
|
||
# 2. 逐字段 store 默认值(用 bi_entry 直接访问,规避跨模块同名 find_struct 找错)
|
||
if bi_entry is not None:
|
||
for fi in range(bi_entry.FieldCount):
|
||
fe: GenTypes.FieldEntry | t.CPtr = self.Gen.StructGen._get_field_entry(
|
||
bi_entry, fi)
|
||
if fe is None or fe.DefaultVal is None:
|
||
continue
|
||
# 静态数组字段 + 列表字面量默认值 → 整体置零 + 逐元素 GEP+store
|
||
# (与局部 AnnAssign 数组初始化一致;translate_value 会把列表字面量
|
||
# 误译成动态 list 对象指针,coerce 到 [N x elem] 会失败)。
|
||
# 单参 CArray 字段(如 t.CArray[str] = [...])经类体字段收集
|
||
# 推断为静态数组,此处保证 __before_init__ 填充真实字符串指针。
|
||
if fe.Ty is not None and self.Gen.ExprGenBase.is_array_type(fe.Ty) != 0 \
|
||
and fe.DefaultVal.kind() == ast.ASTKind.List:
|
||
field_ptr_arr: llvmlite.Value | t.CPtr = llvmlite.build_gep_struct(
|
||
func_builder, struct_ty, fe.Ty, self_val, fe.Index)
|
||
if field_ptr_arr is not None:
|
||
zero_arr_f: llvmlite.Value | t.CPtr = llvmlite.ConstZero(pool, fe.Ty)
|
||
if zero_arr_f is not None:
|
||
llvmlite.build_store(func_builder, zero_arr_f, field_ptr_arr)
|
||
# Mixin 静态绑定:self._xxx 只沿本类查找,跨 Mixin 方法
|
||
# (AssignGenMixin._init_global_array_from_list)会生成不存在
|
||
# 符号 → 必须走 HandlesAnnAssign 模块级委托(延迟 import Gen)。
|
||
self.Gen.AssignGen._init_global_array_from_list(
|
||
func_builder, pool, mod, field_ptr_arr, fe.DefaultVal, trans)
|
||
continue
|
||
# 翻译默认值表达式
|
||
default_val: llvmlite.Value | t.CPtr = self.Gen.ExprGen.translate_value(
|
||
func_builder, pool, mod, fe.DefaultVal, None, 0, trans)
|
||
if default_val is None:
|
||
continue
|
||
# GEP 到字段
|
||
field_ptr: llvmlite.Value | t.CPtr = llvmlite.build_gep_struct(
|
||
func_builder, struct_ty, fe.Ty, self_val, fe.Index)
|
||
if field_ptr is None:
|
||
continue
|
||
# 类型转换并 store
|
||
default_val = self.Gen.ExprGenBase.coerce_to_type(func_builder, default_val, fe.Ty, fe.DefaultVal)
|
||
llvmlite.build_store(func_builder, default_val, field_ptr)
|
||
|
||
# 3. ret void
|
||
llvmlite.build_ret_void(func_builder)
|
||
|
||
return 0 |