注释清理(65 文件 / 约 -2578 行 / 约 516 处):删除/压缩叙述式历史注释——多行根因叙事、工作代号段(D25/D30/N11/B5/S4/阶段E 等)、改前改后与先例叙述、逐条推导块,压成一行讲清作用信息;契约类注释(用途、参数与返回、关键约束与不变量、IR 结构说明)与被注释掉的代码一律保留 存疑 标记 6 处一字未动:StubMergerStore.vp、VpiReader.vp、VLogger.vp、AssignGenMixin.vp、CallGenLib.vp、CallGenLeafKit.vp 本次一并带入并行会话的代码改动(同批文件,按文件粒度无法拆分):fileio.File -> rowptr[fileio.File] 等 已知副作用/残留:① CallGenDispatch.vp 有 2 行非注释行的行尾被 LF->CRLF 规范化(纯字节变化,无文本改动);② core/Gen 区约 24 处压缩因并行会话整文件覆写被写回原样,尚未生效(StmtGenCifMixin/ClassGenVTable/FuncGenDef/ClassGenEnum/StructGenMixin/TypeSpec 等) 清单与复跑判据见 Debugger/comment_cleanup_summary.md(该目录不受版本控制)
384 lines
20 KiB
Plaintext
384 lines
20 KiB
Plaintext
import lib.core.Gen.GenTypes as GenTypes
|
||
import t, c
|
||
from stdint import *
|
||
import ast
|
||
import llvmlite
|
||
import memhub
|
||
import string
|
||
import viperlib
|
||
import lib.core.Gen.Translator as HT
|
||
import lib.core.Gen.GenApi as GenApi
|
||
|
||
from . import CallGenBase
|
||
|
||
|
||
# ============================================================
|
||
# CallGenFd - CallGenMixin 拆分(阶段 B):FakeDuck / requires 字段注入 / provider 栈
|
||
#
|
||
# 继承 CallGenBase(1 级,TPV self 调用仅支持 1 级父类)。
|
||
# 跨 Mixin 调用统一走 HandlesExprCall 委托(经 _g_gen)。
|
||
# @t.NoVTable:静态绑定。
|
||
# ============================================================
|
||
@t.NoVTable
|
||
class CallGenFd(CallGenBase.CallGenBase):
|
||
"""FakeDuck / requires 字段注入 / provider 栈"""
|
||
|
||
# _translate_fakeduck_call:FakeDuck str 变量方法调用 → 扩展类 _Type/_str(对齐 TPC HandlesExprCall.py L2841-2880)。对象是 Name 且有影子({var}__meta__)时 self=影子;否则在入口创建临时影子(__data__=obj 值、__mbuddy__=NULL)后作 self,避免 bitcast i8* → _str* 读垃圾指针
|
||
|
||
# ============================================================
|
||
def _translate_fakeduck_call(self, pool: rowptr[memhub.MemBuddy],
|
||
builder: llvmlite.IRBuilder | t.CPtr,
|
||
mod: llvmlite.LLVMModule | t.CPtr,
|
||
cls_name: str,
|
||
method_name: str,
|
||
cl: ast.Call | t.CPtr,
|
||
trans: HT.Translator | t.CPtr) -> llvmlite.Value | t.CPtr:
|
||
"""FakeDuck: str 变量方法调用解析到扩展类 _Type/_str,返回 call 结果或 None"""
|
||
if pool is None or builder is None or cl is None or trans is None:
|
||
return None
|
||
if method_name is None:
|
||
return None
|
||
# 仅对 str 类型触发(AnnotClassName == "str",对象是 char*);
|
||
# cls_name 为 None(表达式接收者解析失败)时也尝试
|
||
if cls_name is not None and string.strcmp(cls_name, "str") != 0:
|
||
return None
|
||
if cl.func is None or cl.func.kind() != ast.ASTKind.Attribute:
|
||
return None
|
||
fd_at: ast.Attribute | t.CPtr = (ast.Attribute | t.CPtr)(cl.func)
|
||
if fd_at is None or fd_at.value is None or fd_at.attr is None:
|
||
return None
|
||
if string.strcmp(fd_at.attr, method_name) != 0:
|
||
return None
|
||
# 候选扩展类:先 _Type(a.type_id())后 _str(a.upper() 等)
|
||
fd_func: llvmlite.Function | t.CPtr = None
|
||
fd_cls: str = None
|
||
fd_key: str = pool.alloc(160)
|
||
if fd_key is not None:
|
||
for fd_ci in range(2):
|
||
fd_cn: str = "_Type"
|
||
if fd_ci == 1:
|
||
fd_cn = "_str"
|
||
viperlib.snprintf(fd_key, 160, "%s.%s", fd_cn, method_name)
|
||
fd_func = self.find_func_in_module(mod, fd_key)
|
||
if fd_func is not None:
|
||
fd_cls = fd_cn
|
||
break
|
||
if fd_func is None or fd_cls is None:
|
||
return None
|
||
# 扩展类结构体必须已注册(GEP/临时影子需要类型)
|
||
fd_sty: llvmlite.LLVMType | t.CPtr = self.Gen.StructGen.get_struct_type(fd_cls)
|
||
if fd_sty is None:
|
||
return None
|
||
# 扩展类字段数:有字段(_str)时 self 用影子结构体指针;
|
||
# 无字段(_Type)时 self 用对象值 bitcast 到扩展类指针(对齐 TPC L2856-2876)
|
||
fd_entry_fd: GenTypes.StructEntry | t.CPtr = self.Gen.StructGen.find_struct_by_type(fd_sty)
|
||
fd_has_fields: int = 0
|
||
if fd_entry_fd is not None and fd_entry_fd.FieldCount > 0:
|
||
fd_has_fields = 1
|
||
# self 参数:优先使用已有影子 {var}__meta__(fd2 创建,仅当扩展类有字段时)
|
||
fd_self: llvmlite.Value | t.CPtr = None
|
||
if fd_at.value.kind() == ast.ASTKind.Name:
|
||
fd_onm: ast.Name | t.CPtr = (ast.Name | t.CPtr)(fd_at.value)
|
||
if fd_onm.id is not None:
|
||
# pool 持久缓冲(f-string 栈缓冲在函数返回后失效)
|
||
fd_mn: str = pool.alloc(256)
|
||
if fd_mn is not None:
|
||
viperlib.snprintf(fd_mn, 256, "%s__meta__", fd_onm.id)
|
||
fd_meta: llvmlite.Value | t.CPtr = self.Gen.VarGen.lookup_current(
|
||
trans.SymTab, fd_mn)
|
||
if fd_meta is not None and fd_has_fields != 0:
|
||
fd_self = fd_meta
|
||
if fd_self is None:
|
||
if fd_has_fields != 0:
|
||
# 有字段扩展类且无影子(字符串字面量等):入口创建临时影子并初始化
|
||
# 先确保 _str 完整定义(跨模块结构体默认 opaque,alloca 报 unsized)
|
||
self.Gen.StructGen.ensure_struct_def_in_module(pool, mod, fd_sty)
|
||
fd_self = self.Gen.VarGen._alloca_at_entry(builder, fd_sty)
|
||
if fd_self is None:
|
||
return None
|
||
fd_obj_val: llvmlite.Value | t.CPtr = self.Gen.ExprGen.translate_value(
|
||
builder, pool, mod, fd_at.value, None, 0, trans)
|
||
if fd_obj_val is not None:
|
||
fd_dfe: GenTypes.FieldEntry | t.CPtr = \
|
||
self.Gen.StructGen.lookup_field(fd_sty, "__data__")
|
||
if fd_dfe is not None and fd_dfe.Ty is not None:
|
||
fd_dp: llvmlite.Value | t.CPtr = llvmlite.build_gep_struct(
|
||
builder, fd_sty, fd_dfe.Ty, fd_self, fd_dfe.Index)
|
||
if fd_dp is not None:
|
||
llvmlite.build_store(builder, fd_obj_val, fd_dp)
|
||
fd_bfe: GenTypes.FieldEntry | t.CPtr = \
|
||
self.Gen.StructGen.lookup_field(fd_sty, "__mbuddy__")
|
||
if fd_bfe is not None and fd_bfe.Ty is not None:
|
||
fd_bp: llvmlite.Value | t.CPtr = llvmlite.build_gep_struct(
|
||
builder, fd_sty, fd_bfe.Ty, fd_self, fd_bfe.Index)
|
||
fd_null: llvmlite.Value | t.CPtr = llvmlite.ConstNull(
|
||
pool, fd_bfe.Ty, "null")
|
||
if fd_bp is not None and fd_null is not None:
|
||
llvmlite.build_store(builder, fd_null, fd_bp)
|
||
# FakeDuck: with 上下文自动注入 requires 字段(如 __mbuddy__)
|
||
self._inject_requires_fields(
|
||
trans, pool, builder, mod, fd_self, fd_cls)
|
||
else:
|
||
# 无字段扩展类(_Type):对象值 bitcast 到扩展类指针
|
||
fd_obj_v: llvmlite.Value | t.CPtr = self.Gen.ExprGen.translate_value(
|
||
builder, pool, mod, fd_at.value, None, 0, trans)
|
||
if fd_obj_v is None:
|
||
return None
|
||
fd_self = llvmlite.build_bitcast(
|
||
builder, fd_obj_v, llvmlite.Ptr(pool, fd_sty))
|
||
if fd_self is None:
|
||
return None
|
||
# 构建参数链表: self → 其余参数
|
||
llvmlite.value_set_next(fd_self, None)
|
||
fd_head: llvmlite.Value | t.CPtr = fd_self
|
||
fd_tail: llvmlite.Value | t.CPtr = fd_self
|
||
fd_args: list[ast.AST | t.CPtr] | t.CPtr = cl.args
|
||
fd_can: int = 0
|
||
if fd_args is not None:
|
||
fd_can = len(fd_args)
|
||
for fd_ai in range(fd_can):
|
||
fd_arg: ast.AST | t.CPtr = fd_args.get(fd_ai)
|
||
if fd_arg is not None:
|
||
fd_av: llvmlite.Value | t.CPtr = self.Gen.ExprGen.translate_value(
|
||
builder, pool, mod, fd_arg, None, 0, trans)
|
||
# char 常量参数 → 单字符字符串(char 隐式转 str,
|
||
# 如 s1.split(','):',' 是 i32 值 44,传给 str 参数须先字符串化,
|
||
# 否则运行时 strlen/strncmp 解引用 44 崩溃)
|
||
if fd_arg.kind() == ast.ASTKind.Constant:
|
||
fd_ac: ast.Constant | t.CPtr = (ast.Constant | t.CPtr)(fd_arg)
|
||
if fd_ac.const_kind == ast.CONST_CHAR:
|
||
ch_buf: str = pool.alloc(2)
|
||
if ch_buf is not None:
|
||
ch_buf[0] = char(fd_ac.int_val)
|
||
ch_buf[1] = '\0'
|
||
fd_av = self.Gen.ExprGenConst.create_global_string(
|
||
builder, pool, mod, ch_buf, trans)
|
||
if fd_av is not None:
|
||
llvmlite.value_set_next(fd_av, None)
|
||
llvmlite.value_set_next(fd_tail, fd_av)
|
||
fd_tail = fd_av
|
||
# 返回类型与调用名(来自 find_func_in_module 命中的函数定义)
|
||
fd_ret_ty: llvmlite.LLVMType | t.CPtr = llvmlite.function_get_ret_ty(fd_func)
|
||
if fd_ret_ty is None:
|
||
fd_ret_ty = llvmlite.Int32(pool)
|
||
fd_fname: str = llvmlite.function_get_name(fd_func)
|
||
if fd_fname is None:
|
||
return None
|
||
# 返回类型精确化:跨模块 declare 的 list[T] 特化返回类型可能被简化为 Ptr(i8),调用方变量 alloca 类型随之退化 → parts[0] 走字符下标路径而非 list 内联 __getitem__(printf %s 崩溃)。从定义模块 text.ll 读取精确返回类型;仅当函数名确为 "{16hex}.{func}"(判定走唯一真源 GenApi.sha1_prefix_len)才提取模块 sha1
|
||
if GenApi.sha1_prefix_len(fd_fname) != 0:
|
||
fd_sha1: str = pool.alloc(17)
|
||
if fd_sha1 is not None:
|
||
string.strncpy(fd_sha1, fd_fname, 16)
|
||
fd_sha1[16] = '\0'
|
||
fd_exact: llvmlite.LLVMType | t.CPtr = self._LookupMethodRetTyFromTextLL(
|
||
pool, fd_sha1, fd_cls, method_name)
|
||
if fd_exact is not None:
|
||
fd_ret_ty = fd_exact
|
||
fd_total: int = 1 + fd_can
|
||
return llvmlite.build_call(builder, fd_fname, fd_head, fd_total, fd_ret_ty, 0)
|
||
# ============================================================
|
||
# _inject_requires_fields - FakeDuck: with 上下文注入 requires 字段
|
||
#
|
||
# 对齐 TPC HandlesExprCall.py L4021-4079:
|
||
# 对类 __requires__ 元数据(fd1 注册)中的每个字段,运行时调用
|
||
# _find_provider(field) 查找 with 上下文提供的指针;非 NULL 时
|
||
# bitcast 到字段类型写入 meta_ptr 对应槽位(条件注入,避免覆盖
|
||
# 用户已手动设置的值)。_find_provider 未注册(未 import
|
||
# _withcontent)时跳过注入,不影响非 with 场景。
|
||
# ============================================================
|
||
|
||
# ============================================================
|
||
def _inject_requires_fields(self, trans: HT.Translator | t.CPtr,
|
||
pool: rowptr[memhub.MemBuddy],
|
||
builder: llvmlite.IRBuilder | t.CPtr,
|
||
mod: llvmlite.LLVMModule | t.CPtr,
|
||
meta_ptr: llvmlite.Value | t.CPtr,
|
||
class_name: str) -> int:
|
||
"""在 with 上下文注入 requires 字段,返回注入字段数"""
|
||
if trans is None or pool is None or builder is None or mod is None:
|
||
return 0
|
||
if meta_ptr is None or class_name is None:
|
||
return 0
|
||
# _withcontent._find_provider(跨模块):仅当本模块可见(_withcontent
|
||
# 被 import,vpi stub declare 已注入)时才注入。对齐 TPC L4048-4050
|
||
# (Gen.functions.get('_find_provider') 不存在则跳过)——否则非 with
|
||
# 项目(如 HashTableTest 未 import _withcontent)也会为每个 _str(...)
|
||
# 构造发射 {sha1}._find_provider 调用 → ld.lld undefined symbol。
|
||
fd_fn_probe: llvmlite.Function | t.CPtr = self.find_func_in_module(
|
||
mod, "_find_provider")
|
||
if fd_fn_probe is None:
|
||
return 0
|
||
fd_fname: str = llvmlite.function_get_name(fd_fn_probe)
|
||
if fd_fname is None:
|
||
return 0
|
||
cnt: int = self.Gen.ClassGenBase.class_meta_count(
|
||
GenTypes.CLASS_META_REQUIRES, class_name)
|
||
if cnt <= 0:
|
||
return 0
|
||
sty: llvmlite.LLVMType | t.CPtr = self.Gen.StructGen.get_struct_type(class_name)
|
||
if sty is None:
|
||
return 0
|
||
i8_ty_j: llvmlite.LLVMType | t.CPtr = llvmlite.Int8(pool)
|
||
if i8_ty_j is None:
|
||
return 0
|
||
i8_ptr_ty_j: llvmlite.LLVMType | t.CPtr = llvmlite.Ptr(pool, i8_ty_j)
|
||
if i8_ptr_ty_j is None:
|
||
return 0
|
||
cur_func: llvmlite.Function | t.CPtr = trans._cur_func
|
||
if cur_func is None:
|
||
return 0
|
||
injected: int = 0
|
||
for ji in range(cnt):
|
||
fname: str = self.Gen.ClassGenBase.class_meta_field_at(
|
||
GenTypes.CLASS_META_REQUIRES, class_name, ji)
|
||
if fname is None:
|
||
continue
|
||
fe: GenTypes.FieldEntry | t.CPtr = self.Gen.StructGen.lookup_field(
|
||
sty, fname)
|
||
if fe is None or fe.Ty is None:
|
||
continue
|
||
# 参数:字段名字符串(i8*)
|
||
fd_fstr: llvmlite.Value | t.CPtr = self.Gen.ExprGenConst.create_global_string(
|
||
builder, pool, mod, fname, trans)
|
||
if fd_fstr is None:
|
||
continue
|
||
llvmlite.value_set_next(fd_fstr, None)
|
||
self._ensure_method_declare(
|
||
pool, mod, fd_fname, i8_ptr_ty_j, fd_fstr, 1)
|
||
fd_ptr: llvmlite.Value | t.CPtr = llvmlite.build_call(
|
||
builder, fd_fname, fd_fstr, 1, i8_ptr_ty_j, 0)
|
||
if fd_ptr is None:
|
||
continue
|
||
# 条件注入:ptr != NULL 才写入(保留用户手动设置的值)
|
||
fd_null: llvmlite.Value | t.CPtr = llvmlite.ConstNull(
|
||
pool, i8_ptr_ty_j, "null")
|
||
if fd_null is None:
|
||
continue
|
||
fd_cmp: llvmlite.Value | t.CPtr = llvmlite.build_icmp(
|
||
builder, llvmlite.ICMP_NE, fd_ptr, fd_null)
|
||
if fd_cmp is None:
|
||
continue
|
||
# 块名唯一化(create_block 不自动编号,同名 label 在文本 IR 中
|
||
# 冲突 → llc "Terminator found in the middle of a basic block")
|
||
vtc2: int = trans._label_counter
|
||
trans._label_counter = vtc2 + 1
|
||
fd_bb_buf2: str = pool.alloc(64)
|
||
if fd_bb_buf2 is None:
|
||
continue
|
||
viperlib.snprintf(fd_bb_buf2, 64, "fd.skip.%d", vtc2)
|
||
fd_skip_bb: llvmlite.BasicBlock | t.CPtr = llvmlite.create_block(
|
||
pool, cur_func, fd_bb_buf2)
|
||
viperlib.snprintf(fd_bb_buf2, 64, "fd.inject.%d", vtc2)
|
||
fd_inject_bb: llvmlite.BasicBlock | t.CPtr = llvmlite.create_block(
|
||
pool, cur_func, fd_bb_buf2)
|
||
if fd_skip_bb is None or fd_inject_bb is None:
|
||
continue
|
||
llvmlite.build_cond_br(builder, fd_cmp, fd_inject_bb, fd_skip_bb)
|
||
# inject 块:bitcast + GEP + store,跳回 skip
|
||
llvmlite.position_at_end(builder, fd_inject_bb)
|
||
fd_cast: llvmlite.Value | t.CPtr = llvmlite.build_bitcast(
|
||
builder, fd_ptr, fe.Ty)
|
||
if fd_cast is not None:
|
||
fd_fp: llvmlite.Value | t.CPtr = llvmlite.build_gep_struct(
|
||
builder, sty, fe.Ty, meta_ptr, fe.Index)
|
||
if fd_fp is not None:
|
||
llvmlite.build_store(builder, fd_cast, fd_fp)
|
||
llvmlite.build_br(builder, fd_skip_bb)
|
||
# skip 块:恢复 CurBlock,继续后续代码生成
|
||
llvmlite.position_at_end(builder, fd_skip_bb)
|
||
injected += 1
|
||
return injected
|
||
# ============================================================
|
||
# _emit_provider_push / _emit_provider_pop - FakeDuck: with 上下文
|
||
# provider push/pop(__provides__ 元数据,fd1 注册)
|
||
#
|
||
# 对齐 TPC HandlesWith.py L138-174:
|
||
# with 进入时对每个提供字段生成 _push_provider(field_str, ctx_i8);
|
||
# 退出时生成等量 _pop_provider()。运行时 _withcontent 模块负责
|
||
# 维护 TLS provider 栈,供 _inject_requires_fields 查找。
|
||
# ============================================================
|
||
|
||
# ============================================================
|
||
def _emit_provider_push(self, trans: HT.Translator | t.CPtr,
|
||
pool: rowptr[memhub.MemBuddy],
|
||
builder: llvmlite.IRBuilder | t.CPtr,
|
||
mod: llvmlite.LLVMModule | t.CPtr,
|
||
cls_name: str,
|
||
ctx_val: llvmlite.Value | t.CPtr) -> int:
|
||
"""生成 _push_provider(field, ctx_i8) 调用(每提供字段一次),返回字段数"""
|
||
if trans is None or pool is None or builder is None or mod is None:
|
||
return 0
|
||
if cls_name is None or ctx_val is None:
|
||
return 0
|
||
fd_pc: int = self.Gen.ClassGenBase.class_meta_count(
|
||
GenTypes.CLASS_META_PROVIDES, cls_name)
|
||
if fd_pc <= 0:
|
||
return 0
|
||
# _withcontent._push_provider(跨模块,同 _find_provider 的可见性守卫:
|
||
# 本模块未 import _withcontent 时跳过,避免 undefined symbol)
|
||
fd_pfn_probe: llvmlite.Function | t.CPtr = self.find_func_in_module(
|
||
mod, "_push_provider")
|
||
if fd_pfn_probe is None:
|
||
return 0
|
||
fd_pfn: str = llvmlite.function_get_name(fd_pfn_probe)
|
||
if fd_pfn is None:
|
||
return 0
|
||
i8_ty_p: llvmlite.LLVMType | t.CPtr = llvmlite.Int8(pool)
|
||
if i8_ty_p is None:
|
||
return 0
|
||
i8_ptr_ty_p: llvmlite.LLVMType | t.CPtr = llvmlite.Ptr(pool, i8_ty_p)
|
||
if i8_ptr_ty_p is None:
|
||
return 0
|
||
ret_i32_p: llvmlite.LLVMType | t.CPtr = llvmlite.Int32(pool)
|
||
if ret_i32_p is None:
|
||
return 0
|
||
# ctx 值 bitcast 到 i8*(provider 栈存 void*)
|
||
fd_ctx_i8: llvmlite.Value | t.CPtr = llvmlite.build_bitcast(
|
||
builder, ctx_val, i8_ptr_ty_p)
|
||
if fd_ctx_i8 is None:
|
||
return 0
|
||
for pi in range(fd_pc):
|
||
fname: str = self.Gen.ClassGenBase.class_meta_field_at(
|
||
GenTypes.CLASS_META_PROVIDES, cls_name, pi)
|
||
if fname is None:
|
||
continue
|
||
fd_fstr: llvmlite.Value | t.CPtr = self.Gen.ExprGenConst.create_global_string(
|
||
builder, pool, mod, fname, trans)
|
||
if fd_fstr is None:
|
||
continue
|
||
llvmlite.value_set_next(fd_fstr, fd_ctx_i8)
|
||
llvmlite.value_set_next(fd_ctx_i8, None)
|
||
self._ensure_method_declare(
|
||
pool, mod, fd_pfn, ret_i32_p, fd_fstr, 2)
|
||
llvmlite.build_call(builder, fd_pfn, fd_fstr, 2, ret_i32_p, 0)
|
||
return fd_pc
|
||
def _emit_provider_pop(self, trans: HT.Translator | t.CPtr,
|
||
pool: rowptr[memhub.MemBuddy],
|
||
builder: llvmlite.IRBuilder | t.CPtr,
|
||
mod: llvmlite.LLVMModule | t.CPtr,
|
||
cls_name: str) -> int:
|
||
"""生成 _pop_provider() 调用(每提供字段一次),返回字段数"""
|
||
if trans is None or pool is None or builder is None or mod is None:
|
||
return 0
|
||
if cls_name is None:
|
||
return 0
|
||
fd_pc: int = self.Gen.ClassGenBase.class_meta_count(
|
||
GenTypes.CLASS_META_PROVIDES, cls_name)
|
||
if fd_pc <= 0:
|
||
return 0
|
||
# _withcontent._pop_provider(跨模块,同 _find_provider 的可见性守卫:
|
||
# 本模块未 import _withcontent 时跳过,避免 undefined symbol)
|
||
fd_pon_probe: llvmlite.Function | t.CPtr = self.find_func_in_module(
|
||
mod, "_pop_provider")
|
||
if fd_pon_probe is None:
|
||
return 0
|
||
fd_pon: str = llvmlite.function_get_name(fd_pon_probe)
|
||
if fd_pon is None:
|
||
return 0
|
||
ret_i32_q: llvmlite.LLVMType | t.CPtr = llvmlite.Int32(pool)
|
||
if ret_i32_q is None:
|
||
return 0
|
||
self._ensure_method_declare(pool, mod, fd_pon, ret_i32_q, None, 0)
|
||
for _pi in range(fd_pc):
|
||
llvmlite.build_call(builder, fd_pon, None, 0, ret_i32_q, 0)
|
||
return fd_pc |