diff --git a/App/lib/core/Gen/AssignGenMixin.vp b/App/lib/core/Gen/AssignGenMixin.vp index 8b88f77..e5af5ae 100644 --- a/App/lib/core/Gen/AssignGenMixin.vp +++ b/App/lib/core/Gen/AssignGenMixin.vp @@ -884,6 +884,19 @@ novirtual class AssignGenMixin: if rk != 0: return rk return -1 + # _is_module_scope_var - 该名字是否定义在**模块根 scope**(= LLVM 全局存储,静态生命期)。 + # 逃逸检查据此把模块级变量(含其数组名退让)判为 LIFE_STATIC,而不是「本帧局部」。 + # 注意与 is_global_name 区分:后者只认**函数内** `global X` 声明,认不出模块级定义。 + def _is_module_scope_var(self, trans: HT.Translator*, name: str) -> int: + """1 = name is defined in the module root scope (static storage); else 0.""" + if trans is None or name is None or trans.SymTab is None: return 0 + sc_m: GenTypes.Scope* = trans.SymTab.Current + while sc_m is not None: + if self.Gen.VarGen.find_var(sc_m.Vars, sc_m.VarCount, name) is not None: + if sc_m.Parent is None: return 1 + return 0 + sc_m = sc_m.Parent + return 0 # life_of_expr - 求表达式当前值的生命期标签。 # target_ty 参与判定:裸本帧数组名在**指针**目标位置 = 数组退让(交出本帧栈地址), # 在同型聚合目标位置 = 按值拷贝(LIFE_VALUE)。 @@ -901,6 +914,10 @@ novirtual class AssignGenMixin: nm: ast.Name* = ast.Name*(node) if nm.id is None: return GenTypes.LIFE_UNKNOWN if GenApi.is_global_name(trans, nm.id) != 0: return GenTypes.LIFE_STATIC + # 模块级(根 scope)变量 = LLVM 全局存储(静态生命期):裸数组名的「退让」拿到的正是 + # 静态地址,返回/交出它都不会悬垂。此前只认函数内 `global X` 声明,于是模块级数组 + # (如 pyzlib_error_msg)被当成「本帧局部数组」误判成 LIFE_FRAME。 + if self._is_module_scope_var(trans, nm.id) != 0: return GenTypes.LIFE_STATIC if GenApi.is_nonlocal_name(trans, nm.id) != 0: return GenTypes.LIFE_UNKNOWN v: mlirlite.Value* = self.Gen.VarGen.lookup_var(trans.SymTab, nm.id) if v is None: return GenTypes.LIFE_STATIC @@ -918,6 +935,8 @@ novirtual class AssignGenMixin: onm: ast.Name* = ast.Name*(uo.operand) if onm.id is not None: if GenApi.is_global_name(trans, onm.id) != 0: return GenTypes.LIFE_STATIC + # 模块级(根 scope)变量:静态存储,同 Name 分支判据(`&<模块级数组>` 不悬垂) + if self._is_module_scope_var(trans, onm.id) != 0: return GenTypes.LIFE_STATIC if GenApi.is_nonlocal_name(trans, onm.id) != 0: return GenTypes.LIFE_UNKNOWN if self.Gen.VarGen.lookup_var(trans.SymTab, onm.id) is not None: return GenTypes.LIFE_FRAME return GenTypes.LIFE_STATIC