Files
TransPyC/lib/_bootstrap.py
T
TermiNexus f19d25782f refactor(tpc): 退役 t/c 模块并将定宽类型升级为内建
删除 lib/includes/t.py、c.py,类型模型迁入 lib/core/TypeSystem.py;移除 IsTModule/_T_MODULE_NAMES 等名称判据,语法糖与内部标记统一为裸名;builtins 的 sizet/intN/uintN/fast/least/uchar/short/long 等改为编译器内建短名。
2026-10-18 13:00:58 +08:00

138 lines
5.7 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
"""集中化 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()