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)