fix(tpc): 含 raise 函数调用参数补全排除 EH 输出参数,杜绝双重注入 - CallGenMixin 零值兜底与 CallGenCall found_func 参数数回退原将 %__eh_msg_out__/%__eh_code_out__ 计入形参数,为 raise_disk() 无参调用补 2 个 zeroinitializer 占位,_emit_eh_guarded_call 又追加真实 EH 实参 → call 4 参 vs define 2 参 → x64 ABI 错位 → 函数写 null 输出指针 0xC0000005(TestFBProject raise_disk 崩溃根因);三处计数均排除 EH 参数

This commit is contained in:
TermiNexus committed 2026-08-25 14:04:27 +08:00
1 parent 916c1284c9
commit 21e67cac40
2 files changed
+1301 -4

No files matched your search

+18 -4
View File
@@ -459,14 +459,21 @@ class CallGenCall(CallGenBase.CallGenBase):
# 函数表/默认表无 ParamCount 但 found_func(declare)已找到时用其参数数
# 作补全基准,否则省略默认参数(如 translate_value 的 target_ty=None)
# 的调用补全不触发 → call 实参 < define 形参 → ABI 错位读栈残留垃圾。
# 排除 EH 输出参数(%__eh_msg_out__/%__eh_code_out__):含 raise 函数
# 定义尾部注入 2 个 EH 形参,计入会让 _emit_eh_guarded_call 追加真实
# EH 实参前先补 zeroinitializer 占位 → 双重注入 call 实参多 2(TestFBProject
# raise_disk() 崩溃根因,与 CallGenMixin 零值兜底同源)。
if mdf_param_count == 0 and found_func is not None:
ppcnt_f2: int = 0
ppn_f2: llvmlite.Param | t.CPtr = llvmlite.function_get_param_head(found_func)
while ppn_f2 is not None:
ppcnt_f2 += 1
fp_nm_f2: str = llvmlite.param_get_name(ppn_f2)
if fp_nm_f2 is None or (string.strcmp(fp_nm_f2, "%__eh_msg_out__") != 0
and string.strcmp(fp_nm_f2, "%__eh_code_out__") != 0):
ppcnt_f2 += 1
ppn_f2 = llvmlite.param_get_next(ppn_f2)
if ppcnt_f2 > 1:
mdf_param_count = ppcnt_f2 - 1 # 非 self 参数数
mdf_param_count = ppcnt_f2 - 1 # 非 self 非 EH 参数数
# 计算需要填充的参数(不含 self)
# extra_count = 已提供的非 self 参数数量
@@ -1410,14 +1417,21 @@ class CallGenCall(CallGenBase.CallGenBase):
# target_ty=None)的调用补全不触发 → call 实参(8) < define 形参(9)
# → x64 ABI 第 9 参读栈残留垃圾 → is_ptr_type(0x40) 崩溃(SlotsBugTest
# 二代编 translate_assign/AugAssign 崩溃根因)。
# 排除 EH 输出参数(%__eh_msg_out__/%__eh_code_out__):含 raise 方法
# 定义尾部注入 2 个 EH 形参,计入会让补全先补 zeroinitializer 占位,
# _emit_eh_guarded_call 再追加真实 EH 实参 → 双重注入(TestFBProject
# raise_disk() 崩溃同源,与 _call_method_on_ptr/CallGenMixin 一致)。
if mdf_param_count == 0 and found_func is not None:
ppcnt_f: int = 0
ppn_f: llvmlite.Param | t.CPtr = llvmlite.function_get_param_head(found_func)
while ppn_f is not None:
ppcnt_f += 1
fp_nm_f: str = llvmlite.param_get_name(ppn_f)
if fp_nm_f is None or (string.strcmp(fp_nm_f, "%__eh_msg_out__") != 0
and string.strcmp(fp_nm_f, "%__eh_code_out__") != 0):
ppcnt_f += 1
ppn_f = llvmlite.param_get_next(ppn_f)
if ppcnt_f > 1:
mdf_param_count = ppcnt_f - 1 # 非 self 参数数
mdf_param_count = ppcnt_f - 1 # 非 self 非 EH 参数数
# 计算需要填充的参数(不含 self)
# arg_count_eff = 已提供的非 self 参数数量(含关键字模式完整构建)
File diff suppressed because it is too large. Load diff