from __future__ import annotations
from typing import Any
import re
import ast
import llvmlite.ir as ir
from llvmlite.ir.values import _Undefined
from lib.includes import t as _t


class StructGenMixin:

    def _get_align(self, llvm_type: ir.Type) -> int:
        if isinstance(llvm_type, ir.IntType):
            return max(1, llvm_type.width // 8)
        if isinstance(llvm_type, ir.FloatType):
            return 4
        if isinstance(llvm_type, ir.DoubleType):
            return 8
        if isinstance(llvm_type, ir.PointerType):
            return self.ptr_size
        if isinstance(llvm_type, ir.ArrayType):
            return self._get_align(llvm_type.element)
        if isinstance(llvm_type, ir.LiteralStructType):
            return max((self._get_align(f) for f in llvm_type.elements), default=1)
        if isinstance(llvm_type, ir.IdentifiedStructType):
            if llvm_type.elements is None or len(llvm_type.elements) == 0:
                return self.ptr_size  # opaque struct, assume pointer alignment
            return max((self._get_align(f) for f in llvm_type.elements), default=1)
        if isinstance(llvm_type, ir.VoidType):
            return 0
        return 4

    def _resolve_opaque_struct(self, llvm_type: ir.Type) -> ir.Type:
        """尝试从 Gen.structs 中查找已解析的同名 struct，解决跨模块 struct 类型对象不一致的问题"""
        if not isinstance(llvm_type, ir.IdentifiedStructType):
            return llvm_type
        if llvm_type.elements is not None and len(llvm_type.elements) > 0:
            return llvm_type
        # opaque struct，尝试通过名称在 Gen.structs 中查找已解析的版本
        st_name: str
        try:
            st_name = llvm_type.name
        except Exception:
            return llvm_type
        if not st_name:
            return llvm_type
        # 提取短名称
        short_name: str = st_name
        if '.' in st_name:
            short_name = st_name.split('.', 1)[1]
        # 尝试短名称查找
        if short_name in self.structs:
            resolved: ir.IdentifiedStructType = self.structs[short_name]
            if isinstance(resolved, ir.IdentifiedStructType) and resolved.elements is not None and len(resolved.elements) > 0:
                return resolved
        # 尝试全名查找
        if st_name in self.structs:
            resolved: ir.IdentifiedStructType = self.structs[st_name]
            if isinstance(resolved, ir.IdentifiedStructType) and resolved.elements is not None and len(resolved.elements) > 0:
                return resolved
        # 尝试通过导入处理器从 stub 文件加载 struct 定义
        import_handler: Any = self._import_handler_ref
        if import_handler is not None:
            try:
                import_handler._TryLoadStructFromStub(short_name, self)
            except Exception:
                pass
            # 加载后再次查找
            if short_name in self.structs:
                resolved = self.structs[short_name]
                if isinstance(resolved, ir.IdentifiedStructType) and resolved.elements is not None and len(resolved.elements) > 0:
                    return resolved
            if st_name in self.structs:
                resolved = self.structs[st_name]
                if isinstance(resolved, ir.IdentifiedStructType) and resolved.elements is not None and len(resolved.elements) > 0:
                    return resolved
        return llvm_type

    def _get_struct_size(self, llvm_type: ir.Type) -> int:
        if isinstance(llvm_type, ir.IntType):
            return max(1, llvm_type.width // 8)
        if isinstance(llvm_type, ir.FloatType):
            return 4
        if isinstance(llvm_type, ir.DoubleType):
            return 8
        if isinstance(llvm_type, ir.PointerType):
            return self.ptr_size
        if isinstance(llvm_type, ir.ArrayType):
            return self._get_struct_size(llvm_type.element) * llvm_type.count
        if isinstance(llvm_type, ir.LiteralStructType):
            total: int = 0
            max_align: int = 1
            for f in llvm_type.fields:
                fa: int = self._get_align(f)
                fs: int = self._get_struct_size(f)
                max_align = max(max_align, fa)
                if fa > 1:
                    total = (total + fa - 1) // fa * fa
                total += fs
            if max_align > 1:
                total = (total + max_align - 1) // max_align * max_align
            return total
        if isinstance(llvm_type, ir.IdentifiedStructType):
            # 尝试解析 opaque struct 为已注册的版本
            llvm_type = self._resolve_opaque_struct(llvm_type)
            if llvm_type.elements is None or len(llvm_type.elements) == 0:
                return self.ptr_size  # opaque struct, assume pointer size
            total: int = 0
            max_align: int = 1
            for f in llvm_type.elements:
                fa: int = self._get_align(f)
                fs: int = self._get_struct_size(f)
                max_align = max(max_align, fa)
                if fa > 1:
                    total = (total + fa - 1) // fa * fa
                total += fs
            if max_align > 1:
                total = (total + max_align - 1) // max_align * max_align
            return total
        return 4

    @staticmethod
    def _strip_unnecessary_quotes(ir_str: str) -> str:
        def _unquote(m: re.Match) -> str:
            prefix: str = m.group(1)
            name: str = m.group(2)
            if '.' in name:
                return m.group(0)
            if re.match(r'^[a-zA-Z_$][a-zA-Z0-9_$]*$', name):
                return prefix + name
            return m.group(0)
        return re.sub(r'([@%])"([^"]+)"', _unquote, ir_str)

    def finalize(self) -> str:
        self._set_Vtable_initializers()
        self._fix_global_var_init()
        ir_text: str
        try:
            ir_text = str(self.module)
        except TypeError as e:
            for func in self.module.functions:
                for block in func.blocks:
                    for instr in block.instructions:
                        try:
                            str(instr)
                        except TypeError as te:
                            pass
            raise
        ir_text = self._strip_unnecessary_quotes(ir_text)
        struct_defs: list[str] = []
        struct_names: set[str] = set()
        for ClassName, struct_type in self.structs.items():
            if isinstance(struct_type, ir.IdentifiedStructType):
                sname: str = struct_type.name
                sname_ir: str
                if sname[0].isdigit() or '.' in sname or not sname.replace('_', '').replace('.', '').isalnum():
                    sname_ir = f'%"{sname}"'
                else:
                    sname_ir = f'%{sname}'
                if struct_type.elements is None or len(struct_type.elements) == 0:
                    if ClassName not in self.typedef_int_widths:
                        struct_names.add(sname)
                        struct_defs.append(f'{sname_ir} = type opaque')
                    continue
                elems: str = ', '.join(str(e) for e in struct_type.elements)
                if struct_type.packed:
                    struct_defs.append(f'{sname_ir} = type <{{ {elems} }}>')
                else:
                    struct_defs.append(f'{sname_ir} = type {{ {elems} }}')
                struct_names.add(sname)
        if struct_defs:
            lines: list[str] = ir_text.split('\n')
            filtered: list[str] = []
            for line in lines:
                stripped: str = line.strip()
                skip: bool = False
                for name in struct_names:
                    patterns: list[str]
                    if name[0].isdigit() or '.' in name or not name.replace('_', '').replace('.', '').isalnum():
                        patterns = [f'%"{name}" = type', f'%"{name}"=type', f'%{name} = type', f'%{name}=type']
                    else:
                        patterns = [f'%{name} = type', f'%{name}= type', f'%{name}=type']
                    for p in patterns:
                        if stripped.startswith(p):
                            skip = True
                            break
                    if skip:
                        break
                if not skip:
                    filtered.append(line)
            ir_text = '\n'.join(filtered)
            header_end: int = ir_text.find('\ndefine')
            if header_end == -1:
                header_end = ir_text.find('\ndeclare')
            if header_end == -1:
                header_end = ir_text.find('\n@')
            if header_end == -1:
                header_end = len(ir_text)
            insert_pos: int = ir_text.rfind('\n', 0, header_end)
            if insert_pos == -1:
                insert_pos = header_end
            struct_block: str = '\n'.join(struct_defs) + '\n'
            ir_text = ir_text[:insert_pos + 1] + struct_block + ir_text[insert_pos + 1:]
        for name in struct_names:
            if name[0].isdigit() or '.' in name:
                ir_text = re.sub(
                    r'%' + re.escape(name) + r'(?=[^a-zA-Z0-9_$\.]|$)',
                    r'%"' + name + r'"',
                    ir_text
                )

        return ir_text

    def _generate_structs(self) -> None:
        all_classes: set[str] = set(self.class_methods.keys()) | set(self.class_members.keys())
        
        preserved_structs: dict[str, ir.IdentifiedStructType] = {}
        for name, st in self.structs.items():
            if name not in all_classes:
                preserved_structs[name] = st
            elif isinstance(st, ir.IdentifiedStructType):
                preserved_structs[name] = st
        
        self.structs.clear()
        
        for name, st in preserved_structs.items():
            self.structs[name] = st
        
        # Step 1: 先为所有类创建空的 struct，确保后面可以正确引用
        all_classes = set(self.class_methods.keys()) | set(self.class_members.keys())
        for ClassName in all_classes:
            is_packed: bool = ClassName in self.class_packed
            if self.SymbolTable:
                Entry = self.SymbolTable.lookup(ClassName)
                if Entry and Entry.IsExceptionClass:
                    continue
                # 注意：类名可能与 CEnum 成员名冲突（如 ASTKind.Module 枚举成员与 Module 类同名）
                # 如果 ClassName 在 class_methods 中，表明是 _EmitClassLlvm 显式处理的常规类，
                # 不应被 IsEnum/IsTypedef 检查跳过
                if Entry and Entry.IsEnum and ClassName not in self.class_methods:
                    if not Entry.IsRenum:
                        continue
                if Entry and Entry.IsTypedef and ClassName not in self.class_methods:
                    if Entry.BaseType and not isinstance(Entry.BaseType, (type(None),)):
                        if not isinstance(Entry.BaseType, (_t._CTypedef,)):
                            continue
            if ClassName in self.structs:
                if is_packed:
                    self.structs[ClassName].packed = True
                continue
            # 修复跨模块类型定义冲突：如果类是从其他模块导入的（已在 class_sha1_map 注册），
            # 必须使用导入的 source_sha1 作为前缀，而非本地模块的 sha1。
            # 否则会创建缺少基类字段（如 GSListNode.Next）的本地类型定义，
            # 导致字段索引错位 → 访问违规崩溃。
            _imported_sha1: str = self.class_sha1_map.get(ClassName, '')
            if _imported_sha1:
                mangled_name: str = f"{_imported_sha1}.{ClassName}"
            else:
                mangled_name: str = self._mangle_name(ClassName)
            struct_type: ir.IdentifiedStructType = ir.IdentifiedStructType(self.module, mangled_name, packed=is_packed)
            self.structs[ClassName] = struct_type
        
        # Step 2: 解析跨模块的成员类型
        for ClassName, annotations in self.class_member_annotations.items():
            if ClassName not in self.class_members:
                continue
            for i, (member_name, member_type) in enumerate(self.class_members[ClassName]):
                if member_name in annotations:
                    annotation: Any = annotations[member_name]
                    ResolvedType: ir.Type | None = None
                    
                    if isinstance(annotation, ast.Attribute):
                        ClassTypeName: str = annotation.attr
                        if ClassTypeName in self.structs:
                            ResolvedType = self.structs[ClassTypeName]
                    elif isinstance(annotation, ast.BinOp) and isinstance(annotation.op, ast.BitOr):
                        left: Any = annotation.left
                        if isinstance(left, ast.Attribute):
                            ClassTypeName: str = left.attr
                            if ClassTypeName in self.structs:
                                ResolvedType = self.structs[ClassTypeName]
                    
                    if ResolvedType:
                        self.class_members[ClassName][i] = (member_name, ResolvedType)
        
        struct_name_map: dict[str, ir.IdentifiedStructType] = {}
        for struct_name, struct in self.structs.items():
            try:
                struct_name_map[struct.name] = struct
            except AssertionError:
                struct_name_map[struct_name] = struct
            orig: Any = getattr(struct, '_original_name', None)
            if orig:
                struct_name_map[orig] = struct

        # Step 3: 更新成员类型，确保使用正确的 mangled struct 引用
        for ClassName in all_classes:
            if ClassName not in self.class_members:
                continue
            for i, (member_name, member_type) in enumerate(self.class_members[ClassName]):
                if isinstance(member_type, ir.PointerType):
                    pointee: ir.Type = member_type.pointee
                    if isinstance(pointee, ir.IdentifiedStructType):
                        pname: str | None
                        try:
                            pname = pointee.name
                        except AssertionError:
                            pname = None
                        struct: ir.IdentifiedStructType | None = struct_name_map.get(pname) if pname else None
                        if struct is None:
                            orig: Any = getattr(pointee, '_original_name', None)
                            struct = struct_name_map.get(orig) if orig else None
                        if struct is not None:
                            self.class_members[ClassName][i] = (member_name, ir.PointerType(struct))
                        else:
                            raw_name: str = pname or ''
                            if raw_name.startswith('struct.'):
                                raw_name = raw_name[7:]
                            new_struct: ir.IdentifiedStructType = self._get_or_create_struct(raw_name)
                            self.class_members[ClassName][i] = (member_name, ir.PointerType(new_struct))
                elif isinstance(member_type, ir.IdentifiedStructType):
                    mname: str | None
                    try:
                        mname = member_type.name
                    except AssertionError:
                        mname = None
                    struct: ir.IdentifiedStructType | None = struct_name_map.get(mname) if mname else None
                    if struct is None:
                        orig: Any = getattr(member_type, '_original_name', None)
                        struct = struct_name_map.get(orig) if orig else None
                    if struct is not None:
                        self.class_members[ClassName][i] = (member_name, struct)
                    else:
                        raw_name: str = mname or ''
                        if raw_name.startswith('struct.'):
                            raw_name = raw_name[7:]
                        new_struct: ir.IdentifiedStructType = self._get_or_create_struct(raw_name)
                        self.class_members[ClassName][i] = (member_name, new_struct)
        
        # Step 4: 创建最终的 structs 并设置正确的成员类型
        for ClassName in all_classes:
            if self.SymbolTable:
                Entry = self.SymbolTable.lookup(ClassName)
                if Entry and Entry.IsExceptionClass:
                    continue
                # 注意：类名可能与 CEnum 成员名冲突（如 ASTKind.Constant 枚举成员与 Constant 类同名）
                # 如果 ClassName 在 class_methods 中，表明是 _EmitClassLlvm 显式处理的常规类，
                # 不应被 IsEnum 检查跳过（与 Step 1 的守卫保持一致）
                if Entry and Entry.IsEnum and ClassName not in self.class_methods:
                    if not Entry.IsRenum:
                        continue
            existing_st: ir.IdentifiedStructType | None = self.structs.get(ClassName)
            if isinstance(existing_st, ir.IdentifiedStructType) and existing_st.elements is not None and len(existing_st.elements) > 0:
                # 治本修复：检查 struct body 是否不完整（元素数少于 class_members + vtable 预期）。
                # 常见于跨模块继承：子类 struct 在父类 class_members 加载前从 stub 生成，
                # stub 中的定义可能不完整或类型不正确（如 GSList* 代替 AST*、i8* 代替 i32）。
                # 此处检测到不完整后清除 _elements 和 stub 缓存，让后续代码重新从 stub 加载。
                _has_vtable_precheck: bool = ClassName in self.class_vtable or ClassName in self._cross_module_vtable_classes
                if not _has_vtable_precheck:
                    _p_pre: str | None = self.class_parent.get(ClassName)
                    while _p_pre:
                        if _p_pre in self.class_vtable or _p_pre in self._cross_module_vtable_classes:
                            _has_vtable_precheck = True
                            break
                        _p_pre = self.class_parent.get(_p_pre)
                _expected_count_pre: int = len(self.class_members.get(ClassName, [])) + (1 if _has_vtable_precheck else 0)
                # has_vtable 时，首字段必须是 i8*（vtable 指针）。
                # 若首字段非指针（如 i8 占位符），struct body 不完整，需清除重新加载。
                _vtable_first_ok: bool = True
                if _has_vtable_precheck and len(existing_st.elements) > 0:
                    _vtable_first_ok = isinstance(existing_st.elements[0], ir.PointerType)
                # 检测 T* 占位类型（未特化的泛型类型参数）。
                # 当 struct 包含 T* 字段时（如 BasicBlock 继承 GSListNode[BasicBlock] 但 stub 未特化），
                # 说明 stub 使用了未特化的基类，需清除重新生成。
                _has_t_placeholder_pre: bool = False
                for _elem_pre in existing_st.elements:
                    if isinstance(_elem_pre, ir.PointerType) and isinstance(_elem_pre.pointee, ir.IdentifiedStructType):
                        _pname_pre: str = _elem_pre.pointee.name
                        _short_pre: str = _pname_pre.rsplit('.', 1)[-1] if '.' in _pname_pre else _pname_pre
                        if _short_pre == 'T':
                            _has_t_placeholder_pre = True
                            break
                if len(existing_st.elements) >= _expected_count_pre and _vtable_first_ok and not _has_t_placeholder_pre:
                    if ClassName in self.class_packed and not existing_st.packed:
                        existing_st.packed = True
                    continue
                # struct body 不完整，清除 _elements 和 stub 缓存以便重新加载
                existing_st._elements = None
                # 同时清除 sha1 全名 key 的 _elements：
                # self.structs 中可能同时存在 'Value'(短名) 和 'f9e36e2cd6fa659f.Value'(sha1全名) 两个 key，
                # _TryLoadStructFromStub 调用 _get_or_create_struct 时会返回 sha1全名 key 的 struct。
                # 若只清除短名 key 的 _elements，sha1全名 key 的 struct 仍保持错误 body（is_opaque=False），
                # 导致 _TryLoadStructFromStub 跳过 set_body，struct 保持不完整字段数。
                _imported_sha1_pre: str = self.class_sha1_map.get(ClassName, '')
                if _imported_sha1_pre:
                    _full_key_pre: str = f"{_imported_sha1_pre}.{ClassName}"
                    _full_st_pre: ir.IdentifiedStructType | None = self.structs.get(_full_key_pre)
                    if _full_st_pre is not None and isinstance(_full_st_pre, ir.IdentifiedStructType):
                        _full_st_pre._elements = None
                _import_handler_pre: Any = self._import_handler_ref
                if _import_handler_pre is not None:
                    _cache_key_pre: tuple = (id(self), ClassName)
                    if _cache_key_pre in _import_handler_pre._struct_Load_cache:
                        del _import_handler_pre._struct_Load_cache[_cache_key_pre]
                    # 同时清除 sha1全名 key 的 stub 缓存
                    if _imported_sha1_pre:
                        _cache_key_full_pre: tuple = (id(self), f"{_imported_sha1_pre}.{ClassName}")
                        if _cache_key_full_pre in _import_handler_pre._struct_Load_cache:
                            del _import_handler_pre._struct_Load_cache[_cache_key_full_pre]
            has_vtable: bool = ClassName in self.class_vtable or ClassName in self._cross_module_vtable_classes
            if not has_vtable:
                p: str | None = self.class_parent.get(ClassName)
                while p:
                    if p in self.class_vtable or p in self._cross_module_vtable_classes:
                        has_vtable = True
                        self.class_vtable.add(ClassName)
                        break
                    p = self.class_parent.get(p)
            has_bitfield: bool = ClassName in self.class_member_bitfields and any(
                self.class_member_bitfields[ClassName].get(name, 0) > 0
                for name, _ in self.class_members.get(ClassName, [])
            )
            all_members: list[tuple[str, ir.Type]] = self.class_members.get(ClassName, [])
            # 跳过正在发射中且成员尚未填充的类（递归特化时避免过早设置空 body）
            if not all_members and not has_vtable and ClassName in self._classes_in_progress:
                continue
            # 字段收集期间触发的嵌套 _generate_structs：class_members 可能不完整，
            # set_body 只能调用一次，跳过等字段收集完成后再设置 body
            if ClassName in self._collecting_members_set:
                continue
            all_bitfield: bool = all(
                self.class_member_bitfields.get(ClassName, {}).get(name, 0) > 0
                for name, _ in all_members
            ) if all_members else False

            mangled_name: str = self._mangle_name(ClassName)
            
            member_types: list[ir.Type]
            if has_bitfield and all_bitfield:
                total_bits: int = sum(self.class_member_bitfields.get(ClassName, {}).get(name, 0)
                                 for name, _ in all_members)
                storage_type: ir.IntType
                if total_bits <= 8:
                    storage_type = ir.IntType(8)
                elif total_bits <= 16:
                    storage_type = ir.IntType(16)
                elif total_bits <= 32:
                    storage_type = ir.IntType(32)
                else:
                    storage_type = ir.IntType(64)
                member_types = [storage_type]
                bitfield_offsets: dict[str, int] = {}
                current_bit_offset: int = 0
                for name, _ in all_members:
                    bit_width: int = self.class_member_bitfields.get(ClassName, {}).get(name, 0)
                    bitfield_offsets[name] = current_bit_offset
                    current_bit_offset += bit_width
                self.class_member_bitoffsets[ClassName] = bitfield_offsets
            else:
                member_types = []
                if has_vtable:
                    member_types.append(ir.PointerType(ir.IntType(8)))
                if ClassName in self.class_members:
                    for _, member_type in self.class_members[ClassName]:
                        if member_type is None:
                            member_type = ir.IntType(32)
                        member_types.append(member_type)
                else:
                    if has_vtable:
                        # has_vtable 但 class_members 为空（跨模块导入类）：
                        # 保持 member_types 为空（[i8*] 占位会导致 stub 加载跳过，
                        # 因为 set_body 后 is_opaque=False）。让 struct 保持 opaque，
                        # 由 _TryLoadStructFromStub 设置完整 body。
                        member_types = []
                    else:
                        # 无 vtable 且 class_members 为空：常见于 register_method 早期
                        # 调用 _generate_structs（此时 class_members[ClassName]=[] 但尚未
                        # 填充实际字段）。保持 opaque，避免 set_body(*[i8]) 永久损坏 struct
                        # （llvmlite 的 set_body 只能调用一次）。后续 _generate_structs 调用
                        # 会从 class_members 或 stub 设置正确 body。
                        member_types = []

            # 获取之前创建的 struct 并设置成员
            struct_type: ir.IdentifiedStructType = self.structs[ClassName]
            if ClassName in self.class_packed:
                struct_type.packed = True
            # 只在未设置 body 时设置，避免重复定义错误
            if struct_type.elements is None:
                # 跨模块 struct 的 class_members 可能不完整（当前模块只解析了部分字段），
                # 优先从 stub.ll 加载完整定义。set_body 只能对 opaque struct 调用一次，
                # 若用不完整 class_members 设置 body，后续无法修正，会导致 GEP 越界。
                # 但本地定义的类（_classes_in_progress）不从 stub 加载，因为 stub 可能
                # 来自同名导入类，其 vtable 状态与本地定义不同（@t.NoVTable 冲突）
                import_handler: Any = self._import_handler_ref
                if import_handler is not None and ClassName not in self._classes_in_progress:
                    try:
                        # 传入 source_sha1 确保从正确的 stub 文件加载完整定义
                        _src_sha1: str = self.class_sha1_map.get(ClassName, '')
                        import_handler._TryLoadStructFromStub(ClassName, self, source_sha1=_src_sha1 or None)
                    except Exception:
                        pass
                    struct_type = self.structs.get(ClassName, struct_type)
                # 检测 stub body 中的 T* 占位类型（未特化的泛型类型参数）。
                # 若 stub 使用了未特化的基类（如 GSListNode 而非 GSListNode[BasicBlock]），
                # 清除 _elements 让 set_body 用正确的 class_members 重新设置。
                if struct_type.elements is not None and member_types:
                    _has_t_placeholder_post: bool = False
                    for _elem_post in struct_type.elements:
                        if isinstance(_elem_post, ir.PointerType) and isinstance(_elem_post.pointee, ir.IdentifiedStructType):
                            _pname_post: str = _elem_post.pointee.name
                            _short_post: str = _pname_post.rsplit('.', 1)[-1] if '.' in _pname_post else _pname_post
                            if _short_post == 'T':
                                _has_t_placeholder_post = True
                                break
                    if _has_t_placeholder_post:
                        struct_type._elements = None
                if struct_type.elements is None:
                    # 防御性检查：member_types 为空时不调用 set_body。
                    # set_body(*[]) 会设置 elements=() 使 is_opaque=False，
                    # 后续无法再次 set_body（llvmlite 限制），导致跨模块类型永久损坏。
                    # 根因：register_method 在 class_members[ClassName]=[] 时立即调用
                    # _generate_structs，此时 member_types 为空。保持 opaque 状态，
                    # 让后续 _TryLoadStructFromStub 能正确设置 body。
                    if member_types:
                        struct_type.set_body(*member_types)

    def _create_Vtable_globals(self) -> None:
        for ClassName, methods in self.class_methods.items():
            if ClassName in self.Vtables:
                continue
            if not methods:
                continue
            if ClassName not in self.class_vtable and ClassName not in self._cross_module_vtable_classes:
                continue
            # 跳过正在发射中的类：它们的方法列表可能还不完整（如继承方法已添加但自有方法未添加），
            # 此时创建 vtable 会导致大小不匹配。这些类的 vtable 会在其 _EmitClassLlvm 完成后
            # 由 _create_vtable_for_class 显式创建，或在模块级 _create_Vtable_globals 调用中创建。
            if ClassName in self._classes_in_progress:
                continue
            # 跨模块虚表过滤：_precollect_vtable_state 会将所有 includes 的有方法类同时加入
            # _shared_class_vtable 和 _shared_cross_module_vtable，导致 class_vtable 与
            # _cross_module_vtable_classes 内容相同，无法用以区分本模块类与跨模块类。
            # _generate_structs 会为所有 class_methods 的类创建空 struct type，导致 self.structs
            # 也包含所有类。过滤条件是 self.functions：只考虑本模块定义的函数（define，有函数体），
            # 跳过跨模块的 declare（无函数体）。跨模块类的 declare 通过 HandlesImports 加入
            # self.functions（短名如 "MemManager.alloc"），但其 is_declaration=True。
            # 若只存在 declare 而无 define，说明本模块未定义该类，虚表应由定义模块创建。
            # vtable linkage='internal'，跨模块调用通过对象的 vtable 指针（首字段）完成分派，
            # 不依赖本模块的 vtable 全局变量。
            has_local_method: bool = False
            prefix: str = f"{ClassName}."
            for func_name, func_obj in self.functions.items():
                if func_name.startswith(prefix):
                    # 跳过跨模块的 declare（无函数体），只考虑本模块定义的函数
                    if not getattr(func_obj, 'is_declaration', False):
                        has_local_method = True
                        break
            if not has_local_method:
                continue
            VtableType: ir.ArrayType = ir.ArrayType(ir.PointerType(ir.IntType(8)), len(methods))
            Vtable: ir.GlobalVariable = ir.GlobalVariable(self.module, VtableType, name=self._mangle_name(f"{ClassName}_Vtable"))
            Vtable.initializer = ir.Constant(VtableType, [ir.Constant(ir.PointerType(ir.IntType(8)), None)] * len(methods))
            Vtable.linkage = 'internal'
            self.Vtables[ClassName] = Vtable

    def _create_vtable_for_class(self, ClassName: str) -> None:
        """为单个类创建 vtable（用于 _EmitClassLlvm 中当前类的方法已全部注册后）。"""
        methods: list = self.class_methods.get(ClassName, [])
        if not methods:
            return
        if ClassName not in self.class_vtable and ClassName not in self._cross_module_vtable_classes:
            return
        _vtable_name: str = self._mangle_name(f"{ClassName}_Vtable")
        # 如果虚表已在导入阶段创建（方法列表不完整，缺少继承方法），删除旧虚表
        if ClassName in self.Vtables:
            _old_vtable = self.Vtables[ClassName]
            _old_name = _old_vtable.name
            if _old_name in self.module.globals:
                del self.module.globals[_old_name]
            # llvmlite 的 NameScope._useset 追踪所有已使用的名字，
            # del module.globals[name] 不会从 _useset 移除，
            # 导致再次创建同名 GlobalVariable 时 scope.register() 报 DuplicatedNameError
            self.module.scope._useset.discard(_old_name)
            del self.Vtables[ClassName]
        # 防御性：如果全局变量已存在但不在 Vtables 字典中，也删除
        if _vtable_name in self.module.globals:
            del self.module.globals[_vtable_name]
        self.module.scope._useset.discard(_vtable_name)
        VtableType: ir.ArrayType = ir.ArrayType(ir.PointerType(ir.IntType(8)), len(methods))
        Vtable: ir.GlobalVariable = ir.GlobalVariable(self.module, VtableType, name=_vtable_name)
        Vtable.initializer = ir.Constant(VtableType, [ir.Constant(ir.PointerType(ir.IntType(8)), None)] * len(methods))
        Vtable.linkage = 'internal'
        self.Vtables[ClassName] = Vtable

    def _fix_global_var_init(self) -> None:
        for gv_name, gv in list(self.module.globals.items()):
            if not isinstance(gv, ir.GlobalVariable):
                continue
            if gv.linkage in ('external', 'extern_weak'):
                continue
            needs_fix: bool = False
            if gv.initializer is None:
                needs_fix = True
            elif hasattr(gv.initializer, 'constant') and isinstance(gv.initializer.constant, _Undefined):
                needs_fix = True
            elif isinstance(gv.initializer, ir.Constant):
                if isinstance(gv.initializer.constant, list):
                    if any(hasattr(c, 'constant') and isinstance(c.constant, _Undefined) for c in gv.initializer.constant):
                        needs_fix = True
            if not needs_fix:
                continue
            gv.initializer = ir.Constant(gv.value_type, None)
            if gv_name.startswith('str_const_') or gv_name.endswith('_Vtable') or gv_name.endswith('_str'):
                gv.linkage = 'internal'

    def _set_Vtable_initializers(self) -> None:
        for ClassName, methods in self.class_methods.items():
            if ClassName not in self.Vtables:
                continue
            if not methods:
                continue
            struct_type: ir.IdentifiedStructType | None = self.structs.get(ClassName)
            if struct_type is None:
                continue
            Vtable: ir.GlobalVariable = self.Vtables[ClassName]
            Vtable_entries: list[ir.Constant] = []
            for MethodName in methods:
                short_name: str = MethodName.split('.')[-1] if '.' in MethodName else MethodName
                full_MethodName: str = f"{ClassName}.{short_name}"
                func: ir.Function | None = None
                if full_MethodName in self.functions:
                    func = self.functions[full_MethodName]
                if func is None:
                    parent_cls: str | None = self.class_parent.get(ClassName)
                    while parent_cls:
                        parent_full: str = f"{parent_cls}.{short_name}"
                        if parent_full in self.functions:
                            func = self.functions[parent_full]
                            break
                        parent_cls = self.class_parent.get(parent_cls)
                if func is None:
                    Vtable_entries.append(ir.Constant(ir.PointerType(ir.IntType(8)), None))
                    continue
                Vtable_entries.append(func.bitcast(ir.PointerType(ir.IntType(8))))
            Vtable.initializer = ir.Constant(Vtable.type.pointee, Vtable_entries)