From e82640ac94a8bef71439cb3d35dae3e5212e2831 Mon Sep 17 00:00:00 2001 From: TermiNexus Date: Wed, 19 Aug 2026 21:14:13 +0800 Subject: [PATCH] =?UTF-8?q?fix(gentype):=20c.Deref=20=E7=B1=BB=E5=9E=8B?= =?UTF-8?q?=E6=8E=A8=E6=96=AD=E6=94=AF=E6=8C=81=E8=BD=AC=E6=8D=A2=E5=8C=85?= =?UTF-8?q?=E8=A3=B9=E4=B8=8E=E8=81=94=E5=90=88=E5=85=A8=20side?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit _infer_deref_target_type 仅在 Deref 为赋值直接 RHS 时推断加载类型, 被类型转换链包裹(如 (T | t.CPtr)(t.CPtr(c.Deref(p))))时返回 None → 回退 load 1 字节 → 读回垃圾指针(BuildPipeline run_llc_parallel 存 Thread* 后 join/is_alive 失效、llc 并行 5 秒误报失败的根因)。 增强:新增 _IsCastWrappingDeref 放行"转换链包裹 Deref"(ifexp/binop 仍不放行);联合注解(A | B)遍历全部 side,取第一个可解析类型。 --- lib/core/Handles/HandlesSpecialCall.py | 77 +++++++++++++++++--------- 1 file changed, 52 insertions(+), 25 deletions(-) diff --git a/lib/core/Handles/HandlesSpecialCall.py b/lib/core/Handles/HandlesSpecialCall.py index 46f4c46..2c368dd 100644 --- a/lib/core/Handles/HandlesSpecialCall.py +++ b/lib/core/Handles/HandlesSpecialCall.py @@ -12,6 +12,30 @@ from lib.core.VLogger import get_logger as _vlog from lib.constants.config import mode as _config_mode +def _IsTypeExpr(node: ast.AST | None) -> bool: + """判断 AST 节点是否为类型表达式(类型转换的目标,如 Name/Attribute/Subscript/BinOp|)""" + return ( + isinstance(node, ast.Name) + or isinstance(node, ast.Attribute) + or isinstance(node, ast.Subscript) + or (isinstance(node, ast.BinOp) and isinstance(node.op, ast.BitOr)) + ) + + +def _IsCastWrappingDeref(rhs: ast.AST | None, deref_node: ast.Call) -> bool: + """判断 rhs 是否为"类型转换链包裹 c.Deref"(如 (T | t.CPtr)(t.CPtr(c.Deref(p))))。 + + 允许在 c.Deref 处于类型转换调用链中时仍从赋值注解推断加载类型; + ifexp/compare/binop 包裹(非转换调用)不放行,避免把 i8* 错 bitcast 成 + 其他位宽加载(见 _infer_deref_target_type 文档)。 + """ + if rhs is deref_node: + return True + if isinstance(rhs, ast.Call) and len(rhs.args) == 1 and _IsTypeExpr(rhs.func): + return _IsCastWrappingDeref(rhs.args[0], deref_node) + return False + + class CSpecialCallHandle(BaseHandle): def _HandleCIfLlvm(self, Node: ast.Call) -> ir.Value: Gen: LlvmGeneratorMixin = self.Trans.LlvmGen @@ -261,46 +285,49 @@ class CSpecialCallHandle(BaseHandle): def _infer_deref_target_type(self, Gen: LlvmGeneratorMixin, DerefNode: ast.Call | None = None) -> ir.Type | None: """从当前赋值上下文推断 c.Deref 的目标加载类型。 当用户写 v: int = c.Deref(ptr) 时,从赋值注解推断目标类型。 - 注意:仅当 c.Deref 是赋值的直接 RHS 时才推断;若 c.Deref 嵌套在 + 注意:仅当 c.Deref 是赋值的直接 RHS,或 RHS 是类型转换链包裹 + (如 `(T | t.CPtr)(t.CPtr(c.Deref(p)))`)时才推断;若 c.Deref 嵌套在 ifexp/compare/binop 中(如 `a = 1 if c.Deref(p) == 65 else 0`), 不应推断,否则会把 i8* 错误 bitcast 为 i32* 加载 4 字节。""" assign_node: ast.AST | None = getattr(self.Trans, '_current_assign_node', None) if not assign_node: return None - # 仅当 c.Deref 是赋值的直接 RHS 时才推断类型 - if DerefNode is not None and getattr(assign_node, 'value', None) is not DerefNode: - return None + # 仅当 c.Deref 是赋值的直接 RHS 或处于类型转换链中时才推断类型 + if DerefNode is not None: + rhs: ast.AST | None = getattr(assign_node, 'value', None) + if rhs is not DerefNode and not _IsCastWrappingDeref(rhs, DerefNode): + return None ann: ast.AST | None = getattr(assign_node, 'annotation', None) if not ann: return None - ann_name: str | None = None + # 收集候选类型名:Name / Attribute / 联合 BinOp| 的所有 side。 + # 逐个尝试解析,取第一个能解析为 LLVM 类型的(如 + # `vthreading.Thread | t.CPtr` → 'Thread' 未注册 → 'CPtr' → i8*)。 + candidates: list[str] = [] if isinstance(ann, ast.Name): - ann_name = ann.id + candidates.append(ann.id) elif isinstance(ann, ast.Attribute): - ann_name = ann.attr + candidates.append(ann.attr) elif isinstance(ann, ast.BinOp) and isinstance(ann.op, ast.BitOr): # 处理 int | t.CPtr 形式的联合类型注解 for side in (ann.left, ann.right): if isinstance(side, ast.Name): - ann_name = side.id - break + candidates.append(side.id) elif isinstance(side, ast.Attribute): - ann_name = side.attr - break - if not ann_name: - return None - # 使用 BuiltinTypeMap 统一查询(同时支持 Python 类名和字符串速记) - entry: tuple[type, int] | None = BuiltinTypeMap.Get(ann_name) - if entry is not None: - ctype_cls: type = entry[0] - llvm_str: str | None = CTypeRegistry.CTypeToLLVM(ctype_cls) - if llvm_str: - resolved: ir.Type | None = Gen._type_str_to_llvm(llvm_str) - if resolved: - return resolved - # 检查是否是已注册的结构体类型 - if ann_name in Gen.structs: - return Gen.structs[ann_name] + candidates.append(side.attr) + for ann_name in candidates: + # 使用 BuiltinTypeMap 统一查询(同时支持 Python 类名和字符串速记) + entry: tuple[type, int] | None = BuiltinTypeMap.Get(ann_name) + if entry is not None: + ctype_cls: type = entry[0] + llvm_str: str | None = CTypeRegistry.CTypeToLLVM(ctype_cls) + if llvm_str: + resolved: ir.Type | None = Gen._type_str_to_llvm(llvm_str) + if resolved: + return resolved + # 检查是否是已注册的结构体类型 + if ann_name in Gen.structs: + return Gen.structs[ann_name] return None def _HandleCPtrToIntLlvm(self, Node: ast.Call) -> ir.Value: