fix(gen): 非负 define 常量按最小位宽的无符号位模式参与宽化/比较(修 range(50000) 迭代 0 次)

This commit is contained in:
TermiNexus committed 2026-10-12 20:52:52 +08:00
1 parent e3743b185f
commit 00bf7ebf38
1 file changed
+27 -8
+27 -8
View File
@@ -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)