From 00bf7ebf38aa171c0dd09f321863511d1b3d19c8 Mon Sep 17 00:00:00 2001 From: TermiNexus Date: Mon, 12 Oct 2026 20:52:52 +0800 Subject: [PATCH] =?UTF-8?q?fix(gen):=20=E9=9D=9E=E8=B4=9F=20define=20?= =?UTF-8?q?=E5=B8=B8=E9=87=8F=E6=8C=89=E6=9C=80=E5=B0=8F=E4=BD=8D=E5=AE=BD?= =?UTF-8?q?=E7=9A=84=E6=97=A0=E7=AC=A6=E5=8F=B7=E4=BD=8D=E6=A8=A1=E5=BC=8F?= =?UTF-8?q?=E5=8F=82=E4=B8=8E=E5=AE=BD=E5=8C=96/=E6=AF=94=E8=BE=83?= =?UTF-8?q?=EF=BC=88=E4=BF=AE=20range(50000)=20=E8=BF=AD=E4=BB=A3=200=20?= =?UTF-8?q?=E6=AC=A1=EF=BC=89?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- App/lib/core/Gen/Expr/ExprGenOps.vp | 35 ++++++++++++++++++++++------- 1 file changed, 27 insertions(+), 8 deletions(-) diff --git a/App/lib/core/Gen/Expr/ExprGenOps.vp b/App/lib/core/Gen/Expr/ExprGenOps.vp index 4f315db..8df6d97 100644 --- a/App/lib/core/Gen/Expr/ExprGenOps.vp +++ b/App/lib/core/Gen/Expr/ExprGenOps.vp @@ -150,14 +150,30 @@ novirtual class ExprGenOps(ExprGenBase.ExprGenBase): # Name/Subscript, unsignedness comes from trans.SymTab; without trans it returns 0 and sext is wrongly used. if narrow_node is not None: if self._node_type_unsigned(pool, narrow_node, trans) != 0: return 1 - # A CDefine constant with the high bit set (0x80000000..0xFFFFFFFF) -> zext. CDefine is a compile-time value, - # so _node_type_unsigned finds no annotation; the negative-signed range means an unsigned sentinel (e.g. 0xFFFFFFFF). - if narrow_node is not None and narrow_node.kind() == ast.ASTKind.Name: - cdef_nm_zw: ast.Name* = ast.Name*(narrow_node) - if cdef_nm_zw.id is not None: - cdv_zw: int64 = self.Gen.TypeGenCDef.lookup_cdefine_constant(cdef_nm_zw.id) - if self.Gen.TypeGenCDef.is_cdefine_found() != 0: - if cdv_zw > 0x7FFFFFFF: return 1 + # A non-negative CDefine whose minimal width's high bit is set (0x80000000 in 32 bits, or + # 50000 in 16 bits) is materialized as an unsigned bit pattern -> zext. Covered by + # _node_type_unsigned below (which delegates to _cdefine_unsigned_bitpattern); keep return 0. + return 0 + # _cdefine_unsigned_bitpattern - 1 if node 是**非负 CDefine 常量**,且按它的最小可容纳位宽 W_min + # 取无符号位模式时 high bit 已置位(如 50000 → W_min=16 → 0xC350)。规范:非负数按无符号位模式 + # 物化、负值按有符号解释(Debugger/define-constants.md §7.2)。这类常量在**宽化**与**比较** + # (for-range 边界)时必须按无符号处理,否则 32768..65535 的常量会被读成负数(range 变 0 次)。 + def _cdefine_unsigned_bitpattern(self, node: ast.AST*) -> int: + """1 = node is a non-negative CDefine whose minimal width's high bit is set; else 0.""" + if node is None or node.kind() != ast.ASTKind.Name: return 0 + nm_cd: ast.Name* = ast.Name*(node) + if nm_cd.id is None: return 0 + v_cd: int64 = self.Gen.TypeGenCDef.lookup_cdefine_constant(nm_cd.id) + if self.Gen.TypeGenCDef.is_cdefine_found() == 0: return 0 + if v_cd < 0: return 0 + w_cd: int = self.Gen.AssignGen.define_min_width(v_cd) + # 该位宽的有符号上限 2^(w-1)-1;超过即 high bit 置位(只写安全字面量,避免 1<<63 / 4294967295 之类) + if w_cd == 8: + if v_cd > 127: return 1 + elif w_cd == 16: + if v_cd > 32767: return 1 + elif w_cd == 32: + if v_cd > 2147483647: return 1 return 0 def _node_type_unsigned(self, pool: memhub.MemBuddy*, node: ast.AST*, trans: HT.Translator* = None) -> int: """Return 1 if the AST node resolves to an unsigned integer type, else 0.""" @@ -186,6 +202,9 @@ novirtual class ExprGenOps(ExprGenBase.ExprGenBase): vcn_u: str = self.Gen.VarGen.var_annot_class_name(ve) if vcn_u is not None: if self._type_name_unsigned(vcn_u) != 0: return 1 + # 3) 非负 CDefine 常量:按最小可容纳位宽取无符号位模式(Debugger/define-constants.md §7.2)。 + # 例:define N = 50000 → W_min=16、值在 32768..65535 ⇒ 宽化/比较必须按无符号。 + if self._cdefine_unsigned_bitpattern(node) != 0: return 1 return 0 if k == ast.ASTKind.BinOp: bop: ast.BinOp* = ast.BinOp*(node)