diff --git a/lib/core/Handles/HandlesAssign.py b/lib/core/Handles/HandlesAssign.py index 357f7c2..6e7c6b5 100644 --- a/lib/core/Handles/HandlesAssign.py +++ b/lib/core/Handles/HandlesAssign.py @@ -594,8 +594,9 @@ class AssignHandle(BaseHandle): llvm_param_types.append(lp) func_type: ir.FunctionType = ir.FunctionType(ret_type, llvm_param_types) MangledName: str = Gen._mangle_func_name(FuncName) - func_decl: ir.Function = ir.Function(Gen.module, func_type, name=MangledName) - Gen.functions[MangledName] = func_decl + # 走唯一幂等入口(module.globals 已有同名声明复用 / + # 类型冲突 fail-fast),避免裸建抛 DuplicatedNameError。 + func_decl: ir.Function = Gen._CreateOrReuseFuncDecl(MangledName, func_type) Gen.functions[FuncName] = func_decl if not MultiRetTypes and FuncName: func: ir.Function | None = Gen.functions.get(FuncName) diff --git a/lib/core/Handles/HandlesExprBuiltin.py b/lib/core/Handles/HandlesExprBuiltin.py index 5825804..0615343 100644 --- a/lib/core/Handles/HandlesExprBuiltin.py +++ b/lib/core/Handles/HandlesExprBuiltin.py @@ -576,9 +576,9 @@ class ExprBuiltinHandle(BaseHandle): param_types: list[ir.Type] ret_type, param_types = self._C_LIB_FUNCS[func_name]() func_type: ir.FunctionType = ir.FunctionType(ret_type, param_types) - func: ir.Function = ir.Function(Gen.module, func_type, name=func_name) - Gen.functions[func_name] = func - return func + # C 库声明名固定(malloc/strlen/...),同一模块内多次调用必须复用同一符号: + # 裸建会在第二次抛 llvmlite DuplicatedNameError。 + return Gen._CreateOrReuseFuncDecl(func_name, func_type) def _FailFastLenUnsupported(self, arg_node: ast.AST, Gen: LlvmGeneratorMixin, val: ir.Value | None, reason: str) -> None: diff --git a/lib/core/Handles/HandlesExprCall.py b/lib/core/Handles/HandlesExprCall.py index 6026f47..052c010 100644 --- a/lib/core/Handles/HandlesExprCall.py +++ b/lib/core/Handles/HandlesExprCall.py @@ -1220,8 +1220,9 @@ class ExprCallHandle(BaseHandle): if ClassName in Gen.structs and not is_static: llvm_param_types.insert(0, ir.PointerType(Gen.structs[ClassName])) func_type = ir.FunctionType(ret_type, llvm_param_types) - func = ir.Function(Gen.module, func_type, name=MangledName) - Gen.functions[MangledName] = func + # 走唯一幂等入口:module.globals 已有同名函数(stub / 调用点先建) + # 时复用,避免 llvmlite DuplicatedNameError;类型不同则 fail-fast。 + func = Gen._CreateOrReuseFuncDecl(MangledName, func_type) # 方法实际定义类(多继承 this 调整用) method_anc_st: str | None = None # 若 MangledName 只有 stub 声明(无函数体),也走 MRO 回退找定义类方法 @@ -3910,8 +3911,10 @@ class ExprCallHandle(BaseHandle): # 避免 llvmlite DuplicatedNameError(如 gen.__init__ / ImportsHandle.HandleImport) func = Gen._find_function(FullMethodName) if func is None: - func = ir.Function(Gen.module, func_type, name=FullMethodName) - Gen.functions[FullMethodName] = func + # 走唯一幂等入口(module.globals 同名函数复用 / 类型冲突 fail-fast), + # 不再裸建 ir.Function —— Guard 只看 Gen.functions 时漏掉 + # module.globals 已有声明会抛 llvmlite DuplicatedNameError。 + func = Gen._CreateOrReuseFuncDecl(FullMethodName, func_type) if isinstance(ObjVal.type, ir.PointerType) and ObjVal.type.pointee == struct_type: call_self = ObjVal else: @@ -4010,9 +4013,9 @@ class ExprCallHandle(BaseHandle): return None ret_type, param_types = self._C_LIB_FUNCS[func_name]() func_type = ir.FunctionType(ret_type, param_types) - func = ir.Function(Gen.module, func_type, name=func_name) - Gen.functions[func_name] = func - return func + # C 库声明名固定(malloc/strlen/...),同一模块内多次调用必须复用同一符号: + # 裸建会在第二次抛 llvmlite DuplicatedNameError。 + return Gen._CreateOrReuseFuncDecl(func_name, func_type) def _FailFastLenUnsupported(self, arg_node: ast.AST, Gen: LlvmGeneratorMixin, val: ir.Value | None, reason: str) -> None: diff --git a/lib/core/Handles/HandlesFunctions.py b/lib/core/Handles/HandlesFunctions.py index 5ecaab7..fee0b04 100644 --- a/lib/core/Handles/HandlesFunctions.py +++ b/lib/core/Handles/HandlesFunctions.py @@ -1309,19 +1309,29 @@ class FunctionHandle(BaseHandle): return old_func try: old_name: str = old_func.name - if old_name in getattr(Gen.module, 'globals', {}): - del Gen.module.globals[old_name] + # 必须同时清 old_name(对象真名)与 MangledName(字典键 / 目标名): + # 别名场景下二者不同,只清真名会让 MangledName 仍占住 module.scope + # (llvmlite 按名字去重)→ 重建抛 DuplicatedNameError。 module_scope: Any = getattr(Gen.module, 'scope', None) - if getattr(module_scope, '_useset', None): - module_scope._useset.discard(old_name) + for _stale_name in {old_name, MangledName}: + _stale: Any = Gen.module.globals.get(_stale_name) + if isinstance(_stale, ir.Function): + del Gen.module.globals[_stale_name] + if getattr(module_scope, '_useset', None): + module_scope._useset.discard(_stale_name) if getattr(Gen.module, '_guessed_names', None): Gen.module._guessed_names.discard(FuncName) - new_func: ir.Function = ir.Function(Gen.module, NewFuncType, name=MangledName) + new_func: ir.Function = Gen._CreateOrReuseFuncDecl(MangledName, NewFuncType) Gen.functions[MangledName] = new_func if MangledName == FuncName or FuncName not in Gen._export_extern_funcs: Gen.functions[FuncName] = new_func return new_func except Exception as ex: + from lib.core.LLVMCG.FuncGen import FailFastError + if isinstance(ex, FailFastError): + # 同名符号冲突(函数签名分裂 / 名字被非函数 global 占住):必须终止, + # 不能回退成"复用旧声明"——那正是 declare/define 分裂的现场。 + raise traceback.print_exc() Gen.functions[MangledName] = old_func if MangledName == FuncName or FuncName not in Gen._export_extern_funcs: @@ -1737,18 +1747,22 @@ class FunctionHandle(BaseHandle): if not IsUserMarkedExport and FuncName in Gen._export_funcs: Gen._export_funcs.discard(FuncName) MangledName = Gen._mangle_func_name(FuncName) + # 补登记:module.globals 已有同名函数(stub 声明 / 调用点先建)但未登记到 + # Gen.functions 时,先登记再走下方判定 —— 否则 1750 分支裸建 ir.Function + # 会抛 llvmlite DuplicatedNameError(报文只有名字,不含冲突双方)。 + _g_existing_fn: Any = Gen.module.globals.get(MangledName) + if MangledName not in Gen.functions and isinstance(_g_existing_fn, ir.Function): + Gen.functions[MangledName] = _g_existing_fn if MangledName in Gen.functions: func = Gen.functions[MangledName] if getattr(func, 'name', MangledName) != MangledName: - func = ir.Function(Gen.module, FuncType, name=MangledName) - Gen.functions[MangledName] = func + func = Gen._CreateOrReuseFuncDecl(MangledName, FuncType) else: existing_type = getattr(func, 'ftype', None) if existing_type and existing_type != FuncType: func = self._replace_function_decl(Gen, FuncName, FuncType) else: - func = ir.Function(Gen.module, FuncType, name=MangledName) - Gen.functions[MangledName] = func + func = Gen._CreateOrReuseFuncDecl(MangledName, FuncType) if MangledName == FuncName or FuncName not in Gen._export_extern_funcs: Gen.functions[FuncName] = func func.attributes.add('noredzone') diff --git a/lib/core/Handles/HandlesImports.py b/lib/core/Handles/HandlesImports.py index 6620688..35dd0ac 100644 --- a/lib/core/Handles/HandlesImports.py +++ b/lib/core/Handles/HandlesImports.py @@ -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] diff --git a/lib/core/LLVMCG/BaseGen.py b/lib/core/LLVMCG/BaseGen.py index 8e5496d..2884e2c 100644 --- a/lib/core/LLVMCG/BaseGen.py +++ b/lib/core/LLVMCG/BaseGen.py @@ -892,6 +892,16 @@ class BaseGenMixin: 真因,绝不静默复用错签名(会让调用点按错签名传参)。 """ existing: Any = self.module.globals.get(name) + if existing is not None and not isinstance(existing, ir.Function): + # 名字被非函数 global 占住(全局变量 / vtable / 字符串常量…):llvmlite 的 + # NameScope 按名字去重,再建同名 ir.Function 必抛 DuplicatedNameError + # (报文只有名字,不含冲突类型)⇒ 在此把冲突双方摊开,避免裸抛。 + from lib.core.LLVMCG.FuncGen import FailFastError + raise FailFastError( + f"同名全局符号冲突:'{name}' 已在 module.globals 中登记,但不是函数" + f"({type(existing).__name__}):{existing!r}" + f"\n 函数声明无法复用该符号(llvmlite NameScope 按名字去重);" + f"请核对该名字是否同时被用作全局变量 / vtable / 字符串常量。") if isinstance(existing, ir.Function): _old_type: Any = getattr(existing, 'ftype', None) if _old_type is None or str(_old_type) == str(func_type):