From 42aa90c1afdda489b68cc8665b7fbf14de3cb1c3 Mon Sep 17 00:00:00 2001 From: TermiNexus Date: Wed, 19 Aug 2026 21:19:38 +0800 Subject: [PATCH] =?UTF-8?q?fix(gen):=20translate=5Fc=5Fderef=20=E6=94=AF?= =?UTF-8?q?=E6=8C=81=E8=BD=AC=E6=8D=A2=E9=93=BE=E5=8C=85=E8=A3=B9=E6=8E=A8?= =?UTF-8?q?=E6=96=AD=E6=8C=87=E9=92=88=E7=9B=AE=E6=A0=87?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 对齐 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 只绕开了一处) --- App/lib/core/Gen/CallGenCBuiltin.vp | 64 +++++++++++++++++++++++------ 1 file changed, 52 insertions(+), 12 deletions(-) diff --git a/App/lib/core/Gen/CallGenCBuiltin.vp b/App/lib/core/Gen/CallGenCBuiltin.vp index 7ccd0a0..1cbae0f 100644 --- a/App/lib/core/Gen/CallGenCBuiltin.vp +++ b/App/lib/core/Gen/CallGenCBuiltin.vp @@ -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)