修正了 TPC 的一些错误,包括 Test 维护后 TPV 无法重新编译或重编译后越界的部分问题
This commit is contained in:
@@ -9,7 +9,7 @@ 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
|
||||
from lib.core.SymbolUtils import IsListAnnotation, ParseListAnnotation, FindStructNameInAnnotation, AnnotationContainsName, IsCPtrNode
|
||||
|
||||
|
||||
class AnnAssignHandle(BaseHandle):
|
||||
@@ -105,6 +105,16 @@ class AnnAssignHandle(BaseHandle):
|
||||
ObjVal = Gen.builder.bitcast(ObjVal, ir.PointerType(Gen.structs[ClassName]), name=f"cast_{ClassName}")
|
||||
if isinstance(ObjVal.type, ir.PointerType) and isinstance(ObjVal.type.pointee, ir.PointerType):
|
||||
ObjVal = Gen._load(ObjVal, name=f"Load_{ClassName}")
|
||||
# opaque 泛型结构体 → 特化版本 bitcast
|
||||
# 当 ObjVal 的 pointee 是 opaque 基础泛型结构体(如 GSList,来自跨模块 stub),
|
||||
# 而 ClassName 是特化版本(如 GSList[BasicBlock])时,两者是不同的
|
||||
# IdentifiedStructType,直接比较会失败。这里 bitcast 到特化版本,
|
||||
# 使后续 GEP 能正确访问字段。
|
||||
if (isinstance(ObjVal.type, ir.PointerType)
|
||||
and isinstance(ObjVal.type.pointee, ir.IdentifiedStructType)
|
||||
and ObjVal.type.pointee is not Gen.structs[ClassName]
|
||||
and '[' in ClassName):
|
||||
ObjVal = Gen.builder.bitcast(ObjVal, ir.PointerType(Gen.structs[ClassName]), name=f"cast_spec_{ClassName}")
|
||||
if isinstance(ObjVal.type, ir.PointerType) and ObjVal.type.pointee == Gen.structs[ClassName]:
|
||||
if IsUnion:
|
||||
NestedStructName: str = f"{ClassName}_{AttrName}"
|
||||
@@ -139,8 +149,16 @@ class AnnAssignHandle(BaseHandle):
|
||||
if isinstance(TargetType, ir.IntType) and isinstance(Value.type, ir.IntType):
|
||||
if TargetType.width < Value.type.width:
|
||||
Value = Gen.builder.trunc(Value, TargetType, name="trunc")
|
||||
else:
|
||||
Value = Gen.builder.zext(Value, TargetType, name="zext")
|
||||
elif TargetType.width > Value.type.width:
|
||||
if Value.type.width == 1:
|
||||
# i1 是布尔值,无符号语义,必须 zext
|
||||
Value = Gen.builder.zext(Value, TargetType, name="zext")
|
||||
else:
|
||||
is_unsigned: bool = id(Value) in Gen._unsigned_results
|
||||
if is_unsigned:
|
||||
Value = Gen.builder.zext(Value, TargetType, name="zext")
|
||||
else:
|
||||
Value = Gen.builder.sext(Value, TargetType, name="sext")
|
||||
elif isinstance(TargetType, ir.PointerType) and isinstance(Value.type, ir.PointerType):
|
||||
Value = Gen.builder.bitcast(Value, TargetType, name="ptr_bitcast")
|
||||
elif isinstance(TargetType, ir.PointerType) and isinstance(Value.type, ir.IntType):
|
||||
@@ -468,6 +486,33 @@ class AnnAssignHandle(BaseHandle):
|
||||
if VarName not in Gen.var_struct_class:
|
||||
Gen.var_struct_class[VarName] = TypeInfo.Name
|
||||
Gen.global_struct_class[VarName] = TypeInfo.Name
|
||||
# 检测指针到指针缓冲区变量:注解为 StructName | t.CPtr,且赋值来自 t.CPtr(...) 调用。
|
||||
# 这种变量(如 list[T].__getitem__ 中的 elem_ptr: T | t.CPtr = t.CPtr(...))
|
||||
# 实际指向存储结构体指针的缓冲区(T=AST|t.CPtr 时特化为 AST*,缓冲区存 AST* 数组)。
|
||||
# [index] 应 bitcast 为 AST** 后 GEP 指针数组再 load,而非 GEP 结构体数组。
|
||||
# 泛型特化将 T|t.CPtr 降级为 StructName|t.CPtr(丢失一层指针),故通过赋值来源区分:
|
||||
# elem_ptr 的值是 t.CPtr(buf + idx*elem_size)(原始指针运算,缓冲区内容未知),
|
||||
# pts 的值是 (Point|t.CPtr)(...)(类型转换,明确指向 Point 结构体)。
|
||||
_is_cptr_assign: bool = (
|
||||
isinstance(Node.value, ast.Call)
|
||||
and isinstance(Node.value.func, ast.Attribute)
|
||||
and isinstance(Node.value.func.value, ast.Name)
|
||||
and Node.value.func.value.id == 't'
|
||||
and Node.value.func.attr == 'CPtr'
|
||||
)
|
||||
_is_struct_ptr_union: bool = (
|
||||
isinstance(Node.annotation, ast.BinOp)
|
||||
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)
|
||||
or (IsCPtrNode(Node.annotation.right)
|
||||
and isinstance(Node.annotation.left, ast.Name)
|
||||
and Node.annotation.left.id in Gen.structs))
|
||||
)
|
||||
if _is_cptr_assign and _is_struct_ptr_union:
|
||||
Gen.var_ptr_element[VarName] = True
|
||||
Gen.global_var_ptr_element[VarName] = True
|
||||
if VarName in Gen._reg_values:
|
||||
OldVal: ir.Value = Gen._reg_values[VarName]
|
||||
if isinstance(OldVal.type, ir.PointerType):
|
||||
@@ -511,14 +556,22 @@ class AnnAssignHandle(BaseHandle):
|
||||
VarPtr: ir.Value = Gen.variables[VarName]
|
||||
if isinstance(VarPtr.type, ir.PointerType):
|
||||
TargetType: ir.Type = VarPtr.type.pointee
|
||||
if InitValue.type != TargetType:
|
||||
if isinstance(InitValue.type, ir.IntType) and isinstance(TargetType, ir.IntType):
|
||||
if TargetType.width > InitValue.type.width:
|
||||
InitValue = Gen.builder.zext(InitValue, TargetType, name=f"zext_{VarName}")
|
||||
elif TargetType.width < InitValue.type.width:
|
||||
InitValue = Gen.builder.trunc(InitValue, TargetType, name=f"trunc_{VarName}")
|
||||
elif isinstance(InitValue.type, ir.PointerType) and isinstance(TargetType, ir.PointerType):
|
||||
InitValue = Gen.builder.bitcast(InitValue, TargetType, name=f"cast_{VarName}")
|
||||
if InitValue.type != TargetType:
|
||||
if isinstance(InitValue.type, ir.IntType) and isinstance(TargetType, ir.IntType):
|
||||
if TargetType.width > InitValue.type.width:
|
||||
if InitValue.type.width == 1:
|
||||
# i1 是布尔值,无符号语义,必须 zext
|
||||
InitValue = Gen.builder.zext(InitValue, TargetType, name=f"zext_{VarName}")
|
||||
else:
|
||||
is_unsigned: bool = (Node.value is not None and Gen._check_node_unsigned(Node.value)) or id(InitValue) in Gen._unsigned_results
|
||||
if is_unsigned:
|
||||
InitValue = Gen.builder.zext(InitValue, TargetType, name=f"zext_{VarName}")
|
||||
else:
|
||||
InitValue = Gen.builder.sext(InitValue, TargetType, name=f"sext_{VarName}")
|
||||
elif TargetType.width < InitValue.type.width:
|
||||
InitValue = Gen.builder.trunc(InitValue, TargetType, name=f"trunc_{VarName}")
|
||||
elif isinstance(InitValue.type, ir.PointerType) and isinstance(TargetType, ir.PointerType):
|
||||
InitValue = Gen.builder.bitcast(InitValue, TargetType, name=f"cast_{VarName}")
|
||||
Gen._store(InitValue, VarPtr)
|
||||
except Exception as _e:
|
||||
if _config_mode == "strict":
|
||||
@@ -567,9 +620,25 @@ class AnnAssignHandle(BaseHandle):
|
||||
return
|
||||
for CN, ST in Gen.structs.items():
|
||||
if pointee is ST or pointee == ST:
|
||||
if CN != Gen.var_struct_class.get(VarName):
|
||||
Gen.var_struct_class[VarName] = CN
|
||||
Gen.global_struct_class[VarName] = CN
|
||||
# 若注解是泛型特化(如 ndarray[t.CDouble] | t.CPtr),
|
||||
# 构造正确的特化名(如 ndarray[double]),而非用 opaque 基础名
|
||||
resolved_cn: str = CN
|
||||
if isinstance(Node.annotation, ast.BinOp) and isinstance(Node.annotation.op, ast.BitOr) and '[' not in CN:
|
||||
for side in (Node.annotation.left, Node.annotation.right):
|
||||
if isinstance(side, ast.Subscript):
|
||||
bn: ast.expr = side.value
|
||||
bnm: str | None = bn.id if isinstance(bn, ast.Name) else (bn.attr if isinstance(bn, ast.Attribute) else None)
|
||||
if bnm and bnm == CN:
|
||||
sn2: ast.AST = side.slice
|
||||
if hasattr(ast, 'Index') and isinstance(sn2, ast.Index):
|
||||
sn2 = sn2.value
|
||||
r2: tuple[str, str] | None = self.Trans.ExprCallHandle._resolve_generic_slice_type(sn2)
|
||||
if r2:
|
||||
resolved_cn = f'{CN}[{r2[0]}]'
|
||||
break
|
||||
if resolved_cn != Gen.var_struct_class.get(VarName):
|
||||
Gen.var_struct_class[VarName] = resolved_cn
|
||||
Gen.global_struct_class[VarName] = resolved_cn
|
||||
if isinstance(VarType, ir.PointerType) and VarType.pointee is not ST and VarType.pointee != ST:
|
||||
var = Gen._allocaEntry(ir.PointerType(pointee), name=VarName)
|
||||
VarType = ir.PointerType(pointee)
|
||||
@@ -579,7 +648,15 @@ class AnnAssignHandle(BaseHandle):
|
||||
if InitValue.type != VarType:
|
||||
if isinstance(InitValue.type, ir.IntType) and isinstance(VarType, ir.IntType):
|
||||
if VarType.width > InitValue.type.width:
|
||||
InitValue = Gen.builder.zext(InitValue, VarType, name=f"zext_{VarName}")
|
||||
if InitValue.type.width == 1:
|
||||
# i1 是布尔值,无符号语义,必须 zext
|
||||
InitValue = Gen.builder.zext(InitValue, VarType, name=f"zext_{VarName}")
|
||||
else:
|
||||
is_unsigned: bool = (Node.value is not None and Gen._check_node_unsigned(Node.value)) or id(InitValue) in Gen._unsigned_results
|
||||
if is_unsigned:
|
||||
InitValue = Gen.builder.zext(InitValue, VarType, name=f"zext_{VarName}")
|
||||
else:
|
||||
InitValue = Gen.builder.sext(InitValue, VarType, name=f"sext_{VarName}")
|
||||
elif VarType.width < InitValue.type.width:
|
||||
InitValue = Gen.builder.trunc(InitValue, VarType, name=f"trunc_{VarName}")
|
||||
elif isinstance(InitValue.type, ir.PointerType) and isinstance(VarType, ir.PointerType):
|
||||
@@ -622,6 +699,27 @@ class AnnAssignHandle(BaseHandle):
|
||||
|
||||
if isinstance(Node.annotation, ast.BinOp) and isinstance(Node.annotation.op, ast.BitOr):
|
||||
found_struct: str | None = FindStructNameInAnnotation(Node.annotation, Gen.structs)
|
||||
# 若 FindStructNameInAnnotation 仅返回裸模板名(如 'ndarray'),但注解中
|
||||
# 含泛型特化(如 numpy.ndarray[t.CDouble]),用 LLVM 类型名构造特化名
|
||||
# (如 'ndarray[double]')。main.py 的 Gen.structs 可能只有 opaque 'ndarray',
|
||||
# 但 numpy 模块已特化 ndarray[double],方法调用通过 sha1 前缀查找。
|
||||
if found_struct and '[' not in found_struct:
|
||||
for side in (Node.annotation.left, Node.annotation.right):
|
||||
if isinstance(side, ast.Subscript):
|
||||
base_node: ast.expr = side.value
|
||||
base_nm: str | None = None
|
||||
if isinstance(base_node, ast.Name):
|
||||
base_nm = base_node.id
|
||||
elif isinstance(base_node, ast.Attribute):
|
||||
base_nm = base_node.attr
|
||||
if base_nm and base_nm == found_struct:
|
||||
slice_node: ast.AST = side.slice
|
||||
if hasattr(ast, 'Index') and isinstance(slice_node, ast.Index):
|
||||
slice_node = slice_node.value
|
||||
result: tuple[str, str] | None = self.Trans.ExprCallHandle._resolve_generic_slice_type(slice_node)
|
||||
if result:
|
||||
found_struct = f'{base_nm}[{result[0]}]'
|
||||
break
|
||||
if found_struct:
|
||||
Gen.var_struct_class[VarName] = found_struct
|
||||
Gen.global_struct_class[VarName] = found_struct
|
||||
@@ -632,7 +730,10 @@ class AnnAssignHandle(BaseHandle):
|
||||
for CN, ST in Gen.structs.items():
|
||||
if pointee == ST:
|
||||
Gen._var_to_heap_ptr[VarName] = InitValue
|
||||
if CN != Gen.var_struct_class.get(VarName):
|
||||
# 不覆盖已设置的特化名(含 '['):opaque 基础类型(如 ndarray)
|
||||
# 会匹配到裸模板名,但注解已提供更精确的特化名(如 ndarray[double])
|
||||
existing_cn: str | None = Gen.var_struct_class.get(VarName)
|
||||
if not (existing_cn and '[' in existing_cn) and CN != existing_cn:
|
||||
Gen.var_struct_class[VarName] = CN
|
||||
Gen.global_struct_class[VarName] = CN
|
||||
break
|
||||
|
||||
Reference in New Issue
Block a user