diff --git a/llvmlite/__module.vp b/llvmlite/__module.vp index d0863af..7452f29 100644 --- a/llvmlite/__module.vp +++ b/llvmlite/__module.vp @@ -396,6 +396,11 @@ class LLVMModule: stdio.printf("[IR-DUMP] 链表成环: module globals stub(GlobalCount=%zu,dump 终止)\n", self.GlobalCount) stdlib.exit(1) + # 模块内不变量:同名 external 声明若已被同名定义取代则跳过, + # 避免 stub 输出出现同一符号两行(见 _module_has_initializer_global)。 + if gv.Initializer is None and _module_has_initializer_global(self, gv.Name) != 0: + gv = gv.Next + continue _print_global_stub(buf, size, gv, pool) _append_cstr(buf, size, "\n") gv = gv.Next @@ -409,10 +414,15 @@ class LLVMModule: stdio.printf("[IR-DUMP] 链表成环: module globals(GlobalCount=%zu,dump 终止)\n", self.GlobalCount) stdlib.exit(1) - if mode == OUTPUT_TEXT and gv.Initializer is None: - gv = gv.Next - gv_idx += 1 - continue + # text 模式跳过无初值的全局变量(纯声明); + # full 模式亦跳过"已被同名定义取代"的纯声明(见 + # _module_has_initializer_global)——否则单模块 IR 同名声明+定义 + # 并存,llc 报 "redefinition of global"。 + if gv.Initializer is None: + if mode == OUTPUT_TEXT or _module_has_initializer_global(self, gv.Name) != 0: + gv = gv.Next + gv_idx += 1 + continue _print_global(buf, size, gv, pool) _append_cstr(buf, size, "\n") gv = gv.Next @@ -818,6 +828,35 @@ def LLVMModulePrint(buf: str, size: sizet, # ============================================================ # 全局变量打印 # ============================================================ +# _module_has_initializer_global - 模块内是否存在同名"定义"全局(带初值) +# +# 模块内不变量:同一符号名不得同时出现 external 声明与定义,否则 llc 报 +# "redefinition of global '@.'"。 +# 触发场景:循环 import(如 os/__init__ 同时 import os._win32/os._posix,二者又 +# 导入包 os ⇒ imported_modules 含 "os" 自身)使**本模块自己的 .vpi** 被当作依赖 +# 注入;VpiReader._inject_global_variable_declare 先在本模块加一个同名 external +# 声明全局,随后 handle_module_level_var 再发射同名定义 ⇒ 单模块 IR 同名冲突。 +# 打印端按"同名 + 有初值"判定并跳过纯声明,保证单模块 IR 自足合法(对齐旧编译器 +# TransPyC/Phase2Translator 合并期的 external 去重:同名的 external 声明被定义取代)。 +# 只跳过"无初值且有同名初值定义"的声明;依赖模块的合法 external(本模块无同名 +# 定义)一律保留,不做跨模块去重。 +# ============================================================ +def _module_has_initializer_global(mod: rawptr[LLVMModule], name: str) -> int: + if mod is None or name is None: + return 0 + cur: rawptr[GlobalVariable] = mod.GlobalHead + steps: sizet = 0 + while cur is not None: + steps += 1 + if steps > IR_DUMP_CHAIN_LIMIT: + break + if cur.Name is not None and cur.Initializer is not None: + if string.strcmp(cur.Name, name) == 0: + return 1 + cur = cur.Next + return 0 + + def _print_global(buf: str, size: sizet, gv: rawptr[GlobalVariable], pool: memhub.MemBuddy*): """打印单个全局变量: @ = [linkage] [unnamed_addr] [constant] """