fix(gen): CDefine 常量(含 mod.N 属性形态)拓宽方向单独判定——负值 sext、非负 zext,修 zlib 窗口尺寸被 sext 成负数与 Z_DEFAULT_COMPRESSION->255
This commit is contained in:
1 parent
22475e0fda
commit
b859f8a136
1 file changed
+25
-4
@@ -135,6 +135,15 @@ novirtual class ExprGenOps(ExprGenBase.ExprGenBase):
|
||||
if narrow_val is None or narrow_val.Ty is None: return 0
|
||||
narrow_bits: int = self.get_llvm_type_bits(narrow_val.Ty)
|
||||
if narrow_bits == 1: return 1
|
||||
# 编译期 CDefine 常量(裸名 `N` 或模块属性 `mod.N`)单独判定,必须**早于**下方「i8 默认 zext」:
|
||||
# · 负值 → sext(有符号语义,如 `define Z_DEFAULT_COMPRESSION = (-1)` 必须变 i32 -1,而非 255);
|
||||
# · 非负 → zext(无符号位模式,如 `define WINDOW_SIZE = (1 << 15)` 必须变 32768,而非 -32768)。
|
||||
# 否则这两类常量拓宽时必有一类被弄错(i8 位型走「默认 zext」;i16 位型若判不出无符号则走 sext)。
|
||||
if narrow_node is not None:
|
||||
cd_v_zw: int64 = self._cdefine_int_of(narrow_node)
|
||||
if self.Gen.TypeGenCDef.is_cdefine_found() != 0:
|
||||
if cd_v_zw < 0: return 0
|
||||
return 1
|
||||
if narrow_bits == 8:
|
||||
# i8 defaults to unsigned-byte handling (systems convention), but an explicitly signed source annotation
|
||||
# must sext to preserve sign: `int32(v)` with v: int8 = -50 must stay -50, not become 206.
|
||||
@@ -154,16 +163,28 @@ novirtual class ExprGenOps(ExprGenBase.ExprGenBase):
|
||||
# 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_int_of - 取节点引用的 CDefine 常量值。支持两种引用形态:
|
||||
# · 裸名 `N`
|
||||
# · 模块属性 `mod.N`(跨模块经 .vpi 注册;常量名就是 at.attr)
|
||||
# 未命中时 `Gen.TypeGenCDef.is_cdefine_found()` 为 0 —— 本函数每次都刷新该标志(空名也走一次 lookup)。
|
||||
def _cdefine_int_of(self, node: ast.AST*) -> int64:
|
||||
"""CDefine integer value referenced by node (bare name or `mod.N`); check is_cdefine_found()."""
|
||||
nm_cd: str = ""
|
||||
if node is not None:
|
||||
if node.kind() == ast.ASTKind.Name:
|
||||
n_cd: ast.Name* = ast.Name*(node)
|
||||
if n_cd.id is not None: nm_cd = n_cd.id
|
||||
elif node.kind() == ast.ASTKind.Attribute:
|
||||
a_cd: ast.Attribute* = ast.Attribute*(node)
|
||||
if a_cd.attr is not None: nm_cd = a_cd.attr
|
||||
return self.Gen.TypeGenCDef.lookup_cdefine_constant(nm_cd)
|
||||
# _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)
|
||||
v_cd: int64 = self._cdefine_int_of(node)
|
||||
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)
|
||||
|
||||
Reference in new issue
Block a user