fix(tpc): 函数声明创建收口到幂等入口 _CreateOrReuseFuncDecl;清理 DDEBUG 探针
类别:a 编译器缺陷(根因修复)+ 调试探针移除。 现场:翻译 CallGenFd.vp 时抛 llvmlite.ir._utils.DuplicatedNameError: '5d84ea579d83ef73.CallGenFd._translate_fakeduck_call'(llvmlite 的 NameScope 按名字去重,GlobalValue.deduplicate_name=False ⇒ 同名 global 建第二次必抛,且报文只给名字、不给两侧签名)。 根因:BaseGen._get_or_declare_function 建完 ir.Function 后**只加入 module.globals**(llvmlite 自动)而**未登记 Gen.functions**;而 HandlesFunctions._EmitFunctionLlvm 的 need_new 判据只看 Gen.functions (`MangledName not in Gen.functions`)⇒ 同一名字再建一次 → DuplicatedNameError; 该处 except 又把它吞掉(非 strict 模式只 LogWarning)→ 函数始终没进 Gen.functions → 后续其它创建点(FuncGen._get_or_declare_func / get_or_declare_c_func,同样只查 self.functions)再建 → 异常从别处逃逸到 Phase2Translator。 修复: 1. BaseGen 新增 _CreateOrReuseFuncDecl(name, func_type) —— 函数声明创建的 唯一幂等入口:module.globals 已有同名函数且**函数类型结构串相同**则复用 (并补登记 Gen.functions;FunctionType 无 __eq__,只能比 str); 类型不同则 fail-fast 报出两侧签名(declare/define 分裂的真因), 绝不静默复用错签名(调用点会按错签名传参)。 2. _get_or_declare_function 改走该入口(顺带补登记 Gen.functions); FuncGen._get_or_declare_func / get_or_declare_c_func 改走该入口; HandlesFunctions 定义路径改走该入口,且该处 except 对 FailFastError 直接 re-raise(不再吞)。 3. 清理遗留调试探针(含 sys.exit(1)):BaseGen 三处 [DDEBUG] (_get_or_declare_function 双点 / _mangle_func_name 前导点与结果双点)、 HandlesExprAsm 两处 [DDEBUG_ASM]、HandlesExprCall 一处 [DDEBUG] _HandleClosureCallLlvm。
This commit is contained in:
1 parent
3bc3c48dee
commit
9d8aedec4a
5 files changed
+47
-57
No files matched your search
@@ -310,11 +310,6 @@ class ExprAsmHandle(BaseHandle):
|
||||
def _mangle_asm_calls(self, template: str) -> str:
|
||||
Gen: LlvmCodeGenerator = self.Trans.LlvmGen
|
||||
sha1: str = getattr(Gen, 'module_sha1', '')
|
||||
# DDEBUG: 检测 module_sha1 是否带尾随点(双点 bug 根因拦截)
|
||||
if sha1 and sha1.endswith('.'):
|
||||
import sys as _dbg_sys
|
||||
print(f"[DDEBUG_ASM] module_sha1 带尾随点: sha1='{sha1}' len={len(sha1)} template='{template[:80]}'", file=_dbg_sys.stderr)
|
||||
_dbg_sys.exit(1)
|
||||
if not sha1:
|
||||
return template
|
||||
|
||||
@@ -324,11 +319,6 @@ class ExprAsmHandle(BaseHandle):
|
||||
if func_name.lower() in self._X86_REGISTERS:
|
||||
return m.group(0)
|
||||
mangled: str = Gen._mangle_func_name(func_name)
|
||||
# DDEBUG: 检测 mangled 是否含双点(双点 bug 根因拦截)
|
||||
if '..' in mangled:
|
||||
import sys as _dbg_sys
|
||||
print(f"[DDEBUG_ASM] mangled 含双点: func='{func_name}' mangled='{mangled}' sha1='{sha1}'", file=_dbg_sys.stderr)
|
||||
_dbg_sys.exit(1)
|
||||
if '.' in mangled:
|
||||
return f'{prefix}\\22{mangled}\\22'
|
||||
return f"{prefix}{mangled}"
|
||||
|
||||
@@ -2479,15 +2479,6 @@ class ExprCallHandle(BaseHandle):
|
||||
def _HandleClosureCallLlvm(self, Node: ast.Call, FuncName: str) -> ir.Value:
|
||||
Gen = self.Trans.LlvmGen
|
||||
func = Gen.functions.get(FuncName)
|
||||
# DDEBUG: 检测 func.name 含双点(说明 ir.Function 已被错误注册为双点名字)
|
||||
if func is not None and '..' in getattr(func, 'name', ''):
|
||||
import sys
|
||||
sys.stderr.write(f"[DDEBUG] _HandleClosureCallLlvm DOUBLE-DOT func.name='{func.name}' FuncName='{FuncName}'\n")
|
||||
sys.stderr.write(f"[DDEBUG] Gen.functions keys for '{FuncName}': {[k for k in list(Gen.functions.keys()) if '6ddf' in k or k == FuncName][:20]}\n")
|
||||
import traceback
|
||||
traceback.print_stack(file=sys.stderr, limit=10)
|
||||
sys.stderr.flush()
|
||||
sys.exit(1)
|
||||
if not func:
|
||||
if FuncName in self.Trans.FunctionDefCache:
|
||||
FuncDef = self.Trans.FunctionDefCache[FuncName]
|
||||
|
||||
@@ -1253,7 +1253,13 @@ class FunctionHandle(BaseHandle):
|
||||
need_new = True
|
||||
if need_new:
|
||||
try:
|
||||
func: ir.Function = ir.Function(Gen.module, FuncType, name=MangledName)
|
||||
# 统一走幂等入口:module.globals 已有同名函数时复用(并补登记
|
||||
# Gen.functions),签名冲突则 fail-fast —— 绝不直接新建同名
|
||||
# ir.Function(llvmlite NameScope 按名去重,必抛 DuplicatedNameError;
|
||||
# 现场:5d84ea579d83ef73.CallGenFd._translate_fakeduck_call 被此路径新建,
|
||||
# 而 BaseGen._get_or_declare_function 已建过同名声明却未登记
|
||||
# Gen.functions ⇒ need_new 误判为真)。
|
||||
func: ir.Function = Gen._CreateOrReuseFuncDecl(MangledName, FuncType)
|
||||
func.attributes.add('noredzone')
|
||||
if hasattr(self, '_cdefine_funcs') and FuncName in self._cdefine_funcs:
|
||||
func.linkage = 'linkonce_odr'
|
||||
@@ -1270,6 +1276,10 @@ class FunctionHandle(BaseHandle):
|
||||
if MangledName == FuncName or FuncName not in Gen._export_extern_funcs:
|
||||
Gen.functions[FuncName] = func
|
||||
except Exception as _e:
|
||||
from lib.core.LLVMCG.FuncGen import FailFastError
|
||||
if isinstance(_e, FailFastError):
|
||||
# 签名冲突 = declare/define 分裂,必须终止(不吞)
|
||||
raise
|
||||
if _config_mode == "strict":
|
||||
self.Trans.LogWarning(f"异常被忽略: {_e}")
|
||||
else:
|
||||
|
||||
+30
-28
@@ -871,33 +871,43 @@ class BaseGenMixin:
|
||||
return [p]
|
||||
return []
|
||||
|
||||
def _CreateOrReuseFuncDecl(self, name: str, func_type: ir.FunctionType) -> ir.Function:
|
||||
"""函数声明创建的唯一幂等入口(所有"新建 ir.Function"的路径都应走这里)。
|
||||
|
||||
llvmlite 的 NameScope 按名字去重(GlobalValue.deduplicate_name=False):
|
||||
同名 global 再建一次必抛 llvmlite.ir._utils.DuplicatedNameError(只给名字、
|
||||
不给两侧签名,现场:5d84ea579d83ef73.CallGenFd._translate_fakeduck_call)。
|
||||
故此处:
|
||||
· module.globals 已有同名函数且函数类型(按字符串比较,FunctionType 无
|
||||
__eq__ ⇒ 只能比结构串)相同 ⇒ **复用**并补登记 Gen.functions;
|
||||
· 已有但类型不同 ⇒ fail-fast 报出两侧签名 —— 这是 declare / define 分裂的
|
||||
真因,绝不静默复用错签名(会让调用点按错签名传参)。
|
||||
"""
|
||||
existing: Any = self.module.globals.get(name)
|
||||
if isinstance(existing, ir.Function):
|
||||
_old_type: Any = getattr(existing, 'ftype', None)
|
||||
if _old_type is None or str(_old_type) == str(func_type):
|
||||
self.functions[name] = existing
|
||||
return existing
|
||||
from lib.core.LLVMCG.FuncGen import FailFastError
|
||||
raise FailFastError(
|
||||
f"同名函数声明签名冲突(declare/define 分裂):'{name}'"
|
||||
f"\n · 已存在声明: {_old_type}"
|
||||
f"\n · 本次要创建: {func_type}"
|
||||
f"\n 拒绝静默复用(调用点会按错签名传参);请核对同一函数在声明侧"
|
||||
f"(stub / .vpi)与定义侧的注解解析结果是否一致。")
|
||||
func: ir.Function = ir.Function(self.module, func_type, name=name)
|
||||
self.functions[name] = func
|
||||
return func
|
||||
|
||||
def _get_or_declare_function(self, mangled_name: str, func_type: ir.FunctionType) -> ir.Function:
|
||||
# DDEBUG: 检测 mangled_name 含双点(不应到达这里)
|
||||
if '..' in mangled_name:
|
||||
import sys
|
||||
sys.stderr.write(f"[DDEBUG] _get_or_declare_function DOUBLE-DOT mangled_name='{mangled_name}'\n")
|
||||
import traceback
|
||||
traceback.print_stack(file=sys.stderr, limit=10)
|
||||
sys.stderr.flush()
|
||||
sys.exit(1)
|
||||
g = self.module.globals.get(mangled_name)
|
||||
if g and isinstance(g, ir.Function):
|
||||
return g
|
||||
return ir.Function(self.module, func_type, name=mangled_name)
|
||||
return self._CreateOrReuseFuncDecl(mangled_name, func_type)
|
||||
|
||||
def _get_function(self, name: str) -> ir.Function | None:
|
||||
func: ir.Function | None = self._find_function(name)
|
||||
return func
|
||||
|
||||
def _mangle_func_name(self, name: str, module_name: str | None = None) -> str:
|
||||
# DDEBUG: 检测即将产生双点的情况,立即打印并终止
|
||||
if name.startswith('.') or (module_name and module_name.endswith('.') and len(module_name) > 0):
|
||||
import sys
|
||||
sys.stderr.write(f"[DDEBUG] _mangle_func_name LEADING-DOT name='{name}' module_name='{module_name}'\n")
|
||||
import traceback
|
||||
traceback.print_stack(file=sys.stderr, limit=8)
|
||||
sys.stderr.flush()
|
||||
sys.exit(1)
|
||||
if name in self._export_funcs and not module_name:
|
||||
return name
|
||||
if name in self._export_extern_funcs:
|
||||
@@ -955,14 +965,6 @@ class BaseGenMixin:
|
||||
result = f"{self.module_sha1}.{name}"
|
||||
else:
|
||||
result = name
|
||||
# DDEBUG: 检测返回结果中是否含双点
|
||||
if '..' in result:
|
||||
import sys
|
||||
sys.stderr.write(f"[DDEBUG] _mangle_func_name RESULT-DOUBLE-DOT name='{name}' module_name='{module_name}' result='{result}'\n")
|
||||
import traceback
|
||||
traceback.print_stack(file=sys.stderr, limit=10)
|
||||
sys.stderr.flush()
|
||||
sys.exit(1)
|
||||
return result
|
||||
|
||||
def _get_source_line(self, lineno: int) -> str | None:
|
||||
|
||||
@@ -812,9 +812,10 @@ class FuncGenMixin:
|
||||
return fobj
|
||||
if re.match(r'^[0-9a-f]{16,}\.' + re.escape(name) + r'$', fname):
|
||||
return fobj
|
||||
func_decl: ir.Function = ir.Function(self.module, func_type, name=name)
|
||||
self.functions[name] = func_decl
|
||||
return func_decl
|
||||
# module.globals 里可能已有同名函数而 Gen.functions 未登记(如
|
||||
# BaseGen._get_or_declare_function 的历史路径):直接新建必抛 llvmlite
|
||||
# DuplicatedNameError(NameScope 按名去重)⇒ 统一走幂等入口。
|
||||
return self._CreateOrReuseFuncDecl(name, func_type)
|
||||
|
||||
def get_or_declare_c_func(self, name: str, fallback_type: ir.FunctionType | None = None) -> ir.Function | None:
|
||||
if name in self.functions:
|
||||
@@ -831,11 +832,7 @@ class FuncGenMixin:
|
||||
raise
|
||||
_vlog().warning(f"查找桩函数类型失败: {_e}", "Exception")
|
||||
if stub_func_type:
|
||||
func_decl: ir.Function = ir.Function(self.module, stub_func_type, name=name)
|
||||
self.functions[name] = func_decl
|
||||
return func_decl
|
||||
return self._CreateOrReuseFuncDecl(name, stub_func_type)
|
||||
if fallback_type is not None:
|
||||
func_decl: ir.Function = ir.Function(self.module, fallback_type, name=name)
|
||||
self.functions[name] = func_decl
|
||||
return func_decl
|
||||
return self._CreateOrReuseFuncDecl(name, fallback_type)
|
||||
return None
|
||||
Reference in new issue
Block a user