refactor(tpv): SHA1 前缀判定收敛到 GenApi 唯一真源(C10/D3 收尾)
- CallGenCall: list 泛型前缀剥离(719) 与类型名提 sha1(907/1190) 改 GenApi.sha1_prefix_len,不再盲取前 16 字节当 sha1 - CallGenCBuiltin._asm_name_is_mangled / CallGenLib._is_sha1_mangled_call: 改真源(去大写 A-F、去扫描任意位置 '.') - CallGenFd: 类型名提 sha1 加前缀格式校验(裸名不再误取前 16 字节) - CallGenMixin: CExport declare 前缀判定改真源 - StructGenMixin / TypeGenResolve: 类型名、模块段判定改真源;StructGenMixin 补漏掉的 GenApi import(L596/L943 引用原会 fail-fast)
This commit is contained in:
1 parent
471bedbcf4
commit
7e68e76ec4
7 files changed
+56
-65
No files matched your search
@@ -1017,10 +1017,12 @@ class CallGenCBuiltin(CallGenBase.CallGenBase):
|
||||
|
||||
|
||||
def _asm_name_is_mangled(self, name: str) -> int:
|
||||
"""判断 LLVM 名称是否带 SHA1 混淆头(16 hex + '.'),返回 1=是
|
||||
"""判断 LLVM 名称是否带 SHA1 混淆头("{16位小写hex}."),返回 1=是
|
||||
|
||||
兼容 make_global_ref 生成的 '@"sha1.name"' 引用名和 GlobalVariable
|
||||
裸名 "sha1.name"。'@name' 裸引用与局部 SSA(%N)都不算混淆。
|
||||
判定走唯一真源 GenApi.sha1_prefix_len(C10 收敛:不再接受大写 hex,
|
||||
也不再扫描任意位置的 '.' 后回看 16 字节,避免 "a.b..." 形态误判)。
|
||||
"""
|
||||
if name is None:
|
||||
return 0
|
||||
@@ -1029,22 +1031,10 @@ class CallGenCBuiltin(CallGenBase.CallGenBase):
|
||||
# 去掉 '@"..."' 包装(引用名)
|
||||
if nlen >= 3 and n[0] == '@' and n[1] == '"' and n[nlen - 1] == '"':
|
||||
n = n + 2
|
||||
nlen -= 3
|
||||
elif nlen >= 1 and n[0] == '@':
|
||||
n = n + 1
|
||||
nlen -= 1
|
||||
if nlen <= 17:
|
||||
return 0
|
||||
for i in range(16, nlen):
|
||||
if n[i] == '.':
|
||||
ok: int = 1
|
||||
for j in range(16):
|
||||
cc: char = n[i - 16 + j]
|
||||
if not (('0' <= cc <= '9') or ('a' <= cc <= 'f') or ('A' <= cc <= 'F')):
|
||||
ok = 0
|
||||
break
|
||||
if ok != 0:
|
||||
return 1
|
||||
if GenApi.sha1_prefix_len(n) != 0:
|
||||
return 1
|
||||
return 0
|
||||
|
||||
|
||||
|
||||
@@ -714,11 +714,12 @@ class CallGenCall(CallGenBase.CallGenBase):
|
||||
# 保证 get/append 等 list 内置方法一律命中、绝不进入 MRO 解析。
|
||||
if method_name is not None and class_name is not None:
|
||||
lb_cls: str = class_name
|
||||
# 剥离跨模块特化名 sha1 前缀 "{16hex}."({sha}.list[...] 形态)
|
||||
if string.strncmp(lb_cls, "list", 4) != 0 \
|
||||
and string.strlen(lb_cls) > 17 and lb_cls[16] == '.':
|
||||
if string.strncmp(lb_cls + 17, "list", 4) == 0:
|
||||
lb_cls = lb_cls + 17
|
||||
# 剥离跨模块特化名 sha1 前缀 "{16hex}."({sha}.list[...] 形态);
|
||||
# 前缀长度判定走唯一真源 GenApi.sha1_prefix_len(C10 收敛)。
|
||||
lb_pfx_d: int = GenApi.sha1_prefix_len(lb_cls)
|
||||
if string.strncmp(lb_cls, "list", 4) != 0 and lb_pfx_d != 0:
|
||||
if string.strncmp(lb_cls + lb_pfx_d, "list", 4) == 0:
|
||||
lb_cls = lb_cls + lb_pfx_d
|
||||
if self.Gen.CallGenProp._is_list_builtin_method(lb_cls, method_name) != 0:
|
||||
# 双指针槽形态(rowptr[list[...]] 局部变量 alloca Ptr(Ptr(Struct))
|
||||
# 直接传入时先 load 一层得到对象指针 Ptr(Struct),与分派方
|
||||
@@ -903,8 +904,10 @@ class CallGenCall(CallGenBase.CallGenBase):
|
||||
match mc_struct_ty:
|
||||
case llvmlite.LLVMType.Struct(_fs_sp, _fc_sp, type_name_sp):
|
||||
if type_name_sp is not None and type_name_sp[0] != '\0':
|
||||
tl_sp: sizet = string.strlen(type_name_sp)
|
||||
if tl_sp >= 16:
|
||||
# 仅当类型名确为 "{16hex}.{Class}" 才提取 sha1;
|
||||
# 判定走唯一真源 GenApi.sha1_prefix_len(C10 收敛),
|
||||
# 避免把裸类名前 16 字节误当 sha1。
|
||||
if GenApi.sha1_prefix_len(type_name_sp) != 0:
|
||||
sb_sp: str = pool.alloc(17)
|
||||
if sb_sp is not None:
|
||||
string.strncpy(sb_sp, type_name_sp, 16)
|
||||
@@ -1186,8 +1189,9 @@ class CallGenCall(CallGenBase.CallGenBase):
|
||||
match mc_struct_ty:
|
||||
case llvmlite.LLVMType.Struct(_fields_st, _fcount_st, type_name_st):
|
||||
if type_name_st is not None and type_name_st[0] != '\0':
|
||||
type_len_st: sizet = string.strlen(type_name_st)
|
||||
if type_len_st >= 16:
|
||||
# 仅当类型名确为 "{16hex}.{Class}" 才提取 sha1;
|
||||
# 判定走唯一真源 GenApi.sha1_prefix_len(C10 收敛)。
|
||||
if GenApi.sha1_prefix_len(type_name_st) != 0:
|
||||
sha1_from_ty: str = pool.alloc(17)
|
||||
if sha1_from_ty is not None:
|
||||
string.strncpy(sha1_from_ty, type_name_st, 16)
|
||||
@@ -1203,8 +1207,9 @@ class CallGenCall(CallGenBase.CallGenBase):
|
||||
viperlib.snprintf(mangled_anc, ml_anc, "%s.%s.%s",
|
||||
ret_anc_sha1, ret_anc_name, method_name)
|
||||
call_name = mangled_anc
|
||||
# 类型名提取的 sha1 无法保证为真实模块 sha1(跨模块 stub 类型名
|
||||
# 带前缀但 find_struct 未注册时仍可用),此处不校验格式
|
||||
# 类型名提取的 sha1 已按 "{16hex}." 前缀格式校验(sha1_prefix_len);
|
||||
# 不校验它是否为真实已注册模块 sha1(跨模块 stub 类型名带前缀但
|
||||
# find_struct 未注册时仍可用)
|
||||
elif ret_anc_name is not None and ret_anc_sha1 is None:
|
||||
# fail-fast:方法所属类既查不到 SHA1 又从类型名提取失败,
|
||||
# 禁止静默裸名(否则链接期 undefined symbol 难以定位)
|
||||
|
||||
@@ -7,6 +7,7 @@ import memhub
|
||||
import string
|
||||
import viperlib
|
||||
import lib.core.Gen.Translator as HT
|
||||
import lib.core.Gen.GenApi as GenApi
|
||||
|
||||
from . import CallGenBase
|
||||
|
||||
@@ -176,14 +177,17 @@ class CallGenFd(CallGenBase.CallGenBase):
|
||||
# 为 Ptr(i8),调用方变量 alloca 类型随之退化 → parts[0] 走字符下标
|
||||
# 路径而非 list 内联 __getitem__(printf %s 解引用字符值崩溃)。
|
||||
# 从定义模块 text.ll 读取精确返回类型(对齐普通方法调用 _translate_method_call)。
|
||||
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
|
||||
# 仅当函数名确为 "{16hex}.{func}" 才提取模块 sha1(判定走唯一真源
|
||||
# GenApi.sha1_prefix_len,C10 收敛),避免把裸名前 16 字节误当 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)
|
||||
# ============================================================
|
||||
|
||||
@@ -7,6 +7,7 @@ import string
|
||||
import stdlib
|
||||
import lib.core.Gen.Translator as HT
|
||||
import lib.Stub.StubGen.VpiReader as VpiReader
|
||||
import lib.core.Gen.GenApi as GenApi
|
||||
|
||||
from . import CallGenBase
|
||||
|
||||
@@ -636,26 +637,17 @@ class CallGenLib(CallGenBase.CallGenBase):
|
||||
|
||||
return None
|
||||
def _is_sha1_mangled_call(self, call_name: str) -> int:
|
||||
"""判断 call_name 是否为跨模块 Viper 函数("{16位hex}.func" 形式)
|
||||
"""判断 call_name 是否为跨模块 Viper 函数("{16位小写hex}.func" 形式)
|
||||
|
||||
C 库函数(strlen 等裸名)和 Win32 API(VirtualAlloc 等裸名)返回 0,
|
||||
不参与精确返回类型解析(走 _infer_external_func_ret_ty 白名单)。
|
||||
判定走唯一真源 GenApi.sha1_prefix_len(C10 收敛:不再接受大写 hex)。
|
||||
"""
|
||||
if call_name is None:
|
||||
return 0
|
||||
first_dot: str = string.strchr(call_name, '.')
|
||||
if first_dot is None:
|
||||
return 0
|
||||
pre_len: sizet = sizet(uint64(first_dot) - uint64(call_name))
|
||||
if pre_len != 16:
|
||||
return 0
|
||||
for hx in range(16):
|
||||
ch: int = call_name[hx]
|
||||
if ch < 48 or ch > 57:
|
||||
if ch < 97 or ch > 102:
|
||||
if ch < 65 or ch > 70:
|
||||
return 0
|
||||
return 1
|
||||
if GenApi.sha1_prefix_len(call_name) != 0:
|
||||
return 1
|
||||
return 0
|
||||
def _emit_llvm_memcpy_intrinsic(self, pool: rowptr[memhub.MemBuddy],
|
||||
builder: llvmlite.IRBuilder | t.CPtr,
|
||||
mod: llvmlite.LLVMModule | t.CPtr,
|
||||
|
||||
@@ -1254,16 +1254,15 @@ class CallGenMixin(CallGenBase.CallGenBase):
|
||||
# (该分支仅 found_func None 的模块限定路径),这里对带前缀
|
||||
# 的 declare 提取 sha1 再查 CExport 注册表,命中则改用裸名。
|
||||
if found_func.IsDeclared != 0:
|
||||
dot_pos_cx: str = string.strchr(found_name, 46)
|
||||
if dot_pos_cx is not None:
|
||||
cx_pre_len: sizet = string.strlen(found_name) - string.strlen(dot_pos_cx)
|
||||
if cx_pre_len == 16:
|
||||
cx_sha1_buf: str = pool.alloc(17)
|
||||
if cx_sha1_buf is not None:
|
||||
string.memcpy(cx_sha1_buf, found_name, 16)
|
||||
cx_sha1_buf[16] = '\0'
|
||||
if self.Gen.CallGenBase.is_cexport_func(cx_sha1_buf, func_name) != 0:
|
||||
call_name = func_name
|
||||
# 判定走唯一真源 GenApi.sha1_prefix_len(C10 收敛:此前只判
|
||||
# 首个 '.' 前恰 16 字节、不校验 hex 形态)。
|
||||
if GenApi.sha1_prefix_len(found_name) != 0:
|
||||
cx_sha1_buf: str = pool.alloc(17)
|
||||
if cx_sha1_buf is not None:
|
||||
string.memcpy(cx_sha1_buf, found_name, 16)
|
||||
cx_sha1_buf[16] = '\0'
|
||||
if self.Gen.CallGenBase.is_cexport_func(cx_sha1_buf, func_name) != 0:
|
||||
call_name = func_name
|
||||
else:
|
||||
# 跨模块函数调用:found_func 为 None 时,检查是否是模块限定调用
|
||||
# 如 string.strchr(...) → @{sha1_of_string}.strchr
|
||||
|
||||
@@ -14,6 +14,7 @@ import lib.Stub.StubMerger.StubMergerStore as StubMergerStore
|
||||
import lib.core.Gen.GenTypes as GenTypes
|
||||
import lib.core.Gen.Generator as Generator
|
||||
import lib.core.Gen.Type.TypeSpec as TSpec
|
||||
import lib.core.Gen.GenApi as GenApi
|
||||
|
||||
# ============================================================
|
||||
# StructGenMixin - 结构体注册/字段查找 Mixin(对象化 P2-2,wiki/14-oo-refactor.md)
|
||||
@@ -797,13 +798,11 @@ class StructGenMixin:
|
||||
# "Thread") 命中 vthreading 的 entry → 其 arg@3 被当成
|
||||
# sched.Thread.arg(应 4)→ th.func 被 th.arg=None 覆盖 →
|
||||
# _thread_entry call 0 → #UD/#GP)。strncmp 不分配临时缓冲。
|
||||
# 前缀判定走唯一真源 GenApi.sha1_prefix_len(C10 收敛:此前只判
|
||||
# 首个 '.' 前恰 16 字节、不校验 hex 形态)。
|
||||
ty_has_sha1_lf: int = 0
|
||||
dot_ty_lf: str = string.strchr(ty_name, '.')
|
||||
if dot_ty_lf is not None:
|
||||
pre_len_lf: sizet = sizet(
|
||||
uint64(dot_ty_lf) - uint64(ty_name))
|
||||
if pre_len_lf == 16:
|
||||
ty_has_sha1_lf = 1
|
||||
if GenApi.sha1_prefix_len(ty_name) != 0:
|
||||
ty_has_sha1_lf = 1
|
||||
for i in range(self.StructCount):
|
||||
entry: GenTypes.StructEntry | t.CPtr = self._get_struct_entry(i)
|
||||
if entry is not None and entry.Name is not None:
|
||||
|
||||
@@ -2144,7 +2144,9 @@ class TypeGenResolve(TypeGenBase.TypeGenBase):
|
||||
# SHA1 前缀形态优先用完整名 "{sha1}.{Class}" 精确命中定义侧
|
||||
# struct(get_struct_type 类名回退可能命中跨模块同名类)
|
||||
full_attr_ty: llvmlite.LLVMType | t.CPtr = None
|
||||
if is_builtin_attr == 0 and string.strlen(val_name.id) == 16:
|
||||
# val_name.id 是模块名段:恰为 16 位小写 hex 才是 SHA1 别名
|
||||
#(判定走唯一真源 GenApi.is_sha1_hex16,C10 收敛)。
|
||||
if is_builtin_attr == 0 and GenApi.is_sha1_hex16(val_name.id) != 0:
|
||||
full_q: str = self._concat_sha1_class(pool, val_name.id, at.attr)
|
||||
if full_q is not None:
|
||||
full_attr_ty = self.Gen.StructGen.get_struct_type(full_q)
|
||||
|
||||
Reference in new issue
Block a user