from __future__ import annotations
from typing import TYPE_CHECKING
if TYPE_CHECKING:
    from lib.core.translator import Translator
    from lib.core.Translator.LlvmGenerator import LlvmGeneratorMixin
import ast
import llvmlite.ir as ir
from lib.core.Handles.HandlesBase import BaseHandle
from lib.core.VLogger import get_logger as _vlog
from lib.constants.config import mode as _config_mode
from lib.includes.t import CTypeRegistry
from lib.core.SymbolUtils import IsTModule, ExtractTypeNameFromBinOp


class ExprBuiltinHandle(BaseHandle):
    _C_LIB_FUNCS: dict[str, object] = {
        'strlen':    lambda: (ir.IntType(64), [ir.PointerType(ir.IntType(8))]),
        'strlength': lambda: (ir.IntType(64), [ir.PointerType(ir.IntType(8))]),
        'memset':  lambda: (ir.PointerType(ir.IntType(8)), [ir.PointerType(ir.IntType(8)), ir.IntType(32), ir.IntType(64)]),
        'memcpy':  lambda: (ir.PointerType(ir.IntType(8)), [ir.PointerType(ir.IntType(8)), ir.PointerType(ir.IntType(8)), ir.IntType(64)]),
        'memmove': lambda: (ir.PointerType(ir.IntType(8)), [ir.PointerType(ir.IntType(8)), ir.PointerType(ir.IntType(8)), ir.IntType(64)]),
        'memcmp':  lambda: (ir.IntType(32), [ir.PointerType(ir.IntType(8)), ir.PointerType(ir.IntType(8)), ir.IntType(64)]),
        'strcmp':  lambda: (ir.IntType(32), [ir.PointerType(ir.IntType(8)), ir.PointerType(ir.IntType(8))]),
        'strncmp': lambda: (ir.IntType(32), [ir.PointerType(ir.IntType(8)), ir.PointerType(ir.IntType(8)), ir.IntType(64)]),
        'strcpy':  lambda: (ir.PointerType(ir.IntType(8)), [ir.PointerType(ir.IntType(8)), ir.PointerType(ir.IntType(8))]),
        'strncpy': lambda: (ir.PointerType(ir.IntType(8)), [ir.PointerType(ir.IntType(8)), ir.PointerType(ir.IntType(8)), ir.IntType(64)]),
        'strcat': lambda: (ir.PointerType(ir.IntType(8)), [ir.PointerType(ir.IntType(8)), ir.PointerType(ir.IntType(8))]),
        'puts': lambda: (ir.IntType(32), [ir.PointerType(ir.IntType(8))]),
        'atoi': lambda: (ir.IntType(32), [ir.PointerType(ir.IntType(8))]),
        'atol': lambda: (ir.IntType(64), [ir.PointerType(ir.IntType(8))]),
        'abs':  lambda: (ir.IntType(32), [ir.IntType(32)]),
        'labs': lambda: (ir.IntType(64), [ir.IntType(64)]),
    }

    def _HandleBuiltinCallLlvm(self, Node: ast.Call) -> ir.Value | None:
        Gen: LlvmGeneratorMixin = self.Trans.LlvmGen
        if not isinstance(Node.func, ast.Name):
            return None
        FuncName: str = Node.func.id

        if FuncName == 'print':
            return self._HandlePrintLlvm(Node)
        elif FuncName == 'len':
            if Node.args:
                return self._HandleLenLlvm(Node.args[0])
            return ir.Constant(ir.IntType(32), 0)
        elif FuncName == 'sizeof':
            if Node.args:
                return self._HandleSizeofLlvm(Node.args[0])
            return ir.Constant(ir.IntType(32), 0)
        elif FuncName == 'abs':
            if Node.args:
                return self._HandleAbsLlvm(Node.args[0])
            return ir.Constant(ir.IntType(32), 0)
        elif FuncName == 'arg':
            return self._HandleArgLlvm(Node.args)
        elif FuncName == 'bool':
            if Node.args:
                Val = self.HandleExprLlvm(Node.args[0])
                if Val:
                    if isinstance(Val.type, ir.IntType):
                        if Val.type.width == 1:
                            return Val
                        return Gen.builder.icmp_signed('!=', Val, Gen._ZeroConst(Val.type), name="bool_result")
                    elif isinstance(Val.type, ir.PointerType):
                        return Gen.builder.icmp_signed('!=', Val, Gen._ZeroConst(Val.type), name="bool_result")
                    return Val
                return ir.Constant(ir.IntType(1), 0)
        elif FuncName == 'int':
            if Node.args:
                Val = self.HandleExprLlvm(Node.args[0])
                if Val:
                    if isinstance(Val.type, ir.IntType):
                        if Val.type.width < 32:
                            return Gen.builder.zext(Val, ir.IntType(32), name="cast_int")
                        elif Val.type.width > 32:
                            return Gen.builder.trunc(Val, ir.IntType(32), name="trunc_int")
                        return Val
                    elif isinstance(Val.type, ir.PointerType):
                        if isinstance(Val.type.pointee, ir.IntType) and Val.type.pointee.width == 8:
                            result = self._HandleAtoiLlvm(Val)
                            if result:
                                return result
                    elif isinstance(Val.type, (ir.FloatType, ir.DoubleType)):
                        return Gen.builder.fptosi(Val, ir.IntType(32), name="float_to_int")
            return ir.Constant(ir.IntType(32), 0)
        elif FuncName == 'float' or FuncName == 'double':
            if Node.args:
                Val = self.HandleExprLlvm(Node.args[0])
                if Val:
                    target_type = ir.DoubleType() if FuncName == 'double' else ir.FloatType()
                    if isinstance(Val.type, (ir.FloatType, ir.DoubleType)):
                        if Val.type != target_type:
                            if isinstance(target_type, ir.DoubleType):
                                return Gen.builder.fpext(Val, target_type, name="fpext_double")
                            return Gen.builder.fptrunc(Val, target_type, name="fptrunc_float")
                        return Val
                    elif isinstance(Val.type, ir.IntType):
                        if Val.type.width == 1:
                            return Gen.builder.uitofp(Val, target_type, name="uitofp")
                        return Gen.builder.sitofp(Val, target_type, name="sitofp")
            return ir.Constant(ir.DoubleType() if FuncName == 'double' else ir.FloatType(), 0.0)
        elif FuncName == 'min':
            if len(Node.args) >= 2:
                a = self.HandleExprLlvm(Node.args[0])
                b = self.HandleExprLlvm(Node.args[1])
                if a and b:
                    is_float = isinstance(a.type, (ir.FloatType, ir.DoubleType)) or isinstance(b.type, (ir.FloatType, ir.DoubleType))
                    if is_float:
                        fa = Gen._to_float(a, ir.FloatType()) if isinstance(a.type, (ir.FloatType, ir.DoubleType)) else Gen.builder.sitofp(a, ir.FloatType(), name="min_int2float")
                        fb = Gen._to_float(b, ir.FloatType()) if isinstance(b.type, (ir.FloatType, ir.DoubleType)) else Gen.builder.sitofp(b, ir.FloatType(), name="min_int2float")
                        cmp = Gen.builder.fcmp_ordered('olt', fa, fb, name="min_cmp")
                        return Gen.builder.select(cmp, fa, fb, name="min_val")
                    else:
                        cmp = Gen.builder.icmp_signed('<', a, b, name="min_cmp")
                        return Gen.builder.select(cmp, a, b, name="min_val")
            elif len(Node.args) == 1:
                return self.HandleExprLlvm(Node.args[0])
            return ir.Constant(ir.IntType(32), 0)
        elif FuncName == 'max':
            if len(Node.args) >= 2:
                a = self.HandleExprLlvm(Node.args[0])
                b = self.HandleExprLlvm(Node.args[1])
                if a and b:
                    is_float = isinstance(a.type, (ir.FloatType, ir.DoubleType)) or isinstance(b.type, (ir.FloatType, ir.DoubleType))
                    if is_float:
                        fa = Gen._to_float(a, ir.FloatType()) if isinstance(a.type, (ir.FloatType, ir.DoubleType)) else Gen.builder.sitofp(a, ir.FloatType(), name="max_int2float")
                        fb = Gen._to_float(b, ir.FloatType()) if isinstance(b.type, (ir.FloatType, ir.DoubleType)) else Gen.builder.sitofp(b, ir.FloatType(), name="max_int2float")
                        cmp = Gen.builder.fcmp_ordered('ogt', fa, fb, name="max_cmp")
                        return Gen.builder.select(cmp, fa, fb, name="max_val")
                    else:
                        cmp = Gen.builder.icmp_signed('>', a, b, name="max_cmp")
                        return Gen.builder.select(cmp, a, b, name="max_val")
            elif len(Node.args) == 1:
                return self.HandleExprLlvm(Node.args[0])
            return ir.Constant(ir.IntType(32), 0)
        elif FuncName == 'str':
            if Node.args:
                arg_node = Node.args[0]
                arg_val = self.HandleExprLlvm(arg_node)
                if arg_val:
                    if isinstance(arg_val.type, ir.PointerType):
                        ClassName = self.Trans.ExprHandler._get_var_class(arg_node, Gen)
                        if ClassName and Gen._has_function(f'{ClassName}.__str__'):
                            if isinstance(arg_val.type, ir.PointerType) and isinstance(arg_val.type.pointee, ir.IntType) and arg_val.type.pointee.width == 8:
                                if ClassName in Gen.structs:
                                    arg_val = Gen.builder.bitcast(arg_val, ir.PointerType(Gen.structs[ClassName]), name=f"cast_{ClassName}_str")
                            str_val = Gen.builder.call(Gen._get_function(f'{ClassName}.__str__'), [arg_val], name=f"call_{ClassName}.__str__")
                            return str_val
                        return arg_val
                    return self._EmitStringFromValue(arg_val)
            return ir.Constant(ir.IntType(8).as_pointer(), None)
        elif FuncName == 'bytes':
            # bytes() — 类型转换为 i8* 指针 (等同于 t.CPtr / str)
            # bytes(int_addr) → inttoptr; bytes(ptr) → bitcast
            if Node.args:
                arg_val = self.HandleExprLlvm(Node.args[0])
                if arg_val:
                    if isinstance(arg_val.type, ir.PointerType):
                        if isinstance(arg_val.type.pointee, ir.IntType) and arg_val.type.pointee.width == 8:
                            return arg_val
                        return Gen.builder.bitcast(arg_val, ir.IntType(8).as_pointer(), name="bytes_cast")
                    if isinstance(arg_val.type, ir.IntType):
                        return Gen.builder.inttoptr(arg_val, ir.IntType(8).as_pointer(), name="bytes_int2ptr")
            return ir.Constant(ir.IntType(8).as_pointer(), None)
        elif FuncName == 'input':
            return self._HandleInputLlvm(Node)
        elif FuncName == 'isinstance':
            # isinstance(obj, Type) — 静态类型系统下编译时解析
            # TransPyC 是静态类型系统，运行时无 RTTI。
            # 对于编译时已知类型，若变量类型是目标类型的子类则生成 true，否则 false。
            # 若无法确定（如基类指针指向子类），保守生成 false。
            # 注意：这主要让编译时辅助方法（如 c.py 中的 Asm._parse_asm_descr）能通过编译，
            # 这些方法不在运行时被调用，行为不正确不影响程序。
            if len(Node.args) >= 2:
                ObjVal: ir.Value | None = self.HandleExprLlvm(Node.args[0])
                TypeNode: ast.expr = Node.args[1]
                TargetClassName: str = ''
                if isinstance(TypeNode, ast.Name):
                    TargetClassName = TypeNode.id
                elif isinstance(TypeNode, ast.Attribute):
                    TargetClassName = TypeNode.attr
                if ObjVal is not None and TargetClassName:
                    ObjType: ir.Type = ObjVal.type
                    # 解引用指针获取 pointee 类型
                    if isinstance(ObjType, ir.PointerType):
                        ObjType = ObjType.pointee
                    # 检查 pointee 是否是目标结构体类型
                    if isinstance(ObjType, ir.IdentifiedStructType):
                        ObjStructName: str = getattr(ObjType, 'name', '')
                        ShortName: str = ObjStructName.split('.')[-1] if '.' in ObjStructName else ObjStructName
                        if ShortName == TargetClassName:
                            return ir.Constant(ir.IntType(1), 1)
                    # 检查 Gen.var_struct_class
                    if isinstance(Node.args[0], ast.Name):
                        VarClassName: str | None = Gen.var_struct_class.get(Node.args[0].id)
                        if VarClassName == TargetClassName:
                            return ir.Constant(ir.IntType(1), 1)
                return ir.Constant(ir.IntType(1), 0)
            return ir.Constant(ir.IntType(1), 0)
        elif FuncName == 'ord':
            if Node.args:
                return self._HandleOrdLlvm(Node.args[0])
            return ir.Constant(ir.IntType(32), 0)
        elif FuncName == 'chr':
            if Node.args:
                return self._HandleChrLlvm(Node.args[0])
            return ir.Constant(ir.IntType(8), 0)
        elif FuncName == 'malloc':
            return self._HandleMallocLlvm(Node.args)
        elif FuncName == 'realloc':
            return self._HandleReallocLlvm(Node.args)
        elif FuncName == 'free':
            return self._HandleFreeLlvm(Node.args)
        elif FuncName == 'memcpy':
            return self._HandleMemcpyLlvm(Node.args)
        elif FuncName == 'memset':
            return self._HandleMemsetLlvm(Node.args)
        elif FuncName == 'va_start':
            return self._HandleVaStartLlvm(Node.args)
        elif FuncName == 'va_end':
            return self._HandleVaEndLlvm(Node.args)
        elif FuncName == 'va_arg':
            return self._HandleVaArgLlvm(Node.args)
        elif FuncName == 'dir':
            return self._HandleDirLlvm(Node)
        elif FuncName == 'type':
            return self._HandleTypeLlvm(Node)
        return None

    def _HandlePrintLlvm(self, Node: ast.Call) -> ir.Value | None:
        Gen: LlvmGeneratorMixin = self.Trans.LlvmGen
        printf_func: ir.Function = Gen.get_or_declare_c_func('printf', ir.FunctionType(ir.IntType(32), [ir.PointerType(ir.IntType(8))], var_arg=True))
        args: list[ast.expr] = Node.args
        end_arg: ast.expr | None = None
        sep_arg: ast.expr | None = None
        if Node.keywords:
            for kw in Node.keywords:
                if kw.arg == 'end':
                    end_arg = kw.value
                elif kw.arg == 'sep':
                    sep_arg = kw.value
        sep_str: str = ' '
        if sep_arg and isinstance(sep_arg, ast.Constant) and isinstance(sep_arg.value, str):
            sep_str = sep_arg.value
        end_str: str = '\n'
        if end_arg:
            if isinstance(end_arg, ast.Constant) and isinstance(end_arg.value, str):
                end_str = end_arg.value
            elif isinstance(end_arg, ast.Constant) and end_arg.value is None:
                end_str = ''
        if not args:
            if end_str:
                nl_fmt = Gen.emit_constant(end_str, 'string')
                Gen.builder.call(printf_func, [nl_fmt], name="print_nl")
            return ir.Constant(ir.IntType(32), 0)
        has_fstring = any(isinstance(arg, ast.JoinedStr) for arg in args)
        if has_fstring:
            return self._HandlePrintWithFString(Node, printf_func, args, sep_str, end_str)
        fmt_parts = []
        fmt_args = []
        for i, arg in enumerate(args):
            if i > 0:
                fmt_parts.append(sep_str)
            val = self.HandleExprLlvm(arg)
            if not val:
                fmt_parts.append('(null)')
                continue
            if isinstance(val, ir.Constant) and isinstance(val.type, ir.PointerType) and val.constant is None:
                fmt_parts.append('nil')
                continue
            if isinstance(val.type, ir.PointerType):
                pointee = val.type.pointee
                if isinstance(pointee, ir.IntType) and pointee.width == 8:
                    fmt_parts.append('%s')
                    fmt_args.append(val)
                elif isinstance(pointee, ir.ArrayType) and isinstance(pointee.element, ir.IntType) and pointee.element.width == 8:
                    elem_ptr = Gen.builder.gep(val, [ir.Constant(ir.IntType(32), 0), ir.Constant(ir.IntType(32), 0)], name="print_arr_to_ptr")
                    fmt_parts.append('%s')
                    fmt_args.append(elem_ptr)
                elif isinstance(pointee, (ir.IdentifiedStructType, ir.LiteralStructType)):
                    ClassName = self.Trans.ExprHandler._get_var_class(arg, Gen)
                    if not ClassName and isinstance(arg, ast.Name):
                        ClassName = Gen.var_struct_class.get(arg.id)
                    if ClassName and Gen._has_function(f'{ClassName}.__str__'):
                        if isinstance(val.type, ir.PointerType) and isinstance(val.type.pointee, ir.IntType) and val.type.pointee.width == 8:
                            if ClassName in Gen.structs:
                                val = Gen.builder.bitcast(val, ir.PointerType(Gen.structs[ClassName]), name=f"cast_{ClassName}")
                        str_val = Gen.builder.call(Gen._get_function(f'{ClassName}.__str__'), [val], name=f"call_{ClassName}.__str__")
                        fmt_parts.append('%s')
                        fmt_args.append(str_val)
                    else:
                        int_val = Gen.builder.ptrtoint(val, ir.IntType(64), name="print_ptr_to_int")
                        fmt_parts.append('0x%llx')
                        fmt_args.append(int_val)
                else:
                    int_val = Gen.builder.ptrtoint(val, ir.IntType(64), name="print_ptr_to_int")
                    fmt_parts.append('%lld')
                    fmt_args.append(int_val)
            elif isinstance(val.type, ir.IntType):
                is_unsigned = self._is_val_unsigned(arg, val)
                if val.type.width == 1:
                    fmt_parts.append('%d')
                    val = Gen.builder.zext(val, ir.IntType(32), name="zext_bool_print")
                elif val.type.width == 8:
                    if self._is_char_type(arg):
                        char_var = Gen._allocaEntry(ir.IntType(8), name="print_char_buf")
                        Gen.builder.store(val, char_var)
                        fmt_parts.append('%c')
                        fmt_args.append(char_var)
                        continue
                    fmt_parts.append('%d')
                    if is_unsigned:
                        val = Gen.builder.zext(val, ir.IntType(32), name="zext_i8_print")
                    else:
                        val = Gen.builder.sext(val, ir.IntType(32), name="sext_i8_print")
                elif val.type.width == 16:
                    fmt_parts.append('%u' if is_unsigned else '%d')
                    if is_unsigned:
                        val = Gen.builder.zext(val, ir.IntType(32), name="zext_i16_print")
                    else:
                        val = Gen.builder.sext(val, ir.IntType(32), name="sext_i16_print")
                elif val.type.width == 32:
                    fmt_parts.append('%u' if is_unsigned else '%d')
                elif val.type.width == 64:
                    fmt_parts.append('%llu' if is_unsigned else '%lld')
                else:
                    fmt_parts.append('%d')
                    val = Gen.builder.zext(val, ir.IntType(32), name="zext_int_print")
                fmt_args.append(val)
            elif isinstance(val.type, ir.FloatType):
                fmt_parts.append('%f')
                fmt_args.append(Gen.builder.fpext(val, ir.DoubleType(), name="fpext_printf_float"))
            elif isinstance(val.type, ir.DoubleType):
                fmt_parts.append('%f')
                fmt_args.append(val)
            else:
                fmt_parts.append('(unknown)')
        fmt_parts.append(end_str)
        fmt_str = ''.join(fmt_parts)
        fmt_ptr = Gen._create_string_global(fmt_str)
        call_args = [fmt_ptr] + fmt_args
        return Gen.builder.call(printf_func, call_args, name="print_call")

    def _HandlePrintWithFString(self, Node: ast.Call, printf_func: ir.Function, args: list[ast.expr], sep_str: str, end_str: str) -> ir.Value | None:
        Gen: LlvmGeneratorMixin = self.Trans.LlvmGen
        for i, arg in enumerate(args):
            if i > 0:
                sep_const = Gen.emit_constant(sep_str, 'string')
                Gen.builder.call(printf_func, [sep_const], name="print_sep")
            if isinstance(arg, ast.JoinedStr):
                str_val = self.HandleExprLlvm(arg)
                if str_val:
                    Gen._emit_printf([str_val], unsigned_flags=[False], sep=None, end=None)
            else:
                ClassName = self.Trans.ExprHandler._get_var_class(arg, Gen)
                if ClassName and Gen._has_function(f'{ClassName}.__str__'):
                    obj_val = self.HandleExprLlvm(arg)
                    if obj_val:
                        if isinstance(obj_val.type, ir.PointerType) and isinstance(obj_val.type.pointee, ir.IntType) and obj_val.type.pointee.width == 8:
                            if ClassName in Gen.structs:
                                obj_val = Gen.builder.bitcast(obj_val, ir.PointerType(Gen.structs[ClassName]), name=f"cast_{ClassName}")
                        str_val = Gen.builder.call(Gen._get_function(f'{ClassName}.__str__'), [obj_val], name=f"call_{ClassName}.__str__")
                        Gen._RegisterTempPtr(str_val)
                        Gen._emit_printf([str_val], unsigned_flags=[False], sep=None, end=None)
                else:
                    val = self.HandleExprLlvm(arg)
                    if val:
                        if isinstance(val.type, ir.PointerType):
                            pointee = val.type.pointee
                            if not (isinstance(pointee, ir.IntType) and pointee.width == 8):
                                try:
                                    val = Gen._load(val, name="print_Load")
                                except Exception as _e:
                                    if _config_mode == "strict":
                                        self.Trans.LogWarning(f"异常被忽略: {_e}")
                        is_u = Gen._check_node_unsigned(arg)
                        if not is_u and id(val) in Gen._unsigned_results:
                            is_u = True
                        Gen._emit_printf([val], unsigned_flags=[is_u], sep=None, end=None)
        if end_str:
            end_const = Gen.emit_constant(end_str, 'string')
            Gen.builder.call(printf_func, [end_const], name="print_end")
        return ir.Constant(ir.IntType(32), 0)

    def _is_char_type(self, arg_node: ast.AST) -> bool:
        if isinstance(arg_node, ast.Call):
            if isinstance(arg_node.func, ast.Name):
                return arg_node.func.id in ('CChar', 'CUInt8T', 'CInt8T')
            if isinstance(arg_node.func, ast.Attribute):
                return arg_node.func.attr in ('CChar', 'CUInt8T', 'CInt8T')
        return False

    def _is_val_unsigned(self, arg_node: ast.AST, val: ir.Value) -> bool:
        Gen: LlvmGeneratorMixin = self.Trans.LlvmGen
        if isinstance(arg_node, ast.Name):
            var_name: str = arg_node.id
            signedness: object = Gen.var_signedness.get(var_name)
            if signedness:
                if isinstance(signedness, bool):
                    return signedness
                return 'unsigned' in signedness
        if isinstance(val.type, ir.IntType):
            return False
        return False

    def _try_declare_c_lib_func(self, func_name: str, Gen: LlvmGeneratorMixin) -> ir.Function | None:
        if func_name not in self._C_LIB_FUNCS:
            return None
        ret_type: ir.Type
        param_types: list[ir.Type]
        ret_type, param_types = self._C_LIB_FUNCS[func_name]()
        func_type: ir.FunctionType = ir.FunctionType(ret_type, param_types)
        func: ir.Function = ir.Function(Gen.module, func_type, name=func_name)
        Gen.functions[func_name] = func
        return func

    def _HandleLenLlvm(self, arg_node: ast.AST) -> ir.Value | None:
        Gen: LlvmGeneratorMixin = self.Trans.LlvmGen
        if isinstance(arg_node, ast.Attribute) and isinstance(arg_node.value, ast.Name) and arg_node.value.id == 'self':
            attr_name = arg_node.attr
            len_member = f'{attr_name}__len'
            current_class = self.Trans._CurrentCpythonObjectClass
            if current_class and current_class in Gen.class_members:
                for m_name, m_type in Gen.class_members[current_class]:
                    if m_name == len_member:
                        self_val = Gen._get_var_ptr('self')
                        if self_val:
                            self_ptr = Gen._load(self_val, name="self_for_len")
                            offset = Gen._get_member_offset(len_member, current_class)
                            len_ptr = Gen.builder.gep(self_ptr, [ir.Constant(ir.IntType(32), 0), ir.Constant(ir.IntType(32), offset)], name=f"self_{len_member}_ptr")
                            return Gen._load(len_ptr, name=f"self_{len_member}")
        val = self.HandleExprLlvm(arg_node)
        if not val:
            return None
        if isinstance(val.type, ir.PointerType):
            pointee = val.type.pointee
            if isinstance(pointee, ir.PointerType):
                val = Gen._load(val, name="len_deref")
                pointee = val.type.pointee
            if isinstance(pointee, (ir.IdentifiedStructType, ir.LiteralStructType)):
                for CN, ST in Gen.structs.items():
                    if pointee == ST:
                        result = self.Trans.ExprUtils._try_operator_overLoad(CN, '__len__', val, Gen)
                        if result is not None:
                            return result
                        break
            if isinstance(pointee, ir.ArrayType):
                return ir.Constant(ir.IntType(64), pointee.count)
            if isinstance(pointee, (ir.FloatType, ir.DoubleType, ir.IntType)) and pointee.width != 8:
                return ir.Constant(ir.IntType(64), 0)
            if val.type != ir.PointerType(ir.IntType(8)):
                val = Gen.builder.bitcast(val, ir.PointerType(ir.IntType(8)), name="str_ptr_cast")
            correct_strlen_type = ir.FunctionType(ir.IntType(64), [ir.PointerType(ir.IntType(8))])
            strlen_func = None
            if 'strlen' in Gen.functions:
                existing = Gen.functions['strlen']
                if existing.ftype == correct_strlen_type:
                    strlen_func = existing
            if not strlen_func:
                try:
                    strlen_func = ir.Function(Gen.module, correct_strlen_type, name='strlen')
                    Gen.functions['strlen'] = strlen_func
                except Exception as _e:
                    if _config_mode == "strict":
                        self.Trans.LogWarning(f"异常被忽略: {_e}")
            if strlen_func:
                result = Gen.builder.call(strlen_func, [val], name="strlen_call")
                return result
        elif isinstance(val.type, ir.ArrayType):
            return ir.Constant(ir.IntType(64), val.type.count)
        return ir.Constant(ir.IntType(64), 0)

    def _resolve_nested_opaque_structs(self, struct_type: ir.Type, Gen: LlvmGeneratorMixin, visited: set | None = None) -> None:
        """递归解析嵌套的 opaque struct，从 stub 文件中加载其定义"""
        if visited is None:
            visited = set()
        if isinstance(struct_type, ir.PointerType):
            self._resolve_nested_opaque_structs(struct_type.pointee, Gen, visited)
            return
        if not isinstance(struct_type, ir.IdentifiedStructType):
            return
        if struct_type in visited:
            return
        visited.add(struct_type)
        if struct_type.elements is None or len(struct_type.elements) == 0:
            # 尝试从 stub 加载 opaque struct
            try:
                st_name = struct_type.name
            except Exception:
                st_name = None
            if st_name:
                # 提取短名称（去掉模块前缀）
                if '.' in st_name:
                    short_name = st_name.split('.', 1)[1]
                else:
                    short_name = st_name
                self.Trans.ImportHandler._TryLoadStructFromStub(short_name, Gen)
            return
        # 递归解析嵌套的 struct 成员
        for elem in struct_type.elements:
            self._resolve_nested_opaque_structs(elem, Gen, visited)

    def _HandleSizeofLlvm(self, Node: ast.AST) -> ir.Value:
        Gen: LlvmGeneratorMixin = self.Trans.LlvmGen
        type_name: str | None
        if isinstance(Node, ast.Name):
            type_name = Node.id
        elif isinstance(Node, ast.Attribute):
            type_name = Node.attr
        else:
            return ir.Constant(ir.IntType(64), 0)

        if type_name not in Gen.structs:
            # str/bytes 是指针类型 (char*/void*)，sizeof = 指针大小
            if type_name in ('str', 'bytes'):
                return ir.Constant(ir.IntType(64), 8)
            ctype_cls = CTypeRegistry.GetClassByName(type_name)
            if ctype_cls is not None:
                try:
                    ctype_inst = ctype_cls()
                    size_bits = getattr(ctype_inst, 'Size', 0) or 0
                    size_bytes = size_bits // 8
                    return ir.Constant(ir.IntType(64), size_bytes)
                except Exception as _e:
                    if _config_mode == "strict":
                        raise
                    _vlog().warning(f"解析类型失败: {_e}", "Exception")
            resolved = CTypeRegistry.ResolveName(type_name)
            if resolved:
                ctype_cls, ptr_level = resolved
                try:
                    ctype_inst = ctype_cls()
                    size_bits = getattr(ctype_inst, 'Size', 0) or 0
                    size_bytes = size_bits // 8
                    if ptr_level > 0:
                        size_bytes = 8
                    return ir.Constant(ir.IntType(64), size_bytes)
                except Exception as _e:
                    if _config_mode == "strict":
                        raise
                    _vlog().warning(f"解析类型失败: {_e}", "Exception")
            return ir.Constant(ir.IntType(64), 0)

        struct_type = Gen.structs[type_name]
        if isinstance(struct_type, ir.PointerType):
            struct_type = struct_type.pointee
        if isinstance(struct_type, ir.IdentifiedStructType) and (struct_type.elements is None or len(struct_type.elements) == 0):
            self.Trans.ImportHandler._TryLoadStructFromStub(type_name, Gen)
            struct_type = Gen.structs.get(type_name, struct_type)
        # 递归解析所有嵌套的 opaque struct，确保 sizeof 计算正确
        self._resolve_nested_opaque_structs(struct_type, Gen)
        size = Gen._get_struct_size(struct_type)
        if size > 0:
            return ir.Constant(ir.IntType(64), size)
        return ir.Constant(ir.IntType(64), 0)

    def _HandleAbsLlvm(self, arg_node: ast.AST) -> ir.Value | None:
        Gen: LlvmGeneratorMixin = self.Trans.LlvmGen
        val: ir.Value | None = self.HandleExprLlvm(arg_node)
        if not val:
            return None
        if isinstance(val.type, ir.PointerType):
            pointee = val.type.pointee
            if isinstance(pointee, (ir.IdentifiedStructType, ir.LiteralStructType)):
                for CN, ST in Gen.structs.items():
                    if pointee == ST:
                        result = self.Trans.ExprUtils._try_operator_overLoad(CN, '__abs__', val, Gen)
                        if result is not None:
                            return result
                        break
        if isinstance(val.type, ir.IntType):
            neg_val = Gen.builder.neg(val, name="abs_neg")
            is_neg = Gen.builder.icmp_signed('<', val, ir.Constant(val.type, 0), name="is_neg")
            return Gen.builder.select(is_neg, neg_val, val, name="abs_result")
        elif isinstance(val.type, (ir.FloatType, ir.DoubleType)):
            zero = ir.Constant(val.type, 0.0)
            neg_val = Gen.builder.fneg(val, name="fabs_neg")
            is_neg = Gen.builder.fcmp_ordered('<', val, zero, name="f_is_neg")
            return Gen.builder.select(is_neg, neg_val, val, name="fabs_result")
        return None

    def _HandleDirLlvm(self, Node: ast.Call) -> ir.Value:
        Gen: LlvmGeneratorMixin = self.Trans.LlvmGen
        return ir.Constant(ir.IntType(8).as_pointer(), None)

    def _HandleTypeLlvm(self, Node: ast.Call) -> ir.Value:
        Gen: LlvmGeneratorMixin = self.Trans.LlvmGen
        type_str: str
        if not Node.args:
            type_str = "<class 'unknown' size=0 signed=false, ptr=false>"
        else:
            arg = Node.args[0]
            enum_type_name = None

            def _get_attr_path(node: ast.AST) -> str | None:
                if isinstance(node, ast.Name):
                    return node.id
                elif isinstance(node, ast.Attribute):
                    return f"{_get_attr_path(node.value)}.{node.attr}"
                return None

            if isinstance(arg, ast.Name):
                arg_name = arg.id
                Gen = self.Trans.LlvmGen
                if arg_name in Gen.var_type_info:
                    type_info = Gen.var_type_info[arg_name]
                    if isinstance(type_info, dict) and type_info.get('type') == 'enum':
                        enum_type_name = type_info.get('name')
                if not enum_type_name and self.Trans.SymbolTable.has(arg_name):
                    TypeInfo = self.Trans.SymbolTable[arg_name]
                    if TypeInfo.IsEnum:
                        enum_type_name = arg_name
            elif isinstance(arg, ast.Attribute):
                LastPart = None
                enum_class_name = None
                if isinstance(arg.value, ast.Name):
                    LastPart = arg.attr
                    if self.Trans.SymbolTable.has(LastPart):
                        AttrInfo = self.Trans.SymbolTable[LastPart]
                        if AttrInfo.IsEnumMember and AttrInfo.EnumName:
                            enum_type_name = AttrInfo.EnumName
                elif isinstance(arg.value, ast.Attribute):
                    attr_path = _get_attr_path(arg)
                    if attr_path:
                        parts = attr_path.split('.')
                        if len(parts) >= 2:
                            enum_class_name = parts[-2]
                            LastPart = parts[-1]
                            qualified_name_dot = f"{enum_class_name}.{LastPart}"
                            qualified_name_under = f"{enum_class_name}_{LastPart}"
                            enum_member_found = None
                            for qname in (qualified_name_dot, qualified_name_under):
                                if self.Trans.SymbolTable.has(qname):
                                    info = self.Trans.SymbolTable[qname]
                                    if info.IsEnumMember and info.EnumName == enum_class_name:
                                        enum_member_found = info
                                        break
                            if not enum_member_found:
                                for key in self.Trans.SymbolTable:
                                    if key == LastPart:
                                        info = self.Trans.SymbolTable[key]
                                        if info.IsEnumMember and info.EnumName == enum_class_name:
                                            enum_member_found = info
                                            break
                            if enum_member_found:
                                enum_type_name = enum_class_name
            if enum_type_name:
                type_str = f"<enum '{enum_type_name}' size=4 signed=true, ptr=false>"
            else:
                llvm_type = self.Trans.ExprUtils._infer_expr_llvm_type_full(arg)
                if isinstance(llvm_type, ir.PointerType):
                    pointee = llvm_type.pointee
                    if isinstance(pointee, (ir.IdentifiedStructType, ir.LiteralStructType)):
                        llvm_type = pointee
                type_info = self.Trans.ExprUtils._llvm_type_to_detailed_string(llvm_type)
                type_str = f"<class '{type_info['name']}' size={type_info['size']} signed={str(type_info['signed']).lower()}, ptr={str(type_info['ptr']).lower()}>"
        return Gen.emit_constant(type_str, 'string')

    def _HandleInputLlvm(self, Node: ast.Call) -> ir.Value:
        Gen: LlvmGeneratorMixin = self.Trans.LlvmGen
        if Node.args and isinstance(Node.args[0], ast.Constant) and isinstance(Node.args[0].value, str):
            prompt = Node.args[0].value
            prompt_ptr = Gen.emit_constant(prompt, 'string')
            printf_func = Gen.get_or_declare_c_func('printf', ir.FunctionType(ir.IntType(32), [ir.PointerType(ir.IntType(8))], var_arg=True))
            Gen.builder.call(printf_func, [prompt_ptr])
        scanf_func = Gen.get_or_declare_c_func('scanf', ir.FunctionType(ir.IntType(32), [ir.PointerType(ir.IntType(8))], var_arg=True))
        input_buffer = Gen._alloca(ir.ArrayType(ir.IntType(8), 256), name="input_buffer")
        result = Gen.builder.call(scanf_func, [Gen.emit_constant("%255s", 'string'), input_buffer])
        return Gen.builder.gep(input_buffer, [ir.Constant(ir.IntType(32), 0), ir.Constant(ir.IntType(32), 0)], name="input_result")

    def _HandleAtoiLlvm(self, str_ptr: ir.Value) -> ir.Value:
        Gen: LlvmGeneratorMixin = self.Trans.LlvmGen
        atoi_func: ir.Function = Gen.get_or_declare_c_func('atoi', ir.FunctionType(ir.IntType(32), [ir.PointerType(ir.IntType(8))]))
        return Gen.builder.call(atoi_func, [str_ptr], name="atoi_result")

    def _HandleOrdLlvm(self, expr_node: ast.AST) -> ir.Value:
        Gen: LlvmGeneratorMixin = self.Trans.LlvmGen
        val: ir.Value | None = self.HandleExprLlvm(expr_node)
        if val and isinstance(val.type, ir.PointerType) and isinstance(val.type.pointee, ir.IntType) and val.type.pointee.width == 8:
            return Gen._load(val, name="ord_result")
        return ir.Constant(ir.IntType(32), 0)

    def _HandleChrLlvm(self, expr_node: ast.AST) -> ir.Value:
        Gen: LlvmGeneratorMixin = self.Trans.LlvmGen
        val: ir.Value | None = self.HandleExprLlvm(expr_node)
        if val:
            char_ptr = Gen._alloca(ir.IntType(8), name="chr_char")
            Gen.builder.store(Gen.builder.trunc(val, ir.IntType(8), name="trunc_chr"), char_ptr)
            return Gen.builder.gep(char_ptr, [ir.Constant(ir.IntType(32), 0)], name="chr_result")
        return ir.Constant(ir.IntType(8).as_pointer(), None)

    def _EmitStringFromValue(self, val: ir.Value) -> ir.Value:
        Gen: LlvmGeneratorMixin = self.Trans.LlvmGen
        if isinstance(val.type, ir.IntType):
            if val.type.width == 8:
                buf = Gen._alloca(ir.IntType(8), name="str_buf", size=ir.Constant(ir.IntType(32), 2))
                null_ptr = Gen.builder.gep(buf, [ir.Constant(ir.IntType(32), 1)], name="null_byte")
                Gen.builder.store(ir.Constant(ir.IntType(8), 0), null_ptr)
                Gen.builder.store(val, buf)
                return Gen.builder.gep(buf, [ir.Constant(ir.IntType(32), 0)], name="str_result")
            buf = Gen._alloca(ir.IntType(8), name="str_buf", size=ir.Constant(ir.IntType(32), 32))
            snprintf_func = Gen.get_or_declare_c_func('snprintf', ir.FunctionType(ir.IntType(32), [
                ir.PointerType(ir.IntType(8)),
                ir.IntType(64),
                ir.PointerType(ir.IntType(8))
            ], var_arg=True))
            fmt_ptr = Gen.emit_constant("%d", 'string')
            Gen.builder.call(snprintf_func, [buf, ir.Constant(ir.IntType(64), 32), fmt_ptr, val])
            return Gen.builder.gep(buf, [ir.Constant(ir.IntType(32), 0)], name="str_result")
        return ir.Constant(ir.IntType(8).as_pointer(), None)

    def _HandleMallocLlvm(self, args: list[ast.expr]) -> ir.Value:
        Gen: LlvmGeneratorMixin = self.Trans.LlvmGen
        malloc_type: ir.FunctionType = ir.FunctionType(ir.PointerType(ir.IntType(8)), [ir.IntType(64)])
        malloc_func: ir.Function = Gen._get_or_declare_func('malloc', malloc_type)
        param_type: ir.Type = malloc_func.type.pointee.args[0]
        size_val: ir.Value | None = None
        if args:
            size_val = self.HandleExprLlvm(args[0])
            if size_val and isinstance(size_val.type, ir.IntType):
                if isinstance(param_type, ir.IntType) and size_val.type.width != param_type.width:
                    if size_val.type.width < param_type.width:
                        size_val = Gen.builder.zext(size_val, param_type, name="zext_malloc_size")
                    else:
                        size_val = Gen.builder.trunc(size_val, param_type, name="trunc_malloc_size")
        if not size_val:
            size_val = ir.Constant(param_type, 1)
        result: ir.Value = Gen.builder.call(malloc_func, [size_val], name="malloc_result")
        return Gen.builder.bitcast(result, ir.IntType(8).as_pointer(), name="malloc_cast")

    def _HandleReallocLlvm(self, args: list[ast.expr]) -> ir.Value:
        Gen: LlvmGeneratorMixin = self.Trans.LlvmGen
        realloc_type: ir.FunctionType = ir.FunctionType(ir.PointerType(ir.IntType(8)), [ir.PointerType(ir.IntType(8)), ir.IntType(64)])
        realloc_func: ir.Function = Gen._get_or_declare_func('realloc', realloc_type)
        size_param_type: ir.Type = realloc_func.type.pointee.args[1]
        ptr_val: ir.Value | None = None
        size_val: ir.Value | None = None
        if len(args) >= 2:
            ptr_val = self.HandleExprLlvm(args[0])
            size_val = self.HandleExprLlvm(args[1])
        elif len(args) == 1:
            size_val = self.HandleExprLlvm(args[0])
        if not ptr_val:
            ptr_val = ir.Constant(ir.PointerType(ir.IntType(8)), None)
        if isinstance(ptr_val.type, ir.PointerType) and not (isinstance(ptr_val.type.pointee, ir.IntType) and ptr_val.type.pointee.width == 8):
            ptr_val = Gen.builder.bitcast(ptr_val, ir.PointerType(ir.IntType(8)), name="realloc_cast_ptr")
        if size_val and isinstance(size_val.type, ir.IntType):
            if isinstance(size_param_type, ir.IntType) and size_val.type.width != size_param_type.width:
                if size_val.type.width < size_param_type.width:
                    size_val = Gen.builder.zext(size_val, size_param_type, name="zext_realloc_size")
                else:
                    size_val = Gen.builder.trunc(size_val, size_param_type, name="trunc_realloc_size")
        if not size_val:
            size_val = ir.Constant(size_param_type, 0)
        result: ir.Value = Gen.builder.call(realloc_func, [ptr_val, size_val], name="realloc_result")
        return Gen.builder.bitcast(result, ir.IntType(8).as_pointer(), name="realloc_cast")

    def _HandleFreeLlvm(self, args: list[ast.expr]) -> ir.Value:
        Gen: LlvmGeneratorMixin = self.Trans.LlvmGen
        free_type: ir.FunctionType = ir.FunctionType(ir.VoidType(), [ir.PointerType(ir.IntType(8))])
        free_func: ir.Function = Gen._get_or_declare_func('free', free_type)
        if args:
            var_name: str | None = None
            if isinstance(args[0], ast.Name):
                var_name = args[0].id
            ptr_val: ir.Value | None = self.HandleExprLlvm(args[0])
            if ptr_val is not None:
                if var_name and hasattr(Gen, '_var_to_heap_ptr') and var_name in Gen._var_to_heap_ptr:
                    registered_val = Gen._var_to_heap_ptr[var_name]
                    Gen._unregister_local_heap_ptr(registered_val)
                    del Gen._var_to_heap_ptr[var_name]
                if isinstance(ptr_val.type, ir.PointerType):
                    if isinstance(ptr_val.type.pointee, ir.IntType) and ptr_val.type.pointee.width == 8:
                        pass
                    else:
                        ptr_val = Gen.builder.bitcast(ptr_val, ir.PointerType(ir.IntType(8)), name="free_cast_ptr")
                elif isinstance(ptr_val.type, ir.IntType):
                    ptr_val = Gen.builder.inttoptr(ptr_val, ir.PointerType(ir.IntType(8)), name="free_inttoptr")
                Gen.builder.call(free_func, [ptr_val], name="free_call")
        return ir.Constant(ir.IntType(32), 0)

    def _HandleMemcpyLlvm(self, args: list[ast.expr]) -> ir.Value:
        Gen: LlvmGeneratorMixin = self.Trans.LlvmGen
        if 'llvm.memcpy' not in Gen.functions:
            memcpy_type: ir.FunctionType = ir.FunctionType(ir.VoidType(), [ir.PointerType(ir.IntType(8)), ir.PointerType(ir.IntType(8)), ir.IntType(64), ir.IntType(1)])
            Gen.functions['llvm.memcpy'] = ir.Function(Gen.module, memcpy_type, name='llvm.memcpy')
        if len(args) >= 3:
            dst: ir.Value | None = self.HandleExprLlvm(args[0])
            src: ir.Value | None = self.HandleExprLlvm(args[1])
            size: ir.Value | None = self.HandleExprLlvm(args[2])
            if dst and src and size:
                i8ptr: ir.PointerType = ir.PointerType(ir.IntType(8))
                if isinstance(dst.type, ir.PointerType) and dst.type != i8ptr:
                    dst = Gen.builder.bitcast(dst, i8ptr, name="memcpy_dst_cast")
                elif isinstance(dst.type, ir.IntType):
                    if dst.type.width < 64:
                        dst = Gen.builder.zext(dst, ir.IntType(64), name="zext_dst_ptr")
                    dst = Gen.builder.inttoptr(dst, i8ptr, name="dst_int2ptr")
                if isinstance(src.type, ir.PointerType) and src.type != i8ptr:
                    src = Gen.builder.bitcast(src, i8ptr, name="memcpy_src_cast")
                elif isinstance(src.type, ir.IntType):
                    if src.type.width < 64:
                        src = Gen.builder.zext(src, ir.IntType(64), name="zext_src_ptr")
                    src = Gen.builder.inttoptr(src, i8ptr, name="src_int2ptr")
                if isinstance(size.type, ir.IntType) and size.type.width < 64:
                    size = Gen.builder.zext(size, ir.IntType(64), name="zext_memcpy_size")
                isvolatile: ir.Constant = ir.Constant(ir.IntType(1), 0)
                Gen.builder.call(Gen.functions['llvm.memcpy'], [dst, src, size, isvolatile], name="memcpy_call")
        return ir.Constant(ir.IntType(32), 0)

    def _HandleMemsetLlvm(self, args: list[ast.expr]) -> ir.Value:
        Gen: LlvmGeneratorMixin = self.Trans.LlvmGen
        memset_func: ir.Function = Gen.get_or_declare_c_func('memset', ir.FunctionType(ir.PointerType(ir.IntType(8)), [ir.PointerType(ir.IntType(8)), ir.IntType(32), ir.IntType(64)]))
        if len(args) >= 3:
            dst: ir.Value | None = self.HandleExprLlvm(args[0])
            val: ir.Value | None = self.HandleExprLlvm(args[1])
            size: ir.Value | None = self.HandleExprLlvm(args[2])
            if dst and val is not None and size:
                if isinstance(dst.type, ir.PointerType) and not (isinstance(dst.type.pointee, ir.IntType) and dst.type.pointee.width == 8):
                    dst = Gen.builder.bitcast(dst, ir.PointerType(ir.IntType(8)), name="memset_dst_cast")
                elif isinstance(dst.type, ir.IntType):
                    if dst.type.width < 64:
                        dst = Gen.builder.zext(dst, ir.IntType(64), name="zext_memset_dst")
                    elif dst.type.width > 64:
                        dst = Gen.builder.trunc(dst, ir.IntType(64), name="trunc_memset_dst")
                    dst = Gen.builder.inttoptr(dst, ir.PointerType(ir.IntType(8)), name="memset_dst_int2ptr")
                if isinstance(val.type, ir.PointerType):
                    # 0 字面量被推断为 null 指针（i8*），memset 第二参数需要 i32
                    val = ir.Constant(ir.IntType(32), 0)
                elif isinstance(val.type, ir.IntType) and val.type.width != 32:
                    if val.type.width < 32:
                        val = Gen.builder.zext(val, ir.IntType(32), name="zext_memset_val")
                    else:
                        val = Gen.builder.trunc(val, ir.IntType(32), name="trunc_memset_val")
                if isinstance(size.type, ir.IntType) and size.type.width < 64:
                    size = Gen.builder.zext(size, ir.IntType(64), name="zext_memset_size")
                elif isinstance(size.type, ir.IntType) and size.type.width > 64:
                    size = Gen.builder.trunc(size, ir.IntType(64), name="trunc_memset_size")
                Gen.builder.call(memset_func, [dst, val, size], name="memset_call")
        return ir.Constant(ir.IntType(32), 0)

    def _HandleVaStartLlvm(self, args: list[ast.expr]) -> ir.Value:
        Gen: LlvmGeneratorMixin = self.Trans.LlvmGen
        return ir.Constant(ir.IntType(32), 0)

    def _HandleVaEndLlvm(self, args: list[ast.expr]) -> ir.Value:
        Gen: LlvmGeneratorMixin = self.Trans.LlvmGen
        return ir.Constant(ir.IntType(32), 0)

    def _HandleArgLlvm(self, args: list[ast.expr], CallNode: ast.Call | None = None) -> ir.Value | None:
        Gen: LlvmGeneratorMixin = self.Trans.LlvmGen
        va_list_ptr: ir.Value | None = None
        variadic_info: dict | None = getattr(Gen, '_va_arg_info', None)
        if not variadic_info:
            variadic_info = getattr(Gen, '_variadic_info', None)
        if variadic_info:
            va_list_ptr = variadic_info.get('va_list_ptr')
        if not va_list_ptr:
            vararg_name: str = variadic_info.get('vararg_name', 'args') if variadic_info else 'args'
            if vararg_name in Gen._direct_values:
                va_list_ptr = Gen._direct_values[vararg_name]
            elif vararg_name in Gen.variables:
                va_list_ptr = Gen.variables[vararg_name]
        if not va_list_ptr:
            return ir.Constant(ir.IntType(32), 0)
        target_type: ir.Type = ir.IntType(32)
        if args:
            type_arg: ast.expr = args[0]
            if isinstance(type_arg, ast.Name):
                type_name: str = type_arg.id
                if type_name in ('str', 'bytes'):
                    target_type = ir.PointerType(ir.IntType(8))
                elif type_name == 'CPtr':
                    target_type = ir.PointerType(ir.IntType(8))
                elif type_name in Gen.structs:
                    target_type = ir.PointerType(Gen.structs[type_name])
                else:
                    ctype_cls: type | None = CTypeRegistry.GetClassByName(type_name)
                    if ctype_cls is not None:
                        llvm_str: str | None = CTypeRegistry.CTypeToLLVM(ctype_cls)
                        resolved: ir.Type | None = Gen._type_str_to_llvm(llvm_str)
                        if resolved:
                            target_type = resolved
                    else:
                        resolved: tuple | None = CTypeRegistry.ResolveName(type_name)
                        if resolved is not None:
                            ctype_cls, ptr_level = resolved
                            llvm_str = CTypeRegistry.CTypeToLLVM(ctype_cls)
                            if llvm_str:
                                base: ir.Type | None = Gen._type_str_to_llvm(llvm_str)
                                if base is not None:
                                    for _ in range(ptr_level):
                                        if isinstance(base, ir.VoidType):
                                            base = ir.IntType(8).as_pointer()
                                        else:
                                            base = ir.PointerType(base)
                                    target_type = base
            elif isinstance(type_arg, ast.Attribute):
                if isinstance(type_arg.value, ast.Name) and IsTModule(type_arg.value.id, self.Trans.SymbolTable):
                    attr_name: str = type_arg.attr
                    ctype_cls: type | None = CTypeRegistry.GetClassByName(attr_name)
                    if ctype_cls is not None:
                        llvm_str: str | None = CTypeRegistry.CTypeToLLVM(ctype_cls)
                        resolved: ir.Type | None = Gen._type_str_to_llvm(llvm_str)
                        if resolved:
                            target_type = resolved
        else:
            assign_node: ast.AST | None = getattr(self.Trans, '_current_assign_node', None)
            if assign_node:
                ann: ast.AST | None = getattr(assign_node, 'annotation', None)
                if ann:
                    ann_name: str | None = None
                    if isinstance(ann, ast.Name):
                        ann_name = ann.id
                    elif isinstance(ann, ast.Attribute):
                        ann_name = ann.attr
                    elif isinstance(ann, ast.BinOp) and isinstance(ann.op, ast.BitOr):
                        ann_name = ExtractTypeNameFromBinOp(ann)
                    if ann_name:
                        ctype_cls: type | None = CTypeRegistry.GetClassByName(ann_name)
                        if ctype_cls is not None:
                            llvm_str: str | None = CTypeRegistry.CTypeToLLVM(ctype_cls)
                            resolved: ir.Type | None = Gen._type_str_to_llvm(llvm_str)
                            if resolved:
                                target_type = resolved
                        elif ann_name in Gen.structs:
                            target_type = ir.PointerType(Gen.structs[ann_name])
        if not getattr(Gen, '_va_arg_counter', None):
            Gen._va_arg_counter = 0
        Gen._va_arg_counter += 1
        result: ir.Value | None = Gen.emit_va_arg(va_list_ptr, target_type)
        if result is not None and getattr(result, 'name', None):
            result.name = f"va_arg_result_{Gen._va_arg_counter}"
        return result

    def _resolve_vararg_type(self, type_arg: ast.expr, Gen: LlvmGeneratorMixin) -> ir.Type:
        """将类型表达式解析为 LLVM 类型（供 arg/va_arg 共用）。"""
        target_type: ir.Type = ir.IntType(32)
        if isinstance(type_arg, ast.Name):
            type_name: str = type_arg.id
            if type_name in ('str', 'bytes'):
                target_type = ir.PointerType(ir.IntType(8))
            elif type_name == 'CPtr':
                target_type = ir.PointerType(ir.IntType(8))
            elif type_name in Gen.structs:
                target_type = ir.PointerType(Gen.structs[type_name])
            else:
                ctype_cls: type | None = CTypeRegistry.GetClassByName(type_name)
                if ctype_cls is not None:
                    llvm_str: str | None = CTypeRegistry.CTypeToLLVM(ctype_cls)
                    resolved: ir.Type | None = Gen._type_str_to_llvm(llvm_str)
                    if resolved:
                        target_type = resolved
                else:
                    resolved_tuple: tuple | None = CTypeRegistry.ResolveName(type_name)
                    if resolved_tuple is not None:
                        ctype_cls, ptr_level = resolved_tuple
                        llvm_str = CTypeRegistry.CTypeToLLVM(ctype_cls)
                        if llvm_str:
                            base: ir.Type | None = Gen._type_str_to_llvm(llvm_str)
                            if base is not None:
                                for _ in range(ptr_level):
                                    if isinstance(base, ir.VoidType):
                                        base = ir.IntType(8).as_pointer()
                                    else:
                                        base = ir.PointerType(base)
                                target_type = base
        elif isinstance(type_arg, ast.Attribute):
            if isinstance(type_arg.value, ast.Name) and IsTModule(type_arg.value.id, self.Trans.SymbolTable):
                attr_name: str = type_arg.attr
                ctype_cls: type | None = CTypeRegistry.GetClassByName(attr_name)
                if ctype_cls is not None:
                    llvm_str: str | None = CTypeRegistry.CTypeToLLVM(ctype_cls)
                    resolved: ir.Type | None = Gen._type_str_to_llvm(llvm_str)
                    if resolved:
                        target_type = resolved
        return target_type

    def _infer_vararg_type_from_context(self, Gen: LlvmGeneratorMixin) -> ir.Type:
        """从当前赋值上下文推断 va_arg/arg 的目标类型。"""
        target_type: ir.Type = ir.IntType(32)
        assign_node: ast.AST | None = getattr(self.Trans, '_current_assign_node', None)
        if assign_node:
            ann: ast.AST | None = getattr(assign_node, 'annotation', None)
            if ann:
                ann_name: str | None = None
                if isinstance(ann, ast.Name):
                    ann_name = ann.id
                elif isinstance(ann, ast.Attribute):
                    ann_name = ann.attr
                elif isinstance(ann, ast.BinOp) and isinstance(ann.op, ast.BitOr):
                    ann_name = ExtractTypeNameFromBinOp(ann)
                if ann_name:
                    ctype_cls: type | None = CTypeRegistry.GetClassByName(ann_name)
                    if ctype_cls is not None:
                        llvm_str: str | None = CTypeRegistry.CTypeToLLVM(ctype_cls)
                        resolved: ir.Type | None = Gen._type_str_to_llvm(llvm_str)
                        if resolved:
                            target_type = resolved
                    elif ann_name in Gen.structs:
                        target_type = ir.PointerType(Gen.structs[ann_name])
        return target_type

    def _HandleVaArgLlvm(self, args: list[ast.expr]) -> ir.Value:
        Gen: LlvmGeneratorMixin = self.Trans.LlvmGen
        if not args:
            return ir.Constant(ir.IntType(32), 0)
        # 求值 va_list 指针（args[0]）
        va_list_ptr: ir.Value = self.HandleExprLlvm(args[0])
        if va_list_ptr is None:
            return ir.Constant(ir.IntType(32), 0)
        # 解析目标类型
        if len(args) >= 2:
            target_type: ir.Type = self._resolve_vararg_type(args[1], Gen)
        else:
            target_type: ir.Type = self._infer_vararg_type_from_context(Gen)
        if not getattr(Gen, '_va_arg_counter', None):
            Gen._va_arg_counter = 0
        Gen._va_arg_counter += 1
        result: ir.Value | None = Gen.emit_va_arg(va_list_ptr, target_type)
        if result is not None and getattr(result, 'name', None):
            result.name = f"va_arg_explicit_{Gen._va_arg_counter}"
        return result if result is not None else ir.Constant(ir.IntType(32), 0)
