可用的回归测试通过的标准版本
This commit is contained in:
@@ -2,7 +2,7 @@ from __future__ import annotations
|
||||
from typing import TYPE_CHECKING
|
||||
if TYPE_CHECKING:
|
||||
from lib.core.translator import Translator
|
||||
from lib.core.Handles.HandlesBase import BaseHandle, CTypeInfo, FuncMeta
|
||||
from lib.core.Handles.HandlesBase import BaseHandle, CTypeInfo, FuncMeta
|
||||
from lib.includes import t
|
||||
import ast
|
||||
import os
|
||||
@@ -13,13 +13,13 @@ import llvmlite.ir as ir
|
||||
class ImportHandle(BaseHandle):
|
||||
_stub_cache = {}
|
||||
_stub_cache_dir = None
|
||||
_struct_load_cache = {}
|
||||
_struct_Load_cache = {}
|
||||
_pyi_cache = {}
|
||||
_pyi_cache_dir = None
|
||||
_project_root_cache = None
|
||||
|
||||
def _reset_file_cache(self):
|
||||
self._struct_load_cache.clear()
|
||||
self._struct_Load_cache.clear()
|
||||
|
||||
def _find_project_root(self):
|
||||
if self._project_root_cache is not None:
|
||||
@@ -43,17 +43,17 @@ class ImportHandle(BaseHandle):
|
||||
return os.getcwd()
|
||||
|
||||
def _EmitImportDeclarationsLlvm(self, Node, Gen):
|
||||
if not getattr(self.Trans, '_imported_modules', None):
|
||||
self.Trans._imported_modules = set()
|
||||
if not getattr(self.Trans, '_import_aliases', None):
|
||||
self.Trans._import_aliases = {}
|
||||
if not getattr(self.Trans, '_ImportedModules', None):
|
||||
self.Trans._ImportedModules = set()
|
||||
if not getattr(self.Trans, '_ImportAliases', None):
|
||||
self.Trans._ImportAliases = {}
|
||||
for alias in Node.names:
|
||||
name = alias.name
|
||||
if name in ('c', 't'):
|
||||
continue
|
||||
self.Trans._imported_modules.add(name)
|
||||
self.Trans._ImportedModules.add(name)
|
||||
if alias.asname:
|
||||
self.Trans._import_aliases[alias.asname] = name
|
||||
self.Trans._ImportAliases[alias.asname] = name
|
||||
# 同时在符号表中注册模块别名,以便 CTypeInfo.FromNode 能解析
|
||||
AliasInfo = CTypeInfo()
|
||||
AliasInfo.IsModuleAlias = True
|
||||
@@ -63,7 +63,7 @@ class ImportHandle(BaseHandle):
|
||||
self._EmitModuleDeclarationsLlvm(name, Gen, register_module_name=current_module)
|
||||
|
||||
def _RegisterFromImportAliases(self, Node, Gen, module):
|
||||
"""Register 'from module import y as z' aliases after module declarations are loaded"""
|
||||
"""Register 'from module import y as z' aliases after module declarations are Loaded"""
|
||||
if not Node.names:
|
||||
return
|
||||
for alias in Node.names:
|
||||
@@ -125,11 +125,11 @@ class ImportHandle(BaseHandle):
|
||||
def _EmitImportFromDeclarationsLlvm(self, Node, Gen):
|
||||
module = Node.module if Node.module else ''
|
||||
if module in ('c', 't'):
|
||||
if not getattr(self.Trans, '_imported_modules', None):
|
||||
self.Trans._imported_modules = set()
|
||||
if not getattr(self.Trans, '_import_aliases', None):
|
||||
self.Trans._import_aliases = {}
|
||||
self.Trans._imported_modules.add(module)
|
||||
if not getattr(self.Trans, '_ImportedModules', None):
|
||||
self.Trans._ImportedModules = set()
|
||||
if not getattr(self.Trans, '_ImportAliases', None):
|
||||
self.Trans._ImportAliases = {}
|
||||
self.Trans._ImportedModules.add(module)
|
||||
if not hasattr(self.Trans, '_t_c_imported_names'):
|
||||
self.Trans._t_c_imported_names = {}
|
||||
for alias in Node.names:
|
||||
@@ -137,10 +137,10 @@ class ImportHandle(BaseHandle):
|
||||
asname = alias.asname or name
|
||||
self.Trans._t_c_imported_names[asname] = (module, name)
|
||||
return
|
||||
if not getattr(self.Trans, '_imported_modules', None):
|
||||
self.Trans._imported_modules = set()
|
||||
if not getattr(self.Trans, '_import_aliases', None):
|
||||
self.Trans._import_aliases = {}
|
||||
if not getattr(self.Trans, '_ImportedModules', None):
|
||||
self.Trans._ImportedModules = set()
|
||||
if not getattr(self.Trans, '_ImportAliases', None):
|
||||
self.Trans._ImportAliases = {}
|
||||
current_module = self._get_current_module_name()
|
||||
if Node.level and Node.level > 0:
|
||||
current_file = getattr(self.Trans, 'CurrentFile', '') or ''
|
||||
@@ -154,20 +154,20 @@ class ImportHandle(BaseHandle):
|
||||
for ext in SearchExtensions:
|
||||
candidate = sub_path_base + ext
|
||||
if os.path.isfile(candidate):
|
||||
self.Trans._imported_modules.add(module)
|
||||
self.Trans._ImportedModules.add(module)
|
||||
self._LoadModuleDeclarationsFromFile(candidate, Gen, module_name=module, register_module_name=current_module)
|
||||
self._RegisterFromImportAliases(Node, Gen, module)
|
||||
return
|
||||
module_sha1_map = getattr(Gen, 'module_sha1_map', {})
|
||||
ModuleSha1Map = getattr(Gen, 'ModuleSha1Map', {})
|
||||
# 尝试完整模块名和短模块名
|
||||
full_mod_name = f"{current_module}.{module}" if current_module else module
|
||||
target_sha1 = module_sha1_map.get(full_mod_name) or module_sha1_map.get(module)
|
||||
target_sha1 = ModuleSha1Map.get(full_mod_name) or ModuleSha1Map.get(module)
|
||||
if target_sha1:
|
||||
temp_dir = getattr(Gen, '_temp_dir', None)
|
||||
if temp_dir:
|
||||
sha1_pyi = os.path.join(temp_dir, f"{target_sha1}.pyi")
|
||||
if os.path.isfile(sha1_pyi):
|
||||
self.Trans._imported_modules.add(module)
|
||||
self.Trans._ImportedModules.add(module)
|
||||
self._LoadModuleDeclarationsFromFile(sha1_pyi, Gen, module_name=module, register_module_name=current_module)
|
||||
self._RegisterFromImportAliases(Node, Gen, module)
|
||||
return
|
||||
@@ -177,39 +177,39 @@ class ImportHandle(BaseHandle):
|
||||
SearchExtensions = ['.pyi', '.py']
|
||||
pkg_name = ''
|
||||
if not module:
|
||||
# When 'from . import name' is used, load the package's __init__
|
||||
# When 'from . import name' is used, Load the package's __init__
|
||||
# to make package-level names (functions, classes, constants) available
|
||||
pkg_name = self._LoadPackageInitForRelativeImport(mod_dir, Gen, current_module)
|
||||
|
||||
# Also try to load each alias as a submodule
|
||||
# Also try to Load each alias as a submodule
|
||||
for alias in Node.names:
|
||||
found_sub = False
|
||||
for ext in SearchExtensions:
|
||||
sub_path = os.path.join(mod_dir, alias.name + ext)
|
||||
if os.path.isfile(sub_path):
|
||||
self.Trans._imported_modules.add(alias.name)
|
||||
self.Trans._ImportedModules.add(alias.name)
|
||||
self._LoadModuleDeclarationsFromFile(sub_path, Gen, module_name=alias.name, register_module_name=current_module)
|
||||
if alias.asname:
|
||||
self.Trans._import_aliases[alias.asname] = alias.name
|
||||
self.Trans._ImportAliases[alias.asname] = alias.name
|
||||
found_sub = True
|
||||
break
|
||||
if not found_sub:
|
||||
# SHA1 map fallback for submodule
|
||||
module_sha1_map = getattr(Gen, 'module_sha1_map', {})
|
||||
sub_module_path = f"{pkg_name}.{alias.name}" if pkg_name else alias.name
|
||||
target_sha1 = module_sha1_map.get(sub_module_path) or module_sha1_map.get(alias.name)
|
||||
ModuleSha1Map = getattr(Gen, 'ModuleSha1Map', {})
|
||||
sub_ModulePath = f"{pkg_name}.{alias.name}" if pkg_name else alias.name
|
||||
target_sha1 = ModuleSha1Map.get(sub_ModulePath) or ModuleSha1Map.get(alias.name)
|
||||
if target_sha1:
|
||||
temp_dir = getattr(Gen, '_temp_dir', None)
|
||||
if temp_dir:
|
||||
sha1_pyi = os.path.join(temp_dir, f"{target_sha1}.pyi")
|
||||
if os.path.isfile(sha1_pyi):
|
||||
self.Trans._imported_modules.add(sub_module_path)
|
||||
self.Trans._ImportedModules.add(sub_ModulePath)
|
||||
self._LoadModuleDeclarationsFromFile(sha1_pyi, Gen, module_name=alias.name, register_module_name=current_module)
|
||||
if alias.asname:
|
||||
self.Trans._import_aliases[alias.asname] = alias.name
|
||||
self.Trans._ImportAliases[alias.asname] = alias.name
|
||||
self._RegisterFromImportAliases(Node, Gen, module or pkg_name)
|
||||
return
|
||||
self.Trans._imported_modules.add(module)
|
||||
self.Trans._ImportedModules.add(module)
|
||||
self._EmitModuleDeclarationsLlvm(module, Gen, register_module_name=current_module)
|
||||
self._RegisterFromImportAliases(Node, Gen, module)
|
||||
|
||||
@@ -229,15 +229,15 @@ class ImportHandle(BaseHandle):
|
||||
reexport_names = []
|
||||
if module_name and module_name != file_module_name and module_name != effective_register:
|
||||
reexport_names.append(module_name)
|
||||
# When loading a submodule for 'from .xxx import yyy' inside a package's __init__.py,
|
||||
# When Loading a submodule for 'from .xxx import yyy' inside a package's __init__.py,
|
||||
# re-export functions under the package name so 'pkg.func()' resolves correctly
|
||||
if reexport_package and reexport_package != file_module_name and reexport_package not in reexport_names:
|
||||
reexport_names.append(reexport_package)
|
||||
self._EmitExternalFuncDeclLlvm(node, Gen, source_module_name=file_module_name, register_module_name=effective_register, reexport_module_names=reexport_names if reexport_names else None)
|
||||
elif isinstance(node, ast.AnnAssign):
|
||||
self._EmitExternalGlobalDeclLlvm(node, Gen, module_name=module_name, module_path=pyi_path)
|
||||
self._EmitExternalGlobalDeclLlvm(node, Gen, module_name=module_name, ModulePath=pyi_path)
|
||||
elif isinstance(node, ast.Assign):
|
||||
self._EmitExternalGlobalDeclLlvm(node, Gen, module_name=module_name, module_path=pyi_path)
|
||||
self._EmitExternalGlobalDeclLlvm(node, Gen, module_name=module_name, ModulePath=pyi_path)
|
||||
elif isinstance(node, ast.ClassDef):
|
||||
if hasattr(node, 'type_params') and node.type_params:
|
||||
if not hasattr(self.Trans.ClassHandler, '_generic_class_templates'):
|
||||
@@ -263,9 +263,9 @@ class ImportHandle(BaseHandle):
|
||||
if os.path.isfile(candidate):
|
||||
actual_module = f"{register_module_name}.{node.module}" if register_module_name else node.module
|
||||
self._RegisterSubModuleSha1(candidate, actual_module, node.module, Gen)
|
||||
if not getattr(self.Trans, '_imported_modules', None):
|
||||
self.Trans._imported_modules = set()
|
||||
self.Trans._imported_modules.add(actual_module)
|
||||
if not getattr(self.Trans, '_ImportedModules', None):
|
||||
self.Trans._ImportedModules = set()
|
||||
self.Trans._ImportedModules.add(actual_module)
|
||||
for alias in node.names:
|
||||
if alias.name == '*':
|
||||
self._LoadModuleDeclarationsFromFile(candidate, Gen, module_name=module_name, register_module_name=register_module_name, reexport_package=reexport_package or module_name)
|
||||
@@ -276,16 +276,16 @@ class ImportHandle(BaseHandle):
|
||||
# SHA1 map 回退
|
||||
if not found_sub:
|
||||
actual_module = f"{register_module_name}.{node.module}" if register_module_name else node.module
|
||||
module_sha1_map = getattr(Gen, 'module_sha1_map', {})
|
||||
target_sha1 = module_sha1_map.get(actual_module) or module_sha1_map.get(node.module)
|
||||
ModuleSha1Map = getattr(Gen, 'ModuleSha1Map', {})
|
||||
target_sha1 = ModuleSha1Map.get(actual_module) or ModuleSha1Map.get(node.module)
|
||||
if target_sha1:
|
||||
temp_dir = getattr(Gen, '_temp_dir', None)
|
||||
if temp_dir:
|
||||
sha1_pyi = os.path.join(temp_dir, f"{target_sha1}.pyi")
|
||||
if os.path.isfile(sha1_pyi):
|
||||
if not getattr(self.Trans, '_imported_modules', None):
|
||||
self.Trans._imported_modules = set()
|
||||
self.Trans._imported_modules.add(actual_module)
|
||||
if not getattr(self.Trans, '_ImportedModules', None):
|
||||
self.Trans._ImportedModules = set()
|
||||
self.Trans._ImportedModules.add(actual_module)
|
||||
for alias in node.names:
|
||||
if alias.name == '*':
|
||||
self._LoadModuleDeclarationsFromFile(sha1_pyi, Gen, module_name=module_name, register_module_name=register_module_name, reexport_package=reexport_package or module_name)
|
||||
@@ -301,10 +301,10 @@ class ImportHandle(BaseHandle):
|
||||
for ext in SearchExtensions:
|
||||
sub_path = os.path.join(mod_dir, alias.name + ext)
|
||||
if os.path.isfile(sub_path):
|
||||
sub_module_path = f"{register_module_name}.{alias.name}" if register_module_name else alias.name
|
||||
if not getattr(self.Trans, '_imported_modules', None):
|
||||
self.Trans._imported_modules = set()
|
||||
self.Trans._imported_modules.add(sub_module_path)
|
||||
sub_ModulePath = f"{register_module_name}.{alias.name}" if register_module_name else alias.name
|
||||
if not getattr(self.Trans, '_ImportedModules', None):
|
||||
self.Trans._ImportedModules = set()
|
||||
self.Trans._ImportedModules.add(sub_ModulePath)
|
||||
if alias.name == '*':
|
||||
self._LoadModuleDeclarationsFromFile(sub_path, Gen, module_name=module_name, register_module_name=register_module_name, reexport_package=reexport_package or module_name)
|
||||
else:
|
||||
@@ -313,17 +313,17 @@ class ImportHandle(BaseHandle):
|
||||
break
|
||||
# SHA1 map 回退
|
||||
if not found_alias:
|
||||
sub_module_path = f"{register_module_name}.{alias.name}" if register_module_name else alias.name
|
||||
module_sha1_map = getattr(Gen, 'module_sha1_map', {})
|
||||
target_sha1 = module_sha1_map.get(sub_module_path) or module_sha1_map.get(alias.name)
|
||||
sub_ModulePath = f"{register_module_name}.{alias.name}" if register_module_name else alias.name
|
||||
ModuleSha1Map = getattr(Gen, 'ModuleSha1Map', {})
|
||||
target_sha1 = ModuleSha1Map.get(sub_ModulePath) or ModuleSha1Map.get(alias.name)
|
||||
if target_sha1:
|
||||
temp_dir = getattr(Gen, '_temp_dir', None)
|
||||
if temp_dir:
|
||||
sha1_pyi = os.path.join(temp_dir, f"{target_sha1}.pyi")
|
||||
if os.path.isfile(sha1_pyi):
|
||||
if not getattr(self.Trans, '_imported_modules', None):
|
||||
self.Trans._imported_modules = set()
|
||||
self.Trans._imported_modules.add(sub_module_path)
|
||||
if not getattr(self.Trans, '_ImportedModules', None):
|
||||
self.Trans._ImportedModules = set()
|
||||
self.Trans._ImportedModules.add(sub_ModulePath)
|
||||
if alias.name == '*':
|
||||
self._LoadModuleDeclarationsFromFile(sha1_pyi, Gen, module_name=module_name, register_module_name=register_module_name, reexport_package=reexport_package or module_name)
|
||||
else:
|
||||
@@ -339,52 +339,56 @@ class ImportHandle(BaseHandle):
|
||||
return None
|
||||
|
||||
def _RegisterSubModuleSha1(self, candidate_path, actual_module, short_module, Gen):
|
||||
"""Register a submodule's SHA1 in module_sha1_map so cross-module class references work"""
|
||||
"""Register a submodule's SHA1 in ModuleSha1Map so cross-module class references work"""
|
||||
try:
|
||||
with open(candidate_path, 'r', encoding='utf-8') as f:
|
||||
sub_content = f.read()
|
||||
sub_sha1 = hashlib.sha1(sub_content.encode('utf-8')).hexdigest()[:16]
|
||||
if hasattr(Gen, 'module_sha1_map'):
|
||||
Gen.module_sha1_map[actual_module] = sub_sha1
|
||||
if short_module and short_module not in Gen.module_sha1_map:
|
||||
Gen.module_sha1_map[short_module] = sub_sha1
|
||||
except Exception:
|
||||
pass
|
||||
if hasattr(Gen, 'ModuleSha1Map'):
|
||||
Gen.ModuleSha1Map[actual_module] = sub_sha1
|
||||
if short_module and short_module not in Gen.ModuleSha1Map:
|
||||
Gen.ModuleSha1Map[short_module] = sub_sha1
|
||||
except Exception as _e:
|
||||
from lib.core.VLogger import get_logger as _vlog
|
||||
from lib.constants.config import mode as _config_mode
|
||||
if _config_mode == "strict":
|
||||
raise
|
||||
_vlog().warning(f"处理导入失败: {_e}", "Exception")
|
||||
|
||||
def _LoadPackageInitForRelativeImport(self, mod_dir, Gen, register_module_name):
|
||||
"""Load __init__.py from the package directory for 'from . import name' resolution.
|
||||
This makes package-level names (functions, classes, constants) available.
|
||||
Returns the package name."""
|
||||
pkg_name = os.path.basename(mod_dir)
|
||||
init_Loaded = False
|
||||
|
||||
# 跳过当前正在编译的文件,避免重复加载导致 class_members 重复
|
||||
current_sha1 = getattr(Gen, 'module_sha1', None)
|
||||
ModuleSha1Map = getattr(Gen, 'ModuleSha1Map', {})
|
||||
pkg_sha1 = ModuleSha1Map.get(pkg_name)
|
||||
if pkg_sha1 and pkg_sha1 == current_sha1:
|
||||
return pkg_name
|
||||
|
||||
# Try SHA1 map first (correct mangled names from stub)
|
||||
if pkg_sha1:
|
||||
temp_dir = getattr(Gen, '_temp_dir', None)
|
||||
if temp_dir:
|
||||
sha1_pyi = os.path.join(temp_dir, f"{pkg_sha1}.pyi")
|
||||
if os.path.isfile(sha1_pyi):
|
||||
self._LoadModuleDeclarationsFromFile(sha1_pyi, Gen, module_name=pkg_name, register_module_name=register_module_name)
|
||||
init_Loaded = True
|
||||
|
||||
# Fallback: try Loading __init__.py directly from the package directory
|
||||
if not init_Loaded:
|
||||
for ext in ['.pyi', '.py']:
|
||||
init_path = os.path.join(mod_dir, '__init__' + ext)
|
||||
if os.path.isfile(init_path):
|
||||
self._LoadModuleDeclarationsFromFile(init_path, Gen, module_name=pkg_name, register_module_name=register_module_name)
|
||||
init_Loaded = True
|
||||
break
|
||||
|
||||
return pkg_name
|
||||
|
||||
def _LoadPackageInitForRelativeImport(self, mod_dir, Gen, register_module_name):
|
||||
"""Load __init__.py from the package directory for 'from . import name' resolution.
|
||||
This makes package-level names (functions, classes, constants) available.
|
||||
Returns the package name."""
|
||||
pkg_name = os.path.basename(mod_dir)
|
||||
init_loaded = False
|
||||
|
||||
# 跳过当前正在编译的文件,避免重复加载导致 class_members 重复
|
||||
current_sha1 = getattr(Gen, 'module_sha1', None)
|
||||
module_sha1_map = getattr(Gen, 'module_sha1_map', {})
|
||||
pkg_sha1 = module_sha1_map.get(pkg_name)
|
||||
if pkg_sha1 and pkg_sha1 == current_sha1:
|
||||
return pkg_name
|
||||
|
||||
# Try SHA1 map first (correct mangled names from stub)
|
||||
if pkg_sha1:
|
||||
temp_dir = getattr(Gen, '_temp_dir', None)
|
||||
if temp_dir:
|
||||
sha1_pyi = os.path.join(temp_dir, f"{pkg_sha1}.pyi")
|
||||
if os.path.isfile(sha1_pyi):
|
||||
self._LoadModuleDeclarationsFromFile(sha1_pyi, Gen, module_name=pkg_name, register_module_name=register_module_name)
|
||||
init_loaded = True
|
||||
|
||||
# Fallback: try loading __init__.py directly from the package directory
|
||||
if not init_loaded:
|
||||
for ext in ['.pyi', '.py']:
|
||||
init_path = os.path.join(mod_dir, '__init__' + ext)
|
||||
if os.path.isfile(init_path):
|
||||
self._LoadModuleDeclarationsFromFile(init_path, Gen, module_name=pkg_name, register_module_name=register_module_name)
|
||||
init_loaded = True
|
||||
break
|
||||
|
||||
return pkg_name
|
||||
|
||||
def _EmitModuleDeclarationsLlvm(self, module_name, Gen, register_module_name=None):
|
||||
if module_name in ('pyzlib',):
|
||||
source_sig_files = getattr(self.Trans, '_source_module_sig_files', None)
|
||||
@@ -489,10 +493,10 @@ class ImportHandle(BaseHandle):
|
||||
self._EmitExternalFuncDeclLlvm(node, Gen, source_module_name=module_name, register_module_name=effective_register)
|
||||
has_functions_or_classes = True
|
||||
elif isinstance(node, ast.AnnAssign):
|
||||
self._EmitExternalGlobalDeclLlvm(node, Gen, module_name=module_name, module_path=FullModulePath)
|
||||
self._EmitExternalGlobalDeclLlvm(node, Gen, module_name=module_name, ModulePath=FullModulePath)
|
||||
has_functions_or_classes = True
|
||||
elif isinstance(node, ast.Assign):
|
||||
self._EmitExternalGlobalDeclLlvm(node, Gen, module_name=module_name, module_path=FullModulePath)
|
||||
self._EmitExternalGlobalDeclLlvm(node, Gen, module_name=module_name, ModulePath=FullModulePath)
|
||||
has_functions_or_classes = True
|
||||
elif isinstance(node, ast.ClassDef):
|
||||
if hasattr(node, 'type_params') and node.type_params:
|
||||
@@ -520,9 +524,9 @@ class ImportHandle(BaseHandle):
|
||||
if os.path.isfile(candidate):
|
||||
actual_module = f"{module_name}.{node.module}" if module_name else node.module
|
||||
self._RegisterSubModuleSha1(candidate, actual_module, node.module, Gen)
|
||||
if not getattr(self.Trans, '_imported_modules', None):
|
||||
self.Trans._imported_modules = set()
|
||||
self.Trans._imported_modules.add(actual_module)
|
||||
if not getattr(self.Trans, '_ImportedModules', None):
|
||||
self.Trans._ImportedModules = set()
|
||||
self.Trans._ImportedModules.add(actual_module)
|
||||
for alias in node.names:
|
||||
if alias.name == '*':
|
||||
self._LoadModuleDeclarationsFromFile(candidate, Gen, module_name=module_name, register_module_name=register_module_name, reexport_package=module_name)
|
||||
@@ -534,17 +538,17 @@ class ImportHandle(BaseHandle):
|
||||
# SHA1 map 回退:当文件查找失败时,从 SHA1 映射中查找子模块 stub
|
||||
if not found_sub:
|
||||
actual_module = f"{module_name}.{node.module}" if module_name else node.module
|
||||
module_sha1_map = getattr(Gen, 'module_sha1_map', {})
|
||||
ModuleSha1Map = getattr(Gen, 'ModuleSha1Map', {})
|
||||
# 尝试完整模块名和短模块名
|
||||
target_sha1 = module_sha1_map.get(actual_module) or module_sha1_map.get(node.module)
|
||||
target_sha1 = ModuleSha1Map.get(actual_module) or ModuleSha1Map.get(node.module)
|
||||
if target_sha1:
|
||||
temp_dir = getattr(Gen, '_temp_dir', None)
|
||||
if temp_dir:
|
||||
sha1_pyi = os.path.join(temp_dir, f"{target_sha1}.pyi")
|
||||
if os.path.isfile(sha1_pyi):
|
||||
if not getattr(self.Trans, '_imported_modules', None):
|
||||
self.Trans._imported_modules = set()
|
||||
self.Trans._imported_modules.add(actual_module)
|
||||
if not getattr(self.Trans, '_ImportedModules', None):
|
||||
self.Trans._ImportedModules = set()
|
||||
self.Trans._ImportedModules.add(actual_module)
|
||||
for alias in node.names:
|
||||
if alias.name == '*':
|
||||
self._LoadModuleDeclarationsFromFile(sha1_pyi, Gen, module_name=module_name, register_module_name=register_module_name, reexport_package=module_name)
|
||||
@@ -561,10 +565,10 @@ class ImportHandle(BaseHandle):
|
||||
for ext in SearchExtensions:
|
||||
sub_path = os.path.join(mod_dir, alias.name + ext)
|
||||
if os.path.isfile(sub_path):
|
||||
sub_module_path = f"{module_name}.{alias.name}" if module_name else alias.name
|
||||
if not getattr(self.Trans, '_imported_modules', None):
|
||||
self.Trans._imported_modules = set()
|
||||
self.Trans._imported_modules.add(sub_module_path)
|
||||
sub_ModulePath = f"{module_name}.{alias.name}" if module_name else alias.name
|
||||
if not getattr(self.Trans, '_ImportedModules', None):
|
||||
self.Trans._ImportedModules = set()
|
||||
self.Trans._ImportedModules.add(sub_ModulePath)
|
||||
if alias.name == '*':
|
||||
self._LoadModuleDeclarationsFromFile(sub_path, Gen, module_name=module_name, register_module_name=register_module_name, reexport_package=module_name)
|
||||
else:
|
||||
@@ -574,17 +578,17 @@ class ImportHandle(BaseHandle):
|
||||
break
|
||||
# SHA1 map 回退
|
||||
if not found_alias:
|
||||
sub_module_path = f"{module_name}.{alias.name}" if module_name else alias.name
|
||||
module_sha1_map = getattr(Gen, 'module_sha1_map', {})
|
||||
target_sha1 = module_sha1_map.get(sub_module_path) or module_sha1_map.get(alias.name)
|
||||
sub_ModulePath = f"{module_name}.{alias.name}" if module_name else alias.name
|
||||
ModuleSha1Map = getattr(Gen, 'ModuleSha1Map', {})
|
||||
target_sha1 = ModuleSha1Map.get(sub_ModulePath) or ModuleSha1Map.get(alias.name)
|
||||
if target_sha1:
|
||||
temp_dir = getattr(Gen, '_temp_dir', None)
|
||||
if temp_dir:
|
||||
sha1_pyi = os.path.join(temp_dir, f"{target_sha1}.pyi")
|
||||
if os.path.isfile(sha1_pyi):
|
||||
if not getattr(self.Trans, '_imported_modules', None):
|
||||
self.Trans._imported_modules = set()
|
||||
self.Trans._imported_modules.add(sub_module_path)
|
||||
if not getattr(self.Trans, '_ImportedModules', None):
|
||||
self.Trans._ImportedModules = set()
|
||||
self.Trans._ImportedModules.add(sub_ModulePath)
|
||||
if alias.name == '*':
|
||||
self._LoadModuleDeclarationsFromFile(sha1_pyi, Gen, module_name=module_name, register_module_name=register_module_name, reexport_package=module_name)
|
||||
else:
|
||||
@@ -603,13 +607,13 @@ class ImportHandle(BaseHandle):
|
||||
if module_name:
|
||||
self._LoadDeclarationsFromStubLlvm(module_name, Gen)
|
||||
|
||||
def _EmitExternalGlobalDeclLlvm(self, Node, Gen, module_name=None, module_path=None):
|
||||
def _EmitExternalGlobalDeclLlvm(self, Node, Gen, module_name=None, ModulePath=None):
|
||||
"""Emit external global variable declaration from imported module"""
|
||||
if isinstance(Node, ast.AnnAssign) and isinstance(Node.target, ast.Name):
|
||||
VarName = Node.target.id
|
||||
# 不再跳过 _ 开头的全局变量,跨模块引用需要声明它们
|
||||
var_type = ir.IntType(32)
|
||||
is_ptr = False
|
||||
IsPtr = False
|
||||
is_string_val = False
|
||||
if VarName in Gen.module.globals:
|
||||
existing = Gen.module.globals[VarName]
|
||||
@@ -637,12 +641,12 @@ class ImportHandle(BaseHandle):
|
||||
var_type = ir.ArrayType(elem_type, 0)
|
||||
else:
|
||||
var_type = Gen._ctype_to_llvm(ElemTypeInfo)
|
||||
is_ptr = False
|
||||
IsPtr = False
|
||||
else:
|
||||
TypeInfo = CTypeInfo.FromNode(Node.annotation, self.Trans.SymbolTable)
|
||||
if TypeInfo:
|
||||
var_type = Gen._ctype_to_llvm(TypeInfo)
|
||||
is_ptr = TypeInfo.IsPtr
|
||||
IsPtr = TypeInfo.IsPtr
|
||||
elif isinstance(Node.annotation, ast.BinOp) and isinstance(Node.annotation.op, ast.BitOr):
|
||||
list_node = None
|
||||
for side in (Node.annotation.left, Node.annotation.right):
|
||||
@@ -665,20 +669,20 @@ class ImportHandle(BaseHandle):
|
||||
var_type = ir.ArrayType(elem_type, 0)
|
||||
else:
|
||||
var_type = Gen._ctype_to_llvm(ElemTypeInfo)
|
||||
is_ptr = False
|
||||
IsPtr = False
|
||||
else:
|
||||
TypeInfo = CTypeInfo.FromNode(Node.annotation, self.Trans.SymbolTable)
|
||||
if TypeInfo:
|
||||
var_type = Gen._ctype_to_llvm(TypeInfo)
|
||||
is_ptr = TypeInfo.IsPtr
|
||||
IsPtr = TypeInfo.IsPtr
|
||||
else:
|
||||
TypeInfo = CTypeInfo.FromNode(Node.annotation, self.Trans.SymbolTable)
|
||||
if TypeInfo:
|
||||
var_type = Gen._ctype_to_llvm(TypeInfo)
|
||||
is_ptr = TypeInfo.IsPtr
|
||||
IsPtr = TypeInfo.IsPtr
|
||||
if isinstance(var_type, ir.IdentifiedStructType) and (var_type.elements is None or len(var_type.elements) == 0):
|
||||
var_type = ir.IntType(32)
|
||||
if Node.value and module_path and is_ptr and isinstance(Node.value, ast.Constant) and isinstance(Node.value.value, str):
|
||||
if Node.value and ModulePath and IsPtr and isinstance(Node.value, ast.Constant) and isinstance(Node.value.value, str):
|
||||
str_val = Node.value.value + '\x00'
|
||||
str_bytes = str_val.encode('utf-8')
|
||||
arr_type = ir.ArrayType(ir.IntType(8), len(str_bytes))
|
||||
@@ -743,13 +747,21 @@ class ImportHandle(BaseHandle):
|
||||
if Node.value:
|
||||
DefineValue = self._ExtractConstValue(Node.value)
|
||||
# 注册不带前缀的键名(例如 Z_NO_COMPRESSION)
|
||||
self._RegisterCDefineSymbol(VarName, DefineValue, Node.lineno, module_path or 'unknown')
|
||||
self._RegisterCDefineSymbol(VarName, DefineValue, Node.lineno, ModulePath or 'unknown')
|
||||
# 如果提供了模块名,也注册带模块前缀的键名
|
||||
if module_name:
|
||||
FullName = f"{module_name}.{VarName}"
|
||||
self._RegisterCDefineSymbol(FullName, DefineValue, Node.lineno, module_path or 'unknown')
|
||||
self._RegisterCDefineSymbol(FullName, DefineValue, Node.lineno, ModulePath or 'unknown')
|
||||
return # 不再继续生成 LLVM 全局变量
|
||||
|
||||
|
||||
# t.State 标记的全局变量:只声明不定义(external linkage),避免 DSO/non-DSO 重定义
|
||||
if TypeInfo and TypeInfo.IsState:
|
||||
if VarName not in Gen.module.globals:
|
||||
gv = ir.GlobalVariable(Gen.module, var_type, name=VarName)
|
||||
gv.linkage = 'external'
|
||||
Gen._export_funcs.add(VarName)
|
||||
return
|
||||
|
||||
gv = ir.GlobalVariable(Gen.module, var_type, name=VarName)
|
||||
|
||||
if Node.value:
|
||||
@@ -768,7 +780,7 @@ class ImportHandle(BaseHandle):
|
||||
if VarName in Gen.module.globals:
|
||||
return
|
||||
gv = ir.GlobalVariable(Gen.module, ir.IntType(32), name=VarName)
|
||||
if Node.value and module_path:
|
||||
if Node.value and ModulePath:
|
||||
InitVal = self._ExtractValue(Node.value, ir.IntType(32), VarName)
|
||||
if InitVal is not None:
|
||||
gv.initializer = InitVal
|
||||
@@ -893,40 +905,40 @@ class ImportHandle(BaseHandle):
|
||||
return self._ExtractConstValue(value_node.args[0])
|
||||
return None
|
||||
|
||||
def _ExtractTypedefOriginalType(self, value_node):
|
||||
import ast
|
||||
from lib.includes.t import CTypeRegistry
|
||||
if isinstance(value_node, ast.Attribute):
|
||||
if getattr(value_node.value, 'id', None) == 't':
|
||||
llvm_str = CTypeRegistry.NameToLLVM(value_node.attr)
|
||||
if llvm_str:
|
||||
return llvm_str
|
||||
elif isinstance(value_node, ast.Name):
|
||||
llvm_str = CTypeRegistry.NameToLLVM(value_node.id)
|
||||
if llvm_str:
|
||||
return llvm_str
|
||||
elif isinstance(value_node, ast.BinOp) and isinstance(value_node.op, ast.BitOr):
|
||||
left = self._ExtractTypedefOriginalType(value_node.left)
|
||||
right = self._ExtractTypedefOriginalType(value_node.right)
|
||||
parts = []
|
||||
if left:
|
||||
parts.append(left)
|
||||
if right:
|
||||
parts.append(right)
|
||||
if parts:
|
||||
return '|'.join(parts)
|
||||
elif isinstance(value_node, ast.Call):
|
||||
if isinstance(value_node.func, ast.Attribute):
|
||||
if getattr(value_node.func.value, 'id', None) == 't':
|
||||
llvm_str = CTypeRegistry.NameToLLVM(value_node.func.attr)
|
||||
if llvm_str:
|
||||
return llvm_str
|
||||
elif isinstance(value_node.func, ast.Name):
|
||||
llvm_str = CTypeRegistry.NameToLLVM(value_node.func.id)
|
||||
if llvm_str:
|
||||
return llvm_str
|
||||
return None
|
||||
|
||||
def _ExtractTypedefOriginalType(self, value_node):
|
||||
import ast
|
||||
from lib.includes.t import CTypeRegistry
|
||||
if isinstance(value_node, ast.Attribute):
|
||||
if getattr(value_node.value, 'id', None) == 't':
|
||||
llvm_str = CTypeRegistry.NameToLLVM(value_node.attr)
|
||||
if llvm_str:
|
||||
return llvm_str
|
||||
elif isinstance(value_node, ast.Name):
|
||||
llvm_str = CTypeRegistry.NameToLLVM(value_node.id)
|
||||
if llvm_str:
|
||||
return llvm_str
|
||||
elif isinstance(value_node, ast.BinOp) and isinstance(value_node.op, ast.BitOr):
|
||||
left = self._ExtractTypedefOriginalType(value_node.left)
|
||||
right = self._ExtractTypedefOriginalType(value_node.right)
|
||||
parts = []
|
||||
if left:
|
||||
parts.append(left)
|
||||
if right:
|
||||
parts.append(right)
|
||||
if parts:
|
||||
return '|'.join(parts)
|
||||
elif isinstance(value_node, ast.Call):
|
||||
if isinstance(value_node.func, ast.Attribute):
|
||||
if getattr(value_node.func.value, 'id', None) == 't':
|
||||
llvm_str = CTypeRegistry.NameToLLVM(value_node.func.attr)
|
||||
if llvm_str:
|
||||
return llvm_str
|
||||
elif isinstance(value_node.func, ast.Name):
|
||||
llvm_str = CTypeRegistry.NameToLLVM(value_node.func.id)
|
||||
if llvm_str:
|
||||
return llvm_str
|
||||
return None
|
||||
|
||||
def _RegisterCDefineSymbol(self, FullName, DefineValue, lineno, FilePath):
|
||||
"""Register CDefine constant to SymbolTable"""
|
||||
from lib.core.Handles.HandlesBase import CTypeInfo
|
||||
@@ -938,19 +950,19 @@ class ImportHandle(BaseHandle):
|
||||
# 直接添加到 SymbolTable 字典
|
||||
self.Trans.SymbolTable[FullName] = info
|
||||
|
||||
def _check_annotation_for_state(self, annotation) -> bool:
|
||||
import ast
|
||||
if isinstance(annotation, ast.Attribute):
|
||||
if hasattr(annotation, 'attr') and annotation.attr in ('CExport', 'CExtern', 'State'):
|
||||
return True
|
||||
if hasattr(annotation, 'value') and isinstance(annotation.value, ast.Name) and annotation.value.id == 't' and annotation.attr == 'State':
|
||||
return True
|
||||
elif isinstance(annotation, ast.BinOp) and isinstance(annotation.op, ast.BitOr):
|
||||
return self._check_annotation_for_state(annotation.left) or self._check_annotation_for_state(annotation.right)
|
||||
elif isinstance(annotation, ast.Name):
|
||||
return annotation.id in ('CExport', 'CExtern', 'State')
|
||||
return False
|
||||
|
||||
def _check_annotation_for_state(self, annotation) -> bool:
|
||||
import ast
|
||||
if isinstance(annotation, ast.Attribute):
|
||||
if hasattr(annotation, 'attr') and annotation.attr in ('CExport', 'CExtern', 'State'):
|
||||
return True
|
||||
if hasattr(annotation, 'value') and isinstance(annotation.value, ast.Name) and annotation.value.id == 't' and annotation.attr == 'State':
|
||||
return True
|
||||
elif isinstance(annotation, ast.BinOp) and isinstance(annotation.op, ast.BitOr):
|
||||
return self._check_annotation_for_state(annotation.left) or self._check_annotation_for_state(annotation.right)
|
||||
elif isinstance(annotation, ast.Name):
|
||||
return annotation.id in ('CExport', 'CExtern', 'State')
|
||||
return False
|
||||
|
||||
def _EmitExternalFuncDeclLlvm(self, Node, Gen, is_class_method=False, source_module_name=None, register_module_name=None, reexport_module_names=None):
|
||||
FuncName = Node.name
|
||||
if Node.returns and self._check_annotation_for_state(Node.returns):
|
||||
@@ -1086,13 +1098,15 @@ class ImportHandle(BaseHandle):
|
||||
elif d.id == 'classmethod':
|
||||
func_meta |= FuncMeta.CLASS_METHOD
|
||||
elif isinstance(d, ast.Attribute):
|
||||
if isinstance(d.value, ast.Name) and d.value.id == 'property':
|
||||
if d.attr == 'setter':
|
||||
func_meta |= FuncMeta.PROPERTY_SETTER
|
||||
elif d.attr == 'getter':
|
||||
func_meta |= FuncMeta.PROPERTY_GETTER
|
||||
elif d.attr == 'deleter':
|
||||
func_meta |= FuncMeta.PROPERTY_DELETER
|
||||
if isinstance(d.value, ast.Name):
|
||||
# 支持 @property.setter 和 @propname.setter 两种形式
|
||||
if d.value.id == 'property' or d.attr in ('setter', 'getter', 'deleter'):
|
||||
if d.attr == 'setter':
|
||||
func_meta |= FuncMeta.PROPERTY_SETTER
|
||||
elif d.attr == 'getter':
|
||||
func_meta |= FuncMeta.PROPERTY_GETTER
|
||||
elif d.attr == 'deleter':
|
||||
func_meta |= FuncMeta.PROPERTY_DELETER
|
||||
if FuncName not in self.Trans.SymbolTable:
|
||||
FuncInfo = CTypeInfo()
|
||||
FuncInfo.Name = FuncName
|
||||
@@ -1103,6 +1117,28 @@ class ImportHandle(BaseHandle):
|
||||
existing = self.Trans.SymbolTable[FuncName]
|
||||
if existing.MetaList == FuncMeta.NONE and func_meta != FuncMeta.NONE:
|
||||
existing.MetaList = func_meta
|
||||
# 同时注册带模块前缀的符号,以便 module.func_name 查找能命中
|
||||
if source_module_name and source_module_name not in ('c', 't'):
|
||||
FullSymKey = f"{source_module_name}.{FuncName}"
|
||||
if FullSymKey not in self.Trans.SymbolTable:
|
||||
FullFuncInfo = CTypeInfo()
|
||||
FullFuncInfo.Name = FullSymKey
|
||||
FullFuncInfo.IsFunction = True
|
||||
FullFuncInfo.MetaList = func_meta
|
||||
self.Trans.SymbolTable[FullSymKey] = FullFuncInfo
|
||||
# property setter/deleter: 在原始 PropKey(不带后缀)下注册 MetaList
|
||||
if FuncMeta.PROPERTY_SETTER in func_meta or FuncMeta.PROPERTY_DELETER in func_meta:
|
||||
BasePropKey = FuncName.replace('$set', '').replace('$del', '')
|
||||
if BasePropKey in self.Trans.SymbolTable:
|
||||
base_existing = self.Trans.SymbolTable[BasePropKey]
|
||||
if func_meta != FuncMeta.NONE:
|
||||
base_existing.MetaList = base_existing.MetaList | func_meta
|
||||
else:
|
||||
PropInfo = CTypeInfo()
|
||||
PropInfo.Name = BasePropKey
|
||||
PropInfo.IsFunction = True
|
||||
PropInfo.MetaList = func_meta
|
||||
self.Trans.SymbolTable[BasePropKey] = PropInfo
|
||||
if register_module_name and register_module_name != source_module_name:
|
||||
ReexportName = Gen._mangle_func_name(FuncName, module_name=register_module_name)
|
||||
Gen.functions[ReexportName] = func
|
||||
@@ -1207,10 +1243,10 @@ class ImportHandle(BaseHandle):
|
||||
return
|
||||
self._TryLoadStructFromStub(ClassName, Gen)
|
||||
source_sha1 = None
|
||||
if actual_module_name and hasattr(Gen, 'module_sha1_map') and actual_module_name in Gen.module_sha1_map:
|
||||
source_sha1 = Gen.module_sha1_map[actual_module_name]
|
||||
elif module_name and hasattr(Gen, 'module_sha1_map') and module_name in Gen.module_sha1_map:
|
||||
source_sha1 = Gen.module_sha1_map[module_name]
|
||||
if actual_module_name and hasattr(Gen, 'ModuleSha1Map') and actual_module_name in Gen.ModuleSha1Map:
|
||||
source_sha1 = Gen.ModuleSha1Map[actual_module_name]
|
||||
elif module_name and hasattr(Gen, 'ModuleSha1Map') and module_name in Gen.ModuleSha1Map:
|
||||
source_sha1 = Gen.ModuleSha1Map[module_name]
|
||||
# Track which module defines this class (for cross-module name mangling)
|
||||
if source_sha1:
|
||||
if not hasattr(Gen, 'class_sha1_map'):
|
||||
@@ -1268,9 +1304,15 @@ class ImportHandle(BaseHandle):
|
||||
is_item_prop_setter = any(isinstance(d, ast.Attribute) and d.attr == 'setter' and isinstance(d.value, ast.Name) and d.value.id == 'property' for d in item.decorator_list)
|
||||
is_item_prop_getter = any(isinstance(d, ast.Attribute) and d.attr == 'getter' and isinstance(d.value, ast.Name) and d.value.id == 'property' for d in item.decorator_list)
|
||||
is_item_prop_deleter = any(isinstance(d, ast.Attribute) and d.attr == 'deleter' and isinstance(d.value, ast.Name) and d.value.id == 'property' for d in item.decorator_list)
|
||||
if FuncFullName not in Gen.functions:
|
||||
# setter/deleter 使用不同的函数名后缀
|
||||
DeclFuncName = FuncFullName
|
||||
if is_item_prop_setter:
|
||||
DeclFuncName = FuncFullName + '$set'
|
||||
elif is_item_prop_deleter:
|
||||
DeclFuncName = FuncFullName + '$del'
|
||||
if DeclFuncName not in Gen.functions:
|
||||
FuncDeclNode = ast.FunctionDef(
|
||||
name=FuncFullName,
|
||||
name=DeclFuncName,
|
||||
args=item.args,
|
||||
body=item.body,
|
||||
decorator_list=item.decorator_list,
|
||||
@@ -1290,10 +1332,11 @@ class ImportHandle(BaseHandle):
|
||||
func_meta |= FuncMeta.PROPERTY_GETTER
|
||||
if is_item_prop_deleter:
|
||||
func_meta |= FuncMeta.PROPERTY_DELETER
|
||||
SymKey = FuncFullName
|
||||
# setter/deleter 的 SymKey 使用带后缀的函数名
|
||||
SymKey = DeclFuncName
|
||||
if SymKey not in self.Trans.SymbolTable:
|
||||
FuncInfo = CTypeInfo()
|
||||
FuncInfo.Name = FuncFullName
|
||||
FuncInfo.Name = SymKey
|
||||
FuncInfo.IsFunction = True
|
||||
FuncInfo.MetaList = func_meta
|
||||
self.Trans.SymbolTable[SymKey] = FuncInfo
|
||||
@@ -1301,6 +1344,18 @@ class ImportHandle(BaseHandle):
|
||||
existing = self.Trans.SymbolTable[SymKey]
|
||||
if existing.MetaList == FuncMeta.NONE and func_meta != FuncMeta.NONE:
|
||||
existing.MetaList = func_meta
|
||||
# setter/deleter: 同时在原始 PropKey(不带后缀)下注册 MetaList
|
||||
if is_item_prop_setter or is_item_prop_deleter:
|
||||
if FuncFullName in self.Trans.SymbolTable:
|
||||
base_existing = self.Trans.SymbolTable[FuncFullName]
|
||||
if func_meta != FuncMeta.NONE:
|
||||
base_existing.MetaList = base_existing.MetaList | func_meta
|
||||
else:
|
||||
PropInfo = CTypeInfo()
|
||||
PropInfo.Name = FuncFullName
|
||||
PropInfo.IsFunction = True
|
||||
PropInfo.MetaList = func_meta
|
||||
self.Trans.SymbolTable[FuncFullName] = PropInfo
|
||||
if has_methods:
|
||||
if IsCVTable:
|
||||
Gen._cross_module_vtable_classes.add(ClassName)
|
||||
@@ -1308,8 +1363,8 @@ class ImportHandle(BaseHandle):
|
||||
NewFuncName = f'{ClassName}.__before_init__'
|
||||
if not Gen._has_function(NewFuncName) and (IsCpythonObject or IsCVTable):
|
||||
source_sha1 = None
|
||||
if module_name and hasattr(Gen, 'module_sha1_map') and module_name in Gen.module_sha1_map:
|
||||
source_sha1 = Gen.module_sha1_map[module_name]
|
||||
if module_name and hasattr(Gen, 'ModuleSha1Map') and module_name in Gen.ModuleSha1Map:
|
||||
source_sha1 = Gen.ModuleSha1Map[module_name]
|
||||
MangledName = Gen._mangle_name(NewFuncName) if not source_sha1 else f"{source_sha1}.{NewFuncName}"
|
||||
StructType = Gen.structs.get(ClassName)
|
||||
if StructType:
|
||||
@@ -1327,9 +1382,9 @@ class ImportHandle(BaseHandle):
|
||||
|
||||
def _TryLoadStructFromStub(self, class_name: str, Gen):
|
||||
cache_key = class_name
|
||||
if cache_key in self._struct_load_cache:
|
||||
if cache_key in self._struct_Load_cache:
|
||||
return
|
||||
self._struct_load_cache[cache_key] = True
|
||||
self._struct_Load_cache[cache_key] = True
|
||||
|
||||
import os, re
|
||||
ProjectRoot = self._find_project_root()
|
||||
@@ -1358,9 +1413,13 @@ class ImportHandle(BaseHandle):
|
||||
self._stub_cache.setdefault(short_name, []).append((full_name, struct_body, source_sha1))
|
||||
if '.' in full_name:
|
||||
self._stub_cache.setdefault(full_name, []).append((full_name, struct_body, source_sha1))
|
||||
except Exception:
|
||||
pass
|
||||
|
||||
except Exception as _e:
|
||||
from lib.core.VLogger import get_logger as _vlog
|
||||
from lib.constants.config import mode as _config_mode
|
||||
if _config_mode == "strict":
|
||||
raise
|
||||
_vlog().warning(f"处理导入失败: {_e}", "Exception")
|
||||
|
||||
if class_name not in self._stub_cache:
|
||||
return
|
||||
|
||||
@@ -1380,12 +1439,16 @@ class ImportHandle(BaseHandle):
|
||||
elem_types.append(et if et else ir.IntType(32))
|
||||
try:
|
||||
st = Gen._get_or_create_struct(class_name, source_sha1=source_sha1, packed=is_packed)
|
||||
if isinstance(st, ir.IdentifiedStructType) and (st.elements is None or len(st.elements) == 0):
|
||||
if isinstance(st, ir.IdentifiedStructType) and st.is_opaque:
|
||||
st.set_body(*elem_types)
|
||||
if is_packed:
|
||||
Gen.class_packed.add(class_name)
|
||||
except Exception:
|
||||
pass
|
||||
except Exception as _e:
|
||||
from lib.core.VLogger import get_logger as _vlog
|
||||
from lib.constants.config import mode as _config_mode
|
||||
if _config_mode == "strict":
|
||||
raise
|
||||
_vlog().warning(f"处理导入失败: {_e}", "Exception")
|
||||
stub_filename = source_sha1 + '.stub.ll'
|
||||
self._TryLoadClassMembersFromPyi(class_name, stub_filename, Gen)
|
||||
return
|
||||
@@ -1419,13 +1482,13 @@ class ImportHandle(BaseHandle):
|
||||
return
|
||||
source_sha1 = stub_filename.replace('.stub.ll', '')
|
||||
module_name = None
|
||||
if hasattr(Gen, 'module_sha1_map'):
|
||||
for mod_name, mod_sha1 in Gen.module_sha1_map.items():
|
||||
if hasattr(Gen, 'ModuleSha1Map'):
|
||||
for mod_name, mod_sha1 in Gen.ModuleSha1Map.items():
|
||||
if mod_sha1 == source_sha1 and '.' not in mod_name:
|
||||
module_name = mod_name
|
||||
break
|
||||
if module_name is None:
|
||||
for mod_name, mod_sha1 in Gen.module_sha1_map.items():
|
||||
for mod_name, mod_sha1 in Gen.ModuleSha1Map.items():
|
||||
if mod_sha1 == source_sha1:
|
||||
module_name = mod_name
|
||||
break
|
||||
@@ -1513,9 +1576,13 @@ class ImportHandle(BaseHandle):
|
||||
stub_ret = match.group(1).strip()
|
||||
stub_params = match.group(3).strip()
|
||||
self._stub_func_cache[stub_func_name] = (stub_ret, stub_params, '...' in stub_params, source_sha1)
|
||||
except Exception:
|
||||
pass
|
||||
|
||||
except Exception as _e:
|
||||
from lib.core.VLogger import get_logger as _vlog
|
||||
from lib.constants.config import mode as _config_mode
|
||||
if _config_mode == "strict":
|
||||
raise
|
||||
_vlog().warning(f"处理导入失败: {_e}", "Exception")
|
||||
|
||||
if func_name not in self._stub_func_cache:
|
||||
return None
|
||||
|
||||
@@ -1622,8 +1689,8 @@ class ImportHandle(BaseHandle):
|
||||
target_sha1 = os.path.basename(val).replace('.pyi', '')
|
||||
break
|
||||
if not target_sha1:
|
||||
module_sha1_map = getattr(Gen, 'module_sha1_map', {})
|
||||
target_sha1 = module_sha1_map.get(module_name)
|
||||
ModuleSha1Map = getattr(Gen, 'ModuleSha1Map', {})
|
||||
target_sha1 = ModuleSha1Map.get(module_name)
|
||||
|
||||
if target_sha1:
|
||||
target_stub = f"{target_sha1}.stub.ll"
|
||||
@@ -1648,21 +1715,25 @@ class ImportHandle(BaseHandle):
|
||||
elif stripped.startswith('declare '):
|
||||
for m in re.finditer(r'%\"?([a-f0-9]{16})\.', stripped):
|
||||
needed_sha1s.add(m.group(1))
|
||||
except Exception:
|
||||
pass
|
||||
|
||||
preload_files = []
|
||||
except Exception as _e:
|
||||
from lib.core.VLogger import get_logger as _vlog
|
||||
from lib.constants.config import mode as _config_mode
|
||||
if _config_mode == "strict":
|
||||
raise
|
||||
_vlog().warning(f"处理导入失败: {_e}", "Exception")
|
||||
|
||||
preLoad_files = []
|
||||
for sha1 in needed_sha1s:
|
||||
dep_stub = f"{sha1}.stub.ll"
|
||||
if dep_stub in all_stub_files and dep_stub not in stub_files:
|
||||
preload_files.append(dep_stub)
|
||||
preLoad_files.append(dep_stub)
|
||||
|
||||
load_order = preload_files + stub_files
|
||||
Load_order = preLoad_files + stub_files
|
||||
|
||||
for filename in load_order:
|
||||
for filename in Load_order:
|
||||
stub_path = os.path.join(temp_dir, filename)
|
||||
source_sha1 = filename.replace('.stub.ll', '')
|
||||
is_preload = filename in preload_files
|
||||
is_preLoad = filename in preLoad_files
|
||||
try:
|
||||
with open(stub_path, 'r', encoding='utf-8') as f:
|
||||
content = f.read()
|
||||
@@ -1699,14 +1770,18 @@ class ImportHandle(BaseHandle):
|
||||
if isinstance(st, ir.IdentifiedStructType) and (st.elements is None or len(st.elements) == 0):
|
||||
try:
|
||||
st.set_body(*elem_types)
|
||||
except Exception:
|
||||
pass
|
||||
except Exception as _e:
|
||||
from lib.core.VLogger import get_logger as _vlog
|
||||
from lib.constants.config import mode as _config_mode
|
||||
if _config_mode == "strict":
|
||||
raise
|
||||
_vlog().warning(f"处理导入失败: {_e}", "Exception")
|
||||
continue
|
||||
|
||||
if not stripped.startswith('declare '):
|
||||
continue
|
||||
|
||||
if is_preload:
|
||||
if is_preLoad:
|
||||
continue
|
||||
|
||||
func_name_match = stripped.split('@', 1)
|
||||
@@ -1736,10 +1811,18 @@ class ImportHandle(BaseHandle):
|
||||
if '.' in func_name:
|
||||
short_name = func_name.split('.', 1)[1]
|
||||
Gen.functions[short_name] = func
|
||||
except Exception:
|
||||
pass
|
||||
except Exception:
|
||||
pass
|
||||
except Exception as _e:
|
||||
from lib.core.VLogger import get_logger as _vlog
|
||||
from lib.constants.config import mode as _config_mode
|
||||
if _config_mode == "strict":
|
||||
raise
|
||||
_vlog().warning(f"处理导入失败: {_e}", "Exception")
|
||||
except Exception as _e:
|
||||
from lib.core.VLogger import get_logger as _vlog
|
||||
from lib.constants.config import mode as _config_mode
|
||||
if _config_mode == "strict":
|
||||
raise
|
||||
_vlog().warning(f"处理导入失败: {_e}", "Exception")
|
||||
|
||||
def _parse_llvm_declare(self, declare_line: str, Gen):
|
||||
"""解析 LLVM declare 语句"""
|
||||
|
||||
Reference in New Issue
Block a user