fix(gen): translate_c_deref 支持转换链包裹推断指针目标

对齐 TPC HandlesSpecialCall._infer_deref_target_type 增强:
1. 新增 _IsTypeExpr/_IsCastWrappingDeref 模块级辅助,判定
   c.Deref 是否处于类型转换链包裹(如 (T | t.CPtr)(t.CPtr(c.Deref(p))))
2. translate_c_deref 推断条件从仅直接 RHS 扩展为直接 RHS 或
   转换链包裹 Deref,新增 dref_is_ptr 允许指针目标推断
   (bitcast 后 load 8 字节),修复 llc 并行线程数组 list[Thread]
   之外仍受 i8* 退化的场景(1b5246f 只绕开了一处)
This commit is contained in:
TermiNexus committed 2026-08-19 21:19:38 +08:00
1 parent 1b5246f29f
commit 42aa90c1af
1 file changed
+52 -12
+52 -12
View File
@@ -40,6 +40,38 @@ import lib.core.Gen.CallGenBase as CallGenBase
# ============================================================
# ============================================================
# _IsTypeExpr / _IsCastWrappingDeref - c.Deref 加载宽度推断的转换包裹判定
# (镜像 TPC HandlesSpecialCall:转换链包裹 Deref 时允许从赋值注解推断
# 加载宽度;ifexp/binop 包裹不放行,避免 i8* 错 bitcast 成其他位宽读)
# ============================================================
def _IsTypeExpr(node: ast.AST | t.CPtr) -> int:
"""节点是否为类型表达式(Name/Attribute/Subscript/BinOp|)"""
if node is None:
return 0
k: int = node.kind()
if k == ast.ASTKind.Name or k == ast.ASTKind.Attribute or k == ast.ASTKind.Subscript:
return 1
if k == ast.ASTKind.BinOp:
bop: ast.BinOp | t.CPtr = (ast.BinOp | t.CPtr)(node)
if bop.op == ast.OpKind.BitOr:
return 1
return 0
def _IsCastWrappingDeref(rhs: ast.AST | t.CPtr, deref_node: ast.AST | t.CPtr) -> int:
"""rhs 是否为"类型转换链包裹 c.Deref"(如 (T | t.CPtr)(t.CPtr(c.Deref(p))))"""
if rhs is None:
return 0
if t.CUInt64T(rhs) == t.CUInt64T(deref_node):
return 1
if rhs.kind() == ast.ASTKind.Call:
cl: ast.Call | t.CPtr = (ast.Call | t.CPtr)(rhs)
if cl.args is not None and len(cl.args) == 1 and _IsTypeExpr(cl.func) != 0:
return _IsCastWrappingDeref(cl.args.get(0), deref_node)
return 0
# ============================================================
# 常量(与 HandlesExprCall 保持一致,本地副本避免跨模块 CDefine 查找 bug)
# ============================================================
@@ -98,25 +130,33 @@ class CallGenCBuiltin(CallGenBase.CallGenBase):
# 掩盖了缺陷。
match pointee:
case llvmlite.LLVMType.Int(pointee_width):
# 仅当 c.Deref 是赋值语句的直接 RHS(如 v: int = c.Deref(p))
# 时才用注解推断读取宽度(对齐 TPC _infer_deref_target_type
# 的直接 RHS 检查);嵌套在 while 条件/比较/binop/类型转换
# 调用中(如 while c.Deref(p) != 0、total += t.CInt(c.Deref(p)))
# 不推断,否则 i8* 会被残留 CurAssignAnnot 误判为 i32*
# 读 4 字节 → StringIterTest ASCII sum/manual strcmp 失败。
if pointee_width == 8 and trans is not None \
and trans.CurAssignAnnot is not None \
and trans.CurAssignNode is not None \
and t.CUInt64T(cl) == t.CUInt64T(trans.CurAssignNode):
# 允许推断:c.Deref 是赋值语句直接 RHS(v: int = c.Deref(p))
# 或处于类型转换链包裹中(如 vt: t.CVoid | t.CPtr =
# t.CVoid(c.Deref(p)))。嵌套在 while 条件/比较/binop/
# 其他调用中(如 while c.Deref(p) != 0、total +=
# t.CInt(c.Deref(p)))不推断,否则 i8* 会被残留
# CurAssignAnnot 误判为 i32* 读 4 字节 → StringIterTest
# ASCII sum/manual strcmp 失败。
allow_infer: int = 0
if trans is not None and trans.CurAssignNode is not None:
if t.CUInt64T(cl) == t.CUInt64T(trans.CurAssignNode):
allow_infer = 1
elif _IsCastWrappingDeref(trans.CurAssignNode, cl) != 0:
allow_infer = 1
if pointee_width == 8 and allow_infer != 0 \
and trans is not None and trans.CurAssignAnnot is not None:
dref_ty: llvmlite.LLVMType | t.CPtr = HandlesType.resolve_annotation_type(
trans.Pool, trans.CurAssignAnnot,
trans._imported_modules, trans._from_imports, trans)
if dref_ty is not None:
dref_bits: int = HandlesExpr.get_llvm_type_bits(dref_ty)
dref_fbits: int = HandlesExpr.get_llvm_float_bits(dref_ty)
# 仅整数/浮点目标(struct 值目标不推断,保持 i8 读)
dref_is_ptr: int = HandlesExpr.is_ptr_type(dref_ty)
# 整数/浮点/指针目标均推断(指针 → bitcast 后
# load 8 字节;struct 值目标不推断,保持 i8 读)
dref_ptr: llvmlite.Value | t.CPtr = None
if (dref_bits != 0 or dref_fbits != 0) and dref_bits != 8:
if (dref_bits != 0 or dref_fbits != 0 or dref_is_ptr != 0) \
and dref_bits != 8:
dref_ptr_ty: llvmlite.LLVMType | t.CPtr = llvmlite.Ptr(pool, dref_ty)
dref_ptr = llvmlite.build_bitcast(
builder, ptr_val, dref_ptr_ty)