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, FuncMeta from lib.includes import t import ast import llvmlite.ir as ir class AssignHandle: def __init__(self, translator: "Translator"): self.Trans = translator self._CurrentCpythonObjectClass: str = None @staticmethod def _zero_value(var_type): if isinstance(var_type, ir.ArrayType): elem_zv = AssignHandle._zero_value(var_type.element) if elem_zv is None: return None return ir.Constant(var_type, [elem_zv] * var_type.count) elif isinstance(var_type, ir.IntType): return ir.Constant(var_type, 0) elif isinstance(var_type, (ir.FloatType, ir.DoubleType)): return ir.Constant(var_type, 0.0) elif isinstance(var_type, ir.PointerType): return ir.Constant(var_type, None) elif isinstance(var_type, ir.BaseStructType): if var_type.elements is not None and len(var_type.elements) > 0: elem_zvs = [AssignHandle._zero_value(m) for m in var_type.elements] if any(zv is None for zv in elem_zvs): return None return ir.Constant(var_type, elem_zvs) return None return None @staticmethod def _contains_identified_struct(var_type): if isinstance(var_type, ir.IdentifiedStructType): return True if isinstance(var_type, ir.ArrayType): return AssignHandle._contains_identified_struct(var_type.element) if isinstance(var_type, ir.PointerType): return AssignHandle._contains_identified_struct(var_type.pointee) if isinstance(var_type, ir.BaseStructType): if var_type.elements: return any(AssignHandle._contains_identified_struct(e) for e in var_type.elements) return False def HandleExprLlvm(self, Node, VarType=None): return self.Trans.ExprHandler.HandleExprLlvm(Node, VarType) def _HandleAssignLlvm(self, Node): Gen = self.Trans.LlvmGen Gen._set_node_info(Node, "Assign") if len(Node.targets) == 1: Target = Node.targets[0] if isinstance(Target, ast.Name): VarName = Target.id if VarName in Gen.var_const_flags: src_info = Gen._get_node_info() print(f"[错误] 不能对 const 变量 '{VarName}' 赋值{src_info}") import sys sys.exit(1) if isinstance(Node.value, ast.Attribute) and isinstance(Node.value.value, ast.Name) and Node.value.value.id == 't': AttrName = Node.value.attr Gen.var_type_info[VarName] = {'type': 't_type', 'name': AttrName} Gen.var_type_assignments.setdefault(VarName, []).append({'type': 't_type', 'name': AttrName}) from lib.includes.t import CTypeRegistry c_type_name = '' resolved = CTypeRegistry.ResolveName(AttrName) if resolved is not None: ctype_cls, ptr_level = resolved c_type_name = CTypeRegistry.CTypeToCName(ctype_cls) if ptr_level > 0 and c_type_name: c_type_name = c_type_name + ' *' if not c_type_name: if AttrName == 'CPtr': c_type_name = 'void *' is_unsigned = Gen._is_type_unsigned(c_type_name) if c_type_name else False fmt_str = "%u\n" if is_unsigned else "%d\n" fmt_bytes = fmt_str.encode('utf-8') + b'\x00' fmt_type = ir.ArrayType(ir.IntType(8), len(fmt_bytes)) fmt_const = ir.Constant(fmt_type, bytearray(fmt_bytes)) fmt_gvar = ir.GlobalVariable(Gen.module, fmt_type, name=f"str_const_{Gen.string_const_counter}") Gen.string_const_counter += 1 fmt_gvar.initializer = fmt_const fmt_gvar.linkage = 'internal' fmt_ptr = Gen.builder.bitcast(fmt_gvar, ir.PointerType(ir.IntType(8)), name=f"{VarName}_fmt") fmt_var_name = f"__{VarName}_fmt" if fmt_var_name not in Gen.variables: fmt_alloca = Gen._allocaEntry(ir.PointerType(ir.IntType(8)), name=fmt_var_name) Gen.variables[fmt_var_name] = fmt_alloca Gen.builder.store(fmt_ptr, Gen.variables[fmt_var_name]) kind_var_name = f"__{VarName}_kind" if kind_var_name not in Gen.variables: kind_alloca = Gen._allocaEntry(ir.IntType(32), name=kind_var_name) Gen.variables[kind_var_name] = kind_alloca Gen.builder.store(ir.Constant(ir.IntType(32), 0), Gen.variables[kind_var_name]) if VarName not in Gen.variables: dummy_var = Gen._alloca(ir.IntType(8), name=VarName) Gen.variables[VarName] = dummy_var return if isinstance(Node.value, ast.Name) and Node.value.id in Gen.structs: ClassName = Node.value.id Gen.var_type_info[VarName] = {'type': 'class_cast', 'name': ClassName} Gen.var_type_assignments.setdefault(VarName, []).append({'type': 'class_cast', 'name': ClassName}) fmt_str = "%p\n" fmt_bytes = fmt_str.encode('utf-8') + b'\x00' fmt_type = ir.ArrayType(ir.IntType(8), len(fmt_bytes)) fmt_const = ir.Constant(fmt_type, bytearray(fmt_bytes)) fmt_gvar = ir.GlobalVariable(Gen.module, fmt_type, name=f"str_const_{Gen.string_const_counter}") Gen.string_const_counter += 1 fmt_gvar.initializer = fmt_const fmt_gvar.linkage = 'internal' fmt_ptr = Gen.builder.bitcast(fmt_gvar, ir.PointerType(ir.IntType(8)), name=f"{VarName}_fmt") fmt_var_name = f"__{VarName}_fmt" if fmt_var_name not in Gen.variables: fmt_alloca = Gen._allocaEntry(ir.PointerType(ir.IntType(8)), name=fmt_var_name) Gen.variables[fmt_var_name] = fmt_alloca Gen.builder.store(fmt_ptr, Gen.variables[fmt_var_name]) kind_var_name = f"__{VarName}_kind" if kind_var_name not in Gen.variables: kind_alloca = Gen._allocaEntry(ir.IntType(32), name=kind_var_name) Gen.variables[kind_var_name] = kind_alloca Gen.builder.store(ir.Constant(ir.IntType(32), 1), Gen.variables[kind_var_name]) if VarName not in Gen.variables: dummy_var = Gen._alloca(ir.IntType(8), name=VarName) Gen.variables[VarName] = dummy_var return if isinstance(Node.value, ast.Call) and isinstance(Node.value.func, ast.Name) and Node.value.func.id == 'va_list': va_list_ptr = Gen._allocaEntry(ir.IntType(8).as_pointer(), name="va_list") Gen.variables[VarName] = va_list_ptr return IsStructCtor = (isinstance(Node.value, ast.Call) and isinstance(Node.value.func, ast.Name) and Node.value.func.id in Gen.structs) if IsStructCtor: ClassName = Node.value.func.id StructType = Gen.structs[ClassName] IsUnion = False if ClassName in self.Trans.SymbolTable: TypeInfo = self.Trans.SymbolTable[ClassName] if TypeInfo.IsUnion: IsUnion = True if IsUnion: Value = self.HandleExprLlvm(Node.value) if Value: var = Gen._allocaEntry(Value.type, name=VarName) Gen._store(Value, var) Gen.variables[VarName] = var return ExistingPtr = None if VarName in Gen.variables and Gen.variables[VarName] is not None: VarPtr = Gen.variables[VarName] if isinstance(VarPtr.type.pointee, ir.PointerType): ExistingPtr = VarPtr elif 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] ExistingPtr = var elif VarName in Gen._direct_values: OldVal = Gen._direct_values.pop(VarName) if isinstance(OldVal.type, ir.PointerType): var = Gen._allocaEntry(OldVal.type, name=VarName) Gen._store(OldVal, var) Gen.variables[VarName] = var ExistingPtr = var if ExistingPtr: pointee = ExistingPtr.type.pointee if isinstance(pointee, ir.PointerType) and pointee.pointee == StructType: self._InitStructAtPtr(Node.value, ClassName, ExistingPtr) return elif isinstance(pointee, ir.PointerType) and isinstance(pointee.pointee, ir.IntType) and pointee.pointee.width == 8: self._InitStructAtPtr(Node.value, ClassName, ExistingPtr) Gen.var_struct_class[VarName] = ClassName return if isinstance(Node.value, ast.Attribute): enum_type_name = self._CheckEnumMemberAssignment(Node.value) if enum_type_name: Gen.var_type_info[VarName] = {'type': 'enum', 'name': enum_type_name} var_type_for_list = None if isinstance(Node.value, ast.List) and VarName in Gen.var_type_info: type_info = Gen.var_type_info[VarName] if type_info.get('type') == 'list': var_type_for_list = type_info.get('full_type') Value = self.HandleExprLlvm(Node.value, VarType=var_type_for_list) if not Value: return if isinstance(Value.type, ir.VoidType): return Gen._UnregisterTempPtr(Value) if isinstance(Value.type, ir.PointerType) and isinstance(Value.type.pointee, (ir.LiteralStructType, ir.IdentifiedStructType)): found_class = None found = Gen.find_struct_by_pointee(Value.type.pointee) if found: CN, ST = found found_class = CN Gen.var_struct_class[VarName] = CN Gen._var_to_heap_ptr[VarName] = Value if found_class is None and isinstance(Value.type.pointee, ir.IdentifiedStructType): pointee_name = Value.type.pointee.name for CN, ST in Gen.structs.items(): if isinstance(ST, ir.IdentifiedStructType) and ST.name == pointee_name: found_class = CN Gen.var_struct_class[VarName] = CN Gen._var_to_heap_ptr[VarName] = Value break else: if VarName in ('mctx', 's1ctx', 's2ctx', 's5ctx'): pass if isinstance(Value.type, ir.PointerType) and isinstance(Value.type.pointee, (ir.LiteralStructType, ir.IdentifiedStructType)): if VarName in Gen.variables and Gen.variables[VarName] is not None: Gen._store(Value, Gen.variables[VarName]) else: var = Gen._allocaEntry(Value.type, name=VarName) Gen._store(Value, var) Gen.variables[VarName] = var if isinstance(Node.value, ast.Call) and isinstance(Node.value.func, ast.Name): call_func_name = Node.value.func.id if call_func_name in Gen.var_type_info: type_info = Gen.var_type_info[call_func_name] if type_info['type'] in ('t_type', 'class_cast'): src_fmt_var = f"__{call_func_name}_fmt" dst_fmt_var = f"__{VarName}_fmt" if src_fmt_var in Gen.variables: if dst_fmt_var not in Gen.variables: dst_alloca = Gen._allocaEntry(ir.PointerType(ir.IntType(8)), name=dst_fmt_var) Gen.variables[dst_fmt_var] = dst_alloca src_fmt_ptr = Gen._load(Gen.variables[src_fmt_var], name=f"Load_{call_func_name}_fmt_for_{VarName}") Gen.builder.store(src_fmt_ptr, Gen.variables[dst_fmt_var]) src_kind_var = f"__{call_func_name}_kind" dst_kind_var = f"__{VarName}_kind" if src_kind_var in Gen.variables: if dst_kind_var not in Gen.variables: dst_kind_alloca = Gen._allocaEntry(ir.IntType(32), name=dst_kind_var) Gen.variables[dst_kind_var] = dst_kind_alloca src_kind_val = Gen._load(Gen.variables[src_kind_var], name=f"Load_{call_func_name}_kind_for_{VarName}") Gen.builder.store(src_kind_val, Gen.variables[dst_kind_var]) Gen.var_type_info[VarName] = {'type': 't_type_runtime', 'source': call_func_name} return if VarName in Gen.global_vars: if VarName in Gen.module.globals: GVar = Gen.module.globals[VarName] Gen._store(Value, GVar) Gen.variables[VarName] = GVar if isinstance(Value.type, ir.PointerType) and isinstance(Value.type.pointee, (ir.LiteralStructType, ir.IdentifiedStructType)): found = Gen.find_struct_by_pointee(Value.type.pointee) if found: CN, ST = found Gen.var_struct_class[VarName] = CN elif VarName in Gen.variables and Gen.variables[VarName] is not None: Gen._store(Value, Gen.variables[VarName]) return if VarName in Gen._reg_values: OldVal = Gen._reg_values[VarName] var = Gen._allocaEntry(OldVal.type, name=VarName) Gen._store(OldVal, var) Gen.variables[VarName] = var del Gen._reg_values[VarName] if VarName in Gen._direct_values: OldVal = Gen._direct_values.pop(VarName) var = Gen._allocaEntry(OldVal.type, name=VarName) Gen._store(OldVal, var) Gen.variables[VarName] = var if VarName in Gen.variables and Gen.variables[VarName] is not None: VarPtr = Gen.variables[VarName] TargetType = VarPtr.type.pointee if isinstance(VarPtr.type, ir.PointerType) else None try: types_differ = TargetType and Value.type != TargetType except AssertionError: types_differ = False if isinstance(Value.type, ir.PointerType) and isinstance(Value.type.pointee, ir.PointerType): LoadedValue = Gen._load(Value, name=f"Load_{VarName}") try: Loaded_differ = TargetType and LoadedValue.type != TargetType except AssertionError: Loaded_differ = False if Loaded_differ: try: Coerced = Gen._coerce_value(LoadedValue, TargetType) if Coerced is not None: LoadedValue = Coerced except AssertionError: pass Gen._store(LoadedValue, VarPtr) elif types_differ: try: Coerced = Gen._coerce_value(Value, TargetType) if Coerced is not None: Gen._store(Coerced, VarPtr) else: Gen._store(Value, VarPtr) except AssertionError: Gen._store(Value, VarPtr) else: Gen._store(Value, VarPtr) if VarName not in Gen.variables: # 检查是否为模块级全局变量,避免创建局部变量遮蔽全局 if VarName in Gen.module.globals: GVar = Gen.module.globals[VarName] Gen._store(Value, GVar) Gen.variables[VarName] = GVar elif isinstance(Value.type, ir.PointerType) and isinstance(Value.type.pointee, ir.PointerType): LoadedValue = Gen._load(Value, name=f"Load_{VarName}") var = Gen._allocaEntry(LoadedValue.type, name=VarName) Gen._store(LoadedValue, var) Gen.variables[VarName] = var else: var = Gen._allocaEntry(Value.type, name=VarName) Gen._store(Value, var) Gen.variables[VarName] = var is_u = Gen._check_node_unsigned(Node.value) Gen._record_var_signedness(VarName, 'unsigned int' if is_u else 'int') if isinstance(Node.value, ast.Call) and isinstance(Node.value.func, ast.Name): call_func_name = Node.value.func.id if call_func_name in Gen.var_type_info: type_info = Gen.var_type_info[call_func_name] if type_info['type'] in ('t_type', 'class_cast'): src_fmt_var = f"__{call_func_name}_fmt" dst_fmt_var = f"__{VarName}_fmt" if src_fmt_var in Gen.variables: if dst_fmt_var not in Gen.variables: dst_alloca = Gen._allocaEntry(ir.PointerType(ir.IntType(8)), name=dst_fmt_var) Gen.variables[dst_fmt_var] = dst_alloca src_fmt_ptr = Gen._load(Gen.variables[src_fmt_var], name=f"Load_{call_func_name}_fmt_for_{VarName}") Gen.builder.store(src_fmt_ptr, Gen.variables[dst_fmt_var]) src_kind_var = f"__{call_func_name}_kind" dst_kind_var = f"__{VarName}_kind" if src_kind_var in Gen.variables: if dst_kind_var not in Gen.variables: dst_kind_alloca = Gen._allocaEntry(ir.IntType(32), name=dst_kind_var) Gen.variables[dst_kind_var] = dst_kind_alloca src_kind_val = Gen._load(Gen.variables[src_kind_var], name=f"Load_{call_func_name}_kind_for_{VarName}") Gen.builder.store(src_kind_val, Gen.variables[dst_kind_var]) Gen.var_type_info[VarName] = {'type': 't_type_runtime', 'source': call_func_name} else: Gen.var_type_info[VarName] = {'type': 't_type_runtime', 'source': call_func_name} elif isinstance(Target, ast.Attribute): TargetType = None AttrName = Target.attr VarName = None if isinstance(Target.value, ast.Name): VarName = Target.value.id if VarName: ClassName = Gen.var_struct_class.get(VarName) if not ClassName and getattr(Gen, 'global_struct_class', None): ClassName = Gen.global_struct_class.get(VarName) if ClassName: Gen.var_struct_class[VarName] = ClassName if not ClassName: for CN in Gen.structs: if VarName == CN.lower() or VarName.startswith(CN): ClassName = CN break if ClassName and ClassName in Gen.class_members: for m_name, m_type in Gen.class_members[ClassName]: if m_name == AttrName: TargetType = m_type break Value = self.HandleExprLlvm(Node.value, VarType=TargetType) if Value: self._HandleAttributeStoreLlvm(Target, Value) elif isinstance(Target, ast.Subscript): TargetType = None SubVarName = None if isinstance(Target.value, ast.Name): SubVarName = Target.value.id if SubVarName in Gen.var_struct_class: ClassName = Gen.var_struct_class[SubVarName] if ClassName in Gen.class_members: for m_name, m_type in Gen.class_members[ClassName]: if m_name == SubVarName: if isinstance(m_type, ir.PointerType): pointee = m_type.pointee if isinstance(pointee, ir.ArrayType): TargetType = pointee.element elif isinstance(m_type, ir.ArrayType): TargetType = m_type.element break if not TargetType and isinstance(Target.value, ast.Name): SubVarName = Target.value.id var_val = Gen.variables.get(SubVarName) if var_val is None and SubVarName in Gen._direct_values: var_val = Gen._direct_values[SubVarName] if var_val is not None: var_type = var_val.type if isinstance(var_type, ir.PointerType): pointee = var_type.pointee if isinstance(pointee, ir.ArrayType): TargetType = pointee.element elif isinstance(var_type, ir.ArrayType): TargetType = var_type.element Value = self.HandleExprLlvm(Node.value, VarType=TargetType) if Value: self._HandleSubscriptStoreLlvm(Target, Value) elif isinstance(Target, ast.Tuple): if isinstance(Node.value, ast.Call): FuncName = None ModulePath = None if isinstance(Node.value.func, ast.Name): FuncName = Node.value.func.id elif isinstance(Node.value.func, ast.Attribute): FuncName = Node.value.func.attr ModulePath = self.Trans.ExprCallHandle._get_ModulePath(Node.value.func.value) CReturnTypes = [] FuncDef = self.Trans.FunctionDefCache.get(FuncName) if FuncName else None if FuncDef: if FuncDef.returns and isinstance(FuncDef.returns, ast.Subscript): if isinstance(FuncDef.returns.value, ast.Name) and FuncDef.returns.value.id == 'tuple': slice_node = FuncDef.returns.slice if isinstance(slice_node, ast.Tuple): CReturnTypes = slice_node.elts else: CReturnTypes = [slice_node] if FuncDef.decorator_list: for decorator in FuncDef.decorator_list: if isinstance(decorator, ast.Call) and isinstance(decorator.func, ast.Attribute): if decorator.func.attr == 'CReturn': for arg in decorator.args: CReturnTypes.append(arg) if not CReturnTypes and FuncName: func = Gen.functions.get(FuncName) if func: func_ft = getattr(func, 'ftype', None) if func_ft: ret_type = func_ft.return_type if isinstance(ret_type, ir.LiteralStructType): CReturnTypes = [None] * len(ret_type.elements) if not CReturnTypes: sym_key = FuncName if sym_key not in self.Trans.SymbolTable: if ModulePath: sym_key = f"{ModulePath}.{FuncName}" sym_info = self.Trans.SymbolTable.get(sym_key) if sym_info and sym_info.IsFunction: ret_type_info = getattr(sym_info, 'FuncPtrReturn', None) param_type_infos = [pt for _, pt in getattr(sym_info, 'FuncPtrParams', [])] if ret_type_info: if isinstance(ret_type_info, CTypeInfo) and ret_type_info.BaseType: ret_type = ret_type_info.ToLLVM(Gen) else: ret_type = Gen._type_str_to_llvm(str(ret_type_info) if ret_type_info else 'i32', False) if isinstance(ret_type, ir.LiteralStructType): CReturnTypes = [None] * len(ret_type.elements) if FuncName not in Gen.functions: if isinstance(ret_type, ir.VoidType): ret_type = ir.IntType(32) llvm_param_types = [] for pt in param_type_infos: if isinstance(pt, CTypeInfo) and pt.BaseType: lp = pt.ToLLVM(Gen) else: lp = Gen._type_str_to_llvm(str(pt) if pt else 'i32', '*' in str(pt) if isinstance(pt, str) else False) if isinstance(lp, ir.VoidType): lp = ir.IntType(8).as_pointer() llvm_param_types.append(lp) func_type = ir.FunctionType(ret_type, llvm_param_types) MangledName = Gen._mangle_func_name(FuncName) func_decl = ir.Function(Gen.module, func_type, name=MangledName) Gen.functions[MangledName] = func_decl Gen.functions[FuncName] = func_decl if not CReturnTypes and FuncName: func = Gen.functions.get(FuncName) if func: func_ft = getattr(func, 'ftype', None) if func_ft: ret_type = func_ft.return_type if isinstance(ret_type, ir.LiteralStructType): CReturnTypes = [None] * len(ret_type.elements) if CReturnTypes and len(Target.elts) == len(CReturnTypes): CallArgs = [] for arg in Node.value.args: ArgVal = self.HandleExprLlvm(arg) if ArgVal: CallArgs.append(ArgVal) for kw in Node.value.keywords: pass func = Gen.functions.get(FuncName) func_ft = getattr(func, 'ftype', None) if func else None func_params = list(getattr(func_ft, 'args', []) or []) if func_ft else [] while len(CallArgs) < len(func_params): FuncDef = self.Trans.FunctionDefCache.get(FuncName) if FuncDef and len(CallArgs) < len(FuncDef.args.args): arg_def = FuncDef.args.defaults arg_idx = len(CallArgs) total_args = len(FuncDef.args.args) default_start = total_args - len(arg_def) if arg_idx >= default_start: def_idx = arg_idx - default_start if def_idx < len(arg_def): DefVal = self.HandleExprLlvm(arg_def[def_idx]) if DefVal: expected_type = func_params[arg_idx] if DefVal.type != expected_type: if isinstance(expected_type, ir.IntType) and isinstance(DefVal.type, ir.IntType): if DefVal.type.width < expected_type.width: DefVal = Gen.builder.zext(DefVal, expected_type, name=f"zext_default_{arg_idx}") elif DefVal.type.width > expected_type.width: DefVal = Gen.builder.trunc(DefVal, expected_type, name=f"trunc_default_{arg_idx}") CallArgs.append(DefVal) continue if len(CallArgs) < len(func_params): CallArgs.append(ir.Constant(func_params[len(CallArgs)], 0)) else: break adjusted = Gen._adjust_args(CallArgs, func) call_result = Gen.builder.call(func, adjusted, name=f"call_{FuncName}") func_ft = getattr(func, 'ftype', None) ret_type = getattr(func_ft, 'return_type', None) if func_ft else None for j, elt in enumerate(Target.elts): if isinstance(elt, ast.Name): VarName = elt.id field_val = Gen.builder.extract_value(call_result, j, name=f"extract_{FuncName}_{j}") if CReturnTypes[j] is not None: ReturnTypeInfo = CTypeInfo.FromNode(CReturnTypes[j], self.Trans.SymbolTable) if ReturnTypeInfo is None: ReturnTypeInfo = CTypeInfo() ReturnTypeInfo.BaseType = t.CInt() VarType = Gen._ctype_to_llvm(ReturnTypeInfo) elif ret_type and isinstance(ret_type, ir.LiteralStructType) and j < len(ret_type.elements): VarType = ret_type.elements[j] else: VarType = field_val.type if isinstance(VarType, ir.VoidType): VarType = ir.IntType(32) var = Gen._alloca(VarType, name=VarName) Gen.variables[VarName] = var if CReturnTypes[j] is not None: Gen._record_var_signedness(VarName, ReturnTypeStr) elif ret_type and isinstance(ret_type, ir.LiteralStructType) and j < len(ret_type.elements): elem_type = ret_type.elements[j] if isinstance(elem_type, ir.IntType): if elem_type.width == 16: Gen._record_var_signedness(VarName, 'unsigned short') elif elem_type.width == 32: Gen._record_var_signedness(VarName, 'unsigned int') elif elem_type.width == 64: Gen._record_var_signedness(VarName, 'unsigned long long') Gen._store(field_val, var) return def _InitStructAtPtr(self, call_node, ClassName, VarPtr): Gen = self.Trans.LlvmGen if ClassName not in Gen.structs: return StructType = Gen.structs[ClassName] StructPtrType = ir.PointerType(StructType) RawPtr = Gen._load(VarPtr, name=getattr(VarPtr, 'name', 'ptr')) StructPtr = Gen.builder.bitcast(RawPtr, StructPtrType, name=ClassName) members = Gen.class_members.get(ClassName, []) defaults = Gen.class_member_defaults.get(ClassName, {}) member_values = {} for member_name, member_type in members: if member_name in defaults: member_values[member_name] = defaults[member_name] if call_node.args: for i, arg in enumerate(call_node.args): if i < len(members): member_name, _ = members[i] val = self.HandleExprLlvm(arg) if val: member_values[member_name] = val if call_node.keywords: for kw in call_node.keywords: val = self.HandleExprLlvm(kw.value) if val: member_values[kw.arg] = val has_vtable = ClassName in Gen.class_vtable base = 1 if has_vtable else 0 for i, (member_name, member_type) in enumerate(members): if isinstance(member_type, ir.VoidType): continue if member_name in member_values: ElemPtr = Gen.builder.gep(StructPtr, [ir.Constant(ir.IntType(32), 0), ir.Constant(ir.IntType(32), base + i)], name=f"{ClassName}_{member_name}") try: Gen._store(member_values[member_name], ElemPtr) except Exception as _e: if __import__('lib.constants.config', fromlist=['mode']).mode == "strict": self.Trans.LogWarning(f"异常被忽略: {_e}") InitFuncName = f'{ClassName}.__init__' if Gen._has_function(InitFuncName): Args = [self.HandleExprLlvm(arg) for arg in call_node.args] Args = [a for a in Args if a] Gen.builder.call(Gen._get_function(InitFuncName), [StructPtr] + Args, name=f"call_{InitFuncName}") def _StoreOrStrCopy(self, VarName, VarPtr, Value): Gen = self.Trans.LlvmGen DestPtr = Gen._load(VarPtr, name=VarName) if BaseHandle._is_char_pointer(DestPtr): if BaseHandle._is_char_pointer(Value): if 'strcpy' not in Gen.functions: strcpy_type = ir.FunctionType(ir.PointerType(ir.IntType(8)), [ir.PointerType(ir.IntType(8)), ir.PointerType(ir.IntType(8))]) Gen.functions['strcpy'] = ir.Function(Gen.module, strcpy_type, name='strcpy') Gen.builder.call(Gen.functions['strcpy'], [DestPtr, Value]) 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.Trans._CurrentCpythonObjectClass if ClassName and ClassName in Gen.structs: PropKey = f'{ClassName}.{AttrName}' PropInfo = self.Trans.SymbolTable.get(PropKey) if PropInfo and hasattr(PropInfo, 'MetaList') and FuncMeta.PROPERTY_SETTER in PropInfo.MetaList: SelfVar = Gen._get_var_ptr('self') if SelfVar: SelfPtr = Gen._load(SelfVar, name="self") SetterFunc = Gen._get_function(PropKey + '$set') if SetterFunc and SelfPtr: Gen.builder.call(SetterFunc, [SelfPtr, Value], name=f"prop_set_{PropKey}") return SelfVar = Gen._get_var_ptr('self') if not SelfVar: return if SelfVar: SelfPtr = Gen._load(SelfVar, name="self") is_vtable_method = False if ClassName in Gen.class_vtable or ClassName in Gen._cross_module_vtable_classes: if ClassName in Gen.class_methods: for mi, mn in enumerate(Gen.class_methods[ClassName]): method_short = mn.split('.')[-1] if '.' in mn else mn if method_short == AttrName or mn == AttrName: is_vtable_method = True method_idx = mi break if is_vtable_method: VtableSlotPtr = Gen.builder.gep(SelfPtr, [ir.Constant(ir.IntType(32), 0), ir.Constant(ir.IntType(32), 0)], name=f"vtable_slot_{ClassName}") VtablePtr = Gen._load(VtableSlotPtr, name=f"vtable_ptr_{ClassName}") methods = Gen.class_methods[ClassName] VtableArrayType = ir.ArrayType(ir.PointerType(ir.IntType(8)), len(methods)) ClassVtable = Gen.Vtables.get(ClassName) if ClassVtable: ClassVtableAddr = Gen.builder.bitcast(ClassVtable, ir.PointerType(ir.IntType(8)), name=f"class_vtable_addr_{ClassName}") IsSameVtable = Gen.builder.icmp_unsigned('==', VtablePtr, ClassVtableAddr, name=f"is_same_vtable_{ClassName}") CopyBlock = Gen.func.append_basic_block(name=f"vtable_copy_self_{AttrName}") SkipBlock = Gen.func.append_basic_block(name=f"vtable_skip_self_{AttrName}") Gen.builder.cbranch(IsSameVtable, CopyBlock, SkipBlock) Gen.builder.position_at_end(CopyBlock) if not hasattr(Gen, '_vtable_copy_counter'): Gen._vtable_copy_counter = 0 Gen._vtable_copy_counter += 1 CopyName = f"{Gen._mangle_name(ClassName)}_vtable_copy_self_{Gen._vtable_copy_counter}" VtableCopyGlobal = ir.GlobalVariable(Gen.module, VtableArrayType, name=CopyName) VtableCopyGlobal.linkage = 'internal' VtableCopyGlobal.initializer = ir.Constant(VtableArrayType, [ir.Constant(ir.PointerType(ir.IntType(8)), None)] * len(methods)) VtableCopyTyped = Gen.builder.bitcast(VtableCopyGlobal, ir.PointerType(ir.IntType(8)), name=f"vtable_copy_typed") SrcTyped = Gen.builder.bitcast(ClassVtable, ir.PointerType(ir.IntType(8)), name=f"src_vtable_typed") VtableSize = len(methods) * Gen.ptr_size MemcpyFunc = Gen._find_function('llvm.memcpy.p0i8.p0i8.i64') if not MemcpyFunc: MemcpyType = ir.FunctionType(ir.VoidType(), [ir.PointerType(ir.IntType(8)), ir.PointerType(ir.IntType(8)), ir.IntType(64), ir.IntType(1)]) MemcpyFunc = ir.Function(Gen.module, MemcpyType, name='llvm.memcpy.p0i8.p0i8.i64') Gen.functions['llvm.memcpy.p0i8.p0i8.i64'] = MemcpyFunc Gen.builder.call(MemcpyFunc, [VtableCopyTyped, SrcTyped, ir.Constant(ir.IntType(64), VtableSize), ir.Constant(ir.IntType(1), 0)]) VtableCopyGlobalAddr = Gen.builder.bitcast(VtableCopyGlobal, ir.PointerType(ir.IntType(8)), name=f"vtable_copy_addr") Gen._store(VtableCopyGlobalAddr, VtableSlotPtr) Gen.builder.branch(SkipBlock) Gen.builder.position_at_end(SkipBlock) VtablePtr = Gen._load(VtableSlotPtr, name=f"vtable_ptr_{ClassName}_after_copy") VtableTyped = Gen.builder.bitcast(VtablePtr, ir.PointerType(VtableArrayType), name=f"vtable_typed_{ClassName}") MethodPtrAddr = Gen.builder.gep(VtableTyped, [ir.Constant(ir.IntType(32), 0), ir.Constant(ir.IntType(32), method_idx)], name=f"vmethod_slot_{AttrName}") FuncPtrI8 = Gen.builder.bitcast(Value, ir.PointerType(ir.IntType(8)), name=f"func_ptr_i8_{AttrName}") Gen._store(FuncPtrI8, MethodPtrAddr) return offset = Gen._get_member_offset(AttrName, ClassName) struct_type = Gen.structs[ClassName] max_offset = len(struct_type.elements) if isinstance(struct_type, ir.IdentifiedStructType) else 0 if offset >= max_offset: VarName = f"self.{AttrName}" if VarName not in Gen.variables: NewVar = Gen._allocaEntry(Value.type, name=AttrName) Gen.variables[VarName] = NewVar Gen._store(Value, Gen.variables[VarName]) return 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 and getattr(Gen, 'global_struct_class', None): ClassName = Gen.global_struct_class.get(VarName) if ClassName: Gen.var_struct_class[VarName] = ClassName 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.module.globals: GVar = Gen.module.globals[VarName] if isinstance(GVar.type, ir.PointerType) and isinstance(GVar.type.pointee, (ir.IdentifiedStructType, ir.LiteralStructType)): found = Gen.find_struct_by_pointee(GVar.type.pointee) if found: ClassName = found[0] Gen.var_struct_class[VarName] = ClassName if getattr(Gen, 'global_struct_class', None): Gen.global_struct_class[VarName] = ClassName 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 found = Gen.find_struct_by_pointee(pointee) if found: CN, ST = found ClassName = CN IsUnion = False if ClassName and ClassName in self.Trans.SymbolTable: TypeInfo = self.Trans.SymbolTable[ClassName] if TypeInfo.IsUnion: IsUnion = True if ClassName and ClassName in Gen.structs: PropKey = f'{ClassName}.{AttrName}' PropInfo = self.Trans.SymbolTable.get(PropKey) if PropInfo and hasattr(PropInfo, 'MetaList') and FuncMeta.PROPERTY_SETTER in PropInfo.MetaList: ObjVal = self.Trans.ExprHandler.HandleExprLlvm(Target.value) SetterFunc = Gen._get_function(PropKey + '$set') if SetterFunc and ObjVal: if isinstance(ObjVal.type, ir.PointerType) and isinstance(ObjVal.type.pointee, ir.PointerType): ObjVal = Gen._load(ObjVal, name=f"Load_{ClassName}") Gen.builder.call(SetterFunc, [ObjVal, Value], name=f"prop_set_{PropKey}") return ObjVal = self.Trans.ExprHandler.HandleExprLlvm(Target.value) if ObjVal: if BaseHandle._is_char_pointer(ObjVal): 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 bitfield_offsets = Gen.class_member_bitoffsets.get(ClassName, {}) if AttrName in bitfield_offsets: self._store_bitfield_member(ObjVal, ClassName, AttrName, Value) return bitfields = Gen.class_member_bitfields.get(ClassName, {}) if AttrName in bitfields and bitfields[AttrName] > 0: if ClassName not in Gen.class_member_bitoffsets: Gen.class_member_bitoffsets[ClassName] = {} if AttrName not in Gen.class_member_bitoffsets[ClassName]: bo = 0 for bf_name, bf_width in bitfields.items(): if bf_name == AttrName: break bo += bf_width Gen.class_member_bitoffsets[ClassName][AttrName] = bo self._store_bitfield_member(ObjVal, ClassName, AttrName, Value) return is_vtable_method = False if ClassName in Gen.class_vtable or ClassName in Gen._cross_module_vtable_classes: if ClassName in Gen.class_methods: for mi, mn in enumerate(Gen.class_methods[ClassName]): method_short = mn.split('.')[-1] if '.' in mn else mn if method_short == AttrName or mn == AttrName: is_vtable_method = True method_idx = mi break if is_vtable_method: VtableSlotPtr = Gen.builder.gep(ObjVal, [ir.Constant(ir.IntType(32), 0), ir.Constant(ir.IntType(32), 0)], name=f"vtable_slot_{ClassName}") VtablePtr = Gen._load(VtableSlotPtr, name=f"vtable_ptr_{ClassName}") methods = Gen.class_methods[ClassName] VtableArrayType = ir.ArrayType(ir.PointerType(ir.IntType(8)), len(methods)) ClassVtable = Gen.Vtables.get(ClassName) if ClassVtable: ClassVtableAddr = Gen.builder.bitcast(ClassVtable, ir.PointerType(ir.IntType(8)), name=f"class_vtable_addr_{ClassName}") IsSameVtable = Gen.builder.icmp_unsigned('==', VtablePtr, ClassVtableAddr, name=f"is_same_vtable_{ClassName}") CopyBlock = Gen.func.append_basic_block(name=f"vtable_copy_{AttrName}") SkipBlock = Gen.func.append_basic_block(name=f"vtable_skip_{AttrName}") Gen.builder.cbranch(IsSameVtable, CopyBlock, SkipBlock) Gen.builder.position_at_end(CopyBlock) if not hasattr(Gen, '_vtable_copy_counter'): Gen._vtable_copy_counter = 0 Gen._vtable_copy_counter += 1 CopyName = f"{Gen._mangle_name(ClassName)}_vtable_copy_{Gen._vtable_copy_counter}" VtableCopyGlobal = ir.GlobalVariable(Gen.module, VtableArrayType, name=CopyName) VtableCopyGlobal.linkage = 'internal' VtableCopyGlobal.initializer = ir.Constant(VtableArrayType, [ir.Constant(ir.PointerType(ir.IntType(8)), None)] * len(methods)) VtableCopyTyped = Gen.builder.bitcast(VtableCopyGlobal, ir.PointerType(ir.IntType(8)), name=f"vtable_copy_typed") SrcTyped = Gen.builder.bitcast(ClassVtable, ir.PointerType(ir.IntType(8)), name=f"src_vtable_typed") VtableSize = len(methods) * Gen.ptr_size MemcpyFunc = Gen._find_function('llvm.memcpy.p0i8.p0i8.i64') if not MemcpyFunc: MemcpyType = ir.FunctionType(ir.VoidType(), [ir.PointerType(ir.IntType(8)), ir.PointerType(ir.IntType(8)), ir.IntType(64), ir.IntType(1)]) MemcpyFunc = ir.Function(Gen.module, MemcpyType, name='llvm.memcpy.p0i8.p0i8.i64') Gen.functions['llvm.memcpy.p0i8.p0i8.i64'] = MemcpyFunc Gen.builder.call(MemcpyFunc, [VtableCopyTyped, SrcTyped, ir.Constant(ir.IntType(64), VtableSize), ir.Constant(ir.IntType(1), 0)]) VtableCopyGlobalAddr = Gen.builder.bitcast(VtableCopyGlobal, ir.PointerType(ir.IntType(8)), name=f"vtable_copy_addr") Gen._store(VtableCopyGlobalAddr, VtableSlotPtr) Gen.builder.branch(SkipBlock) Gen.builder.position_at_end(SkipBlock) VtablePtr = Gen._load(VtableSlotPtr, name=f"vtable_ptr_{ClassName}_after_copy") VtableTyped = Gen.builder.bitcast(VtablePtr, ir.PointerType(VtableArrayType), name=f"vtable_typed_{ClassName}") MethodPtrAddr = Gen.builder.gep(VtableTyped, [ir.Constant(ir.IntType(32), 0), ir.Constant(ir.IntType(32), method_idx)], name=f"vmethod_slot_{AttrName}") FuncPtrI8 = Gen.builder.bitcast(Value, ir.PointerType(ir.IntType(8)), name=f"func_ptr_i8_{AttrName}") Gen._store(FuncPtrI8, MethodPtrAddr) return offset = Gen._get_member_offset(AttrName, ClassName) StructType = Gen.structs.get(ClassName) if isinstance(StructType, ir.IdentifiedStructType) and (StructType.elements is None or len(StructType.elements) == 0): self.Trans.ImportHandler._TryLoadStructFromStub(ClassName, Gen) StructType = Gen.structs.get(ClassName) if isinstance(StructType, ir.IdentifiedStructType) and (StructType.elements is None or len(StructType.elements) == 0): return if StructType is not None and StructType.elements is not None and isinstance(ObjVal.type, ir.PointerType) and isinstance(ObjVal.type.pointee, ir.IdentifiedStructType) and ObjVal.type.pointee.elements is None: ObjVal = Gen.builder.bitcast(ObjVal, ir.PointerType(StructType), name=f"cast_{ClassName}") if offset is not None and StructType is not None and StructType.elements is not None and offset < len(StructType.elements): MemberPtr = Gen.builder.gep(ObjVal, [ir.Constant(ir.IntType(32), 0), ir.Constant(ir.IntType(32), offset)], name=AttrName) else: return byte_order = getattr(Gen, 'class_member_byteorders', {}).get(ClassName, {}).get(AttrName, "") if byte_order == 'big': st = Gen.structs.get(ClassName) if st is None or st.elements is None or len(st.elements) == 0: return member_type = st.elements[offset] if isinstance(member_type, ir.IntType): if member_type.width == 16: Value = Gen.builder.bswap(Value, name=f"bswap_store_{AttrName}") elif member_type.width == 32: Value = Gen.builder.bswap(Value, name=f"bswap_store_{AttrName}") elif member_type.width == 64: Value = Gen.builder.bswap(Value, name=f"bswap_store_{AttrName}") self._StoreWithCoerce(Value, MemberPtr) if not ClassName: imported_modules = getattr(self.Trans, '_ImportedModules', None) import_aliases = getattr(self.Trans, '_ImportAliases', {}) resolved_mod = import_aliases.get(VarName, VarName) if imported_modules and (VarName in imported_modules or resolved_mod in imported_modules): PossibleKeys = [f"{VarName}.{AttrName}", AttrName] for mod_name in imported_modules: if mod_name.endswith(f".{VarName}") or mod_name == VarName: key = f"{mod_name}.{AttrName}" if key not in PossibleKeys: PossibleKeys.append(key) for key in PossibleKeys: if key in Gen.module.globals: GVar = Gen.module.globals[key] if isinstance(GVar, ir.Function): return if isinstance(GVar.type, ir.PointerType) and isinstance(GVar.type.pointee, (ir.IdentifiedStructType, ir.LiteralStructType, ir.ArrayType)): return self._StoreWithCoerce(Value, GVar) return ModuleSha1Map = getattr(Gen, 'ModuleSha1Map', {}) sha1_candidates = [VarName, resolved_mod] for mod_name in imported_modules: if mod_name.endswith(f".{VarName}") or mod_name == VarName: if mod_name not in sha1_candidates: sha1_candidates.append(mod_name) for cand in sha1_candidates: sha1 = ModuleSha1Map.get(cand) if sha1: prefixed = f"{sha1}.{AttrName}" if prefixed in Gen.module.globals: GVar2 = Gen.module.globals[prefixed] if isinstance(GVar2, ir.Function): return if isinstance(GVar2.type, ir.PointerType) and isinstance(GVar2.type.pointee, (ir.IdentifiedStructType, ir.LiteralStructType, ir.ArrayType)): return self._StoreWithCoerce(Value, GVar2) return 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)): if isinstance(pointee, ir.IdentifiedStructType) and pointee.elements is None: for CN, ST in Gen.structs.items(): if isinstance(ST, ir.IdentifiedStructType) and ST.name == pointee.name and ST.elements is not None: pointee = ST ObjVal = Gen.builder.bitcast(ObjVal, ir.PointerType(ST), name=f"cast_{CN}") break found_match = False for CN, ST in Gen.structs.items(): if pointee == ST or (isinstance(pointee, ir.IdentifiedStructType) and isinstance(ST, ir.IdentifiedStructType) and pointee.name == ST.name): found_match = True if ST.elements is None: self.Trans.ImportHandler._TryLoadStructFromStub(CN, Gen) ST = Gen.structs.get(CN, ST) if ST.elements is not None and isinstance(ObjVal.type, ir.PointerType) and isinstance(ObjVal.type.pointee, ir.IdentifiedStructType) and ObjVal.type.pointee.elements is None: ObjVal = Gen.builder.bitcast(ObjVal, ir.PointerType(ST), name=f"cast_{CN}") bitfield_offsets = Gen.class_member_bitoffsets.get(CN, {}) if AttrName in bitfield_offsets: self._store_bitfield_member(ObjVal, CN, AttrName, Value) return offset = Gen._get_member_offset(AttrName, CN) if offset is not None and ST.elements is not None and offset < len(ST.elements): MemberPtr = Gen.builder.gep(ObjVal, [ir.Constant(ir.IntType(32), 0), ir.Constant(ir.IntType(32), offset)], name=AttrName) self._StoreWithCoerce(Value, MemberPtr) break if not found_match: if isinstance(pointee, ir.IdentifiedStructType): matched_cn = None for CN in Gen.class_members: members = Gen.class_members[CN] for mname, mtype in members: if mname == AttrName: matched_cn = CN break if matched_cn: break if matched_cn and matched_cn in Gen.structs: ST = Gen.structs[matched_cn] if isinstance(ST, ir.IdentifiedStructType) and (ST.elements is None or len(ST.elements) == 0): self.Trans.ImportHandler._TryLoadStructFromStub(matched_cn, Gen) ST = Gen.structs.get(matched_cn, ST) if ST.elements is not None and isinstance(ObjVal.type, ir.PointerType) and isinstance(ObjVal.type.pointee, ir.IdentifiedStructType) and ObjVal.type.pointee.elements is None: ObjVal = Gen.builder.bitcast(ObjVal, ir.PointerType(ST), name=f"cast_{matched_cn}") offset = Gen._get_member_offset(AttrName, matched_cn) if offset is not None and ST.elements is not None and offset < len(ST.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 elif isinstance(Target.value, ast.Call): # Check if this is c.Deref(...) — we need the pointer, not the Loaded value ObjVal = None is_cderef = (isinstance(Target.value.func, ast.Attribute) and isinstance(Target.value.func.value, ast.Name) and Target.value.func.value.id == 'c' and Target.value.func.attr == 'Deref' and Target.value.args) if is_cderef: # Get the pointer from c.Deref argument, don't Load the value deref_arg = Target.value.args[0] inner_val = self.HandleExprLlvm(deref_arg) if inner_val and isinstance(inner_val.type, ir.PointerType): if isinstance(inner_val.type.pointee, ir.PointerType): ObjVal = Gen._load(inner_val, name="deref_load_ptr") else: ObjVal = inner_val if ObjVal is None: ObjVal = self.Trans.ExprHandler.HandleExprLlvm(Target.value) if ObjVal and isinstance(ObjVal.type, ir.PointerType): pointee = ObjVal.type.pointee if isinstance(pointee, ir.PointerType): ObjVal = Gen._load(ObjVal, name="load_ptr_for_attr") pointee = ObjVal.type.pointee for CN, ST in Gen.structs.items(): if pointee == ST or (isinstance(pointee, ir.IdentifiedStructType) and isinstance(ST, ir.IdentifiedStructType) and pointee.name == ST.name): if isinstance(ST, ir.IdentifiedStructType) and (ST.elements is None or len(ST.elements) == 0): self.Trans.ImportHandler._TryLoadStructFromStub(CN, Gen) ST = Gen.structs.get(CN, ST) if ST.elements is not None and isinstance(ObjVal.type, ir.PointerType) and isinstance(ObjVal.type.pointee, ir.IdentifiedStructType) and ObjVal.type.pointee.elements is None: ObjVal = Gen.builder.bitcast(ObjVal, ir.PointerType(ST), name=f"cast_{CN}") bitfield_offsets = Gen.class_member_bitoffsets.get(CN, {}) if AttrName in bitfield_offsets: self._store_bitfield_member(ObjVal, CN, AttrName, Value) return offset = Gen._get_member_offset(AttrName, CN) if offset is not None and ST.elements is not None and offset < len(ST.elements): MemberPtr = Gen.builder.gep(ObjVal, [ir.Constant(ir.IntType(32), 0), ir.Constant(ir.IntType(32), offset)], name=AttrName) self._StoreWithCoerce(Value, MemberPtr) break elif isinstance(Target.value, ast.Subscript): SubPtr = self.Trans.ExprAttrHandle.HandleSubscriptPtrLlvm(Target.value) if SubPtr and isinstance(SubPtr.type, ir.PointerType): pointee = SubPtr.type.pointee if isinstance(Target.value.value, ast.Attribute): AttrNameSub = Target.value.value.attr if AttrNameSub == 'items' and 'Item' in Gen.structs: ObjValCast = Gen.builder.bitcast(SubPtr, ir.PointerType(Gen.structs['Item']), name=f"cast_Item") offset = Gen._get_member_offset(AttrName, 'Item') MemberPtr = Gen.builder.gep(ObjValCast, [ir.Constant(ir.IntType(32), 0), ir.Constant(ir.IntType(32), offset)], name=AttrName) self._StoreWithCoerce(Value, MemberPtr) return if BaseHandle._is_char_pointer(SubPtr): for CN, ST in Gen.structs.items(): ObjValCast = Gen.builder.bitcast(SubPtr, ir.PointerType(ST), name=f"cast_{CN}") offset = Gen._get_member_offset(AttrName, CN) MemberPtr = Gen.builder.gep(ObjValCast, [ir.Constant(ir.IntType(32), 0), ir.Constant(ir.IntType(32), offset)], name=AttrName) self._StoreWithCoerce(Value, MemberPtr) break elif isinstance(pointee, (ir.LiteralStructType, ir.IdentifiedStructType)): found = Gen.find_struct_by_pointee(pointee) if found: CN, ST = found if isinstance(ST, ir.IdentifiedStructType) and (ST.elements is None or len(ST.elements) == 0): self.Trans.ImportHandler._TryLoadStructFromStub(CN, Gen) ST = Gen.structs.get(CN, ST) if ST.elements is not None and isinstance(SubPtr.type, ir.PointerType) and isinstance(SubPtr.type.pointee, ir.IdentifiedStructType) and SubPtr.type.pointee.elements is None: SubPtr = Gen.builder.bitcast(SubPtr, ir.PointerType(ST), name=f"cast_{CN}") offset = Gen._get_member_offset(AttrName, CN) if offset is not None and ST.elements is not None and offset < len(ST.elements): MemberPtr = Gen.builder.gep(SubPtr, [ir.Constant(ir.IntType(32), 0), ir.Constant(ir.IntType(32), offset)], name=AttrName) self._StoreWithCoerce(Value, MemberPtr) elif isinstance(pointee, ir.PointerType): LoadedPtr = Gen._load(SubPtr, name=f"Load_{AttrName}_ptr") if isinstance(LoadedPtr.type, ir.PointerType) and isinstance(LoadedPtr.type.pointee, (ir.IdentifiedStructType, ir.LiteralStructType)): found = Gen.find_struct_by_pointee(LoadedPtr.type.pointee) if found: CN, ST = found offset = Gen._get_member_offset(AttrName, CN) MemberPtr = Gen.builder.gep(LoadedPtr, [ir.Constant(ir.IntType(32), 0), ir.Constant(ir.IntType(32), offset)], name=AttrName) self._StoreWithCoerce(Value, MemberPtr) def _HandleSubscriptStoreLlvm(self, Target, Value): Gen = self.Trans.LlvmGen if isinstance(Target.value, ast.Name): SubVarName = Target.value.id if SubVarName in Gen.var_const_flags: src_info = Gen._get_node_info() self.Trans.LogError(f"不能对 const 变量 '{SubVarName}' 的元素赋值{src_info}") ClassName = self.Trans.ExprHandler._get_var_class(Target.value, Gen) if ClassName and Gen._has_function(f'{ClassName}.__setitem__'): obj_val = self.Trans.ExprHandler.HandleExprLlvm(Target.value) idx_val = self.Trans.ExprHandler.HandleExprLlvm(Target.slice) if obj_val and idx_val: if BaseHandle._is_char_pointer(obj_val): obj_val = Gen.builder.bitcast(obj_val, ir.PointerType(Gen.structs[ClassName]), name=f"cast_{ClassName}") Gen.builder.call(Gen._get_function(f'{ClassName}.__setitem__'), [obj_val, idx_val, Value], name=f"call_{ClassName}.__setitem__") return ValueVal = self.HandleExprLlvm(Target.value) IndexVal = self.HandleExprLlvm(Target.slice) if not ValueVal or not IndexVal: return if BaseHandle._is_char_pointer(IndexVal): Loaded_byte = Gen._load(IndexVal, name="Load_char_idx_store") IndexVal = Gen.builder.zext(Loaded_byte, ir.IntType(32), name="char_to_int_idx_store") if isinstance(ValueVal.type, ir.IntType): var_ptr = self._get_int_ptr(Target.value) if var_ptr: i8_ptr = Gen.builder.bitcast(var_ptr, ir.PointerType(ir.IntType(8)), name="int_to_i8ptr_store") if isinstance(IndexVal.type, ir.IntType) and IndexVal.type.width < 64: IndexVal = Gen.builder.zext(IndexVal, ir.IntType(64), name="zext_int_index_store") ptr = Gen.builder.gep(i8_ptr, [IndexVal], name="int_subscript_ptr_store") self._StoreWithCoerce(Value, ptr) return if isinstance(ValueVal.type, ir.PointerType) and isinstance(ValueVal.type.pointee, ir.PointerType): if isinstance(IndexVal.type, ir.IntType) and IndexVal.type.width < 64: IndexVal = Gen.builder.zext(IndexVal, ir.IntType(64), name="zext_ptr_index_store") ElemPtr = Gen.builder.gep(ValueVal, [IndexVal], name="subscript") self._StoreWithCoerce(Value, ElemPtr) return if isinstance(ValueVal.type, ir.PointerType): pointee = ValueVal.type.pointee if isinstance(pointee, ir.ArrayType): zero = ir.Constant(ir.IntType(32), 0) if isinstance(IndexVal.type, ir.IntType) and IndexVal.type.width != 32: if IndexVal.type.width < 32: IndexVal = Gen.builder.zext(IndexVal, ir.IntType(32), name="zext_arr_index") else: IndexVal = Gen.builder.trunc(IndexVal, ir.IntType(32), name="trunc_arr_index") ElemPtr = Gen.builder.gep(ValueVal, [zero, IndexVal], name="subscript") else: ElemPtr = Gen.builder.gep(ValueVal, [IndexVal], name="subscript") self._StoreWithCoerce(Value, ElemPtr) elif isinstance(ValueVal.type, ir.ArrayType): zero = ir.Constant(ir.IntType(32), 0) if isinstance(Target.value, ast.Name): VarName = Target.value.id if VarName in Gen.variables and Gen.variables[VarName] is not None: VarPtr = Gen.variables[VarName] if isinstance(VarPtr.type, ir.PointerType) and isinstance(VarPtr.type.pointee, ir.ArrayType): if isinstance(IndexVal.type, ir.IntType) and IndexVal.type.width != 32: if IndexVal.type.width < 32: IndexVal = Gen.builder.zext(IndexVal, ir.IntType(32), name="zext_arr_index") else: IndexVal = Gen.builder.trunc(IndexVal, ir.IntType(32), name="trunc_arr_index") ElemPtr = Gen.builder.gep(VarPtr, [zero, IndexVal], name="subscript") self._StoreWithCoerce(Value, ElemPtr) return if isinstance(Target.value, ast.Subscript): InnerPtr = self.Trans.ExprAttrHandle.HandleSubscriptPtrLlvm(Target.value) if InnerPtr: if isinstance(IndexVal.type, ir.IntType) and IndexVal.type.width != 32: if IndexVal.type.width < 32: IndexVal = Gen.builder.zext(IndexVal, ir.IntType(32), name="zext_arr_index") else: IndexVal = Gen.builder.trunc(IndexVal, ir.IntType(32), name="trunc_arr_index") ElemPtr = Gen.builder.gep(InnerPtr, [zero, IndexVal], name="subscript") self._StoreWithCoerce(Value, ElemPtr) return if isinstance(Target.value, ast.Attribute): AttrPtr = self.Trans.ExprAttrHandle._get_attr_ptr(Target.value) if AttrPtr and isinstance(AttrPtr.type, ir.PointerType) and isinstance(AttrPtr.type.pointee, ir.ArrayType): if isinstance(IndexVal.type, ir.IntType) and IndexVal.type.width != 32: if IndexVal.type.width < 32: IndexVal = Gen.builder.zext(IndexVal, ir.IntType(32), name="zext_arr_index") else: IndexVal = Gen.builder.trunc(IndexVal, ir.IntType(32), name="trunc_arr_index") ElemPtr = Gen.builder.gep(AttrPtr, [zero, IndexVal], name="subscript") self._StoreWithCoerce(Value, ElemPtr) return arr_alloc = Gen._allocaEntry(ValueVal.type, name="arr_subscript_tmp") Gen._store(ValueVal, arr_alloc) ElemPtr = Gen.builder.gep(arr_alloc, [zero, IndexVal], name="subscript") self._StoreWithCoerce(Value, ElemPtr) ModifiedArr = Gen._load(arr_alloc, name="modified_arr") if isinstance(Target.value, ast.Subscript): OuterPtr = self.Trans.ExprAttrHandle.HandleSubscriptPtrLlvm(Target.value) if OuterPtr: Gen._store(ModifiedArr, OuterPtr) elif isinstance(Target.value, ast.Attribute): OuterPtr = self.Trans.ExprAttrHandle._get_attr_ptr(Target.value) if OuterPtr: Gen._store(ModifiedArr, OuterPtr) 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.ArrayType) and isinstance(Value.type, ir.PointerType): ElemType = TargetType.element ElemSize = Gen._get_struct_size(ElemType) for i in range(TargetType.count): DstElem = Gen.builder.gep(Ptr, [ir.Constant(ir.IntType(32), 0), ir.Constant(ir.IntType(32), i)], name=f"arr_dst_{i}") if ElemSize == 1: SrcPtr = Gen.builder.gep(Value, [ir.Constant(ir.IntType(32), i)], name=f"arr_src_{i}") else: PtrInt = Gen.builder.ptrtoint(Value, ir.IntType(64)) Offset = ir.Constant(ir.IntType(64), i * ElemSize) NewPtrInt = Gen.builder.add(PtrInt, Offset) SrcPtr = Gen.builder.inttoptr(NewPtrInt, ir.PointerType(ElemType), name=f"arr_src_{i}") SrcVal = Gen._load(SrcPtr, name=f"arr_elem_{i}") if SrcVal.type != ElemType: try: SrcVal = Gen.builder.bitcast(SrcVal, ElemType, name=f"arr_cast_{i}") except Exception: # 回退:bitcast 失败时跳过该元素 continue Gen._store(SrcVal, DstElem) return if isinstance(TargetType, ir.PointerType) and isinstance(Value, ir.Constant) and Value.constant is None: Value = ir.Constant(TargetType, None) elif isinstance(TargetType, ir.PointerType) and isinstance(Value.type, ir.PointerType): try: Value = Gen.builder.bitcast(Value, TargetType, name="null_ptr_bitcast") except Exception: # 回退:bitcast 失败时设为 null 常量 Value = ir.Constant(TargetType, None) else: Coerced = Gen._coerce_value(Value, TargetType) if Coerced is not None: Value = Coerced Gen._store(Value, Ptr) def _get_int_ptr(self, target): Gen = self.Trans.LlvmGen if isinstance(target, ast.Name): VarName = target.id if VarName in Gen.variables and Gen.variables[VarName] is not None: VarPtr = Gen.variables[VarName] if isinstance(VarPtr.type, ir.PointerType): pointee = VarPtr.type.pointee if isinstance(pointee, ir.ArrayType): return Gen.builder.gep(VarPtr, [ir.Constant(ir.IntType(32), 0), ir.Constant(ir.IntType(32), 0)], name=f"arr_start_{VarName}") return None def _EmitGlobalAnnAssignLlvm(self, Node, Gen): if isinstance(Node.target, ast.Name): VarName = Node.target.id EffectiveAnnotation = Node.annotation if VarName in self.Trans.SymbolTable: Info = self.Trans.SymbolTable[VarName] if Info.get('type') == 'typedef': return if isinstance(EffectiveAnnotation, ast.BinOp) and isinstance(EffectiveAnnotation.op, ast.BitOr): for side in [EffectiveAnnotation.left, EffectiveAnnotation.right]: if isinstance(side, ast.Subscript) and isinstance(side.value, ast.Name) and side.value.id == 'list': EffectiveAnnotation = side break if isinstance(EffectiveAnnotation, ast.Subscript) and isinstance(EffectiveAnnotation.value, ast.Name) and EffectiveAnnotation.value.id == 'list': slice_node = EffectiveAnnotation.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] if isinstance(elem_type_node, ast.Name) and elem_type_node.id in Gen.structs: SymEntry = self.Trans.SymbolTable.get(elem_type_node.id) if SymEntry and isinstance(SymEntry, CTypeInfo) and SymEntry.IsFuncPtr: ElemType = ir.IntType(8).as_pointer() else: ElemType = Gen.structs[elem_type_node.id] else: ElemTypeInfo = CTypeInfo.FromNode(elem_type_node, self.Trans.SymbolTable) if ElemTypeInfo and ElemTypeInfo.IsFuncPtr: ElemType = ir.IntType(8).as_pointer() else: if ElemTypeInfo is None: ElemTypeInfo = CTypeInfo() ElemTypeInfo.BaseType = t.CInt() 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 elif isinstance(count_node, ast.Name): if count_node.id in self.Trans.SymbolTable: SymInfo = self.Trans.SymbolTable[count_node.id] if isinstance(getattr(SymInfo, 'value', None), int): ArrayCount = SymInfo.value if ArrayCount == 1 and count_node.id in getattr(Gen, '_define_constants', {}): DefVal = Gen._define_constants[count_node.id] if isinstance(DefVal, int): ArrayCount = DefVal elif isinstance(count_node, ast.Attribute): ev = self._eval_global_count(count_node, Gen) if ev is not None: ArrayCount = ev elif isinstance(count_node, ast.BinOp): ev = self._eval_global_count(count_node, Gen) if ev is not None: ArrayCount = ev 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.List): ArrayCount = len(Node.value.elts) elif 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) if VarName not in Gen.variables and VarName not in Gen.module.globals: GlobalVar = ir.GlobalVariable(Gen.module, VarType, name=VarName) if isinstance(ElemType, ir.IdentifiedStructType): GlobalVar.linkage = 'common' 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 len(str_bytes) < ArrayCount: str_bytes.extend(b'\x00' * (ArrayCount - len(str_bytes))) try: GlobalVar.initializer = ir.Constant(VarType, str_bytes[:ArrayCount]) except Exception: # 回退:初始化常量失败时用零值 GlobalVar.initializer = self._zero_value(VarType) else: InitConstants = self.Trans._BuildArrayInitConstants(Node.value, ElemType, elem_type_node, ArrayCount, Gen) if InitConstants: GlobalVar.initializer = ir.Constant(VarType, InitConstants) elif ArrayCount > 256: GlobalVar.linkage = 'common' else: if self._contains_identified_struct(VarType): GlobalVar.linkage = 'common' else: GlobalVar.initializer = ir.Constant(VarType, [ir.Constant(ElemType, ir.Undefined)] * ArrayCount) Gen.variables[VarName] = GlobalVar if isinstance(elem_type_node, ast.Name) and elem_type_node.id in Gen.structs: Gen.global_struct_class[VarName] = elem_type_node.id return if isinstance(EffectiveAnnotation, ast.Subscript) and isinstance(EffectiveAnnotation.value, ast.Name) and EffectiveAnnotation.value.id == 'list': slice_node = EffectiveAnnotation.slice elem_type_node = slice_node if isinstance(elem_type_node, ast.Name) and elem_type_node.id in Gen.structs: ElemType = Gen.structs[elem_type_node.id] else: ElemTypeInfo = CTypeInfo.FromNode(elem_type_node, self.Trans.SymbolTable) if ElemTypeInfo is None: ElemTypeInfo = CTypeInfo() ElemTypeInfo.BaseType = t.CInt() ElemType = Gen._ctype_to_llvm(ElemTypeInfo) if isinstance(ElemType, ir.VoidType): ElemType = ir.IntType(32) VarType = ir.PointerType(ElemType) if VarName not in Gen.variables and VarName not in Gen.module.globals: GlobalVar = ir.GlobalVariable(Gen.module, VarType, name=VarName) GlobalVar.initializer = ir.Constant(VarType, None) Gen.variables[VarName] = GlobalVar if isinstance(elem_type_node, ast.Name) and elem_type_node.id in Gen.structs: Gen.global_struct_class[VarName] = elem_type_node.id return if isinstance(Node.annotation, ast.Name) and Node.annotation.id in Gen.structs: StructName = Node.annotation.id VarType = Gen.structs[StructName] if VarName not in Gen.variables and VarName not in Gen.module.globals: GlobalVar = ir.GlobalVariable(Gen.module, VarType, name=VarName) if Node.value and isinstance(Node.value, ast.Call) and isinstance(Node.value.func, ast.Name) and Node.value.func.id == StructName: const = self.Trans.ClassHandler._BuildStructConstant(Node.value, StructName, Gen) if const: GlobalVar.initializer = const else: GlobalVar.initializer = ir.Constant(VarType, None) else: GlobalVar.initializer = ir.Constant(VarType, None) Gen.variables[VarName] = GlobalVar Gen.global_struct_class[VarName] = StructName return TypeInfo = CTypeInfo.FromNode(Node.annotation, self.Trans.SymbolTable) if not TypeInfo or not TypeInfo.BaseType: ArrayTypeInfo = CTypeInfo._HandleArraySubscript(Node.annotation, self.Trans.SymbolTable) if ArrayTypeInfo: TypeInfo = ArrayTypeInfo IsCDefine = False if TypeInfo and TypeInfo.BaseType: if isinstance(TypeInfo.BaseType, t._CTypedef): return if isinstance(TypeInfo.BaseType, t.CDefine): IsCDefine = True if not IsCDefine and self._IsTypedefAnnotation(Node.annotation): IsCDefine = True TTypeInfo = self.Trans.TypeMergeHandler.GetCTypeInfo(Node.annotation) if TTypeInfo: TTypeInfo.IsTypedef = True TTypeInfo.Name = VarName self.Trans.SymbolTable[VarName] = TTypeInfo if IsCDefine: if Node.value: define_constants = vars(Gen).setdefault('_define_constants', {}) try: const_value = self._eval_const_expr(Node.value, Gen) if const_value is not None: define_constants[VarName] = const_value except Exception as _e: if __import__('lib.constants.config', fromlist=['mode']).mode == "strict": self.Trans.LogWarning(f"异常被忽略: {_e}") return if TypeInfo is None: TypeInfo = CTypeInfo() TypeInfo.BaseType = t.CInt() VarType = Gen._ctype_to_llvm(TypeInfo) if isinstance(VarType, ir.VoidType): VarType = ir.IntType(32) if VarName in Gen.variables or VarName in Gen.module.globals: return if isinstance(VarType, (ir.IdentifiedStructType, ir.LiteralStructType)): GlobalVar = ir.GlobalVariable(Gen.module, VarType, name=VarName) GlobalVar.initializer = ir.Constant(VarType, None) Gen.variables[VarName] = GlobalVar if TypeInfo and TypeInfo.IsStruct and TypeInfo.Name: Gen.global_struct_class[VarName] = TypeInfo.Name return GlobalVar = ir.GlobalVariable(Gen.module, VarType, name=VarName) if Node.value: if isinstance(Node.value, ast.Constant) and isinstance(Node.value.value, str) and isinstance(VarType, ir.PointerType): str_val = Node.value.value + '\x00' str_bytes = str_val.encode('utf-8') arr_type = ir.ArrayType(ir.IntType(8), len(str_bytes)) str_gv_name = VarName + '_str' if str_gv_name not in Gen.module.globals: str_gv = ir.GlobalVariable(Gen.module, arr_type, name=str_gv_name) str_gv.initializer = ir.Constant(arr_type, bytearray(str_bytes)) str_gv.linkage = 'internal' else: str_gv = Gen.module.globals[str_gv_name] ptr_type = ir.PointerType(ir.IntType(8)) if VarName not in Gen.module.globals: ptr_gv = ir.GlobalVariable(Gen.module, ptr_type, name=VarName) ptr_gv.initializer = ir.Constant(ptr_type, str_gv) ptr_gv.linkage = 'internal' else: ptr_gv = Gen.module.globals[VarName] Gen.variables[VarName] = ptr_gv else: if isinstance(VarType, ir.ArrayType) and isinstance(Node.value, (ast.List, ast.Set)): InitConstants = self.Trans._BuildMultiDimArrayInitConstants(Node.value, VarType, Gen) if InitConstants: GlobalVar.initializer = ir.Constant(VarType, InitConstants) else: if self._contains_identified_struct(VarType): GlobalVar.linkage = 'common' else: zv = self._zero_value(VarType) if zv: GlobalVar.initializer = zv else: GlobalVar.linkage = 'common' else: init_val = self._eval_global_const(Node.value, VarType, Gen) if init_val: GlobalVar.initializer = init_val elif isinstance(VarType, ir.BaseStructType): GlobalVar.linkage = 'common' else: GlobalVar.initializer = self._zero_value(VarType) else: if isinstance(VarType, ir.BaseStructType) or self._contains_identified_struct(VarType): GlobalVar.linkage = 'common' else: GlobalVar.initializer = self._zero_value(VarType) Gen.variables[VarName] = GlobalVar def _eval_global_const(self, value_node, var_type, Gen): if isinstance(value_node, ast.Constant): if isinstance(value_node.value, bool): if isinstance(var_type, ir.IntType): return ir.Constant(var_type, int(value_node.value)) elif isinstance(value_node.value, int): if isinstance(var_type, ir.IntType): return ir.Constant(var_type, value_node.value) elif isinstance(var_type, (ir.FloatType, ir.DoubleType)): return ir.Constant(var_type, float(value_node.value)) elif isinstance(value_node.value, float): if isinstance(var_type, (ir.FloatType, ir.DoubleType)): return ir.Constant(var_type, value_node.value) elif isinstance(var_type, ir.IntType): return ir.Constant(var_type, int(value_node.value)) elif isinstance(value_node.value, str): return None # Handle type constructor calls like t.CDouble(1e-9), t.CFloat(3.14), t.CInt(42) if isinstance(value_node, ast.Call): inner_val = self._eval_type_ctor_const(value_node, var_type, Gen) if inner_val is not None: return inner_val if isinstance(value_node, ast.UnaryOp) and isinstance(value_node.op, ast.USub): inner = self._eval_global_const(value_node.operand, var_type, Gen) if inner: return ir.Constant(var_type, -inner.constant) return None def _eval_type_ctor_const(self, call_node, var_type, Gen): """Try to evaluate t.CDouble(val), t.CFloat(val), t.CInt(val) etc. as a compile-time constant.""" if not isinstance(call_node.func, ast.Attribute): return None if not isinstance(call_node.func.value, ast.Name): return None if call_node.func.value.id != 't': return None if not call_node.args or len(call_node.args) != 1: return None arg = call_node.args[0] # Recursively evaluate the argument as a constant arg_val = self._eval_global_const(arg, var_type, Gen) if arg_val is not None: return arg_val return None def _store_bitfield_member(self, struct_ptr, ClassName, field_name, Value): Gen = self.Trans.LlvmGen bitfield_offsets = Gen.class_member_bitoffsets.get(ClassName, {}) bitfield_widths = Gen.class_member_bitfields.get(ClassName, {}) if field_name not in bitfield_offsets: return False bit_offset = bitfield_offsets[field_name] bit_width = bitfield_widths.get(field_name, 0) if bit_width == 0: return False struct_type = Gen.structs.get(ClassName) if struct_type is None or struct_type.elements is None or len(struct_type.elements) == 0: return False storage_type = struct_type.elements[0] member_ptr = Gen.builder.gep(struct_ptr, [ir.Constant(ir.IntType(32), 0), ir.Constant(ir.IntType(32), 0)], name=f"{field_name}_storage_ptr") old_val = Gen._load(member_ptr, name=f"{field_name}_old_storage") mask = (1 << bit_width) - 1 shifted_mask = mask << bit_offset inverted_mask = ir.Constant(storage_type, ~shifted_mask & ((1 << storage_type.width) - 1)) cleared = Gen.builder.and_(old_val, inverted_mask, name=f"{field_name}_cleared") if isinstance(Value.type, ir.IntType) and Value.type.width < storage_type.width: if getattr(Value.type, 'is_signed', False): Value = Gen.builder.sext(Value, storage_type, name=f"{field_name}_sext_store") else: Value = Gen.builder.zext(Value, storage_type, name=f"{field_name}_zext_store") elif Value.type.width != storage_type.width: Value = Gen.builder.trunc(Value, storage_type, name=f"{field_name}_trunc_store") if Value.type.width > storage_type.width else Gen.builder.zext(Value, storage_type, name=f"{field_name}_zext_store") shifted_value = Gen.builder.shl(Value, ir.Constant(storage_type, bit_offset), name=f"{field_name}_shift_store") masked_value = Gen.builder.and_(shifted_value, ir.Constant(storage_type, shifted_mask), name=f"{field_name}_mask_store") new_val = Gen.builder.or_(cleared, masked_value, name=f"{field_name}_new_storage") Gen._store(new_val, member_ptr) return True def _CheckEnumMemberAssignment(self, node): def _get_attr_path(n): if isinstance(n, ast.Name): return n.id elif isinstance(n, ast.Attribute): return f"{_get_attr_path(n.value)}.{n.attr}" return None attr_path = _get_attr_path(node) if not attr_path: return None parts = attr_path.split('.') if len(parts) >= 2: enum_class_name = parts[-2] member_name = parts[-1] qualified_name = f"{enum_class_name}.{member_name}" if qualified_name in self.Trans.SymbolTable: info = self.Trans.SymbolTable[qualified_name] if info.IsEnumMember and info.EnumName: return info.EnumName under_name = f"{enum_class_name}_{member_name}" if under_name in self.Trans.SymbolTable: info = self.Trans.SymbolTable[under_name] if info.IsEnumMember and info.EnumName: return info.EnumName for key in self.Trans.SymbolTable: if key == member_name: info = self.Trans.SymbolTable[key] if info.IsEnumMember and info.EnumName and info.EnumName == enum_class_name: return enum_class_name return None def _IsTypedefAnnotation(self, annotation): if isinstance(annotation, ast.Attribute): if annotation.attr in ('CTypedef', 'CDefine'): return True if isinstance(annotation, ast.BinOp) and isinstance(annotation.op, ast.BitOr): return self._IsTypedefAnnotation(annotation.left) or self._IsTypedefAnnotation(annotation.right) if isinstance(annotation, ast.Subscript): return self._IsTypedefAnnotation(annotation.value) return False def _EmitGlobalAssignLlvm(self, Node, Gen): if len(Node.targets) == 1 and isinstance(Node.targets[0], ast.Name): VarName = Node.targets[0].id if VarName in Gen.variables or VarName in Gen.module.globals: return if isinstance(Node.value, ast.Call) and isinstance(Node.value.func, ast.Name): FuncName = Node.value.func.id if FuncName in Gen.structs: IsUnion = False if FuncName in self.Trans.SymbolTable: TypeInfo = self.Trans.SymbolTable[FuncName] if TypeInfo.IsUnion: IsUnion = True if IsUnion: StructType = Gen.structs[FuncName] StructPtrType = ir.PointerType(StructType) GlobalVar = ir.GlobalVariable(Gen.module, StructPtrType, name=VarName) GlobalVar.initializer = ir.Constant(StructPtrType, None) Gen.variables[VarName] = GlobalVar Gen.global_struct_class[VarName] = FuncName return StructName = FuncName VarType = Gen.structs[StructName] GlobalVar = ir.GlobalVariable(Gen.module, VarType, name=VarName) const = self.Trans.ClassHandler._BuildStructConstant(Node.value, StructName, Gen) if const: GlobalVar.initializer = const else: GlobalVar.linkage = 'common' Gen.variables[VarName] = GlobalVar Gen.global_struct_class[VarName] = StructName return GlobalVar = ir.GlobalVariable(Gen.module, ir.IntType(32), name=VarName) init_val = self._eval_global_const(Node.value, ir.IntType(32), Gen) GlobalVar.initializer = init_val if init_val else ir.Constant(ir.IntType(32), 0) Gen.variables[VarName] = GlobalVar def _eval_const_expr(self, node, Gen): """计算常量表达式的值""" import ast if isinstance(node, ast.Constant): return node.value elif isinstance(node, ast.BinOp): left = self._eval_const_expr(node.left, Gen) right = self._eval_const_expr(node.right, Gen) if left is None or right is None: return None if isinstance(node.op, ast.Add): return left + right elif isinstance(node.op, ast.Sub): return left - right elif isinstance(node.op, ast.Mult): return left * right elif isinstance(node.op, ast.Div): return left // right if isinstance(left, int) and isinstance(right, int) else left / right elif isinstance(node.op, ast.FloorDiv): return left // right elif isinstance(node.op, ast.Mod): return left % right elif isinstance(node.op, ast.Pow): return left ** right elif isinstance(node.op, ast.LShift): return left << right elif isinstance(node.op, ast.RShift): return left >> right elif isinstance(node.op, ast.BitOr): return left | right elif isinstance(node.op, ast.BitXor): return left ^ right elif isinstance(node.op, ast.BitAnd): return left & right elif isinstance(node, ast.UnaryOp): operand = self._eval_const_expr(node.operand, Gen) if operand is None: return None if isinstance(node.op, ast.USub): return -operand elif isinstance(node.op, ast.UAdd): return +operand elif isinstance(node.op, ast.Invert): return ~operand elif isinstance(node, ast.Name): if node.id in getattr(Gen, '_define_constants', {}): return Gen._define_constants[node.id] if node.id in self.Trans.SymbolTable: SymInfo = self.Trans.SymbolTable[node.id] val = getattr(SymInfo, 'value', None) if isinstance(val, (int, float)): return val if getattr(SymInfo, 'IsDefine', None) and isinstance(getattr(SymInfo, 'DefineValue', None), (int, float)): return SymInfo.DefineValue elif isinstance(node, ast.Attribute): module_name = node.value.id if isinstance(node.value, ast.Name) else None attr_name = node.attr if module_name and attr_name: combined_key = f"{module_name}.{attr_name}" if combined_key in getattr(Gen, '_define_constants', {}): val = Gen._define_constants[combined_key] if isinstance(val, (int, float)): return int(val) if isinstance(val, float) and val == int(val) else val for key, SymInfo in self.Trans.SymbolTable.items(): if key.endswith(f".{combined_key}") or key == combined_key: if getattr(SymInfo, 'IsDefine', None) and isinstance(getattr(SymInfo, 'DefineValue', None), (int, float)): return int(SymInfo.DefineValue) if isinstance(SymInfo.DefineValue, float) and SymInfo.DefineValue == int(SymInfo.DefineValue) else SymInfo.DefineValue all_dc = getattr(self.Trans, '_all_define_constants', None) or getattr(Gen, '_all_define_constants', {}) if combined_key in all_dc: val = all_dc[combined_key] if isinstance(val, (int, float)): return int(val) if isinstance(val, float) and val == int(val) else val if attr_name in all_dc: val = all_dc[attr_name] if isinstance(val, (int, float)): return int(val) if isinstance(val, float) and val == int(val) else val for dc_key, dc_val in all_dc.items(): if dc_key == attr_name or dc_key.endswith(f".{attr_name}"): if isinstance(dc_val, (int, float)): return int(dc_val) if isinstance(dc_val, float) and dc_val == int(dc_val) else dc_val if attr_name in self.Trans.SymbolTable: SymInfo = self.Trans.SymbolTable[attr_name] if getattr(SymInfo, 'IsDefine', None) and isinstance(getattr(SymInfo, 'DefineValue', None), (int, float)): return int(SymInfo.DefineValue) if isinstance(SymInfo.DefineValue, float) and SymInfo.DefineValue == int(SymInfo.DefineValue) else SymInfo.DefineValue if attr_name in getattr(Gen, '_define_constants', {}): val = Gen._define_constants[attr_name] if isinstance(val, (int, float)): return int(val) if isinstance(val, float) and val == int(val) else val return None def _eval_global_count(self, node, Gen): val = self._eval_const_expr(node, Gen) if val is not None: if isinstance(val, float): return int(val) if isinstance(val, int): return val return None