diff --git a/lib/core/Handles/HandlesBase.py b/lib/core/Handles/HandlesBase.py index 191a46c..503d675 100644 --- a/lib/core/Handles/HandlesBase.py +++ b/lib/core/Handles/HandlesBase.py @@ -1144,6 +1144,14 @@ class BaseHandle: replace_name 传递给 _replace_function_decl(通常为未 mangle 的 func_name)。 """ if name not in Gen.functions: + # Gen.functions 未登记、但 module.globals 已有同名函数(本模块其它调用点 + # 或依赖 stub 先建过声明)→ 复用并登记,绝不重建:llvmlite 的 NameScope + # 按名字去重(GlobalValue.deduplicate_name=False),重复 ir.Function 必抛 + # DuplicatedNameError。 + g_existing: Any = Gen.module.globals.get(name) + if g_existing is not None: + Gen.functions[name] = g_existing + return g_existing func_type = _ir.FunctionType(ret_type, param_types, var_arg=is_variadic) func_decl = _ir.Function(Gen.module, func_type, name=name) Gen.functions[name] = func_decl @@ -1168,12 +1176,21 @@ class BaseHandle: ) -> Any: """创建 stub 函数声明,可选注册别名。 - check_existing=False 时跳过存在性检查(用于确定不存在的场景)。 + check_existing=False 时跳过 Gen.functions 存在性检查(用于确定不存在的场景), + 但**仍复用 module.globals 里的同名声明**——llvmlite 的 NameScope 按名字去重 + (GlobalValue.deduplicate_name=False),"强制新建同名 global"在 llvmlite 下 + 不成立、必抛 DuplicatedNameError,故此路必须幂等。 + 真实事故:同一模块两处 `self.Gen.ExprGen.translate_value(...)`(VarGenMixin.vp) + 都走 check_existing=False,第一处建声明成功、第二处抛 DuplicatedNameError。 """ if check_existing and decl_name in Gen.functions: func_decl = Gen.functions[decl_name] else: - func_decl = _ir.Function(Gen.module, stub_func_type, name=decl_name) + g_ex_decl: Any = Gen.module.globals.get(decl_name) + if g_ex_decl is not None: + func_decl = g_ex_decl + else: + func_decl = _ir.Function(Gen.module, stub_func_type, name=decl_name) Gen.functions[decl_name] = func_decl if alias and alias != decl_name: if not check_existing or alias not in Gen.functions: diff --git a/lib/core/Handles/HandlesExprCall.py b/lib/core/Handles/HandlesExprCall.py index 2eabcfe..9477d24 100644 --- a/lib/core/Handles/HandlesExprCall.py +++ b/lib/core/Handles/HandlesExprCall.py @@ -1936,10 +1936,16 @@ class ExprCallHandle(BaseHandle): if ModulePath and 'win32console' in ModulePath and func_name in win32_apis: ret_type, param_types = win32_apis[func_name] if func_name not in Gen.functions: - func_type = ir.FunctionType(ret_type, param_types) - func_decl = ir.Function(Gen.module, func_type, name=func_name) - func_decl.linkage = 'external' - Gen.functions[func_name] = func_decl + # module.globals 已有同名声明(其它路径/依赖 stub 先建)→ 直接登记复用, + # 不重建(llvmlite NameScope 按名字去重,重建必抛 DuplicatedNameError) + g_ex_w32: Any = Gen.module.globals.get(func_name) + if g_ex_w32 is not None: + Gen.functions[func_name] = g_ex_w32 + else: + func_type = ir.FunctionType(ret_type, param_types) + func_decl = ir.Function(Gen.module, func_type, name=func_name) + func_decl.linkage = 'external' + Gen.functions[func_name] = func_decl call_args = [] if Node.args: arg_val = self.HandleExprLlvm(Node.args[0]) diff --git a/lib/core/Handles/HandlesImports.py b/lib/core/Handles/HandlesImports.py index bb83498..c728fb4 100644 --- a/lib/core/Handles/HandlesImports.py +++ b/lib/core/Handles/HandlesImports.py @@ -3398,7 +3398,15 @@ class ImportHandle(BaseHandle): at_pos: int = stripped.rindex('@', 0, paren_pos) func_name: str = stripped[at_pos + 1:paren_pos].strip().strip('"') if func_name not in Gen.functions: - func = ir.Function(Gen.module, func_type, name=func_name) + # module.globals 已有同名声明 → 复用(llvmlite NameScope + # 按名字去重,重复 ir.Function 必抛 DuplicatedNameError; + # 此前该异常被下方 except 静默吞掉 → 声明未登记 → 后续 + # 调用点找不到签名) + g_ex_stub = Gen.module.globals.get(func_name) + if g_ex_stub is not None: + func = g_ex_stub + else: + func = ir.Function(Gen.module, func_type, name=func_name) Gen.functions[func_name] = func if '.' in func_name: short_fn = func_name.split('.', 1)[1]