fix(gen): 非负 define 常量按最小位宽的无符号位模式参与宽化/比较(修 range(50000) 迭代 0 次)
This commit is contained in:
1 parent
e3743b185f
commit
00bf7ebf38
1 file changed
+27
-8
@@ -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)
|
||||
|
||||
Reference in new issue
Block a user