fix(subscript): 泛型 T|t.CPtr 指针槽变量优先走 i8** load,修 8fbba list[str].get 返回类型不匹配

TPC 编译 TPV 时 _list.vp 泛型方法体 elem_ptr: T|t.CPtr = t.CPtr(...):
T 未解析时 var_struct_class[elem_ptr] 误注册 llvmlite.Value →
_HandleSubscriptLlvm 的 elem_class 推断为 Value → cast Value* → 与
get 声明 i8* 不匹配(llc 报错)。修复:
1. _is_struct_ptr_union 放宽——泛型参数 Name(单字母大写)也判定指针槽
   联合(标量 T 退化为 Ptr(i32) 不命中 i8 分支,安全)
2. _HandleSubscriptLlvm 的 var_ptr_element 分支提前到 elem_class 推断
   之前——T|t.CPtr 指针槽变量优先 i8** load i8*(8 字节)
This commit is contained in:
TermiNexus committed 2026-08-18 10:12:06 +08:00
1 parent a2378e6878
commit 0e80019033
2 files changed
+36 -6

No files matched your search

+19 -3
View File
@@ -9,7 +9,21 @@ from lib.core.Handles.HandlesBase import BaseHandle, CTypeInfo
from lib.core.VLogger import get_logger as _vlog
from lib.constants.config import mode as _config_mode
from lib.includes import t
from lib.core.SymbolUtils import IsListAnnotation, ParseListAnnotation, FindStructNameInAnnotation, AnnotationContainsName, IsCPtrNode
from lib.core.SymbolUtils import IsListAnnotation, ParseListAnnotation, FindStructNameInAnnotation, AnnotationContainsName, IsCPtrNode
def _IsGenericTpName(name: str) -> bool:
"""判断名称是否为泛型类型参数(单字母大写,如 T/U/V)
用于 _is_struct_ptr_union 判定:elem_ptr: T | t.CPtr = t.CPtr(...)
(_list.vp 泛型方法体,T 未解析)时按 8 字节指针槽处理,避免
var_struct_class 误注册 llvmlite.Value 后 elem_ptr[0] cast 到 Value*
与函数声明 i8* 不匹配(8fbba llc 报错根因)。标量 T(如 int)退化为
Ptr(i32) 不命中 _HandleSubscriptLlvm 的 i8 分支,不受此影响。
"""
if not name:
return False
return len(name) == 1 and name.isalpha() and name.isupper()
class AnnAssignHandle(BaseHandle):
@@ -496,10 +510,12 @@ class AnnAssignHandle(BaseHandle):
and isinstance(Node.annotation.op, ast.BitOr)
and ((IsCPtrNode(Node.annotation.left)
and isinstance(Node.annotation.right, ast.Name)
and Node.annotation.right.id in Gen.structs)
and (Node.annotation.right.id in Gen.structs
or _IsGenericTpName(Node.annotation.right.id)))
or (IsCPtrNode(Node.annotation.right)
and isinstance(Node.annotation.left, ast.Name)
and Node.annotation.left.id in Gen.structs))
and (Node.annotation.left.id in Gen.structs
or _IsGenericTpName(Node.annotation.left.id))))
)
if _is_cptr_assign and _is_struct_ptr_union:
Gen.var_ptr_element[VarName] = True
+17 -3
View File
@@ -1035,6 +1035,20 @@ class ExprAttrHandle(BaseHandle):
return self._load_arr_elem_with_bswap(Gen, ElemPtr, arr_byte_order)
else:
if isinstance(pointee, ir.IntType) and pointee.width == 8:
# 指针槽变量优先(8fbba 修复):T|t.CPtr 指针槽(elem_ptr 指向
# 8 字节指针数组,如 _list.vp 泛型方法体)→ i8** load i8*。
# 必须放在 _infer_element_struct_class 之前——泛型 T 未解析时
# var_struct_class 误注册 llvmlite.Value,若先推断 elem_class
# 会 cast 到 Value*,与函数声明 i8* 不匹配(llc 报错)。
if isinstance(Node.value, ast.Name):
_ptr_elem_flag: bool = (getattr(Gen, 'var_ptr_element', {}).get(Node.value.id, False)
or getattr(Gen, 'global_var_ptr_element', {}).get(Node.value.id, False))
if _ptr_elem_flag:
CastedPtrPtr: Any = Gen.builder.bitcast(ValueVal, ir.PointerType(ir.PointerType(ir.IntType(8))), name="cast_pp_str")
if isinstance(IndexVal.type, ir.IntType) and IndexVal.type.width < 64:
IndexVal = Gen.builder.zext(IndexVal, ir.IntType(64), name="zext_pp_str_index")
ElemPtr = Gen.builder.gep(CastedPtrPtr, [IndexVal], name="subscript")
return Gen._load(ElemPtr, name="str_ptr_load")
elem_class: str | None = self._infer_element_struct_class(Node.value, Gen)
if elem_class and elem_class in Gen.structs:
CastedPtr: Any = Gen.builder.bitcast(ValueVal, ir.PointerType(Gen.structs[elem_class]), name=f"cast_{elem_class}_arr")
@@ -1047,10 +1061,10 @@ class ExprAttrHandle(BaseHandle):
# 指针到 str/bytes 的变量 (BinOp 注解如 str | t.CPtr)
# elem_ptr 是 i8* 但实际指向 i8* (字符串指针), elem_ptr[0] 应加载 8 字节
if isinstance(Node.value, ast.Name):
_ptr_elem_flag: bool = (getattr(Gen, 'var_ptr_element', {}).get(Node.value.id, False)
or getattr(Gen, 'global_var_ptr_element', {}).get(Node.value.id, False))
_ptr_elem_flag = (getattr(Gen, 'var_ptr_element', {}).get(Node.value.id, False)
or getattr(Gen, 'global_var_ptr_element', {}).get(Node.value.id, False))
if _ptr_elem_flag:
CastedPtrPtr: Any = Gen.builder.bitcast(ValueVal, ir.PointerType(ir.PointerType(ir.IntType(8))), name="cast_pp_str")
CastedPtrPtr = Gen.builder.bitcast(ValueVal, ir.PointerType(ir.PointerType(ir.IntType(8))), name="cast_pp_str")
if isinstance(IndexVal.type, ir.IntType) and IndexVal.type.width < 64:
IndexVal = Gen.builder.zext(IndexVal, ir.IntType(64), name="zext_pp_str_index")
ElemPtr = Gen.builder.gep(CastedPtrPtr, [IndexVal], name="subscript")