diff --git a/App/lib/core/Gen/TranslatorGenMixin.vp b/App/lib/core/Gen/TranslatorGenMixin.vp index 5c9c87d..83c341a 100644 --- a/App/lib/core/Gen/TranslatorGenMixin.vp +++ b/App/lib/core/Gen/TranslatorGenMixin.vp @@ -896,6 +896,16 @@ novirtual class TranslatorGenMixin: is_global_cexport: int = 0 if annot_node is not None: is_global_cexport = self.Gen.TypeGenErr.has_decorator_marker(annot_node, "CExport", 0) + # extern 全局(`extern NAME: T` → 注解含 t.State / t.CExtern):符号定义在 + # 外部(C 库 / 汇编 / 其它翻译单元),本模块只生成外部声明 + # `@裸名 = external global T`——external linkage、无初始值、无 storage。 + # 与 export 的差别:export 是**本模块定义**(裸名导出);extern 是**仅声明**。 + # `t.State` = t.CExtern | t.CExport(parser 的 `extern NAME: T` 展开产物)。 + is_global_extern: int = 0 + if annot_node is not None: + is_global_extern = self.Gen.TypeGenErr.has_decorator_marker(annot_node, "CExtern", 0) + if is_global_extern == 0: + is_global_extern = self.Gen.TypeGenErr.has_decorator_marker(annot_node, "State", 0) # 全局变量侧 t.attr.* 属性(`T | t.attr.xxx` 注解联合形态): # section→gv.Section、aligned→gv.Align、weak→gv.Linkage(见下方应用点)。 # 仅在 AnnAssign(annot_node 非 None)时存在,与 t.CExport 同一条路。 @@ -907,7 +917,7 @@ novirtual class TranslatorGenMixin: gv_attr_align = self._extract_global_attr_aligned(annot_node, var_name) gv_attr_weak = self._extract_global_attr_weak(annot_node) mangled_name: str = var_name - if is_global_cexport == 0: + if is_global_cexport == 0 and is_global_extern == 0: mangled_name = self.Gen.FuncGenBase._mangle_name(trans, var_name) gv: llvmlite.GlobalVariable* = llvmlite.new_global_variable(pool, mangled_name, var_ty) if gv is None: @@ -937,10 +947,14 @@ novirtual class TranslatorGenMixin: gv.Align = al_entry.Align # 设置初始值(有初始值时清除 external linkage,因为 LLVM 22+ 不允许 external global 带初始值) - gv.Linkage = None - # t.attr.weak → weak linkage(须在 Linkage 清空之后设置)。 - if gv_attr_weak != 0: - llvmlite.global_set_linkage(gv, "weak") + # extern 全局例外:保持 external(仅外部声明,绝不写初始值 / storage)。 + if is_global_extern != 0: + gv.Linkage = "external" + else: + gv.Linkage = None + # t.attr.weak → weak linkage(须在 Linkage 清空之后设置)。 + if gv_attr_weak != 0: + llvmlite.global_set_linkage(gv, "weak") if init_kind == 1: # 整数初始值 init_buf: str = pool.alloc(48) @@ -995,7 +1009,7 @@ novirtual class TranslatorGenMixin: # 此处不覆盖;但 = None 懒初始化全局(is_none_init)既无 storage 也无其他 # Initializer → 必须显式 zeroinitializer(LLVM 对指针类型输出为 null), # 否则 gv 无初始化器 → 全局声明残缺。 - if resolved_stg_ty is None or is_none_init != 0: + if (resolved_stg_ty is None or is_none_init != 0) and is_global_extern == 0: gv.Initializer = "zeroinitializer" # 对象类全局:创建静态 storage 全局(BSS)承载对象实例,@g 编译期引用它。 @@ -1003,7 +1017,8 @@ novirtual class TranslatorGenMixin: # 不再依赖栈 alloca(悬垂);c.Addr(g) load @g 得到 &storage,均非 NULL。 # 豁免:显式 `= None` 初始化(is_none_init)的懒初始化指针全局 # (如 _kw_head/_op_head)不建 storage,保持 NULL 语义。 - if resolved_stg_ty is not None and is_none_init == 0: + # extern 全局(is_global_extern)同样不建 storage:外部声明无本模块实例。 + if resolved_stg_ty is not None and is_none_init == 0 and is_global_extern == 0: # 值类型 storage 需要完整 struct 定义(跨模块类默认 opaque → # @g.stg = global %T zeroinitializer 报 "use of undefined type") self.Gen.StructGen.ensure_struct_def_in_module(pool, mod, resolved_stg_ty)