fix(tpc): >> 符号性只按左操作数判定,去掉“残留变量名”误判(负数右移发成 lshr)
- 现场:`b: int64 = -196608; b >> 1` 发成 lshr ⇒ 负数变大正数;而同样注解的 `c: int64 = 0 - 196608; c >> 1` 却正确 ⇒ 与 RHS/位置相关(IntWidthTest Test 5/6) - 根因:emit_binary_op 在 i32/i64 分支又用 self._last_var_name 重判符号性,而它只是“最近见过的变量名”,可能是上一条表达式残留的别的(无符号)变量 ⇒ 误判无符号 - 改动:① ExprGen.emit_binary_op 删除 i32/i64 的 _last_var_name 分支(符号性只信调用方;i8/i16 仍按宽度定无符号);② HandlesExprOps 的 `>>` 改用 _check_node_unsigned(Node.left),覆盖 Name 之外的形态 - 验收:Test/IntWidthTest(Test 5/6),目标 TPC 侧 9/9 PASS
This commit is contained in:
1 parent
23b47053d9
commit
55a6856c4e
2 files changed
+11
-9
No files matched your search
@@ -140,9 +140,11 @@ class ExprOpsHandle(BaseHandle):
|
||||
RightVal = Gen.builder.zext(RightVal, LeftVal.type, name="zext_deref_right")
|
||||
elif RightVal.type.width > LeftVal.type.width:
|
||||
LeftVal = Gen.builder.zext(LeftVal, RightVal.type, name="zext_left_deref")
|
||||
if Op in ('>>', 'RShift') and isinstance(Node.left, ast.Name):
|
||||
vname: str = Node.left.id
|
||||
if vname in Gen.var_signedness and Gen.var_signedness[vname]:
|
||||
# `>>` 的符号性按**左操作数**判定:Name 之外的形态(字段/下标/表达式)也要覆盖。
|
||||
# 注意不要退回 emit_binary_op 里那个“残留变量名”判据(已移除,见 ExprGen.emit_binary_op):
|
||||
# b: int64 = -196608; b >> 1 曾是误判成 lshr 的现场(IntWidthTest Test 5/6)。
|
||||
if Op in ('>>', 'RShift'):
|
||||
if Gen._check_node_unsigned(Node.left):
|
||||
is_unsigned = True
|
||||
# 双指针算术 fail-fast 已**下沉到单一收敛点** `Gen.emit_binary_op`
|
||||
# (LLVMCG/ExprGen.py):BinOp 与 AugAssign(+=、-=、*= …)都经该函数,
|
||||
|
||||
@@ -179,12 +179,12 @@ class ExprGenMixin:
|
||||
is_unsigned = True
|
||||
elif left.type.width == 16:
|
||||
is_unsigned = True
|
||||
elif left.type.width == 32:
|
||||
if self._last_var_name:
|
||||
is_unsigned = self._is_var_unsigned(self._last_var_name)
|
||||
elif left.type.width == 64:
|
||||
if self._last_var_name:
|
||||
is_unsigned = self._is_var_unsigned(self._last_var_name)
|
||||
# i32/i64 的符号性**只由调用方按左操作数判定**(调用方拿得到 Node.left,
|
||||
# 见 HandlesExprOps / HandlesAugAssign)。此前这里又用 self._last_var_name
|
||||
# 判一次,而它只是“最近见过的变量名”,可能是**上一条表达式残留的别的变量**:
|
||||
# b: int64 = -196608
|
||||
# b >> 1 # 若残留名恰好是某个无符号变量(t.CSizeT 等) ⇒ 误判无符号 ⇒ lshr
|
||||
# 结果:负数右移变大正数(IntWidthTest Test 5/6 的 FAIL 即此)。
|
||||
shift_ops: dict[str, Any] = {
|
||||
'>>': self.builder.lshr if is_unsigned else self.builder.ashr,
|
||||
'RShift': self.builder.lshr if is_unsigned else self.builder.ashr,
|
||||
|
||||
Reference in new issue
Block a user