from __future__ import annotations
from typing import Any
import ast
import os
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


class VaArgInstruction(ir.Instruction):
    def descr(self, buf: list[str]) -> None:
        ptr: ir.Value = self.operands[0]
        buf.append("va_arg {0} {1}, {2}\n".format(
            ptr.type, ptr.get_reference(), self.type))


class BaseGenMixin:

    @staticmethod
    def _parse_triple(triple: str | None) -> dict[str, bool | int]:
        """解析目标三元组，返回平台信息字典"""
        info: dict[str, bool | int] = {
            'is_windows': False, 'is_linux': False, 'is_macos': False,
            'is_x86_64': False, 'is_arm64': False, 'is_32bit': False,
            'ptr_size': 8, 'long_size': 8, 'wchar_t_size': 32,
        }
        if not triple:
            return info
        triple_lower: str = triple.lower()
        # 检测操作系统
        if 'windows' in triple_lower or 'win32' in triple_lower or 'mingw' in triple_lower or 'msvc' in triple_lower or 'cygwin' in triple_lower:
            info['is_windows'] = True
            # Windows LLP64: long = 32 位, wchar_t = 16 位
            info['long_size'] = 32
            info['wchar_t_size'] = 16
        elif 'linux' in triple_lower:
            info['is_linux'] = True
        elif 'darwin' in triple_lower or 'macos' in triple_lower or 'apple' in triple_lower:
            info['is_macos'] = True
        # 检测架构
        if 'x86_64' in triple_lower or 'amd64' in triple_lower or 'x64' in triple_lower:
            info['is_x86_64'] = True
        elif 'aarch64' in triple_lower or 'arm64' in triple_lower:
            info['is_arm64'] = True
        elif 'i386' in triple_lower or 'i686' in triple_lower or 'arm' in triple_lower:
            info['is_32bit'] = True
            info['ptr_size'] = 4
            info['long_size'] = 32
            if info['is_windows']:
                info['wchar_t_size'] = 16
            else:
                info['wchar_t_size'] = 32
        return info

    def __init__(self, triple: str | None = None, datalayout: str | None = None) -> None:
        self.module: ir.Module = ir.Module(name="transpyc_module")
        if triple:
            self.module.triple = triple
        else:
            self.module.triple = "x86_64-none-elf"
        if datalayout:
            self.module.data_layout = datalayout
        else:
            self.module.data_layout = "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128"

        # 解析目标平台信息
        self._platform_info: dict[str, bool | int] = self._parse_triple(self.module.triple)
        self.ptr_size: int = self._platform_info['ptr_size']
        # 根据目标平台配置 t 模块中的平台相关类型大小
        _t.configure_platform(self.module.triple)
        self.builder: ir.IRBuilder | None = None
        self.func: ir.Function | None = None
        self.functions: dict[str, ir.Function] = {}
        self.variables: dict[str, ir.Value | None] = {}
        self._direct_values: dict[str, ir.Value] = {}
        self._reg_values: dict[str, ir.Value] = {}
        self.var_signedness: dict[str, bool] = {}
        self._unsigned_results: set[int] = {}
        self.string_const_counter: int = 0
        self.Vtables: dict[str, ir.GlobalVariable] = {}
        self.class_methods: dict[str, list[str]] = {}
        self.class_members: dict[str, list[tuple[str, ir.Type]]] = {}
        self.class_member_defaults: dict[str, dict[str, Any]] = {}
        self.class_member_signeds: dict[str, dict[str, bool]] = {}
        self.class_member_bitfields: dict[str, dict[str, int]] = {}
        self.class_member_byteorders: dict[str, dict[str, str]] = {}
        self.local_var_byteorders: dict[str, str] = {}
        self.class_member_element_class: dict[str, dict[str, str]] = {}
        self.class_member_bitoffsets: dict[str, dict[str, int]] = {}
        self.structs: dict[str, ir.IdentifiedStructType] = {}
        self.typedef_int_widths: dict[str, int] = {}  # typedef名称 -> 底层整数位宽 (如 'UINT' -> 32, 'BYTE' -> 8)
        self._cross_module_vtable_classes: set[str] = set()
        self._cross_module_novtable: set[str] = set()
        self.class_vtable: set[str] = set()
        self._class_graph: dict[str, Any] = {}
        self.class_parent: dict[str, str] = {}
        # Store member annotations for deferred type resolution (cross-module class references)
        self.class_member_annotations: dict[str, dict[str, Any]] = {}
        self.loop_break_targets: list[ir.Block] = []
        self.loop_continue_targets: list[ir.Block] = []
        self.eh_jmp_buf_stack: list[ir.Value] = []
        self.eh_except_block_stack: list[ir.Block] = []
        self.eh_finally_stack: list[Any] = []
        self.global_vars: set[str] = set()
        self.nonlocal_params: dict[str, Any] = {}
        self._variable_scope_stack: list[dict[str, Any]] = []  # Stack of outer scope variables for nested function nonlocal lookup
        self.var_struct_class: dict[str, str] = {}
        self.var_ptr_element: dict[str, bool] = {}
        # 全局变量的指针元素标志（持久，不受函数重置影响）
        # 用于全局变量 _argv: bytes | t.CPtr 等，使 _argv[index] 使用 8 字节指针步长
        self.global_var_ptr_element: dict[str, bool] = {}
        self.class_provides: dict[str, list[str]] = {}
        self.class_requires: dict[str, list[str]] = {}
        self.class_require_must: dict[str, list[str]] = {}
        # 编译期 with 上下文栈：记录当前嵌套 with 链中所有可用的 provides 字段名
        # 用于 __require_must__ 的纯编译期静态可达性检查
        self._with_provides_stack: list[list[str]] = []
        # 函数参数自动取地址模式: func_name -> [None, None, 'need', 'always', ...]
        # 'need': t.CNeedPtr — 仅对非指针值取地址
        # 'always': t.CAutoPtr — 无条件取地址
        self._auto_addr_params: dict[str, list[str | None]] = {}
        self.global_struct_class: dict[str, str] = {}
        self.var_type_info: dict[str, Any] = {}
        self.var_const_flags: dict[str, bool] = {}
        self._current_source_file: str | None = None
        self._current_source_lines: list[str] = []
        self._ns_cache: dict[str, str] = {}
        self._type_cache: dict[tuple[str, bool], ir.Type] = {}
        self._typedef_cache: dict[str, Any] = {}
        self._func_sig_cache: dict[str, Any] = {}
        self.var_type_assignments: dict[str, Any] = {}
        self._temp_struct_ptrs: list[ir.Value] = []
        self._stop_iter_flag_param: ir.Value | None = None
        self._local_heap_ptrs: list[tuple[ir.Value, str, str | None]] = []
        self._var_to_heap_ptr: dict[str, ir.Value] = {}
        self.known_return_types: dict[str, ir.Type] = {}
        self._current_lineno: int = 0
        self._current_node_info: str = ""
        self.module_sha1: str | None = None
        self.ModuleSha1Map: dict[str, str] = {}
        self._temp_dir: str | None = None
        self._export_funcs: set[str] = set()
        self._export_extern_funcs: dict[str, str] = {}
        self._current_module_func_names: set[str] = set()
        # __doc__ 魔法字符串注册表：symbol_name -> docstring 文本（None 表示空/优化剥离）
        self._doc_strings: dict[str, str | None] = {}
        self.class_packed: set[str] = set()
        self._define_constants: dict[str, int] = {}
        # 以下属性原先在外部懒注入，此处显式初始化以避免 hasattr/getattr 动态反射
        self._struct_sha1_map: dict[str, str] = {}
        self.SymbolTable: Any = None
        self._Trans: Any = None
        self.class_sha1_map: dict[str, str] = {}
        # 以下属性原先懒注入，此处显式初始化以消除 hasattr/getattr 动态反射
        self._import_handler_ref: Any = None
        self._classes_in_progress: set[str] = set()
        # 字段收集期间添加当前类名，阻止 CollectAnnAssignMember 触发的嵌套
        # _generate_structs 用不完整 class_members 调用 set_body（set_body 只能调用一次）
        # 用集合而非单值，因为嵌套特化类 _EmitClassLlvm 会清除单值，导致外层类被错误设置 body
        self._collecting_members_set: set[str] = set()
        self._last_var_name: str | None = None
        self._variadic_info: dict | None = None
        self._vtable_copy_counter: int = 0
        self._decorated_funcs: dict = {}
        self._current_tree: Any = None
        self._DefineConstants: dict = {}
        self._all_define_constants: dict = {}
        # 闭包追踪：记录返回闭包的函数和变量
        # _closure_return_types: func_name -> (fn_return_type, nonlocal_arg_types)
        self._closure_return_types: dict[str, tuple[Any, list[Any]]] = {}
        # _closure_var_types: var_name -> (fn_return_type, nonlocal_arg_types)
        self._closure_var_types: dict[str, tuple[Any, list[Any]]] = {}
        pi: dict[str, bool | int] = self._platform_info
        # 根据目标平台设置宏（声明式，从三元组推导）
        if pi['is_windows']:
            self._define_constants['_WIN32'] = 1
            if not pi['is_32bit']:
                self._define_constants['_WIN64'] = 1
                self._define_constants['WIN64'] = 1
            self._define_constants['WIN32'] = 1
        if pi['is_linux']:
            self._define_constants['__linux__'] = 1
        if pi['is_macos']:
            self._define_constants['__APPLE__'] = 1
            self._define_constants['__MACH__'] = 1
        if pi['is_x86_64']:
            self._define_constants['__x86_64__'] = 1
            self._define_constants['__x86_64'] = 1
            self._define_constants['_M_X64'] = 1
        elif pi['is_arm64']:
            self._define_constants['__aarch64__'] = 1
            self._define_constants['_M_ARM64'] = 1
        if not pi['is_32bit'] and pi['is_linux']:
            self._define_constants['__LP64__'] = 1
        elif pi['is_32bit']:
            self._define_constants['_ILP32'] = 1
        self._define_constants['SIZEOF_VOID_P'] = pi['ptr_size']
        self._define_constants['__SIZEOF_POINTER__'] = pi['ptr_size']

    def find_struct_by_pointee(self, pointee: ir.Type) -> tuple[str, ir.IdentifiedStructType] | None:
        """根据 pointee 类型查找匹配的结构体，返回 (class_name, struct_type) 或 None"""
        for class_name, struct_type in self.structs.items():
            if pointee == struct_type:
                return (class_name, struct_type)
        return None

    @staticmethod
    def _extract_short_name(name: str) -> str:
        """从结构体类型名中提取短名（去掉 sha1 前缀）。
        如 "6bc91356c652f8ca.Function" → "Function"
        如 "Function" → "Function"（无 sha1 前缀时原样返回）
        """
        if '.' in name:
            prefix: str = name.split('.', 1)[0]
            if len(prefix) == 16 and all(c in '0123456789abcdef' for c in prefix):
                return name.split('.', 1)[1]
        return name

    @staticmethod
    def _extract_struct_sha1(st: ir.IdentifiedStructType) -> str:
        """从 IdentifiedStructType 的 name 中提取 sha1 前缀（16 位十六进制）。
        返回空字符串表示无 sha1 前缀。用于同名类冲突检测。
        """
        if not isinstance(st, ir.IdentifiedStructType):
            return ''
        try:
            name: str = st.name
        except (AssertionError, AttributeError):
            return ''
        if '.' in name:
            prefix: str = name.split('.', 1)[0]
            if len(prefix) == 16 and all(c in '0123456789abcdef' for c in prefix):
                return prefix
        return ''

    def _get_or_create_struct(self, name: str, source_sha1: str | None = None, packed: bool = False) -> ir.IdentifiedStructType:
        clean_name: str = name.replace(' *', '').replace('*', '').replace(' ', '_').replace('const', 'const_').replace('volatile', 'volatile_')
        # 如果名称包含模块前缀（如 "a9fa0f6200c09e65.zbit_writer"），
        # 先尝试用短名称（如 "zbit_writer"）查找已注册的 struct，
        # 避免为同一 struct 创建多个不同的类型对象导致跨模块引用类型不一致
        if '.' in clean_name and clean_name not in self.structs:
            parts: list[str] = clean_name.split('.', 1)
            if len(parts[0]) == 16 and all(c in '0123456789abcdef' for c in parts[0]):
                short_name: str = parts[1]
                if short_name in self.structs:
                    existing_short: ir.IdentifiedStructType = self.structs[short_name]
                    # 治本修复：同名类 sha1 冲突检测。
                    # 当请求的 sha1 前缀与现有 struct 的 sha1 前缀不一致时
                    # （如 stmts.py:Module 与 __module.py:Module 同名冲突），
                    # 不能复用已有 struct（set_body 已锁定为错误布局），
                    # 需创建独立 struct 并以 sha1 前缀全名存储。
                    _existing_sha1: str = self._extract_struct_sha1(existing_short)
                    if _existing_sha1 and _existing_sha1 != parts[0]:
                        if clean_name in self.structs:
                            return self.structs[clean_name]
                        st_new: ir.IdentifiedStructType = ir.IdentifiedStructType(self.module, name=clean_name, packed=packed)
                        self.structs[clean_name] = st_new
                        return st_new
                    return existing_short
        # 优先解析 typedef 整数类型（如 INT/UINT/BYTE），避免将其注册为 opaque struct。
        # 必须在 `if clean_name in self.structs` 缓存检查之前执行，
        # 否则首次调用（SymbolTable 未就绪时）会将 typedef 名缓存为 opaque struct，
        # 后续调用即使 SymbolTable 就绪也只会返回缓存的错误类型。
        # 此修复同时解决两个问题：
        #   1. alloca unsized type：变量声明 `argc: INT = 6` 不再生成 `alloca %"...INT"`
        #   2. 下标访问：FindStructNameInAnnotation 不再匹配 typedef 名（因不在 Gen.structs）
        td_width: int | None = self._resolve_typedef_int_width(clean_name)
        if td_width is not None:
            if td_width > 0:
                self.typedef_int_widths[clean_name] = td_width
                return ir.IntType(td_width)
            # td_width == 0: 特殊 typedef 名称（str/bytes/list 等），返回 i8
            self.typedef_int_widths[clean_name] = 0
            return ir.IntType(8)
        if clean_name in self.structs:
            existing: ir.IdentifiedStructType = self.structs[clean_name]
            # 治本修复：同名类 sha1 冲突检测（短名调用路径）。
            # 当 source_sha1 与现有 struct 的 sha1 前缀不一致时（跨模块同名类冲突），
            # 不能复用已有 struct（set_body 已锁定为错误布局），
            # 需创建独立 struct 并以 sha1 前缀全名存储，不覆盖短名条目。
            if source_sha1:
                _existing_sha1: str = self._extract_struct_sha1(existing)
                if _existing_sha1 and _existing_sha1 != source_sha1:
                    full_key: str = f"{source_sha1}.{clean_name}"
                    if full_key in self.structs:
                        st_full: ir.IdentifiedStructType = self.structs[full_key]
                        if packed and isinstance(st_full, ir.IdentifiedStructType) and not st_full.packed:
                            st_full.packed = True
                        return st_full
                    ns_name: str = f"{source_sha1}.{clean_name}"
                    st_new: ir.IdentifiedStructType = ir.IdentifiedStructType(self.module, name=ns_name, packed=packed)
                    self.structs[full_key] = st_new
                    return st_new
            if packed and isinstance(existing, ir.IdentifiedStructType) and not existing.packed:
                existing.packed = True
            return existing
        if clean_name in {'typedef', 'CType', 'CVolatile', 'CEnum', 'CUnion', 'CStruct', 'enum', 'REnum', 'renum', 'Void', 'void'}:
            return ir.IntType(8)
        # typing.Any 是"任意类型"标记，应解析为 i8*（通用指针），
        # 而非创建为 opaque 结构体（否则包含 Any 字段的结构体会变成 unsized）。
        if clean_name == 'Any':
            return ir.IntType(8).as_pointer()
        # t.CType 的基本类型子类（CInt/CChar/CSizeT/CLong/CFloat/CDouble 等，
        # position 含 BASE 且 Size>0）有具体 LLVM 类型，应直接返回对应的
        # ir.IntType/ir.FloatType/ir.DoubleType，而非创建结构体。
        # _is_ctype_marker_name 对这些类型返回 False（不跳过），需要在此处拦截。
        _basic_llvm_type: ir.Type | None = self._try_resolve_ctype_basic(clean_name)
        if _basic_llvm_type is not None:
            return _basic_llvm_type
        # t.CType 及其子类是"类型强转"标记，不应被编译为真实结构体。
        # 动态检查 t 模块中所有 CType 子类名（排除 CStruct/CEnum/CUnion/REnum 子类，
        # 因为用户定义的结构体类继承自它们，需要被创建为结构体）。
        if self._is_ctype_marker_name(clean_name):
            return ir.IntType(8)
        if self.SymbolTable:
            Entry: _CTypeInfo | None = self.SymbolTable.lookup(clean_name)
            if Entry and Entry.IsTypedef:
                resolved_str: str = self._resolve_typedef(clean_name)
                if resolved_str != clean_name:
                    return self._type_str_to_llvm(resolved_str)
                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)
            if Entry and Entry.IsRenum:
                if clean_name in self.structs:
                    return self.structs[clean_name]
                # REnum 结构体尚未创建时不能 fall through 到 IsEnum（会返回 i32），
                # 需要继续到下方正常结构体创建路径，创建 opaque 结构体。
                # 这对自引用 REnum（如 LLVMType 包含 LLVMType*）至关重要：
                # _parse_llvm_type 先通过此路径创建 opaque 结构体，_TryLoadStructFromStub 再 set_body。
            elif Entry and Entry.IsEnum and clean_name not in self.class_methods:
                return ir.IntType(32)
            # 治本修复：当 clean_name 是已注册的类（在 class_methods 或 class_members 中）时，
            # 不应走 IsExceptionClass/IsFunction/IsVariable 分支返回非结构体类型。
            # 否则 _get_or_create_struct 返回指针类型（如 _TypedPointerType）而非 IdentifiedStructType，
            # 导致 _TryLoadStructFromStub 的 set_body 被跳过（isinstance 检查失败），
            # struct 保持不完整字段数，引发跨模块 GEP 越界崩溃。
            _is_class_name: bool = clean_name in self.class_methods or clean_name in self.class_members
            if Entry and Entry.IsExceptionClass and not _is_class_name:
                return ir.IntType(32)
            if Entry and Entry.IsFunction and not _is_class_name:
                return ir.PointerType(ir.IntType(8))
            if Entry and Entry.IsVariable and not _is_class_name:
                return ir.PointerType(ir.IntType(8))
            if Entry and Entry.BaseType:
                if isinstance(Entry.BaseType, type) and issubclass(Entry.BaseType, _t.CEnum):
                    return ir.IntType(32)
                if Entry.BaseType is _t.CEnum:
                    return ir.IntType(32)
        ns_name: str
        if source_sha1:
            ns_name = f"{source_sha1}.{clean_name}"
        elif clean_name in self._struct_sha1_map:
            ns_name = f"{self._struct_sha1_map[clean_name]}.{clean_name}"
        else:
            ns_name = self._mangle_name(clean_name)
        st: ir.IdentifiedStructType = ir.IdentifiedStructType(self.module, name=ns_name, packed=packed)
        self.structs[clean_name] = st
        # 尝试解析 typedef 的底层整数位宽
        width: int | None = self._resolve_typedef_int_width(clean_name)
        if width is not None:
            self.typedef_int_widths[clean_name] = width
        return st

    def _resolve_typedef_int_width(self, name: str) -> int | None:
        """解析 typedef 名称的底层整数位宽

        通过 CTypeRegistry 和 BuiltinTypeMap 动态解析，
        替代硬编码的 TYPEDEF_NAMES 映射表。
        返回 int 位宽或 None（无法解析）。
        """
        # 1. 先查 BuiltinTypeMap（覆盖 BYTEPTR 等指针别名）
        bm: Any = BuiltinTypeMap.Get(name)
        if bm:
            ctype_cls: Any
            ptr_count: int
            ctype_cls, ptr_count = bm
            if ptr_count > 0:
                return None  # 指针类型，不是整数 typedef
            llvm_str: str = CTypeRegistry.CTypeToLLVM(ctype_cls)
            if llvm_str and llvm_str.startswith('i') and llvm_str[1:].isdigit():
                return int(llvm_str[1:])

        # 2. 再查 SymbolTable（用户定义的 typedef）
        if self.SymbolTable:
            Entry: _CTypeInfo | None = self.SymbolTable.lookup(name)
            if Entry and Entry.IsTypedef:
                if Entry.BaseType:
                    if not isinstance(Entry.BaseType, (_t._CTypedef,)) and Entry.PtrCount == 0:
                        llvm_str: str = CTypeRegistry.CTypeToLLVM(type(Entry.BaseType) if isinstance(Entry.BaseType, _t.CType) else Entry.BaseType)
                        if llvm_str and llvm_str.startswith('i') and llvm_str[1:].isdigit():
                            return int(llvm_str[1:])
                if Entry.OriginalType:
                    if isinstance(Entry.OriginalType, _CTypeInfo) and Entry.OriginalType.BaseType:
                        if not isinstance(Entry.OriginalType.BaseType, (_t._CTypedef,)) and Entry.OriginalType.PtrCount == 0:
                            llvm_str: str = CTypeRegistry.CTypeToLLVM(type(Entry.OriginalType.BaseType) if isinstance(Entry.OriginalType.BaseType, _t.CType) else Entry.OriginalType.BaseType)
                            if llvm_str and llvm_str.startswith('i') and llvm_str[1:].isdigit():
                                return int(llvm_str[1:])
                    elif isinstance(Entry.OriginalType, str):
                        # OriginalType 是类型名字符串（如 'CInt', 'CUnsignedInt'），
                        # 通过 CTypeRegistry 解析为整数位宽
                        cls: Any = CTypeRegistry.GetClassByName(Entry.OriginalType)
                        if cls:
                            llvm_str: str = CTypeRegistry.CTypeToLLVM(cls)
                            if llvm_str and llvm_str.startswith('i') and llvm_str[1:].isdigit():
                                return int(llvm_str[1:])

        # 3. 尝试 CTypeRegistry 直接按名称查找
        ctype_cls: Any = CTypeRegistry.GetClassByName(name)
        if ctype_cls:
            llvm_str: str = CTypeRegistry.CTypeToLLVM(ctype_cls)
            if llvm_str and llvm_str.startswith('i') and llvm_str[1:].isdigit():
                return int(llvm_str[1:])

        # 4. 特殊名称（非整数类型，但需要标记为 typedef 以跳过 opaque 定义）
        # 注意：如果 name 已注册为 struct（用户定义了同名 class，如 includes/_dict.py 中的 dict），
        # 则不应视为 typedef，应返回 None 让调用方走 struct 创建路径。
        # 解决时序问题：_parse_llvm_declare 从 stub.ll 解析时 dict 可能尚未注册到 Gen.structs，
        # 但 SymbolTable 在 .pyi 解析阶段已就绪，可通过 is_struct 检查区分 class 和 typedef。
        _SPECIAL_TYPEDEFS: set[str] = {
            'typedef', 'CType', 'CVolatile', 'CEnum', 'CUnion',
            'CStruct', 'enum', 'REnum', 'renum',
            'list', 'dict', 'tuple', 'set', 'str', 'bytes', 'array', 'type', 'CArray',
        }
        if name in _SPECIAL_TYPEDEFS:
            if name in self.structs:
                return None  # 已注册为 struct，不视为 typedef
            if self.SymbolTable is not None:
                try:
                    if self.SymbolTable.is_struct(name):
                        return None  # SymbolTable 中标记为 struct，不视为 typedef
                except Exception:
                    pass
            return 0  # 标记为 typedef，但位宽为 0（非整数）

        # t.CType 及其子类是"类型强转"标记，不应被创建为结构体。
        # 动态检查 t 模块中所有 CType 子类名（排除 CStruct/CEnum/CUnion/REnum 子类）。
        # 返回 0 标记为 typedef，使 _get_or_create_struct 走 typedef 路径返回 i8。
        if self._is_ctype_marker_name(name):
            return 0

        return None

    @staticmethod
    def _is_ctype_marker_name(name: str) -> bool:
        """检查名称是否是 t.CType 的"类型强转"标记子类名。

        只有 position 不含 BASE 的纯修饰符/标记类型（CPtr/CVolatile/CConst/
        CInline/CStatic/CExtern/CExport/CRegister/CAuto/_CTypedef/CTypeDefault 等）
        才应该跳过结构体创建。有 BASE position 的基本类型（CInt/CChar/CSizeT/
        CLong/CFloat/CDouble 等）有具体大小，应被正常解析为对应宽度的整数/浮点。

        CStruct/CEnum/CUnion/REnum 的用户子类是合法结构体，需要被创建。

        注意：CTypeRegistry.GetClassByName 会跳过 CType 本身和 CTypeDefault，
        所以这里直接用 getattr(t, name) 检查 t 模块属性。

        Returns:
            True 如果 name 是 CType 标记子类名（应跳过结构体创建）
        """
        if not name:
            return False
        # 去除可能的 SHA1 前缀（如 "abc123.CPtr" -> "CPtr"）
        short_name: str = name.split('.')[-1] if '.' in name else name
        # 直接查 t 模块属性（CTypeRegistry._build 会跳过 CType/CTypeDefault/BigEndian/LittleEndian）
        t_cls: Any = getattr(_t, short_name, None)
        if not isinstance(t_cls, type) or not issubclass(t_cls, _t.CType):
            return False
        # 排除 CStruct/CEnum/CUnion/REnum 子类（它们是命名类型的基类，
        # 用户定义的结构体继承自它们，需要被创建为结构体）
        if issubclass(t_cls, (_t.CStruct, _t.CEnum, _t.REnum, _t.CUnion)):
            return False
        # 基本类型（position 含 BASE 且 Size > 0）有具体大小，不应跳过
        # （CInt→i32, CChar→i8, CSizeT→i64, CLong→i64, CFloat→f32 等）
        # CVoid 虽含 BASE 但 Size=0，CType Size=None，仍需跳过
        if _t.CType.BASE in t_cls.position:
            # 检查实例的 Size（类属性可能未设置，用实例获取）
            try:
                inst = t_cls()
                size_val = getattr(inst, 'Size', None)
                if size_val is not None and size_val > 0:
                    return False
            except Exception:
                pass
        return True

    def _try_resolve_ctype_basic(self, name: str) -> ir.Type | None:
        """尝试将 t.CType 的基本类型子类名解析为对应的 LLVM 基本类型。

        仅对 t 模块内的 CType 基本类型子类（CInt/CChar/CSizeT/CLong/CFloat/
        CDouble 等，即 position 含 BASE 且 Size>0）生效，返回对应的
        ir.IntType/ir.FloatType/ir.DoubleType。

        CStruct/CEnum/CUnion/REnum 子类不在此处理（用户自定义结构体需要被
        创建为结构体）。CVoid/CType/CPtr 等无 Size 或 Size=0 的类型也不在此
        处理（应通过 _is_ctype_marker_name 跳过结构体创建）。

        Returns:
            对应的 ir.Type，或 None 表示不是基本类型，需要继续走结构体创建路径。
        """
        if not name:
            return None
        short_name: str = name.split('.')[-1] if '.' in name else name
        cls: Any = getattr(_t, short_name, None)
        if not isinstance(cls, type) or not issubclass(cls, _t.CType):
            return None
        if issubclass(cls, (_t.CStruct, _t.CEnum, _t.REnum, _t.CUnion)):
            return None
        if _t.CType.BASE not in getattr(cls, 'position', frozenset()):
            return None
        try:
            inst = cls()
            size_val = getattr(inst, 'Size', None)
            if size_val is None or size_val <= 0:
                return None
        except Exception:
            return None
        llvm_str: str | None = CTypeRegistry.NameToLLVM(short_name)
        if not llvm_str:
            return None
        return self._type_str_to_llvm(llvm_str)

    def _set_node_info(self, node: ast.AST, extra_info: str = "") -> None:
        if hasattr(node, 'lineno'):
            self._current_lineno = node.lineno
        else:
            self._current_lineno = 0
        if hasattr(node, 'col_offset'):
            self._current_node_info = f"line {self._current_lineno}, col {node.col_offset}"
        else:
            self._current_node_info = f"line {self._current_lineno}"
        if extra_info:
            self._current_node_info += f" ({extra_info})"

    def _set_source_info(self, filepath: str) -> None:
        self._current_source_file = filepath
        try:
            with open(filepath, 'r', encoding='utf-8') as f:
                self._current_source_lines = f.readlines()
        except Exception:  # 文件读取失败时回退为空行列表
            self._current_source_lines = []

    def _skip_mangle(self, name: str) -> bool:
        skip_prefixes: tuple[str, ...] = ('llvm.', 'str_const_', 'printf', 'memset_pattern')
        if any(name.startswith(p) for p in skip_prefixes):
            return True
        if '.' in name:
            parts: list[str] = name.split('.', 1)
            if len(parts[0]) >= 8 and all(c in '0123456789abcdef' for c in parts[0]):
                return True
        return False

    def _mangle_name(self, name: str) -> str:
        if self._skip_mangle(name):
            return name
        if name in self._export_funcs:
            return name
        if self.module_sha1:
            return f"{self.module_sha1}.{name}"
        return name

    def _find_function(self, name: str) -> ir.Function | None:
        if name in self.functions:
            return self.functions[name]
        g: Any = self.module.globals.get(name)
        if g and isinstance(g, ir.Function):
            self.functions[name] = g
            return g
        mangled: str = self._mangle_func_name(name)
        if mangled != name:
            if mangled in self.functions:
                self.functions[name] = self.functions[mangled]
                return self.functions[mangled]
            g = self.module.globals.get(mangled)
            if g and isinstance(g, ir.Function):
                self.functions[mangled] = g
                self.functions[name] = g
                return g
        for sha1 in self.ModuleSha1Map.values():
            prefixed: str = f"{sha1}.{name}"
            if prefixed in self.functions:
                self.functions[name] = self.functions[prefixed]
                return self.functions[prefixed]
            g = self.module.globals.get(prefixed)
            if g and isinstance(g, ir.Function):
                self.functions[prefixed] = g
                self.functions[name] = g
                return g
        return None

    def _has_function(self, name: str) -> bool:
        return self._find_function(name) is not None

    def _get_or_declare_function(self, mangled_name: str, func_type: ir.FunctionType) -> ir.Function:
        g = self.module.globals.get(mangled_name)
        if g and isinstance(g, ir.Function):
            return g
        return ir.Function(self.module, func_type, name=mangled_name)

    def _get_function(self, name: str) -> ir.Function | None:
        func: ir.Function | None = self._find_function(name)
        return func

    def _mangle_func_name(self, name: str, module_name: str | None = None) -> str:
        if name in self._export_funcs and not module_name:
            return name
        if name in self._export_extern_funcs:
            target_sha1: str = self._export_extern_funcs[name]
            if module_name:
                # 显式带 module_name 调用（如 stdlib.system）：即使当前模块定义了同名函数，
                # 也应按模块匹配 extern，返回裸名。snprintf 之所以工作而 system 不工作，
                # 就是因为 os._win32 定义了自己的 system 包装，导致旧逻辑跳过了 extern 匹配。
                if module_name == target_sha1:
                    return name
                if module_name in self.ModuleSha1Map and self.ModuleSha1Map[module_name] == target_sha1:
                    return name
                init_name: str = f"{module_name}.__init__"
                if init_name in self.ModuleSha1Map and self.ModuleSha1Map[init_name] == target_sha1:
                    return name
                # 兜底：module_name 不在 ModuleSha1Map 中或 sha1 不匹配，
                # 但函数在 _export_extern_funcs 中（C extern 不应混淆），
                # 仅当当前模块未定义同名函数时才返回裸名。
                if name not in self._current_module_func_names:
                    return name
            elif name not in self._current_module_func_names:
                # 无 module_name 调用（如 from stdlib import system; system()）：
                # 仅当当前模块未定义同名函数时才返回 extern 裸名，
                # 否则让本地定义走正常 mangle 路径（本地 def 遮蔽 import 语义）。
                return name
        # main 函数作为程序入口点，永远不混淆
        if name == 'main':
            return name
        # Try class_sha1_map first for class methods (e.g., 'md5.__init__' -> class 'md5')
        class_sha1_map: dict[str, str] = self.class_sha1_map
        if class_sha1_map:
            if '.' in name:
                base_class: str = name.split('.')[0]
                if base_class in class_sha1_map:
                    sha1: str = class_sha1_map[base_class]
                    return f"{sha1}.{name}"
            elif name in class_sha1_map:
                sha1: str = class_sha1_map[name]
                return f"{sha1}.{name}"
        # If module_name is already a SHA1 hash (16 hex chars), use it directly
        if module_name and len(module_name) == 16 and all(c in '0123456789abcdef' for c in module_name):
            return f"{module_name}.{name}"
        if module_name and module_name in self.ModuleSha1Map:
            sha1: str = self.ModuleSha1Map[module_name]
            return f"{sha1}.{name}"
        # Try parent package name (e.g., 'hashlib' -> 'hashlib.__init__')
        if module_name:
            init_name: str = f"{module_name}.__init__"
            if init_name in self.ModuleSha1Map:
                sha1: str = self.ModuleSha1Map[init_name]
                return f"{sha1}.{name}"
        if self._skip_mangle(name):
            return name
        if self.module_sha1:
            return f"{self.module_sha1}.{name}"
        return name

    def _get_source_line(self, lineno: int) -> str | None:
        if 0 < lineno <= len(self._current_source_lines):
            return self._current_source_lines[lineno - 1].rstrip('\r\n')
        return None

    def _get_node_info(self) -> str:
        info: str = ""
        if self._current_node_info:
            info = f" [{self._current_node_info}]"
        if self._current_source_file:
            info += f" in {self._current_source_file}"
            lineno: int = self._current_lineno
            if lineno > 0:
                info += f", line {lineno}:"
                source_line: str | None = self._get_source_line(lineno)
                if source_line:
                    info += f"\n  → {source_line}"
        return info

    # ========== 统一工具方法 ==========

    def _create_string_global(self, s: str, name: str | None = None) -> ir.Constant:
        """创建字符串全局变量并返回 i8* 指针。

        统一字符串全局变量创建模式：编码为 utf-8 + '\\x00' 终止符，
        创建 internal linkage 的 GlobalVariable，返回 i8* 指针常量。
        """
        str_val: str = s + '\x00'
        str_bytes: bytes = str_val.encode('utf-8')
        arr_type: ir.ArrayType = ir.ArrayType(ir.IntType(8), len(str_bytes))
        gv_name: str = name or f"str_const_{self.string_const_counter}"
        self.string_const_counter += 1
        gv: ir.GlobalVariable = ir.GlobalVariable(self.module, arr_type, name=gv_name)
        gv.initializer = ir.Constant(arr_type, bytearray(str_bytes))
        gv.linkage = 'internal'
        return ir.Constant(ir.PointerType(ir.IntType(8)), gv.get_reference())

    def _create_doc_global(self, symbol_name: str, docstring: str | None) -> None:
        """为符号创建 __doc__ 全局常量。

        - docstring 为 None 或空字符串时，不创建常量（访问时内联空指针）
        - slice_level != 0（优化开启）时，内容视为空
        - 非空时创建 internal linkage、global_constant=True 的只读字符串常量
        - 常量名格式：{module_sha1}.{symbol_name}.__doc__
        """
        slice_level: int = getattr(self._Trans, 'SliceLevel', 3)
        if slice_level != 0:
            docstring = None
        if docstring is None or docstring == '':
            self._doc_strings[symbol_name] = None
            return
        self._doc_strings[symbol_name] = docstring
        mangled: str = self._mangle_name(f"{symbol_name}.__doc__")
        self._create_string_global(docstring, name=mangled)
        gv: ir.GlobalVariable | None = self.module.globals.get(mangled)
        if gv is not None:
            gv.global_constant = True

    def _get_doc_ptr(self, symbol_name: str) -> ir.Value | None:
        """获取符号 __doc__ 的 i8* 指针。

        - 若符号未注册 __doc__，返回 None（调用方回退到其他解析）
        - 若 __doc__ 为空（无 docstring 或优化剥离），返回 i8* null 内联空指针
        - 若 __doc__ 非空，返回指向字符串全局常量的 i8* 指针
        - 跨模块 docstring（在 _doc_strings 中有文本但 module.globals 无对应常量）首次访问时创建本地 internal linkage 只读副本
        """
        if symbol_name not in self._doc_strings:
            return None
        docstring: str | None = self._doc_strings[symbol_name]
        if docstring is None or docstring == '':
            return ir.Constant(ir.PointerType(ir.IntType(8)), None)
        mangled: str = self._mangle_name(f"{symbol_name}.__doc__")
        gv: ir.GlobalVariable | None = self.module.globals.get(mangled)
        if gv is None:
            # 跨模块 docstring：创建本地 internal linkage 只读字符串常量副本
            self._create_string_global(docstring, name=mangled)
            gv = self.module.globals.get(mangled)
            if gv is None:
                return ir.Constant(ir.PointerType(ir.IntType(8)), None)
            gv.global_constant = True
        zero: ir.Constant = ir.Constant(ir.IntType(32), 0)
        return self.builder.gep(gv, [zero, zero], name=f"{symbol_name}_doc_ptr")

    def _apply_bswap_if_big(self, val: ir.Value, byte_order: str, name: str) -> ir.Value:
        """大端字节序时对整数应用 bswap，否则原值返回。

        仅对 16/32/64 位整数生效，统一 bswap 逻辑。
        """
        if byte_order == 'big' and isinstance(val.type, ir.IntType) and val.type.width in (16, 32, 64):
            return self.builder.bswap(val, name=name)
        return val

    def _zero_value_for_type(self, llvm_type: ir.Type) -> ir.Constant | None:
        """为指定 LLVM 类型生成零值常量。

        合并原 HandlesAssign._zero_value 与 StructGen._zero_value_for_type 的逻辑。
        返回 ir.Constant 或 None（无法生成零值的类型，如 opaque struct）。
        """
        if isinstance(llvm_type, ir.IntType):
            return ir.Constant(llvm_type, 0)
        elif isinstance(llvm_type, (ir.FloatType, ir.DoubleType)):
            return ir.Constant(llvm_type, 0.0)
        elif isinstance(llvm_type, ir.PointerType):
            return ir.Constant(llvm_type, None)
        elif isinstance(llvm_type, ir.ArrayType):
            elem_zv: ir.Constant | None = self._zero_value_for_type(llvm_type.element)
            if elem_zv is None:
                return None
            return ir.Constant(llvm_type, [elem_zv] * llvm_type.count)
        elif isinstance(llvm_type, ir.BaseStructType):
            if llvm_type.elements is not None and len(llvm_type.elements) > 0:
                elem_zvs: list[ir.Constant | None] = [self._zero_value_for_type(m) for m in llvm_type.elements]
                if any(zv is None for zv in elem_zvs):
                    return None
                return ir.Constant(llvm_type, elem_zvs)
            return None
        return None