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:
1 parent
1b5246f29f
commit
42aa90c1af
1 file changed
+52
-12
@@ -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)
|
||||
|
||||
Reference in new issue
Block a user