fix(gentype): c.Deref 类型推断支持转换包裹与联合全 side
_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,取第一个可解析类型。
This commit is contained in:
1 parent
0db1ccd1bb
commit
e82640ac94
1 file changed
+52
-25
@@ -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:
|
||||
|
||||
Reference in new issue
Block a user