475 lines
29 KiB
Python
475 lines
29 KiB
Python
from __future__ import annotations
|
||
from typing import TYPE_CHECKING
|
||
if TYPE_CHECKING:
|
||
from lib.core.translator import Translator
|
||
from lib.core.Handles.HandlesBase import BaseHandle, CTypeInfo
|
||
from lib.includes import t
|
||
import ast
|
||
import llvmlite.ir as ir
|
||
|
||
|
||
class AnnAssignHandle(BaseHandle):
|
||
def _GetCTypeInfo(self, annotation):
|
||
return self.Trans.TypeMergeHandler.GetCTypeInfo(annotation)
|
||
|
||
def _StoreOrStrCopy(self, VarName, VarPtr, Value):
|
||
Gen = self.Trans.LlvmGen
|
||
DestPtr = Gen._load(VarPtr, name=VarName)
|
||
if isinstance(DestPtr.type, ir.PointerType) and isinstance(DestPtr.type.pointee, ir.IntType) and DestPtr.type.pointee.width == 8:
|
||
if isinstance(Value.type, ir.PointerType) and isinstance(Value.type.pointee, ir.IntType) and Value.type.pointee.width == 8:
|
||
if 'llvm.memcpy' not in Gen.functions:
|
||
memcpy_type = ir.FunctionType(ir.VoidType(), [ir.PointerType(ir.IntType(8)), ir.PointerType(ir.IntType(8)), ir.IntType(64), ir.IntType(32), ir.IntType(1)])
|
||
Gen.functions['llvm.memcpy'] = ir.Function(Gen.module, memcpy_type, name='llvm.memcpy')
|
||
if isinstance(DestPtr.type.pointee, ir.IntType) and not isinstance(DestPtr.type.pointee, ir.IntType(8)):
|
||
DestPtr = Gen.builder.bitcast(DestPtr, ir.PointerType(ir.IntType(8)), name=f"strcpy_dst_cast_{VarName}")
|
||
if isinstance(Value.type.pointee, ir.IntType) and not isinstance(Value.type.pointee, ir.IntType(8)):
|
||
Value = Gen.builder.bitcast(Value, ir.PointerType(ir.IntType(8)), name=f"strcpy_src_cast_{VarName}")
|
||
size = ir.Constant(ir.IntType(64), 8)
|
||
align = ir.Constant(ir.IntType(32), 1)
|
||
isvolatile = ir.Constant(ir.IntType(1), 0)
|
||
Gen.builder.call(Gen.functions['llvm.memcpy'], [DestPtr, Value, size, align, isvolatile], name=f"strcpy_call_{VarName}")
|
||
return
|
||
try:
|
||
CastedVal = Gen.builder.bitcast(Value, VarPtr.type.pointee, name=f"cast_{VarName}")
|
||
Gen._store(CastedVal, VarPtr)
|
||
except Exception: # 回退:bitcast 失败时 alloca 新变量
|
||
NewVar = Gen._allocaEntry(Value.type, name=VarName)
|
||
Gen._store(Value, NewVar)
|
||
Gen.variables[VarName] = NewVar
|
||
|
||
def _HandleAttributeStoreLlvm(self, Target, Value):
|
||
Gen = self.Trans.LlvmGen
|
||
AttrName = Target.attr
|
||
if isinstance(Target.value, ast.Name) and Target.value.id == 'self':
|
||
ClassName = self._CurrentCpythonObjectClass
|
||
if not ClassName:
|
||
self_var = Gen.variables.get('self')
|
||
if self_var:
|
||
var_type = self_var.type
|
||
if isinstance(var_type, ir.PointerType) and isinstance(var_type.pointee, ir.PointerType):
|
||
var_type = var_type.pointee
|
||
if isinstance(var_type, ir.PointerType):
|
||
pointee = var_type.pointee
|
||
for cn, st in Gen.structs.items():
|
||
if st == pointee:
|
||
ClassName = cn
|
||
break
|
||
if ClassName and ClassName in Gen.structs:
|
||
SelfVar = Gen._get_var_ptr('self')
|
||
if SelfVar:
|
||
SelfPtr = Gen._load(SelfVar, name="self")
|
||
offset = Gen._get_member_offset(AttrName, ClassName)
|
||
MemberPtr = Gen.builder.gep(SelfPtr, [ir.Constant(ir.IntType(32), 0), ir.Constant(ir.IntType(32), offset)], name=AttrName)
|
||
self._StoreWithCoerce(Value, MemberPtr)
|
||
elif isinstance(Target.value, ast.Name):
|
||
VarName = Target.value.id
|
||
ClassName = Gen.var_struct_class.get(VarName)
|
||
if not ClassName:
|
||
for CN in Gen.structs:
|
||
if VarName == CN.lower() or VarName.startswith(CN):
|
||
ClassName = CN
|
||
break
|
||
if not ClassName and VarName in Gen.variables:
|
||
VarPtr = Gen.variables[VarName]
|
||
if isinstance(VarPtr.type, ir.PointerType):
|
||
pointee = VarPtr.type.pointee
|
||
if isinstance(pointee, ir.PointerType):
|
||
pointee = pointee.pointee
|
||
for CN, ST in Gen.structs.items():
|
||
if pointee == ST:
|
||
ClassName = CN
|
||
break
|
||
IsUnion = False
|
||
if ClassName and self.Trans.SymbolTable.has(ClassName):
|
||
TypeInfo = self.Trans.SymbolTable[ClassName]
|
||
if TypeInfo.IsUnion:
|
||
IsUnion = True
|
||
if ClassName and ClassName in Gen.structs:
|
||
ObjVal = self.Trans.ExprHandler.HandleExprLlvm(Target.value)
|
||
if ObjVal:
|
||
if isinstance(ObjVal.type, ir.PointerType) and isinstance(ObjVal.type.pointee, ir.IntType) and ObjVal.type.pointee.width == 8:
|
||
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}")
|
||
if isinstance(ObjVal.type, ir.PointerType) and ObjVal.type.pointee == Gen.structs[ClassName]:
|
||
if IsUnion:
|
||
NestedStructName = f"{ClassName}_{AttrName}"
|
||
if NestedStructName in Gen.structs:
|
||
NestedStructType = Gen.structs[NestedStructName]
|
||
ObjVal = Gen.builder.bitcast(ObjVal, ir.PointerType(NestedStructType), name=f"cast_{NestedStructName}")
|
||
offset = Gen._get_member_offset(AttrName, NestedStructName)
|
||
if offset is not None and offset < len(NestedStructType.elements):
|
||
MemberPtr = Gen.builder.gep(ObjVal, [ir.Constant(ir.IntType(32), 0), ir.Constant(ir.IntType(32), offset)], name=AttrName)
|
||
self._StoreWithCoerce(Value, MemberPtr)
|
||
return
|
||
offset = Gen._get_member_offset(AttrName, ClassName)
|
||
MemberPtr = Gen.builder.gep(ObjVal, [ir.Constant(ir.IntType(32), 0), ir.Constant(ir.IntType(32), offset)], name=AttrName)
|
||
self._StoreWithCoerce(Value, MemberPtr)
|
||
elif isinstance(Target.value, ast.Attribute):
|
||
ObjVal = self.Trans.ExprHandler.HandleExprLlvm(Target.value)
|
||
if ObjVal and isinstance(ObjVal.type, ir.PointerType):
|
||
pointee = ObjVal.type.pointee
|
||
if isinstance(pointee, (ir.LiteralStructType, ir.IdentifiedStructType)):
|
||
for CN, ST in Gen.structs.items():
|
||
if pointee == ST:
|
||
offset = Gen._get_member_offset(AttrName, CN)
|
||
MemberPtr = Gen.builder.gep(ObjVal, [ir.Constant(ir.IntType(32), 0), ir.Constant(ir.IntType(32), offset)], name=AttrName)
|
||
self._StoreWithCoerce(Value, MemberPtr)
|
||
break
|
||
|
||
def _StoreWithCoerce(self, Value, Ptr):
|
||
Gen = self.Trans.LlvmGen
|
||
if isinstance(Ptr.type, ir.PointerType):
|
||
TargetType = Ptr.type.pointee
|
||
if Value.type != TargetType:
|
||
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 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):
|
||
Value = Gen.builder.inttoptr(Value, TargetType, name="int_to_ptr")
|
||
elif isinstance(TargetType, ir.IntType) and isinstance(Value.type, ir.PointerType):
|
||
Value = Gen.builder.ptrtoint(Value, TargetType, name="ptr_to_int")
|
||
Gen._store(Value, Ptr)
|
||
|
||
def _HandleAnnAssignLlvm(self, Node):
|
||
Gen = self.Trans.LlvmGen
|
||
self.Trans._current_assign_node = Node
|
||
try:
|
||
self._HandleAnnAssignLlvmInner(Node)
|
||
finally:
|
||
self.Trans._current_assign_node = None
|
||
|
||
def _HandleAnnAssignLlvmInner(self, Node):
|
||
Gen = self.Trans.LlvmGen
|
||
if isinstance(Node.target, ast.Name):
|
||
VarName = Node.target.id
|
||
TypeInfo = self.Trans.TypeMergeHandler.GetCTypeInfo(Node.annotation)
|
||
if TypeInfo is None:
|
||
TypeInfo = CTypeInfo()
|
||
TypeInfo.BaseType = t.CInt()
|
||
IsPtr = TypeInfo.IsPtr
|
||
|
||
if TypeInfo.IsDefine:
|
||
if Node.value and isinstance(Node.value, ast.Constant):
|
||
if not hasattr(Gen, '_define_constants'):
|
||
Gen._define_constants = {}
|
||
Gen._define_constants[VarName] = Node.value.value
|
||
info = CTypeInfo()
|
||
info.IsDefine = True
|
||
info.DefineValue = Node.value.value
|
||
self.Trans.SymbolTable.insert(VarName, info)
|
||
Gen._record_var_signedness(VarName, TypeInfo.IsUInt)
|
||
return
|
||
if TypeInfo.IsStr or (isinstance(Node.annotation, ast.Name) and Node.annotation.id == 'str'):
|
||
TypeInfo = CTypeInfo()
|
||
TypeInfo.BaseType = t.CChar()
|
||
TypeInfo.PtrCount = 1
|
||
IsPtr = True
|
||
if isinstance(Node.annotation, ast.Subscript) and isinstance(Node.annotation.value, ast.Name) and Node.annotation.value.id == 'list':
|
||
slice_node = Node.annotation.slice
|
||
if isinstance(slice_node, ast.Tuple) and len(slice_node.elts) == 2:
|
||
elem_type_node = slice_node.elts[0]
|
||
count_node = slice_node.elts[1]
|
||
ElemTypeInfo = CTypeInfo.FromNode(elem_type_node, self.Trans.SymbolTable)
|
||
if isinstance(elem_type_node, ast.Name) and elem_type_node.id in Gen.structs:
|
||
ElemType = Gen.structs[elem_type_node.id]
|
||
else:
|
||
if isinstance(elem_type_node, ast.Name) and elem_type_node.id == 'str':
|
||
ElemType = ir.PointerType(ir.IntType(8))
|
||
else:
|
||
ElemType = Gen._ctype_to_llvm(ElemTypeInfo)
|
||
if isinstance(ElemType, ir.VoidType):
|
||
ElemType = ir.IntType(32)
|
||
ArrayCount = 1
|
||
if isinstance(count_node, ast.Constant) and isinstance(count_node.value, int):
|
||
ArrayCount = count_node.value
|
||
else:
|
||
eval_count = CTypeInfo.TryEvalConstExpr(count_node, self.Trans.SymbolTable)
|
||
if eval_count is not None and isinstance(eval_count, int) and eval_count > 0:
|
||
ArrayCount = eval_count
|
||
elif count_node is None or (isinstance(count_node, ast.Constant) and count_node.value is None):
|
||
if Node.value and isinstance(Node.value, ast.Constant) and isinstance(Node.value.value, str):
|
||
ArrayCount = len(Node.value.value) + 1
|
||
VarType = ir.ArrayType(ElemType, ArrayCount)
|
||
var = Gen._allocaEntry(VarType, name=VarName)
|
||
Gen.variables[VarName] = var
|
||
Gen._record_var_signedness(VarName, False)
|
||
if Node.value and isinstance(Node.value, ast.List):
|
||
InitConstants = self.Trans._BuildArrayInitConstants(Node.value, ElemType, elem_type_node, ArrayCount, Gen)
|
||
if InitConstants:
|
||
try:
|
||
InitVal = ir.Constant(VarType, InitConstants)
|
||
Gen.builder.store(InitVal, var)
|
||
except Exception as _e:
|
||
if __import__('lib.constants.config', fromlist=['mode']).mode == "strict":
|
||
self.Trans.LogWarning(f"异常被忽略: {_e}")
|
||
elif Node.value and isinstance(Node.value, ast.Constant) and isinstance(Node.value.value, str):
|
||
str_val = Node.value.value + '\x00'
|
||
str_bytes = bytearray(str_val, 'utf-8')
|
||
if isinstance(VarType, ir.ArrayType) and len(str_bytes) < VarType.count:
|
||
str_bytes.extend(b'\x00' * (VarType.count - len(str_bytes)))
|
||
try:
|
||
InitVal = ir.Constant(VarType, str_bytes[:VarType.count] if isinstance(VarType, ir.ArrayType) else str_bytes)
|
||
Gen.builder.store(InitVal, var)
|
||
except Exception as _e:
|
||
if __import__('lib.constants.config', fromlist=['mode']).mode == "strict":
|
||
self.Trans.LogWarning(f"异常被忽略: {_e}")
|
||
if self.Trans.VarScopes:
|
||
self.Trans.VarScopes[-1][VarName] = ElemTypeInfo
|
||
return
|
||
if TypeInfo.IsVoid and isinstance(Node.annotation, ast.BinOp):
|
||
def _find_struct_name_in_annot(node):
|
||
if isinstance(node, ast.Name) and node.id in Gen.structs:
|
||
return node.id
|
||
if isinstance(node, ast.Constant) and isinstance(node.value, str) and node.value in Gen.structs:
|
||
return node.value
|
||
if isinstance(node, ast.Attribute) and node.attr in Gen.structs:
|
||
return node.attr
|
||
if isinstance(node, ast.BinOp) and isinstance(node.op, ast.BitOr):
|
||
result = _find_struct_name_in_annot(node.left)
|
||
if result:
|
||
return result
|
||
return _find_struct_name_in_annot(node.right)
|
||
return None
|
||
found = _find_struct_name_in_annot(Node.annotation)
|
||
if found:
|
||
TypeInfo = CTypeInfo()
|
||
TypeInfo.BaseType = t.CStruct(name=found)
|
||
TypeInfo.PtrCount = 1
|
||
IsPtr = True
|
||
elif isinstance(Node.annotation.left, ast.Attribute):
|
||
AttrTypeInfo = self.Trans.TypeMergeHandler.GetCTypeInfo(Node.annotation.left)
|
||
if AttrTypeInfo and AttrTypeInfo.BaseType:
|
||
TypeInfo = AttrTypeInfo
|
||
TypeInfo.PtrCount = max(TypeInfo.PtrCount, 1)
|
||
IsPtr = True
|
||
VarType = Gen._ctype_to_llvm(TypeInfo)
|
||
if not IsPtr and TypeInfo.IsStruct and TypeInfo.Name:
|
||
stripped = TypeInfo.Name
|
||
if stripped in Gen.class_vtable and stripped in Gen.structs:
|
||
VarType = ir.PointerType(Gen.structs[stripped])
|
||
IsPtr = True
|
||
if isinstance(VarType, ir.IdentifiedStructType):
|
||
struct_name = getattr(VarType, 'name', '')
|
||
if struct_name and Gen.class_vtable:
|
||
for cls_name in Gen.class_vtable:
|
||
if struct_name.endswith(f'.{cls_name}') or struct_name == cls_name:
|
||
VarType = ir.PointerType(VarType)
|
||
IsPtr = True
|
||
break
|
||
if isinstance(VarType, ir.VoidType):
|
||
VarType = ir.IntType(32)
|
||
IsUnsigned = TypeInfo.IsUInt
|
||
if VarName in Gen._reg_values:
|
||
OldVal = Gen._reg_values[VarName]
|
||
if isinstance(OldVal.type, ir.PointerType):
|
||
var = Gen._allocaEntry(OldVal.type, name=VarName)
|
||
Gen._store(OldVal, var)
|
||
Gen.variables[VarName] = var
|
||
del Gen._reg_values[VarName]
|
||
if Node.value:
|
||
InitValue = self.HandleExprLlvm(Node.value, VarType=VarType)
|
||
if InitValue:
|
||
self._StoreOrStrCopy(VarName, var, InitValue)
|
||
Gen._record_var_signedness(VarName, IsUnsigned)
|
||
return
|
||
del Gen._reg_values[VarName]
|
||
InitValue = None
|
||
if Node.value:
|
||
InitValue = self.HandleExprLlvm(Node.value, VarType=VarType)
|
||
if VarName in Gen._reg_values:
|
||
del Gen._reg_values[VarName]
|
||
if VarName in Gen.variables and Gen.variables[VarName] is not None:
|
||
if InitValue and isinstance(InitValue.type, ir.PointerType):
|
||
pointee = InitValue.type.pointee
|
||
if isinstance(pointee, ir.IdentifiedStructType):
|
||
struct_name = getattr(pointee, 'name', '')
|
||
is_vtable_class = False
|
||
for cls_name in Gen.class_vtable:
|
||
if struct_name.endswith(f'.{cls_name}') or struct_name == cls_name:
|
||
is_vtable_class = True
|
||
break
|
||
if is_vtable_class:
|
||
var = Gen._allocaEntry(InitValue.type, name=VarName)
|
||
Gen._store(InitValue, var)
|
||
Gen.variables[VarName] = var
|
||
if isinstance(Node.annotation, ast.Name) and Node.annotation.id in Gen.structs:
|
||
Gen.var_struct_class[VarName] = Node.annotation.id
|
||
Gen.global_struct_class[VarName] = Node.annotation.id
|
||
Gen._record_var_signedness(VarName, IsUnsigned)
|
||
return
|
||
if InitValue:
|
||
try:
|
||
VarPtr = Gen.variables[VarName]
|
||
if isinstance(VarPtr.type, ir.PointerType):
|
||
TargetType = 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}")
|
||
Gen._store(InitValue, VarPtr)
|
||
except Exception as _e:
|
||
if __import__('lib.constants.config', fromlist=['mode']).mode == "strict":
|
||
self.Trans.LogWarning(f"异常被忽略: {_e}")
|
||
Gen._record_var_signedness(VarName, IsUnsigned)
|
||
return
|
||
if VarName in Gen.global_vars:
|
||
if VarName in Gen.module.globals:
|
||
GVar = Gen.module.globals[VarName]
|
||
if InitValue:
|
||
Gen._store(InitValue, GVar)
|
||
Gen.variables[VarName] = GVar
|
||
Gen._record_var_signedness(VarName, IsUnsigned)
|
||
return
|
||
var = Gen._allocaEntry(VarType, name=VarName)
|
||
if InitValue and isinstance(InitValue.type, ir.PointerType):
|
||
pointee = InitValue.type.pointee
|
||
if isinstance(pointee, ir.IdentifiedStructType):
|
||
struct_name = getattr(pointee, 'name', '')
|
||
is_vtable_class = False
|
||
for cls_name in Gen.class_vtable:
|
||
if struct_name.endswith(f'.{cls_name}') or struct_name == cls_name:
|
||
is_vtable_class = True
|
||
break
|
||
if is_vtable_class and not isinstance(VarType, ir.PointerType):
|
||
var = Gen._allocaEntry(InitValue.type, name=VarName)
|
||
VarType = InitValue.type
|
||
IsPtr = True
|
||
Gen._store(InitValue, var)
|
||
Gen.variables[VarName] = var
|
||
if isinstance(Node.annotation, ast.Name) and Node.annotation.id in Gen.structs:
|
||
Gen.var_struct_class[VarName] = Node.annotation.id
|
||
Gen.global_struct_class[VarName] = Node.annotation.id
|
||
Gen._record_var_signedness(VarName, IsUnsigned)
|
||
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
|
||
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)
|
||
break
|
||
if InitValue:
|
||
try:
|
||
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}")
|
||
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):
|
||
InitValue = Gen.builder.bitcast(InitValue, VarType, name=f"cast_{VarName}")
|
||
elif isinstance(VarType, ir.PointerType) and isinstance(InitValue.type, ir.IntType):
|
||
InitValue = Gen.builder.inttoptr(InitValue, VarType, name=f"int2ptr_{VarName}")
|
||
elif isinstance(VarType, ir.IntType) and isinstance(InitValue.type, ir.PointerType):
|
||
InitValue = Gen.builder.ptrtoint(InitValue, VarType, name=f"ptr2int_{VarName}")
|
||
Gen._store(InitValue, var)
|
||
except Exception as _e:
|
||
if __import__('lib.constants.config', fromlist=['mode']).mode == "strict":
|
||
self.Trans.LogWarning(f"异常被忽略: {_e}")
|
||
Gen.variables[VarName] = var
|
||
Gen._record_var_signedness(VarName, IsUnsigned)
|
||
|
||
if isinstance(Node.annotation, ast.BinOp) and isinstance(Node.annotation.op, ast.BitOr):
|
||
def _find_struct_in_binop(node):
|
||
if isinstance(node, ast.Name) and node.id in Gen.structs:
|
||
return node.id
|
||
if isinstance(node, ast.Constant) and isinstance(node.value, str) and node.value in Gen.structs:
|
||
return node.value
|
||
if isinstance(node, ast.Attribute) and node.attr in Gen.structs:
|
||
return node.attr
|
||
if isinstance(node, ast.BinOp) and isinstance(node.op, ast.BitOr):
|
||
result = _find_struct_in_binop(node.left)
|
||
if result:
|
||
return result
|
||
return _find_struct_in_binop(node.right)
|
||
return None
|
||
found_struct = _find_struct_in_binop(Node.annotation)
|
||
if found_struct:
|
||
Gen.var_struct_class[VarName] = found_struct
|
||
Gen.global_struct_class[VarName] = found_struct
|
||
|
||
if InitValue and isinstance(InitValue.type, ir.PointerType):
|
||
pointee = InitValue.type.pointee
|
||
if isinstance(pointee, (ir.LiteralStructType, ir.IdentifiedStructType)):
|
||
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):
|
||
Gen.var_struct_class[VarName] = CN
|
||
Gen.global_struct_class[VarName] = CN
|
||
break
|
||
|
||
if self.Trans.VarScopes:
|
||
if TypeInfo:
|
||
self.Trans.VarScopes[-1][VarName] = TypeInfo
|
||
else:
|
||
DefaultInfo = CTypeInfo()
|
||
DefaultInfo.BaseType = t.CInt
|
||
self.Trans.VarScopes[-1][VarName] = DefaultInfo
|
||
elif isinstance(Node.target, ast.Attribute):
|
||
if isinstance(Node.target.value, ast.Name) and Node.target.value.id == 'self':
|
||
if Node.value:
|
||
AttrVarType = None
|
||
try:
|
||
if isinstance(Node.annotation, ast.Subscript) and isinstance(Node.annotation.value, ast.Name) and Node.annotation.value.id == 'list':
|
||
slice_node = Node.annotation.slice
|
||
if isinstance(slice_node, ast.Name):
|
||
AttrVarType = f'list[{slice_node.id}]'
|
||
elif isinstance(slice_node, ast.Tuple):
|
||
elts = ', '.join(getattr(e, 'id', str(e)) for e in slice_node.elts)
|
||
AttrVarType = f'list[{elts}]'
|
||
elif isinstance(slice_node, ast.Attribute):
|
||
AttrVarType = f'list[{ast.dump(slice_node)}]'
|
||
if AttrVarType is None:
|
||
AttrTypeInfo = CTypeInfo.FromNode(Node.annotation, self.Trans.SymbolTable)
|
||
if AttrTypeInfo:
|
||
AttrVarType = Gen._ctype_to_llvm(AttrTypeInfo)
|
||
except Exception as _e:
|
||
from lib.core.VLogger import get_logger as _vlog
|
||
from lib.constants.config import mode as _config_mode
|
||
if _config_mode == "strict":
|
||
raise
|
||
_vlog().warning(f"解析类型失败: {_e}", "Exception")
|
||
Value = self.HandleExprLlvm(Node.value, VarType=AttrVarType)
|
||
if Value:
|
||
self._HandleAttributeStoreLlvm(Node.target, Value)
|
||
AttrName = Node.target.attr
|
||
len_name = f'{AttrName}__len'
|
||
ClassName = self._CurrentCpythonObjectClass
|
||
if not ClassName:
|
||
self_var = Gen.variables.get('self')
|
||
if self_var:
|
||
var_type = self_var.type
|
||
if isinstance(var_type, ir.PointerType) and isinstance(var_type.pointee, ir.PointerType):
|
||
var_type = var_type.pointee
|
||
if isinstance(var_type, ir.PointerType):
|
||
pointee = var_type.pointee
|
||
for cn, st in Gen.structs.items():
|
||
if st == pointee:
|
||
ClassName = cn
|
||
break
|
||
if ClassName and ClassName in Gen.class_members:
|
||
for m_name, m_type in Gen.class_members[ClassName]:
|
||
if m_name == len_name:
|
||
list_len = None
|
||
if isinstance(Node.value, ast.List):
|
||
list_len = ir.Constant(ir.IntType(64), len(Node.value.elts))
|
||
if list_len is not None:
|
||
SelfVar = Gen._get_var_ptr('self')
|
||
if SelfVar:
|
||
SelfPtr = Gen._load(SelfVar, name="self")
|
||
offset = Gen._get_member_offset(len_name, ClassName)
|
||
LenPtr = Gen.builder.gep(SelfPtr, [ir.Constant(ir.IntType(32), 0), ir.Constant(ir.IntType(32), offset)], name=len_name)
|
||
Gen._store(list_len, LenPtr)
|
||
break |