删除 lib/includes/t.py、c.py,类型模型迁入 lib/core/TypeSystem.py;移除 IsTModule/_T_MODULE_NAMES 等名称判据,语法糖与内部标记统一为裸名;builtins 的 sizet/intN/uintN/fast/least/uchar/short/long 等改为编译器内建短名。
138 lines
5.7 KiB
Python
138 lines
5.7 KiB
Python
"""集中化 sys.path 引导模块
|
||
|
||
在首次导入时一次性设置好编译器运行所需的 sys.path:
|
||
- 项目根目录:让 ``import TransPyC``、``from StubGen import``、动态 importlib 能解析
|
||
(lib 目录加入 sys.path,使 ``import vast`` 直接可用。)
|
||
|
||
入口点(TransPyC.py / Projectrans.py)应在最开头 ``import lib._bootstrap``。
|
||
lib 内部模块也可 ``import lib._bootstrap`` 作为安全网,重复导入是无副作用的 no-op。
|
||
"""
|
||
from __future__ import annotations
|
||
|
||
import os
|
||
import sys
|
||
|
||
_BOOTSTRAPPED: bool = False
|
||
|
||
|
||
def _bootstrap() -> None:
|
||
global _BOOTSTRAPPED
|
||
if _BOOTSTRAPPED:
|
||
return
|
||
_BOOTSTRAPPED = True
|
||
|
||
# lib/_bootstrap.py 所在目录
|
||
_LibDir: str = os.path.dirname(os.path.abspath(__file__))
|
||
# 项目根目录 = lib 的父目录
|
||
_ProjectRoot: str = os.path.dirname(_LibDir)
|
||
|
||
if _ProjectRoot not in sys.path:
|
||
sys.path.insert(0, _ProjectRoot)
|
||
if _LibDir not in sys.path:
|
||
# lib 目录入 path:使 vast 包(lib/vast/)可直接 import vast
|
||
sys.path.append(_LibDir)
|
||
|
||
# ============================================================
|
||
# LLVM IR 兼容性补丁:llvmlite 不允许 void* 指针类型
|
||
#
|
||
# LLVM IR 规范中不存在 void*,C 的 void* 在 IR 层对应的是 i8*。
|
||
# 但编译链(REnum / Python 推理)可能错误地构造 ir.PointerType(ir.VoidType()),
|
||
# 这会导致 llc 报 "pointers to void are invalid - use i8* instead" 直接失败。
|
||
#
|
||
# 这里在入口对 ir.PointerType.__new__ 和 __init__ 做 monkey patch:
|
||
# 所有传入 VoidType 的 pointee(无论多少级 Ptr 嵌套)都自动替换为 i8。
|
||
# 这样 _nonlocal_types / 闭包环境 / 任何代码路径产生的 Ptr(Void) 都会被静默修正。
|
||
# ============================================================
|
||
try:
|
||
import llvmlite.ir as _llvmlite_ir
|
||
except Exception: # noqa: BLE001
|
||
_llvmlite_ir = None # type: ignore[assignment]
|
||
|
||
if _llvmlite_ir is not None:
|
||
_I8 = _llvmlite_ir.IntType(8)
|
||
|
||
def _IsBadPointee(pointee) -> bool:
|
||
"""只在明确传入了 VoidType 或 Ptr(...Void...) 这类坏 pointee 时返回 True;
|
||
None 由 llvmlite 内部 super 调用使用,不能替换!"""
|
||
if pointee is None:
|
||
return False
|
||
cur = pointee
|
||
while isinstance(cur, _llvmlite_ir.PointerType):
|
||
if isinstance(getattr(cur, 'pointee', None), _llvmlite_ir.VoidType):
|
||
return True
|
||
cur = getattr(cur, 'pointee', None)
|
||
if isinstance(pointee, _llvmlite_ir.VoidType):
|
||
return True
|
||
return False
|
||
|
||
# llvmlite 内部:PointerType(pointee=Int8) 实际返回的是内部类 _TypedPointerType 实例,
|
||
# 它的 __init__ 会 super 调 PointerType.__init__(pointee=None, addrspace),
|
||
# 因此我们只在明确看到 VoidType 传入(pointee is not None)时才做替换。
|
||
def _PatchPointerInitAndNew(cls) -> None:
|
||
try:
|
||
orig_new = cls.__new__
|
||
orig_init = cls.__init__
|
||
except Exception: # noqa: BLE001
|
||
return
|
||
|
||
if getattr(orig_init, '__void_patch_applied__', False):
|
||
return
|
||
|
||
def _patched_new(klass, pointee=None, addrspace=None, *args, **kwargs):
|
||
if _IsBadPointee(pointee):
|
||
return orig_new(klass, _I8, addrspace, *args, **kwargs)
|
||
return orig_new(klass, pointee, addrspace, *args, **kwargs)
|
||
|
||
def _patched_init(self_self, pointee=None, addrspace=None, *args, **kwargs):
|
||
if _IsBadPointee(pointee):
|
||
return orig_init(self_self, _I8, addrspace, *args, **kwargs)
|
||
return orig_init(self_self, pointee, addrspace, *args, **kwargs)
|
||
|
||
_patched_init.__void_patch_applied__ = True # type: ignore[attr-defined]
|
||
try:
|
||
cls.__new__ = _patched_new # type: ignore[method-assign]
|
||
cls.__init__ = _patched_init # type: ignore[method-assign]
|
||
except Exception: # noqa: BLE001
|
||
pass
|
||
|
||
import inspect as _inspect
|
||
|
||
# 收集所有继承自 PointerType 的类(含 _TypedPointerType)
|
||
_all_ir_classes: list = [
|
||
obj for _name, obj in vars(_llvmlite_ir).items()
|
||
if _inspect.isclass(obj)
|
||
]
|
||
for _cls in _all_ir_classes:
|
||
if issubclass(_cls, _llvmlite_ir.PointerType) or _cls is _llvmlite_ir.PointerType:
|
||
_PatchPointerInitAndNew(_cls)
|
||
|
||
# 同步 patch as_pointer() 的结果(它走的是 PointerType 构造器,但保险起见)
|
||
_as_pointer_patched = set()
|
||
|
||
def _PatchAsPointer(holder_cls) -> None:
|
||
if not hasattr(holder_cls, 'as_pointer') or id(holder_cls.as_pointer) in _as_pointer_patched:
|
||
return
|
||
_orig = holder_cls.as_pointer
|
||
|
||
def _PatchedAsPointer(self_self, *aa, **kk):
|
||
res = _orig(self_self, *aa, **kk)
|
||
rcur = res
|
||
while isinstance(rcur, _llvmlite_ir.PointerType):
|
||
if isinstance(getattr(rcur, 'pointee', None), _llvmlite_ir.VoidType):
|
||
return _I8.as_pointer()
|
||
rcur = getattr(rcur, 'pointee', None)
|
||
return res
|
||
|
||
try:
|
||
holder_cls.as_pointer = _PatchedAsPointer # type: ignore[attr-defined]
|
||
_as_pointer_patched.add(id(_orig))
|
||
except Exception: # noqa: BLE001
|
||
pass
|
||
|
||
for _obj in _all_ir_classes:
|
||
if hasattr(_obj, 'as_pointer') and callable(getattr(_obj, 'as_pointer', None)):
|
||
_PatchAsPointer(_obj)
|
||
|
||
|
||
_bootstrap()
|