from __future__ import annotations
from typing import Any
import ast
import re
import logging
import llvmlite.ir as ir
from lib.includes import t as _t
from lib.includes.t import CTypeRegistry
from lib.core.Handles.HandlesBase import CTypeInfo as _CTypeInfo, BuiltinTypeMap
from lib.constants.config import mode as _config_mode
from lib.core.VLogger import get_logger as _vlog
from lib.core.SymbolUtils import IsTModule


class TypeConvertMixin:

    # 限定符前缀映射表：(前缀字符串, 去除长度)
    # 这些限定符（const/volatile/static/extern/register/inline/export/CAuto 等）
    # 仅影响 C 语义，对 LLVM IR 类型本身无影响，统一去除后递归解析内部类型。
    _QUALIFIER_PREFIXES: tuple[tuple[str, int], ...] = (
        ('const ', 6), ('volatile ', 9), ('const_', 6), ('volatile_', 9),
        ('static ', 7), ('extern ', 7), ('register ', 9), ('inline ', 7),
        ('export ', 7),
        ('CStatic ', 8), ('CExtern ', 8), ('CRegister ', 10),
        ('CInline ', 8), ('CAuto ', 6),
    )

    def _ctype_to_llvm(self, type_info: _CTypeInfo | str | None) -> ir.Type:
        if type_info is None:
            return ir.IntType(32)

        if isinstance(type_info, str):
            return self._type_str_to_llvm(type_info)

        if not isinstance(type_info, _CTypeInfo):
            return ir.IntType(32)

        if type_info.IsFuncPtr:
            ret_type: ir.Type = self._ctype_to_llvm(type_info.FuncPtrReturn) if type_info.FuncPtrReturn else ir.VoidType()
            param_types: list[ir.Type] = []
            if type_info.FuncPtrParams:
                for _name, param_info in type_info.FuncPtrParams:
                    if isinstance(param_info, _CTypeInfo):
                        param_types.append(self._ctype_to_llvm(param_info))
                    else:
                        param_types.append(ir.IntType(32))
            fn_type: ir.FunctionType = ir.FunctionType(ret_type, param_types)
            return ir.PointerType(fn_type)

        if type_info.IsState and type_info.PtrCount == 0 and not type_info.IsTypedef:
            if type_info.BaseType is None or (isinstance(type_info.BaseType, type) and issubclass(type_info.BaseType, _t.CVoid)) or isinstance(type_info.BaseType, _t.CVoid):
                return ir.VoidType()

        if type_info.IsTypedef and type_info.Name:
            resolved: ir.Type | None = self._resolve_typedef_ctype(type_info)
            if resolved is not None:
                return resolved

        # REnum 类型：通过 Name 查找或创建结构体（BaseType 可能为 None）
        # 这对 BinOp `LLVMType | t.CPtr` 合并后的 CTypeInfo 至关重要
        if type_info.IsRenum and type_info.Name:
            if type_info.Name in self.structs:
                base: ir.Type = self.structs[type_info.Name]
            else:
                base = self._get_or_create_struct(type_info.Name)
            result: ir.Type = base
            for _ in range(type_info.PtrCount):
                result = ir.PointerType(result)
            return result

        BaseType: ir.Type = self._base_ctype_to_llvm(type_info.BaseType, type_info)

        result: ir.Type = BaseType
        for _ in range(type_info.PtrCount):
            if isinstance(result, ir.VoidType):
                result = ir.IntType(8).as_pointer()
            else:
                result = ir.PointerType(result)

        for dim in reversed(type_info.ArrayDims):
            try:
                dim_val: int = int(dim)
                if dim_val > 0:
                    result = ir.ArrayType(result, dim_val)
            except (ValueError, TypeError):
                pass

        return result

    def _resolve_typedef_ctype(self, type_info: _CTypeInfo) -> ir.Type | None:
        name: str = type_info.Name
        if not name or not self.SymbolTable:
            return None

        entry: Any = self.SymbolTable.lookup(name)
        if not entry or not isinstance(entry, _CTypeInfo):
            return None

        if entry.BaseType and (not isinstance(entry.BaseType, _t._CTypedef) or entry.PtrCount > 0):
            resolved: Any = entry.Copy()
            resolved.IsTypedef = False
            if type_info.PtrCount > resolved.PtrCount:
                resolved.PtrCount = type_info.PtrCount
            return self._ctype_to_llvm(resolved)

        if entry.OriginalType:
            if isinstance(entry.OriginalType, _CTypeInfo):
                resolved: Any = entry.OriginalType.Copy()
                resolved.IsTypedef = False
                if type_info.PtrCount > resolved.PtrCount:
                    resolved.PtrCount = type_info.PtrCount
                return self._ctype_to_llvm(resolved)
            elif isinstance(entry.OriginalType, str):
                resolved: Any = _CTypeInfo.FromTypeName(entry.OriginalType)
                if resolved and resolved.BaseType:
                    resolved.IsTypedef = False
                    if type_info.PtrCount > resolved.PtrCount:
                        resolved.PtrCount = type_info.PtrCount
                    return self._ctype_to_llvm(resolved)

        return None

    def _base_ctype_to_llvm(self, BaseType: Any, type_info: _CTypeInfo | None = None) -> ir.Type:
        if BaseType is None:
            return ir.VoidType()

        if isinstance(BaseType, (tuple, list)):
            elem_types: list[ir.Type] = [self._base_ctype_to_llvm(bt, type_info) for bt in BaseType]
            return ir.LiteralStructType(elem_types) if elem_types else ir.IntType(32)

        if isinstance(BaseType, type) and issubclass(BaseType, _t.CType):
            BaseType = BaseType()

        if isinstance(BaseType, _t.CVoid):
            return ir.VoidType()

        if isinstance(BaseType, _t.CStruct):
            struct_name: str = getattr(BaseType, 'name', '') or (type_info.Name if type_info else '')
            if struct_name and struct_name in self.structs:
                return self.structs[struct_name]
            if struct_name:
                return self._get_or_create_struct(struct_name)
            return ir.LiteralStructType([])

        if isinstance(BaseType, (_t.CEnum, _t.REnum)):
            enum_name: str = type_info.Name if type_info else ''
            if enum_name and enum_name in self.structs:
                return self.structs[enum_name]
            return ir.IntType(32)

        if isinstance(BaseType, _t.CUnion):
            union_name: str = type_info.Name if type_info else ''
            if union_name and union_name in self.structs:
                return self.structs[union_name]
            if union_name:
                return self._get_or_create_struct(union_name)
            return ir.IntType(32)

        if isinstance(BaseType, _t._CTypedef):
            typedef_name: str = getattr(BaseType, 'value', '') or (type_info.Name if type_info else '')
            if typedef_name and self.SymbolTable:
                entry: Any = self.SymbolTable.lookup(typedef_name)
                if entry and isinstance(entry, _CTypeInfo) and entry.BaseType:
                    if not isinstance(entry.BaseType, _t._CTypedef) or entry.PtrCount > 0:
                        return self._base_ctype_to_llvm(entry.BaseType, entry)
            return ir.IntType(32)

        if isinstance(BaseType, _t.CDefine):
            # Use 64-bit type if the define value exceeds 32-bit range
            if type_info and isinstance(type_info.DefineValue, int):
                if type_info.DefineValue < 0 or type_info.DefineValue > 0xFFFFFFFF:
                    return ir.IntType(64)
            return ir.IntType(32)

        if isinstance(BaseType, _t.CPass):
            return ir.VoidType()

        llvm_str: str = CTypeRegistry.CTypeToLLVM(type(BaseType))
        return self._llvm_str_to_ir(llvm_str)

    def _get_source_sha1_from_type_str(self, type_str: str) -> str | None:
        """从类型字符串中提取模块名，返回对应的源模块 SHA1。
        用于跨模块类型引用（如 memhub.MemBuddy），确保用源模块的 SHA1 创建 struct。
        """
        if not type_str or '.' not in type_str:
            return None
        # 去除指针标记和空格
        clean: str = type_str.replace('*', '').strip()
        if '.' not in clean:
            return None
        # 提取模块名（最后一个 '.' 之前的部分）
        parts: list[str] = clean.rsplit('.', 1)
        if len(parts) < 2:
            return None
        module_name: str = parts[0]
        # 跳过 t/c 等内建模块
        if module_name in {'t', 'c'}:
            return None
        # 从 ModuleSha1Map 查找 SHA1（支持完整路径名和短名）
        sha1_map: dict[str, str] = getattr(self, 'ModuleSha1Map', {})
        source_sha1: str | None = sha1_map.get(module_name)
        if not source_sha1 and '.' in module_name:
            source_sha1 = sha1_map.get(module_name.split('.')[-1])
        return source_sha1

    def _resolve_typedef(self, type_name: str) -> str:
        if type_name in {'typedef', 'CType', 'CVolatile', 'CEnum', 'CUnion', 'CStruct', 'enum', 'REnum', 'renum', 'CPtr'}:
            return type_name
        if type_name == 'Callable':
            return 'Callable'
        visited: set[str] = set()
        current: str = type_name
        while current not in visited:
            visited.add(current)
            if self.SymbolTable:
                Entry: _CTypeInfo | None = self.SymbolTable.lookup(current)
                if isinstance(Entry, dict) and Entry.get('type') == 'typedef':
                    OriginalType: str = Entry.get('OriginalType', '')
                    if OriginalType:
                        current = OriginalType
                        continue
                elif Entry and Entry.IsTypedef:
                    if Entry.OriginalType:
                        if isinstance(Entry.OriginalType, _CTypeInfo):
                            if Entry.OriginalType.IsFuncPtr:
                                return 'Callable'
                            return Entry.OriginalType.ToString() if Entry.OriginalType.BaseType else current
                        elif isinstance(Entry.OriginalType, str):
                            current = Entry.OriginalType
                            continue
                    if Entry.BaseType:
                        if not isinstance(Entry.BaseType, (_t._CTypedef,)) or Entry.PtrCount > 0:
                            resolved: str = self._resolve_ctype_to_str(Entry)
                            if resolved and resolved != current:
                                current = resolved
                                continue
                    bm: Any = BuiltinTypeMap.Get(current)
                    if bm:
                        base_cls: Any = bm[0]
                        try:
                            instance: Any = base_cls()
                            cname: str = type(instance).__name__
                            if cname:
                                current = cname + ' *' * bm[1]
                                continue
                        except Exception as _e:
                            if _config_mode == "strict":
                                logging.warning(f"异常被忽略: {_e}")
                            pass
            bm: Any = BuiltinTypeMap.Get(current)
            if bm and bm[1] > 0:
                base_cls: Any = bm[0]
                try:
                    instance: Any = base_cls()
                    cname: str = type(instance).__name__
                    if cname:
                        current = cname + ' *' * bm[1]
                        continue
                except Exception as _e:
                    if _config_mode == "strict":
                        logging.warning(f"异常被忽略: {_e}")
                    pass
            break
        return current

    def _resolve_ctype_to_str(self, type_info: _CTypeInfo) -> str:
        parts: list[str] = []
        base: Any = type_info.BaseType
        if base is None or base is _t.CVoid or isinstance(base, _t.CVoid):
            parts.append('void')
        elif isinstance(base, _t._CTypedef) or base is _t._CTypedef:
            return ''
        elif isinstance(base, _t.CStruct) or base is _t.CStruct:
            parts.append(f'struct {getattr(base, "name", "")}')
        elif isinstance(base, _t.CEnum) or base is _t.CEnum:
            parts.append(f'enum {getattr(base, "name", "")}')
        else:
            cname: str = ''
            if isinstance(base, type) and issubclass(base, _t.CType):
                cname = base.__name__
            elif isinstance(base, _t.CType):
                cname = type(base).__name__
            if cname:
                parts.append(cname)
            else:
                return ''
        if type_info.PtrCount > 0:
            parts.append('*' * type_info.PtrCount)
        return ' '.join(parts)

    def _type_str_to_llvm(self, type_str: str, IsPtr: bool = False) -> ir.Type:
        type_str = type_str.strip()
        cache_key: tuple[str, bool] = (type_str, IsPtr)
        cached: ir.Type | None = self._type_cache.get(cache_key)
        if cached is not None:
            return cached
        result: ir.Type = self._type_str_to_llvm_impl(type_str, IsPtr)
        if result is not None:
            if isinstance(result, (ir.IntType, ir.FloatType, ir.DoubleType, ir.VoidType)):
                self._type_cache[cache_key] = result
            elif isinstance(result, ir.PointerType) and isinstance(result.pointee, (ir.IntType, ir.FloatType, ir.DoubleType, ir.VoidType)):
                self._type_cache[cache_key] = result
            elif isinstance(result, ir.ArrayType) and not isinstance(result.element, (ir.IdentifiedStructType, ir.LiteralStructType)):
                self._type_cache[cache_key] = result
        return result

    _CType2LLVM = _type_str_to_llvm

    def _type_str_to_llvm_impl(self, type_str: str, IsPtr: bool = False) -> ir.Type:
        array_dims: list[int] = []
        dim_match: list[str] = re.findall(r'\[(\d+)\]', type_str)
        if dim_match:
            array_dims = [int(d) for d in dim_match]
            type_str = re.sub(r'\s*\[\d+\]', '', type_str).strip()
        result: ir.Type = self._type_str_to_llvm_base(type_str, IsPtr)
        for dim in reversed(array_dims):
            result = ir.ArrayType(result, dim)
        return result

    def _type_str_to_llvm_base(self, type_str: str, IsPtr: bool = False) -> ir.Type:
        ptr_depth: int = 0
        while type_str.endswith('*'):
            ptr_depth += 1
            type_str = type_str[:-1].strip()
        if ptr_depth > 0:
            IsPtr = True
        if type_str in {'typedef', 'CType', 'CVolatile', 'CEnum', 'CUnion', 'CStruct', 'enum', 'REnum', 'renum'}:
            result: ir.Type
            if IsPtr:
                result = ir.IntType(8).as_pointer()
                for _ in range(ptr_depth - 1):
                    result = ir.PointerType(result)
                return result
            return ir.IntType(32)
        if type_str in {'const', 'volatile'}:
            return ir.IntType(8)
        if type_str == 'Callable':
            return ir.IntType(8).as_pointer()
        for _q_prefix, _q_offset in self._QUALIFIER_PREFIXES:
            if type_str.startswith(_q_prefix):
                return self._type_str_to_llvm(type_str[_q_offset:].strip(), IsPtr)
        resolved: str = self._resolve_typedef(type_str)
        if resolved != type_str:
            if '*' in resolved:
                IsPtr = False
            return self._type_str_to_llvm(resolved, IsPtr)
        if type_str.endswith('*'):
            BaseType: str = type_str[:-1].strip()
            base_llvm: ir.Type | None = self._basic_type_to_llvm(BaseType)
            if base_llvm is not None and isinstance(base_llvm, ir.VoidType):
                result: ir.Type = ir.IntType(8).as_pointer()
                for _ in range(ptr_depth):
                    result = ir.PointerType(result)
                return result
            if base_llvm is not None and not isinstance(base_llvm, ir.VoidType):
                if isinstance(base_llvm, ir.PointerType):
                    return base_llvm
                return ir.PointerType(base_llvm)
            if BaseType in self.structs:
                return ir.PointerType(self.structs[BaseType])
            if BaseType.startswith('struct '):
                stripped: str = BaseType[7:].strip()
                if stripped in self.structs:
                    return ir.PointerType(self.structs[stripped])
            if '.' in BaseType:
                LastPart: str = BaseType.split('.')[-1]
                if LastPart in self.structs:
                    return ir.PointerType(self.structs[LastPart])
                _src_sha1: str | None = self._get_source_sha1_from_type_str(BaseType)
                placeholder: ir.IdentifiedStructType = self._get_or_create_struct(LastPart, source_sha1=_src_sha1)
                return ir.PointerType(placeholder)
            if base_llvm is not None and isinstance(base_llvm, ir.VoidType):
                return ir.PointerType(ir.IntType(8))
        if type_str.startswith('{') and type_str.endswith('}'):
            inner: str = type_str[1:-1].strip()
            elem_strs: list[str] = []
            depth: int = 0
            current: str = ''
            for ch in inner:
                if ch == ',' and depth == 0:
                    elem_strs.append(current.strip())
                    current = ''
                else:
                    if ch == '{':
                        depth += 1
                    elif ch == '}':
                        depth -= 1
                    current += ch
            if current.strip():
                elem_strs.append(current.strip())
            elem_types: list[ir.Type] = []
            for es in elem_strs:
                et: ir.Type = self._type_str_to_llvm(es, '*' in es)
                if isinstance(et, ir.VoidType):
                    et = ir.IntType(8).as_pointer()
                elem_types.append(et)
            if elem_types:
                return ir.LiteralStructType(elem_types)
            return ir.IntType(32)
        if type_str in {'typedef', 'CType', 'CVolatile', 'CEnum', 'CUnion', 'CStruct', 'enum', 'REnum', 'renum'}:
            return ir.IntType(32)
        if type_str.startswith('%'):
            stripped: str = type_str[1:]
            if stripped in {'typedef', 'CType', 'CVolatile', 'CEnum', 'CUnion', 'CStruct', 'enum', 'REnum', 'renum'}:
                return ir.IntType(32) if not IsPtr else ir.PointerType(ir.IntType(32))
            basic_stripped: ir.Type | None = self._basic_type_to_llvm(stripped)
            if basic_stripped is not None:
                if IsPtr and not isinstance(basic_stripped, ir.VoidType):
                    return ir.PointerType(basic_stripped)
                return basic_stripped
        if self.SymbolTable:
            _Entry: _CTypeInfo | None = self.SymbolTable.lookup(type_str)
            if _Entry and _Entry.IsTypedef:
                resolved_str: str = self._resolve_typedef(type_str)
                if resolved_str != type_str:
                    return self._type_str_to_llvm(resolved_str, IsPtr)
                if _Entry.BaseType:
                    if not isinstance(_Entry.BaseType, (_t._CTypedef,)) or _Entry.PtrCount > 0:
                        resolved: str = self._resolve_ctype_to_str(_Entry)
                        if resolved:
                            return self._type_str_to_llvm(resolved, IsPtr)
            if _Entry and _Entry.IsRenum:
                if type_str in self.structs:
                    if IsPtr:
                        return ir.PointerType(self.structs[type_str])
                    return self.structs[type_str]
                # REnum 结构体尚未创建时不能 fall through 到 IsEnum（会返回 i32），
                # 需要通过 _get_or_create_struct 创建 opaque 结构体（自引用安全）。
                _renum_sha1: str | None = self._get_source_sha1_from_type_str(type_str)
                opaque: ir.Type = self._get_or_create_struct(type_str, source_sha1=_renum_sha1)
                if IsPtr:
                    return ir.PointerType(opaque)
                return opaque
            if _Entry and _Entry.IsStruct:
                # 结构体类型（来自 _InsertClassSymbol）：必须返回结构体类型而非 i32，
                # 否则 (ast.Import | t.CPtr) 联合转换会得到 i32* 导致字段访问 GEP 偏移错误
                if type_str in self.structs:
                    if IsPtr:
                        return ir.PointerType(self.structs[type_str])
                    return self.structs[type_str]
                # 结构体尚未创建时，通过 _get_or_create_struct 创建 opaque 结构体
                # （_TryLoadStructFromStub 会在后续阶段填充字段）
                _struct_sha1: str | None = self._get_source_sha1_from_type_str(type_str)
                opaque_struct: ir.IdentifiedStructType = self._get_or_create_struct(type_str, source_sha1=_struct_sha1)
                if IsPtr:
                    return ir.PointerType(opaque_struct)
                return opaque_struct
            if _Entry and _Entry.IsEnum:
                return ir.IntType(32) if not IsPtr else ir.PointerType(ir.IntType(32))
            if _Entry and _Entry.IsExceptionClass:
                return ir.IntType(32) if not IsPtr else ir.PointerType(ir.IntType(32))
            if _Entry and _Entry.IsFunction:
                return ir.PointerType(ir.IntType(8))
            if _Entry and _Entry.BaseType:
                if (isinstance(_Entry.BaseType, type) and issubclass(_Entry.BaseType, _t.CEnum)) or _Entry.BaseType is _t.CEnum:
                    return ir.IntType(32) if not IsPtr else ir.PointerType(ir.IntType(32))
        for ClassName in self.structs:
            if type_str == ClassName:
                if IsPtr:
                    return ir.PointerType(self.structs[ClassName])
                return self.structs[ClassName]
        if '.' in type_str and not type_str.startswith('%'):
            LastPart: str = type_str.split('.')[-1]
            basic_last: ir.Type | None = self._basic_type_to_llvm(LastPart)
            if basic_last is not None:
                if IsPtr and not isinstance(basic_last, ir.VoidType):
                    return ir.PointerType(basic_last)
                return basic_last
            if self.SymbolTable:
                _Entry: _CTypeInfo | None = self.SymbolTable.lookup(LastPart)
                if _Entry and _Entry.IsTypedef:
                    resolved_str: str = self._resolve_typedef(LastPart)
                    if resolved_str != LastPart:
                        return self._type_str_to_llvm(resolved_str, IsPtr)
                    if _Entry.BaseType:
                        if not isinstance(_Entry.BaseType, (_t._CTypedef,)) or _Entry.PtrCount > 0:
                            resolved: str = self._resolve_ctype_to_str(_Entry)
                            if resolved:
                                return self._type_str_to_llvm(resolved, IsPtr)
                if _Entry and _Entry.IsRenum:
                    if LastPart in self.structs:
                        if IsPtr:
                            return ir.PointerType(self.structs[LastPart])
                        return self.structs[LastPart]
                    # REnum 结构体尚未创建时不能 fall through 到 IsEnum（会返回 i32）。
                    _lp_sha1: str | None = self._get_source_sha1_from_type_str(type_str)
                    opaque_lp: ir.Type = self._get_or_create_struct(LastPart, source_sha1=_lp_sha1)
                    if IsPtr:
                        return ir.PointerType(opaque_lp)
                    return opaque_lp
                if _Entry and _Entry.IsEnum:
                    return ir.IntType(32) if not IsPtr else ir.PointerType(ir.IntType(32))
                if _Entry and _Entry.IsExceptionClass:
                    return ir.IntType(32) if not IsPtr else ir.PointerType(ir.IntType(32))
                if _Entry and _Entry.IsFunction:
                    return ir.PointerType(ir.IntType(8))
                if _Entry and _Entry.BaseType:
                    if (isinstance(_Entry.BaseType, type) and issubclass(_Entry.BaseType, _t.CEnum)) or _Entry.BaseType is _t.CEnum:
                        return ir.IntType(32) if not IsPtr else ir.PointerType(ir.IntType(32))
            if LastPart in self.structs:
                if IsPtr:
                    return ir.PointerType(self.structs[LastPart])
                return self.structs[LastPart]
            _lp_sha1_2: str | None = self._get_source_sha1_from_type_str(type_str)
            placeholder: ir.IdentifiedStructType = self._get_or_create_struct(LastPart, source_sha1=_lp_sha1_2)
            if IsPtr:
                return ir.PointerType(placeholder)
            return placeholder
        if type_str.startswith('struct '):
            stripped: str = type_str[7:].strip().replace(' *', '').replace('*', '')
            if stripped in self.structs:
                if IsPtr:
                    return ir.PointerType(self.structs[stripped])
                return self.structs[stripped]
            basic_match: ir.Type | None = self._basic_type_to_llvm(stripped)
            if basic_match is not None:
                if IsPtr and not isinstance(basic_match, ir.VoidType):
                    return ir.PointerType(basic_match)
                return basic_match
            _stripped_sha1: str | None = self._get_source_sha1_from_type_str(stripped)
            placeholder: ir.IdentifiedStructType = self._get_or_create_struct(stripped, source_sha1=_stripped_sha1)
            if IsPtr:
                return ir.PointerType(placeholder)
            return placeholder
        if type_str.startswith('%struct.'):
            stripped: str = type_str[8:].strip().replace(' *', '').replace('*', '')
            if stripped in self.structs:
                if IsPtr:
                    return ir.PointerType(self.structs[stripped])
                return self.structs[stripped]
            basic_match: ir.Type | None = self._basic_type_to_llvm(stripped)
            if basic_match is not None:
                if IsPtr and not isinstance(basic_match, ir.VoidType):
                    return ir.PointerType(basic_match)
                return basic_match
            _stripped_sha1_2: str | None = self._get_source_sha1_from_type_str(stripped)
            placeholder: ir.IdentifiedStructType = self._get_or_create_struct(stripped, source_sha1=_stripped_sha1_2)
            if IsPtr:
                return ir.PointerType(placeholder)
            return placeholder
        if type_str.startswith('union '):
            stripped: str = type_str[6:].strip()
            basic_match: ir.Type | None = self._basic_type_to_llvm(stripped)
            if basic_match is not None:
                if IsPtr and not isinstance(basic_match, ir.VoidType):
                    return ir.PointerType(basic_match)
                return basic_match
        if type_str.endswith('*'):
            pointee: ir.Type = self._type_str_to_llvm(type_str[:-1].strip())
            if isinstance(pointee, ir.VoidType):
                return ir.PointerType(ir.IntType(8))
            return ir.PointerType(pointee)
        result: ir.Type | None = self._basic_type_to_llvm(type_str)
        if result is None:
            # 未知类型：可能是跨模块结构体（如 'Import' 来自 ast 模块）。
            # 尝试通过 _get_or_create_struct 创建/查找结构体，
            # 该方法内部会检查 typedef/enum 等并返回正确类型。
            # 必须在 fallback 到 i32 之前执行，否则 (ast.Import | t.CPtr) 联合转换
            # 会得到 i32* 导致字段访问 GEP 偏移错误（AccessViolation 崩溃）。
            _cand_sha1: str | None = self._get_source_sha1_from_type_str(type_str)
            candidate: ir.Type = self._get_or_create_struct(type_str, source_sha1=_cand_sha1)
            if isinstance(candidate, ir.IdentifiedStructType):
                result = candidate
            else:
                result = ir.IntType(32)
        if IsPtr:
            if isinstance(result, ir.VoidType):
                result = ir.PointerType(ir.IntType(8))
            elif isinstance(result, ir.PointerType):
                pass
            else:
                result = ir.PointerType(result)
            for _ in range(ptr_depth - 1):
                result = ir.PointerType(result)
        return result

    def _llvm_str_to_ir(self, llvm_str: str) -> ir.Type | None:
        _LLVM_IR_TYPES: dict[str, ir.Type] = {
            'void': ir.VoidType(), 'i1': ir.IntType(1), 'i8': ir.IntType(8),
            'i16': ir.IntType(16), 'i32': ir.IntType(32), 'i64': ir.IntType(64),
            'i128': ir.IntType(128), 'float': ir.FloatType(), 'double': ir.DoubleType(),
            'half': ir.IntType(16), 'fp128': ir.IntType(128),
        }
        return _LLVM_IR_TYPES.get(llvm_str)

    def _basic_type_to_llvm(self, type_str: str) -> ir.Type | None:
        _LLVM_IR_TYPES: dict[str, ir.Type] = {
            'void': ir.VoidType(), 'i1': ir.IntType(1), 'i8': ir.IntType(8),
            'i16': ir.IntType(16), 'i32': ir.IntType(32), 'i64': ir.IntType(64),
            'i128': ir.IntType(128), 'f32': ir.FloatType(), 'f64': ir.DoubleType(),
            'half': ir.IntType(16), 'fp128': ir.IntType(128),
        }
        if type_str in _LLVM_IR_TYPES:
            return _LLVM_IR_TYPES[type_str]
        resolved: Any = CTypeRegistry.ResolveName(type_str)
        if resolved is not None:
            ctype_cls: Any
            ptr_level: int
            ctype_cls, ptr_level = resolved
            llvm_str: str = CTypeRegistry.CTypeToLLVM(ctype_cls)
            if llvm_str:
                # CTypeToLLVM 对 CPtr 等指针类型已返回含 * 的串（如 'i8*'），
                # 此时 ptr_level 已内含在 llvm_str 中，直接解析即可
                if '*' in llvm_str:
                    return self._type_str_to_llvm(llvm_str)
                base: ir.Type | None = self._llvm_str_to_ir(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)
                    return base
        if type_str == '*':
            return ir.IntType(8)
        if type_str in ('const_', 'const'):
            return ir.IntType(8)
        return None

    def _is_type_unsigned(self, type_str: str) -> bool:
        s: str = type_str.strip()
        if s.endswith('*'):
            return True
        if s.startswith('unsigned'):
            return True
        resolved: Any = CTypeRegistry.ResolveName(s)
        if resolved is not None:
            ctype_cls: Any
            _: int
            ctype_cls, _ = resolved
            try:
                inst: Any = ctype_cls()
                if getattr(inst, 'IsSigned', None) is False:
                    return True
            except Exception as _e:
                if _config_mode == "strict":
                    raise
                _vlog().warning(f"判断类型符号性失败: {_e}", "Exception")
        return False

    def _record_var_signedness(self, name: str, type_str_or_bool: str | bool) -> None:
        if isinstance(type_str_or_bool, bool):
            self.var_signedness[name] = type_str_or_bool
        else:
            self.var_signedness[name] = self._is_type_unsigned(type_str_or_bool)

    def _is_var_unsigned(self, name: str) -> bool:
        return self.var_signedness.get(name, False)

    def _check_node_unsigned(self, node: ast.AST) -> bool:
        if isinstance(node, ast.Name):
            return self._is_var_unsigned(node.id)
        if isinstance(node, ast.BinOp):
            return self._check_node_unsigned(node.left) or self._check_node_unsigned(node.right)
        if isinstance(node, ast.UnaryOp):
            return self._check_node_unsigned(node.operand)
        if isinstance(node, ast.Call):
            return self._check_call_unsigned(node)
        if isinstance(node, ast.Subscript):
            return self._check_node_unsigned(node.value)
        if isinstance(node, ast.Attribute):
            # 检查是否为结构体字段，并查询其符号性
            field_signed: bool | None = self._check_attribute_signedness(node)
            if field_signed is not None:
                return not field_signed  # IsSigned=False 表示无符号 → 返回 True
            return self._check_node_unsigned(node.value)
        return False

    def _check_call_unsigned(self, node: ast.Call) -> bool:
        """推断函数调用返回值的无符号性。

        修复：原代码对所有 Call 节点返回 False，导致函数调用返回值
        直接参与 >>/% 等运算时丢失无符号性，退化成 ashr/srem。

        规则（用户确认）：
        - a = b 赋值时，若 a 无显式类型注解，则自动推导为 b 的类型（含符号性）
        - 若 a 有显式有符号类型，b 无符号，则相当于将 b 强转为 a 的有符号类型
        - 此处仅推断 b（调用本身）的符号性，赋值时的强转由赋值逻辑处理
        """
        func_node: ast.AST = node.func
        func_name: str = ''

        if isinstance(func_node, ast.Name):
            # 直接调用: rdrand64()
            func_name = func_node.id
        elif isinstance(func_node, ast.Attribute):
            # t.CUInt64T(x) 等类型转换调用
            if hasattr(func_node.value, 'id') and IsTModule(func_node.value.id, self.SymbolTable):
                if self._is_type_unsigned(func_node.attr):
                    return True
            # module.func() 形式的调用
            try:
                func_name = f"{func_node.value.id}.{func_node.attr}"
            except AttributeError:
                return False
        else:
            return False

        if not func_name or not self.SymbolTable:
            return False

        try:
            sym_info: Any = self.SymbolTable.lookup(func_name)
        except Exception:
            return False

        if sym_info and isinstance(sym_info, _CTypeInfo):
            if sym_info.IsFunction or sym_info.IsFuncPtr:
                ret_info: Any = sym_info.FuncPtrReturn
                if ret_info and isinstance(ret_info, _CTypeInfo):
                    # 指针类型视为无符号
                    if ret_info.PtrCount > 0:
                        return True
                    # 检查返回类型的 IsUInt 属性（IsSigned is False）
                    if ret_info.IsUInt:
                        return True
            elif sym_info.IsTypedef:
                # 修复：typedef 强转调用（如 ULONGLONG(0x11)）需要解析底层类型的无符号性
                # IsUInt 对组合类型（CType | CType 产生的 list）会失败，需多策略回退
                if sym_info.IsUInt:
                    return True
                # 策略1：直接检查 BaseType（可能是组合类型，如 ULONGLONG = CUnsignedLong | CLong）
                bt: Any = sym_info.BaseType
                if isinstance(bt, (tuple, list)):
                    for elem in bt:
                        if isinstance(elem, _t.CType) and getattr(elem, 'IsSigned', None) is False:
                            return True
                elif isinstance(bt, _t.CType) and getattr(bt, 'IsSigned', None) is False:
                    return True
                # 策略2：通过 OriginalType 解析
                if sym_info.OriginalType:
                    ot: Any = sym_info.OriginalType
                    if isinstance(ot, str):
                        if self._is_type_unsigned(ot):
                            return True
                    elif isinstance(ot, _CTypeInfo):
                        if ot.IsUInt:
                            return True
                    elif isinstance(ot, (tuple, list)):
                        for elem in ot:
                            if isinstance(elem, _t.CType) and getattr(elem, 'IsSigned', None) is False:
                                return True
                # 策略3：通过 _resolve_typedef 解析为字符串后判断
                resolved_str: str = self._resolve_typedef(func_name)
                if resolved_str and self._is_type_unsigned(resolved_str):
                    return True
        return False

    def _check_attribute_signedness(self, node: ast.Attribute) -> bool | None:
        """检查 Attribute 节点是否引用具有已知符号性的结构体字段。

        Returns:
            True:   字段是有符号类型
            False:  字段是无符号类型
            None:   无法确定（非结构体字段或符号性未知）
        """
        if not isinstance(node.value, ast.Name):
            return None
        var_name: str = node.value.id
        field_name: str = node.attr
        class_name: str | None = self._resolve_class_for_var(var_name)
        if not class_name:
            return None
        signed_dict: dict[str, bool] = self.class_member_signeds.get(class_name, {})
        if field_name in signed_dict:
            return signed_dict[field_name]
        return None