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


class CSpecialCallHandle(BaseHandle):
    def _HandleCIfLlvm(self, Node: ast.Call) -> ir.Value:
        Gen: LlvmGeneratorMixin = self.Trans.LlvmGen
        if Node.args:
            ArgVal: ir.Value | None = self.HandleExprLlvm(Node.args[0])
            if ArgVal:
                if isinstance(ArgVal, ir.Constant) and isinstance(ArgVal.type, ir.IntType):
                    return ir.Constant(ir.IntType(1), 1 if ArgVal.constant != 0 else 0)
                if isinstance(ArgVal.type, ir.IntType):
                    return Gen.builder.icmp_signed('!=', ArgVal, Gen._ZeroConst(ArgVal.type), name="cif_cond")
                if isinstance(ArgVal.type, ir.PointerType):
                    return Gen.builder.icmp_signed('!=', ArgVal, Gen._ZeroConst(ArgVal.type), name="cif_cond")
        return ir.Constant(ir.IntType(1), 0)
    def _HandleCAddrLlvm(self, Node: ast.Call) -> ir.Value:
        Gen: LlvmGeneratorMixin = self.Trans.LlvmGen
        if not Node.args:
            return ir.Constant(ir.IntType(8).as_pointer(), None)
        Arg = Node.args[0]
        if isinstance(Arg, ast.Call):
            ClassName = None
            if isinstance(Arg.func, ast.Name):
                ClassName = Arg.func.id
            elif isinstance(Arg.func, ast.Attribute):
                ClassName = Arg.func.attr
            if ClassName and ClassName in Gen.structs:
                StructType = Gen.structs[ClassName]
                if isinstance(StructType, ir.PointerType):
                    StructType = StructType.pointee
                ObjPtr = Gen._allocaEntry(StructType, name=f"{ClassName}_obj")
                zero_val = Gen._zero_value_for_type(StructType)
                if zero_val is not None:
                    Gen.builder.store(zero_val, ObjPtr)
                ConstructorName = f"{ClassName}.__init__"
                if ConstructorName in Gen.functions:
                    func = Gen.functions[ConstructorName]
                    InitArgs = [ObjPtr]
                    for carg in Arg.args:
                        ArgVal = self.HandleExprLlvm(carg)
                        if ArgVal:
                            InitArgs.append(ArgVal)
                    for kw in Arg.keywords:
                        ArgVal = self.HandleExprLlvm(kw.value)
                        if ArgVal:
                            InitArgs.append(ArgVal)
                    if hasattr(self.Trans.ExprCallHandle, '_append_eh_msg_out_arg'):
                        self.Trans.ExprCallHandle._append_eh_msg_out_arg(InitArgs, func, Gen)
                    adjusted = Gen._adjust_args(InitArgs, func)
                    Gen.builder.call(func, adjusted, name=f"{ClassName}_construct")
                return Gen.builder.bitcast(ObjPtr, ir.IntType(8).as_pointer(), name=f"{ClassName}_as_i8ptr")
        if isinstance(Arg, ast.Subscript):
            SubPtr = self.Trans.ExprAttrHandle.HandleSubscriptPtrLlvm(Arg)
            if SubPtr and isinstance(SubPtr.type, ir.PointerType):
                return Gen.builder.bitcast(SubPtr, ir.IntType(8).as_pointer(), name="addr_subscript_as_i8ptr")
        if isinstance(Arg, ast.Attribute):
            AttrPtr = self.Trans.ExprAttrHandle._get_attr_ptr(Arg)
            if AttrPtr and isinstance(AttrPtr.type, ir.PointerType):
                return Gen.builder.bitcast(AttrPtr, ir.IntType(8).as_pointer(), name="addr_attr_as_i8ptr")
        if isinstance(Arg, ast.Name):
            VarName = Arg.id
            if VarName in Gen.functions:
                func = Gen.functions[VarName]
                return Gen.builder.bitcast(func, ir.IntType(8).as_pointer(), name="addr_func_as_i8ptr")
            if VarName in Gen.variables and Gen.variables[VarName] is not None:
                var_ptr = Gen.variables[VarName]
                if isinstance(var_ptr.type, ir.PointerType):
                    # For pointer-to-pointer allocas (var_ptr is T**):
                    # - If T is a named struct (@t.Object class), the variable semantically
                    #   IS the struct, so c.Addr should return the struct pointer value.
                    # - If T is a primitive pointer type (e.g., i8*), the variable semantically
                    #   holds a pointer, so c.Addr should return &var (alloca address).
                    if isinstance(var_ptr.type.pointee, ir.PointerType):
                        pointee = var_ptr.type.pointee.pointee
                        if isinstance(pointee, ir.IdentifiedStructType):
                            # @t.Object class variable — return Loaded struct pointer
                            ArgVal = self.HandleExprLlvm(Arg)
                            if ArgVal and isinstance(ArgVal.type, ir.PointerType):
                                return Gen.builder.bitcast(ArgVal, ir.IntType(8).as_pointer(), name="addr_as_i8ptr")
                        # Pointer-type variable — return alloca address (&var)
                        return Gen.builder.bitcast(var_ptr, ir.IntType(8).as_pointer(), name="addr_as_i8ptr")
                    return Gen.builder.bitcast(var_ptr, ir.IntType(8).as_pointer(), name="addr_as_i8ptr")
        ArgVal = self.HandleExprLlvm(Arg)
        if ArgVal:
            if isinstance(ArgVal.type, ir.IntType):
                alloca = Gen._alloca(ArgVal.type, name="addr_tmp")
                Gen._store(ArgVal, alloca)
                return Gen.builder.bitcast(alloca, ir.IntType(8).as_pointer(), name="addr_as_i8ptr")
            elif isinstance(ArgVal.type, ir.PointerType):
                return Gen.builder.bitcast(ArgVal, ir.IntType(8).as_pointer(), name="addr_bitcast")
        return ir.Constant(ir.IntType(8).as_pointer(), None)

    def _HandleCSetLlvm(self, Node: ast.Call) -> ir.Value:
        Gen: LlvmGeneratorMixin = self.Trans.LlvmGen
        if len(Node.args) >= 2:
            target_arg: ast.expr = Node.args[0]
            value_arg: ast.expr = Node.args[1]
            target_ptr: ir.Value | None = None
            if isinstance(target_arg, ast.Call) and isinstance(target_arg.func, ast.Attribute):
                if isinstance(target_arg.func.value, ast.Name) and target_arg.func.value.id == 'c':
                    if target_arg.func.attr == 'Deref' and target_arg.args:
                        deref_arg = target_arg.args[0]
                        if isinstance(deref_arg, ast.Name) and deref_arg.id in Gen.variables and Gen.variables[deref_arg.id] is not None:
                            target_ptr = Gen._load(Gen.variables[deref_arg.id], name="deref_load_ptr")
                        else:
                            inner_value = self.HandleExprLlvm(deref_arg)
                            if inner_value:
                                if isinstance(inner_value.type, ir.PointerType):
                                    if isinstance(inner_value.type.pointee, ir.PointerType):
                                        inner_value = Gen._load(inner_value, name="cast_deref")
                                    target_ptr = inner_value
                    elif target_arg.func.attr == 'Addr' and target_arg.args:
                        target_ptr = self.HandleExprLlvm(target_arg)
                elif isinstance(target_arg.func.value, ast.Name) and IsTModule(target_arg.func.value.id, self.Trans.SymbolTable):
                    type_attr = target_arg.func.attr
                    resolved_cname = self.Trans.TSpecialCallHandle._ResolveTAttrToCName(type_attr)
                    if target_arg.args and resolved_cname is not None:
                        inner_val = self.HandleExprLlvm(target_arg.args[0])
                        if inner_val and isinstance(inner_val.type, ir.PointerType):
                            target_llvm_type = Gen._basic_type_to_llvm(resolved_cname)
                            if target_llvm_type:
                                target_ptr = Gen.builder.bitcast(inner_val, ir.PointerType(target_llvm_type), name="tcast_ptr")
            if not target_ptr:
                if isinstance(target_arg, ast.Subscript):
                    target_ptr = self.Trans.ExprAttrHandle.HandleSubscriptPtrLlvm(target_arg)
                else:
                    target_ptr = self.HandleExprLlvm(target_arg)
            Val = self.HandleExprLlvm(value_arg)
            if target_ptr and Val:
                if isinstance(target_ptr.type, ir.PointerType):
                    ValToStore = Val
                    pointee = target_ptr.type.pointee
                    if isinstance(pointee, ir.PointerType) and isinstance(pointee.pointee, ir.IntType) and pointee.pointee.width == 8:
                        if isinstance(Val.type, ir.PointerType) and isinstance(Val.type.pointee, ir.IntType) and Val.type.pointee.width == 8:
                            ValToStore = Val
                        elif isinstance(Val.type, ir.IntType):
                            ValToStore = Gen.builder.inttoptr(Val, pointee, name="int_to_ptr_set")
                    elif isinstance(pointee, ir.IntType):
                        if isinstance(Val.type, ir.ArrayType) and isinstance(Val.type.element, ir.IntType) and Val.type.element.width == 8:
                            zero = ir.Constant(ir.IntType(32), 0)
                            value_ptr = Gen.builder.gep(Val, [zero, zero], name="value_ptr")
                            ValToStore = Gen._load(value_ptr, name="Load_value")
                        elif isinstance(Val.type, ir.PointerType) and isinstance(Val.type.pointee, ir.IntType) and Val.type.pointee.width == 8:
                            ValToStore = Gen._load(Val, name="Load_char_value")
                        if isinstance(ValToStore.type, ir.IntType) and isinstance(pointee, ir.IntType):
                            if ValToStore.type.width < pointee.width:
                                ValToStore = Gen.builder.zext(ValToStore, pointee, name="zext_set")
                            elif ValToStore.type.width > pointee.width:
                                ValToStore = Gen.builder.trunc(ValToStore, pointee, name="trunc_set")
                    elif Val.type != pointee:
                        if isinstance(pointee, ir.PointerType) and isinstance(Val.type, ir.PointerType):
                            ValToStore = Gen.builder.bitcast(Val, pointee, name="bitcast_set")
                    Gen._store(ValToStore, target_ptr)
        return ir.Constant(ir.IntType(32), 1)

    def _HandleCLoadLlvm(self, Node: ast.Call) -> ir.Value:
        Gen: LlvmGeneratorMixin = self.Trans.LlvmGen
        if len(Node.args) < 2:
            return ir.Constant(ir.IntType(32), 0)
        # c.Load(a, b) 语义: *a = *b（a 是目标，b 是源）
        # wiki 文档: c.Load(ptr, value) -> *ptr = *value;
        dst_val: ir.Value | None = self.HandleExprLlvm(Node.args[0])
        src_val: ir.Value | None = self.HandleExprLlvm(Node.args[1])
        if not src_val or not dst_val:
            return ir.Constant(ir.IntType(32), 0)
        if not isinstance(src_val.type, ir.PointerType) or not isinstance(dst_val.type, ir.PointerType):
            return ir.Constant(ir.IntType(32), 0)
        pointee = dst_val.type.pointee
        # c.Addr 统一返回 i8* 通用指针，丢失原始类型信息。
        # 若 dst 是 c.Addr(var)，从 var 的 alloca 类型推断真实 pointee（如 i64），
        # 否则 c.Load 只会按 i8 加载 1 字节（IEEE 754 double→u64 位重解释 bug）。
        if (isinstance(pointee, ir.IntType) and pointee.width == 8
                and isinstance(Node.args[0], ast.Call)
                and isinstance(Node.args[0].func, ast.Attribute)
                and Node.args[0].func.attr == 'Addr'
                and Node.args[0].args
                and isinstance(Node.args[0].args[0], ast.Name)):
            var_name = Node.args[0].args[0].id
            if var_name in Gen.variables and Gen.variables[var_name] is not None:
                var_ptr = Gen.variables[var_name]
                if isinstance(var_ptr.type, ir.PointerType):
                    pointee = var_ptr.type.pointee
        # 按 pointee 类型 bitcast src 加载，bitcast dst 存储
        if src_val.type.pointee != pointee:
            src_cast = Gen.builder.bitcast(src_val, ir.PointerType(pointee), name="cLoad_src_cast")
        else:
            src_cast = src_val
        Loaded = Gen._load(src_cast, name="cLoad_loaded")
        if Loaded is None:
            return ir.Constant(ir.IntType(32), 0)
        if dst_val.type.pointee != pointee:
            dst_cast = Gen.builder.bitcast(dst_val, ir.PointerType(pointee), name="cLoad_dst_cast")
        else:
            dst_cast = dst_val
        Gen._store(Loaded, dst_cast)
        return ir.Constant(ir.IntType(32), 1)

    def _HandleCDerefLlvm(self, Node: ast.Call) -> ir.Value:
        Gen: LlvmGeneratorMixin = self.Trans.LlvmGen
        if not Node.args:
            return ir.Constant(ir.IntType(64), 0)
        # 检测嵌套 c.Deref(c.Deref(...))：设置标志让内层 Deref 加载为指针
        IsNestedDeref: bool = (
            isinstance(Node.args[0], ast.Call)
            and isinstance(Node.args[0].func, ast.Attribute)
            and Node.args[0].func.attr == 'Deref'
        )
        if IsNestedDeref:
            Gen._nested_deref_load_ptr = True
        try:
            arg_val: ir.Value | None = self.HandleExprLlvm(Node.args[0])
        finally:
            if IsNestedDeref:
                Gen._nested_deref_load_ptr = False
        if arg_val is None:
            return ir.Constant(ir.IntType(32), 0)
        if isinstance(arg_val.type, ir.PointerType):
            pointee: ir.Type = arg_val.type.pointee
            # 嵌套 Deref 的内层：加载为指针 (i8*)，不推断目标类型
            # 因为结果会被外层 Deref 再次解引用
            NestedLoadPtr: bool = getattr(Gen, '_nested_deref_load_ptr', False)
            if NestedLoadPtr:
                PtrType: ir.Type = ir.PointerType(ir.IntType(8))
                casted: ir.Value = Gen.builder.bitcast(arg_val, ir.PointerType(PtrType), name="deref_cast")
                Loaded = Gen._load(casted, name="deref")
                if Loaded is not None:
                    return Loaded
            # void* (i8*) 需要根据赋值目标类型推断加载类型
            elif isinstance(pointee, ir.IntType) and pointee.width == 8:
                target_type: ir.Type | None = self._infer_deref_target_type(Gen, Node)
                if target_type is not None and not isinstance(target_type, ir.IntType):
                    # bitcast i8* -> target_type* then load
                    casted: ir.Value = Gen.builder.bitcast(arg_val, ir.PointerType(target_type), name="deref_cast")
                    Loaded = Gen._load(casted, name="deref")
                    if Loaded is not None:
                        return Loaded
                elif target_type is not None and isinstance(target_type, ir.IntType):
                    # 目标是整数类型 (如 i32/i64): bitcast 并加载
                    if target_type.width != 8:
                        casted: ir.Value = Gen.builder.bitcast(arg_val, ir.PointerType(target_type), name="deref_cast")
                        Loaded = Gen._load(casted, name="deref")
                        if Loaded is not None:
                            return Loaded
            Loaded = Gen._load(arg_val, name="deref")
            if Loaded is not None:
                return Loaded
        return arg_val

    def _infer_deref_target_type(self, Gen: LlvmGeneratorMixin, DerefNode: ast.Call | None = None) -> ir.Type | None:
        """从当前赋值上下文推断 c.Deref 的目标加载类型。
        当用户写 v: int = c.Deref(ptr) 时，从赋值注解推断目标类型。
        注意：仅当 c.Deref 是赋值的直接 RHS 时才推断；若 c.Deref 嵌套在
        ifexp/compare/binop 中（如 `a = 1 if c.Deref(p) == 65 else 0`），
        不应推断，否则会把 i8* 错误 bitcast 为 i32* 加载 4 字节。"""
        assign_node: ast.AST | None = getattr(self.Trans, '_current_assign_node', None)
        if not assign_node:
            return None
        # 仅当 c.Deref 是赋值的直接 RHS 时才推断类型
        if DerefNode is not None and getattr(assign_node, 'value', None) is not DerefNode:
            return None
        ann: ast.AST | None = getattr(assign_node, 'annotation', None)
        if not ann:
            return None
        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):
            # 处理 int | t.CPtr 形式的联合类型注解
            for side in (ann.left, ann.right):
                if isinstance(side, ast.Name):
                    ann_name = side.id
                    break
                elif isinstance(side, ast.Attribute):
                    ann_name = side.attr
                    break
        if not ann_name:
            return None
        # 使用 BuiltinTypeMap 统一查询（同时支持 Python 类名和字符串速记）
        entry: tuple[type, int] | None = BuiltinTypeMap.Get(ann_name)
        if entry is not None:
            ctype_cls: type = entry[0]
            llvm_str: str | None = CTypeRegistry.CTypeToLLVM(ctype_cls)
            if llvm_str:
                resolved: ir.Type | None = Gen._type_str_to_llvm(llvm_str)
                if resolved:
                    return resolved
        # 检查是否是已注册的结构体类型
        if ann_name in Gen.structs:
            return Gen.structs[ann_name]
        return None

    def _HandleCPtrToIntLlvm(self, Node: ast.Call) -> ir.Value:
        Gen: LlvmGeneratorMixin = self.Trans.LlvmGen
        if not Node.args:
            return ir.Constant(ir.IntType(64), 0)
        arg_val: ir.Value | None = self.HandleExprLlvm(Node.args[0])
        if arg_val is None:
            return ir.Constant(ir.IntType(64), 0)
        if isinstance(arg_val.type, ir.PointerType):
            return Gen.builder.ptrtoint(arg_val, ir.IntType(64), name="ptrtoint_result")
        if isinstance(arg_val.type, ir.IntType):
            if arg_val.type.width < 64:
                return Gen.builder.zext(arg_val, ir.IntType(64), name="zext_ptrtoint")
            elif arg_val.type.width > 64:
                return Gen.builder.trunc(arg_val, ir.IntType(64), name="trunc_ptrtoint")
            return arg_val
        return ir.Constant(ir.IntType(64), 0)


class TSpecialCallHandle(BaseHandle):

    @staticmethod
    def _ResolveTAttrToCName(attr: str) -> str | None:
        ctype_cls: type | None = CTypeRegistry.GetClassByName(attr)
        if ctype_cls is not None:
            try:
                inst = ctype_cls()
                cname = type(inst).__name__
                if cname:
                    return cname
            except Exception as _e:
                if _config_mode == "strict":
                    raise
                _vlog().warning(f"处理函数调用失败: {_e}", "Exception")
        return None

    def _HandleTSpecialCallLlvm(self, Node: ast.Call) -> ir.Value | None:
        Gen: LlvmGeneratorMixin = self.Trans.LlvmGen
        if not Node.args:
            return None
        attr: str = Node.func.attr

        if attr == 'CType':
            return self._HandleCTypeLlvm(Node)

        target_type: str | None = self._ResolveTAttrToCName(attr)
        if target_type is not None:
            IsPtr_cast = False
            if len(Node.args) >= 2:
                second_arg = Node.args[1]
                if isinstance(second_arg, ast.Attribute) and isinstance(second_arg.value, ast.Name) and IsTModule(second_arg.value.id, self.Trans.SymbolTable) and second_arg.attr == 'CPtr':
                    IsPtr_cast = True
                elif isinstance(second_arg, ast.Name) and second_arg.id == 'CPtr':
                    IsPtr_cast = True
                if IsPtr_cast:
                    return self._HandleTPtrCastLlvm(Node, attr)
            if target_type == 'void':
                target_type = 'void *'
            return self.Trans.ExprCallHandle._HandleTypeCastLlvm(Node.args[0], target_type)
        return None

    def _HandleCTypeLlvm(self, Node: ast.Call) -> ir.Value | None:
        Gen: LlvmGeneratorMixin = self.Trans.LlvmGen
        arg_val: ir.Value | None = self.HandleExprLlvm(Node.args[0])
        if not arg_val:
            return None
        target_type_str: str = 'unsigned long long'
        if len(Node.args) >= 2:
            type_parts: list[str] = []
            ptr_count: int = 0
            for i in range(1, len(Node.args)):
                type_arg = Node.args[i]
                if isinstance(type_arg, ast.Attribute) and isinstance(type_arg.value, ast.Name) and IsTModule(type_arg.value.id, self.Trans.SymbolTable):
                    type_attr = type_arg.attr
                    _PREFIX_MAP: dict[str, str] = {
                        'CUnsigned': 'unsigned', 'CSigned': 'signed',
                        'CConst': 'const', 'CVolatile': 'volatile',
                    }
                    if type_attr in _PREFIX_MAP:
                        type_parts.append(_PREFIX_MAP[type_attr])
                    elif type_attr in ('CPtr', 'CArrayPtr'):
                        ptr_count += 1
                    else:
                        resolved = self._ResolveTAttrToCName(type_attr)
                        if resolved is not None:
                            type_parts.append(resolved)
            if type_parts:
                target_type_str = ' '.join(type_parts)
            if ptr_count > 0:
                target_type_str += ' ' + '*' * ptr_count
        if isinstance(arg_val.type, ir.PointerType):
            int_val = Gen.builder.ptrtoint(arg_val, ir.IntType(64), name="ptr_to_int")
            return int_val
        return self.Trans.ExprCallHandle._HandleTypeCastLlvm(Node.args[0], target_type_str)

    def _HandleTPtrCastLlvm(self, Node: ast.Call, attr: str) -> ir.Value | None:
        Gen: LlvmGeneratorMixin = self.Trans.LlvmGen
        if attr in ('CChar', 'CUnsignedChar'):
            first_arg = Node.args[0]
            if isinstance(first_arg, ast.Call) and isinstance(first_arg.func, ast.Attribute) and isinstance(first_arg.func.value, ast.Name) and IsTModule(first_arg.func.value.id, self.Trans.SymbolTable) and first_arg.func.attr == 'CInt' and first_arg.args:
                inner_val = self.HandleExprLlvm(first_arg.args[0])
                if isinstance(inner_val.type, ir.PointerType):
                    return Gen.builder.bitcast(inner_val, ir.PointerType(ir.IntType(8)), name=f"c{attr.lower()}_ptr_from_cint")
            expr_val = self.HandleExprLlvm(Node.args[0])
            if isinstance(expr_val.type, ir.IntType) and expr_val.type.width == 8:
                var = Gen._alloca(ir.ArrayType(ir.IntType(8), 2), name=f"c{attr.lower()}_ptr")
                zero = ir.Constant(ir.IntType(32), 0)
                char_ptr = Gen.builder.gep(var, [zero, zero], name="char_ptr")
                Gen._store(expr_val, char_ptr)
                null_char = ir.Constant(ir.IntType(8), 0)
                null_ptr = Gen.builder.gep(var, [zero, ir.Constant(ir.IntType(32), 1)], name="null_ptr")
                Gen._store(null_char, null_ptr)
                return char_ptr
            elif isinstance(expr_val.type, ir.PointerType):
                if isinstance(expr_val.type.pointee, ir.PointerType):
                    Loaded_ptr = Gen._load(expr_val, name="load_ptr")
                    if isinstance(Loaded_ptr.type, ir.PointerType) and isinstance(Loaded_ptr.type.pointee, ir.IntType) and Loaded_ptr.type.pointee.width == 8:
                        return Loaded_ptr
                if isinstance(expr_val.type.pointee, ir.IntType) and expr_val.type.pointee.width == 8:
                    return expr_val
                return Gen.builder.bitcast(expr_val, ir.PointerType(ir.IntType(8)), name="cast_to_char_ptr")
            elif isinstance(expr_val.type, ir.IntType):
                if expr_val.type.width == 32:
                    expr_val = Gen.builder.zext(expr_val, ir.IntType(64), name="zext_to_64")
                return Gen.builder.inttoptr(expr_val, ir.PointerType(ir.IntType(8)), name=f"inttoptr_c{attr.lower()}")
            return Gen.emit_constant(0, 'int')
        elif attr == 'CVoid':
            return self.Trans.ExprCallHandle._HandleTypeCastLlvm(Node.args[0], 'void *')
        elif attr == 'CInt':
            expr_val = self.HandleExprLlvm(Node.args[0])
            if expr_val:
                if isinstance(expr_val.type, ir.IntType):
                    if expr_val.type.width < 64:
                        expr_val = Gen.builder.zext(expr_val, ir.IntType(64), name="zext_to_64")
                    return Gen.builder.inttoptr(expr_val, ir.PointerType(ir.IntType(32)), name="cint_ptr")
                return Gen.builder.bitcast(expr_val, ir.PointerType(ir.IntType(32)), name="cint_ptr")
        else:
            ctype_cls = CTypeRegistry.GetClassByName(attr)
            if ctype_cls is not None:
                llvm_str = CTypeRegistry.CTypeToLLVM(ctype_cls)
                target_type = Gen._type_str_to_llvm(llvm_str)
                if target_type:
                    # 基础类型 (int/float) → 加一层指针 → T*
                    if isinstance(target_type, (ir.IntType, ir.FloatType, ir.DoubleType)):
                        target_ptr_type = ir.PointerType(target_type)
                        expr_val = self.HandleExprLlvm(Node.args[0])
                        if expr_val:
                            if isinstance(expr_val.type, ir.IntType):
                                if expr_val.type.width < 64:
                                    expr_val = Gen.builder.zext(expr_val, ir.IntType(64), name="zext_to_64")
                                return Gen.builder.inttoptr(expr_val, target_ptr_type, name=f"{attr.lower()}_ptr")
                            return Gen.builder.bitcast(expr_val, target_ptr_type, name=f"{attr.lower()}_ptr")
                    # 指针类型 (如 CPtr → i8*) → 再加一层指针 → i8**
                    elif isinstance(target_type, ir.PointerType):
                        target_ptr_type = ir.PointerType(target_type)
                        expr_val = self.HandleExprLlvm(Node.args[0])
                        if expr_val:
                            if isinstance(expr_val.type, ir.IntType):
                                if expr_val.type.width < 64:
                                    expr_val = Gen.builder.zext(expr_val, ir.IntType(64), name="zext_to_64")
                                return Gen.builder.inttoptr(expr_val, target_ptr_type, name=f"{attr.lower()}_ptr")
                            return Gen.builder.bitcast(expr_val, target_ptr_type, name=f"{attr.lower()}_ptr")
        return None
