fix(tpc): 函数声明创建全部收口到唯一幂等入口,消除 DuplicatedNameError 裸抛
类别 a(编译器缺陷)+ b(机制漏豁免)。报错:翻译 lib\core\Gen\Expr\ExprGenName.vp
失败,报文只有名字 dddc595175f00c66.ExprGenAttr.find_global_in_module
⇒ llvmlite DuplicatedNameError(NameScope.register 对 GlobalValue
deduplicate_name=False,同名 global 再建必抛,__str__ 只回名字)。
根因(已取证,非猜测):
- llvmlite Module 里 `scope`(NameScope,注册/去重)与 `globals`(OrderedDict)
是两套结构;`add_global` 只在构造时写入 ===> 「名字已在 scope._useset、
但 globals 查不到」这一状态一旦出现,任何"先查 globals 再建"的守卫都会失效。
- 该状态由**清理不完整**制造:删旧名时只删"对象真名 existing_func.name/old_name",
而字典键/目标名(func_name / MangledName)仍留在 scope._useset。
别名注册(Gen.functions[短名] = 名为全名的对象)恰好让二者不同名。
- 另有若干创建点只看 Gen.functions、完全不看 module.globals(裸建 ir.Function),
只要 module.globals 已有同名声明就裸抛 DuplicatedNameError。
本次收口(函数声明创建的唯一入口 = BaseGen._CreateOrReuseFuncDecl):
1. BaseGen._CreateOrReuseFuncDecl:新增"名字被非函数 global 占住"分支,把冲突
双方(类型 + repr)报出来,替代原 llvmlite 只给名字的裸抛。
2. 清理不完整处补全为「同时清 真名 + 目标名」:
- HandlesImports.py 模板 declare 装载(clearing func_name 之外还清 existing_func.name)
- HandlesFunctions._replace_function_decl(clearing {old_name, MangledName})
- 其 except 对 FailFastError 改为上抛(不再回退成复用旧声明)
3. 裸建 ir.Function 的创建点改走唯一入口(module.globals 同名则复用、
签名冲突/非函数冲突则 fail-fast):
- HandlesExprCall._HandleStaticMethodCallLlvm({sha1}.Class.Method) ← 本现场形态
- HandlesExprCall._HandleMethodCallLlvm 的 class_sha1 回退分支
- HandlesExprCall._try_declare_c_lib_func / HandlesExprBuiltin._try_declare_c_lib_func
- HandlesAssign 模块级全局赋值处的函数声明
- HandlesImports.__before_init__ 声明(原查 NewFuncName 却建 MangledName)
- HandlesFunctions._EmitFunctionLlvm(补登记 module.globals 已有声明,
使既有的签名修复路径生效,而不是裸建撞名)
行为等价性:上述各点原先"撞名"时必然抛 DuplicatedNameError(即必失败),
收口后要么复用同一符号、要么 fail-fast 报出两侧签名/冲突类型,无静默降级。
This commit is contained in:
1 parent
8c831a38d3
commit
f4c8c48748
6 files changed
+68
-29
No files matched your search
@@ -2578,7 +2578,10 @@ class ImportHandle(BaseHandle):
|
||||
if StructType is not None:
|
||||
StructPtrType = ir.PointerType(StructType)
|
||||
NewFuncType = ir.FunctionType(ir.VoidType(), [StructPtrType])
|
||||
NewFunc = ir.Function(Gen.module, NewFuncType, name=MangledName)
|
||||
# 走唯一幂等入口:查的是 NewFuncName 而建的是 MangledName,二者不同名
|
||||
# ⇒ 此处若裸建,MangledName 已被 stub / 调用点占住时必抛
|
||||
# llvmlite DuplicatedNameError。
|
||||
NewFunc = Gen._CreateOrReuseFuncDecl(MangledName, NewFuncType)
|
||||
Gen.functions[NewFuncName] = NewFunc
|
||||
bitfields = Gen.class_member_bitfields.get(ClassName, {})
|
||||
if any(v > 0 for v in bitfields.values()):
|
||||
@@ -3406,14 +3409,22 @@ class ImportHandle(BaseHandle):
|
||||
existing_func = Gen.functions[func_name]
|
||||
existing_ftype = getattr(existing_func, 'ftype', None) or existing_func.type.pointee
|
||||
if str(existing_ftype) != str(func_type):
|
||||
# 类型不一致:清理 module.globals + module.scope._useset 后重建,避免 DuplicatedNameError
|
||||
old_name = existing_func.name
|
||||
if old_name in Gen.module.globals:
|
||||
del Gen.module.globals[old_name]
|
||||
# 类型不一致:清理 module.globals + module.scope._useset 后重建,
|
||||
# 避免 DuplicatedNameError。必须同时清 existing_func.name(真名)
|
||||
# 与 func_name(字典键):别名场景下两者不同(如
|
||||
# Gen.functions['ExprGenAttr.find_global_in_module'] 指向名为
|
||||
# 'dddc595175f00c66.ExprGenAttr.find_global_in_module' 的对象),
|
||||
# 只删真名会留下字典键仍占住 module.scope(llvmlite 按名字去重)
|
||||
# → 重建仍抛 DuplicatedNameError(报文只有名字,不含冲突双方)。
|
||||
module_scope = getattr(Gen.module, 'scope', None)
|
||||
if getattr(module_scope, '_useset', None):
|
||||
module_scope._useset.discard(old_name)
|
||||
func = ir.Function(Gen.module, func_type, name=func_name)
|
||||
_useset = getattr(module_scope, '_useset', None)
|
||||
for _stale_name in {existing_func.name, func_name}:
|
||||
_stale = Gen.module.globals.get(_stale_name)
|
||||
if isinstance(_stale, ir.Function):
|
||||
del Gen.module.globals[_stale_name]
|
||||
if _useset is not None:
|
||||
_useset.discard(_stale_name)
|
||||
func = Gen._CreateOrReuseFuncDecl(func_name, func_type)
|
||||
Gen.functions[func_name] = func
|
||||
if '.' in func_name:
|
||||
short_name = func_name.split('.', 1)[1]
|
||||
|
||||
Reference in new issue
Block a user