fix(codegen): widen from the value expression, not the enclosing statement
should_zext_widen decides the widening direction from the narrow side's AST node, but the return and assignment coercions passed the statement node. A statement has no type of its own, so the literal rule and the annotated variable rule were skipped and the value fell through to sext: `def f() -> uint64: return 0xDEADBEEF` produced 0xFFFFFFFFDEADBEEF and the caller compared against 0xDEADBEEF and failed. Unwrap Return/Assign/AnnAssign/AugAssign/Expr to their value expression before the direction rules run, so a non-negative literal wider than INT32_MAX zero-extends (0xDEADBEEF -> 0xDEADBEEF) and a negative one keeps its sign (-1 -> 0xFFFFFFFFFFFFFFFF).
This commit is contained in:
1 parent
19f9c53a5f
commit
d5d05ec11e
1 file changed
+17
@@ -144,6 +144,11 @@ novirtual class ExprGenOps(ExprGenBase.ExprGenBase):
|
||||
6. 其余 → sext。
|
||||
"""
|
||||
if narrow_val is None or narrow_val.Ty is None: return 0
|
||||
# Some call sites hand over the enclosing statement (return / assignment) instead of the
|
||||
# value expression. The statement carries no type of its own, so rules 2/3/5 would miss a
|
||||
# literal or an annotated variable and fall through to sext (`return 0xDEADBEEF` from a
|
||||
# uint64 function became 0xFFFFFFFFDEADBEEF). Unwrap to the value expression first.
|
||||
narrow_node = self._widen_value_node(narrow_node)
|
||||
narrow_bits: int = self.get_llvm_type_bits(narrow_val.Ty)
|
||||
if narrow_bits == 1: return 1
|
||||
# 2. 整数字面量:以字面量数值为准(`0xFFFFFFFF` 是 4294967295 > INT32_MAX,必须 zext)
|
||||
@@ -170,6 +175,18 @@ novirtual class ExprGenOps(ExprGenBase.ExprGenBase):
|
||||
if narrow_node is not None:
|
||||
if self._node_type_unsigned(pool, narrow_node, trans) != 0: return 1
|
||||
return 0
|
||||
# _widen_value_node - 取语句节点的值表达式(Return/Assign/AnnAssign/AugAssign/Expr),
|
||||
# 其他节点原样返回。加宽方向的判定必须落在**有类型的值节点**上。
|
||||
def _widen_value_node(self, node: ast.AST*) -> ast.AST*:
|
||||
"""Value expression of a statement node (Return/Assign/AnnAssign/AugAssign/Expr)."""
|
||||
if node is None: return node
|
||||
nk_wv: int = node.kind()
|
||||
if nk_wv == ast.ASTKind.Return: return (ast.Return*(node)).value
|
||||
if nk_wv == ast.ASTKind.Assign: return (ast.Assign*(node)).value
|
||||
if nk_wv == ast.ASTKind.AnnAssign: return (ast.AnnAssign*(node)).value
|
||||
if nk_wv == ast.ASTKind.AugAssign: return (ast.AugAssign*(node)).value
|
||||
if nk_wv == ast.ASTKind.Expr: return (ast.Expr*(node)).value
|
||||
return node
|
||||
# _cdefine_int_of - 取节点引用的 DefineT 常量值。支持两种引用形态:
|
||||
# · 裸名 `N`
|
||||
# · 模块属性 `mod.N`(跨模块经 .vpi 注册;常量名就是 at.attr)
|
||||
|
||||
Reference in new issue
Block a user