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 等改为编译器内建短名。
This commit is contained in:
1 parent
8d27747c7c
commit
f19d25782f
66 files changed
+2445
-3638
No files matched your search
@@ -4,7 +4,7 @@ import re
|
||||
import vast as ast
|
||||
import llvmlite.ir as ir
|
||||
from llvmlite.ir.values import _Undefined
|
||||
from lib.includes import t as _t
|
||||
from lib.core import TypeSystem as _t
|
||||
from lib.core.VLogger import get_logger as _vlog
|
||||
|
||||
# vtable 槽类型 `i8*` 的共享实例:llvmlite 的类型是不可变值语义(`_TypedPointerType`
|
||||
@@ -305,100 +305,100 @@ class StructGenMixin:
|
||||
|
||||
return ir_text
|
||||
|
||||
def _MemberSlotAccepts(self, Declared: Any, Slot: Any) -> bool:
|
||||
"""声明类型能否**隐式写进**该 struct 槽(判据与存储侧同一套)。
|
||||
|
||||
用于判定已冻结的 struct body 是否与 `class_members` 自洽。判定放宽到与
|
||||
存储侧一致,避免误清:通用指针槽(i8*/void*)照旧放行(历史 stub 普遍
|
||||
如此),继承上转/数组退让亦放行;只有**存储时必被拒绝**的组合——层数
|
||||
不同、指针与非指针混位——才判为不一致,触发重建。
|
||||
"""
|
||||
if Declared is None or Slot is None:
|
||||
return True
|
||||
# 同一对象直接放行:llvmlite 的 Type.__eq__ 走类型键比较(profile:
|
||||
# 本函数被 _generate_structs 调 54.2M 次,其中 types.py __eq__ 合计 ~30s)
|
||||
# ⇒ 先做身份判定短路,等价且避免绝大多数 __eq__/str() 开销。
|
||||
if Declared is Slot:
|
||||
return True
|
||||
if Declared == Slot or str(Declared) == str(Slot):
|
||||
return True
|
||||
_d_ptr: bool = isinstance(Declared, ir.PointerType)
|
||||
_s_ptr: bool = isinstance(Slot, ir.PointerType)
|
||||
if _d_ptr != _s_ptr:
|
||||
return False
|
||||
if not _d_ptr:
|
||||
# 数值/浮点宽度差异不在本次收紧范围:保持既有行为(不清 body)。
|
||||
return True
|
||||
try:
|
||||
Allowed, _Reason = self._ClassifyPtrImplicitConvert(Declared, Slot)
|
||||
return bool(Allowed)
|
||||
except Exception:
|
||||
# 判据不可用(缺上下文)时保守放行,避免误清已正确的布局。
|
||||
return True
|
||||
|
||||
def _IsRenumLayoutClass(self, ClassName: str | None) -> bool:
|
||||
"""该类是否属 **REnum 布局**(主 REnum 自身,或其变体嵌套结构体 `<REnum>_<Variant>`)。
|
||||
|
||||
REnum 的 struct body 是 **max-variant 镜像布局**:`class_members` 里那些名字是
|
||||
*变体*(不是字段),变体嵌套结构体也必须逐字镜像主结构体。因此**一律不得**用
|
||||
class_members 的"声明类型"去改写或校验它们的布局 —— 否则跨模块 GEP 偏移与
|
||||
定义端失配(变体载荷槽本就允许与 max-variant 槽类型不同,取值处靠 bitcast)。
|
||||
"""
|
||||
if not ClassName:
|
||||
return False
|
||||
_tbl: Any = getattr(self, 'SymbolTable', None)
|
||||
if _tbl is None:
|
||||
return False
|
||||
try:
|
||||
_e: Any = _tbl.lookup(ClassName)
|
||||
except Exception:
|
||||
return False
|
||||
if _e is not None and getattr(_e, 'IsRenum', False):
|
||||
return True
|
||||
if '_' in ClassName:
|
||||
_prefix: str = ClassName.rsplit('_', 1)[0]
|
||||
try:
|
||||
_pe: Any = _tbl.lookup(_prefix)
|
||||
except Exception:
|
||||
_pe = None
|
||||
if _pe is not None and getattr(_pe, 'IsRenum', False):
|
||||
return True
|
||||
return False
|
||||
|
||||
def _StructBodyHasPlaceholderT(self, St: Any) -> bool:
|
||||
"""该 struct body 是否含未特化的 `T*` 占位字段(结果按 body 对象记忆)。
|
||||
|
||||
`_generate_structs` 里有两处对"全部类的全部元素"做这一扫描(Step 4 的完整性与
|
||||
set_body 前的复核),每次调用都全量重扫 —— profile(2026-09-29 main_prof_72472):
|
||||
这两处是本函数 62.5M 次 `isinstance`(6.20s)与 4.98M 次 `rsplit`(1.12s)的主源。
|
||||
|
||||
判定精确性:扫描是 `st.elements` 的**纯函数**,而 `elements` 在 llvmlite 里是
|
||||
**整体替换**(`set_body` 赋新 tuple;作废时置 None;从不原地改元素)⇒ 用
|
||||
`elements` 的**对象身份**当版本号即可精确判定"body 未变"。缓存条目**强引用**
|
||||
struct 实例与 elements 对象,二者存活 ⇒ `id()` 不会被回收复用 ⇒ 不会误判命中。
|
||||
(代价:被替换掉的旧 body tuple 会被缓存多留一份引用;量级 = 结构体数量级,可忽略。)
|
||||
"""
|
||||
_cache: dict | None = getattr(self, '_struct_t_placeholder_cache', None)
|
||||
if _cache is None:
|
||||
_cache = {}
|
||||
self._struct_t_placeholder_cache = _cache
|
||||
_key: int = id(St)
|
||||
_elems: Any = getattr(St, 'elements', None)
|
||||
_hit: Any = _cache.get(_key)
|
||||
if _hit is not None and _hit[0] is St and _hit[1] is _elems:
|
||||
return _hit[2]
|
||||
_found: bool = False
|
||||
if _elems:
|
||||
for _elem in _elems:
|
||||
if isinstance(_elem, ir.PointerType) and isinstance(_elem.pointee, ir.IdentifiedStructType):
|
||||
_pname: str = _elem.pointee.name
|
||||
_short: str = _pname.rsplit('.', 1)[-1] if '.' in _pname else _pname
|
||||
if _short == 'T':
|
||||
_found = True
|
||||
break
|
||||
_cache[_key] = (St, _elems, _found)
|
||||
return _found
|
||||
|
||||
def _MemberSlotAccepts(self, Declared: Any, Slot: Any) -> bool:
|
||||
"""声明类型能否**隐式写进**该 struct 槽(判据与存储侧同一套)。
|
||||
|
||||
用于判定已冻结的 struct body 是否与 `class_members` 自洽。判定放宽到与
|
||||
存储侧一致,避免误清:通用指针槽(i8*/void*)照旧放行(历史 stub 普遍
|
||||
如此),继承上转/数组退让亦放行;只有**存储时必被拒绝**的组合——层数
|
||||
不同、指针与非指针混位——才判为不一致,触发重建。
|
||||
"""
|
||||
if Declared is None or Slot is None:
|
||||
return True
|
||||
# 同一对象直接放行:llvmlite 的 Type.__eq__ 走类型键比较(profile:
|
||||
# 本函数被 _generate_structs 调 54.2M 次,其中 types.py __eq__ 合计 ~30s)
|
||||
# ⇒ 先做身份判定短路,等价且避免绝大多数 __eq__/str() 开销。
|
||||
if Declared is Slot:
|
||||
return True
|
||||
if Declared == Slot or str(Declared) == str(Slot):
|
||||
return True
|
||||
_d_ptr: bool = isinstance(Declared, ir.PointerType)
|
||||
_s_ptr: bool = isinstance(Slot, ir.PointerType)
|
||||
if _d_ptr != _s_ptr:
|
||||
return False
|
||||
if not _d_ptr:
|
||||
# 数值/浮点宽度差异不在本次收紧范围:保持既有行为(不清 body)。
|
||||
return True
|
||||
try:
|
||||
Allowed, _Reason = self._ClassifyPtrImplicitConvert(Declared, Slot)
|
||||
return bool(Allowed)
|
||||
except Exception:
|
||||
# 判据不可用(缺上下文)时保守放行,避免误清已正确的布局。
|
||||
return True
|
||||
|
||||
def _IsRenumLayoutClass(self, ClassName: str | None) -> bool:
|
||||
"""该类是否属 **REnum 布局**(主 REnum 自身,或其变体嵌套结构体 `<REnum>_<Variant>`)。
|
||||
|
||||
REnum 的 struct body 是 **max-variant 镜像布局**:`class_members` 里那些名字是
|
||||
*变体*(不是字段),变体嵌套结构体也必须逐字镜像主结构体。因此**一律不得**用
|
||||
class_members 的"声明类型"去改写或校验它们的布局 —— 否则跨模块 GEP 偏移与
|
||||
定义端失配(变体载荷槽本就允许与 max-variant 槽类型不同,取值处靠 bitcast)。
|
||||
"""
|
||||
if not ClassName:
|
||||
return False
|
||||
_tbl: Any = getattr(self, 'SymbolTable', None)
|
||||
if _tbl is None:
|
||||
return False
|
||||
try:
|
||||
_e: Any = _tbl.lookup(ClassName)
|
||||
except Exception:
|
||||
return False
|
||||
if _e is not None and getattr(_e, 'IsRenum', False):
|
||||
return True
|
||||
if '_' in ClassName:
|
||||
_prefix: str = ClassName.rsplit('_', 1)[0]
|
||||
try:
|
||||
_pe: Any = _tbl.lookup(_prefix)
|
||||
except Exception:
|
||||
_pe = None
|
||||
if _pe is not None and getattr(_pe, 'IsRenum', False):
|
||||
return True
|
||||
return False
|
||||
|
||||
def _StructBodyHasPlaceholderT(self, St: Any) -> bool:
|
||||
"""该 struct body 是否含未特化的 `T*` 占位字段(结果按 body 对象记忆)。
|
||||
|
||||
`_generate_structs` 里有两处对"全部类的全部元素"做这一扫描(Step 4 的完整性与
|
||||
set_body 前的复核),每次调用都全量重扫 —— profile(2026-09-29 main_prof_72472):
|
||||
这两处是本函数 62.5M 次 `isinstance`(6.20s)与 4.98M 次 `rsplit`(1.12s)的主源。
|
||||
|
||||
判定精确性:扫描是 `st.elements` 的**纯函数**,而 `elements` 在 llvmlite 里是
|
||||
**整体替换**(`set_body` 赋新 tuple;作废时置 None;从不原地改元素)⇒ 用
|
||||
`elements` 的**对象身份**当版本号即可精确判定"body 未变"。缓存条目**强引用**
|
||||
struct 实例与 elements 对象,二者存活 ⇒ `id()` 不会被回收复用 ⇒ 不会误判命中。
|
||||
(代价:被替换掉的旧 body tuple 会被缓存多留一份引用;量级 = 结构体数量级,可忽略。)
|
||||
"""
|
||||
_cache: dict | None = getattr(self, '_struct_t_placeholder_cache', None)
|
||||
if _cache is None:
|
||||
_cache = {}
|
||||
self._struct_t_placeholder_cache = _cache
|
||||
_key: int = id(St)
|
||||
_elems: Any = getattr(St, 'elements', None)
|
||||
_hit: Any = _cache.get(_key)
|
||||
if _hit is not None and _hit[0] is St and _hit[1] is _elems:
|
||||
return _hit[2]
|
||||
_found: bool = False
|
||||
if _elems:
|
||||
for _elem in _elems:
|
||||
if isinstance(_elem, ir.PointerType) and isinstance(_elem.pointee, ir.IdentifiedStructType):
|
||||
_pname: str = _elem.pointee.name
|
||||
_short: str = _pname.rsplit('.', 1)[-1] if '.' in _pname else _pname
|
||||
if _short == 'T':
|
||||
_found = True
|
||||
break
|
||||
_cache[_key] = (St, _elems, _found)
|
||||
return _found
|
||||
|
||||
def _generate_structs(self) -> None:
|
||||
# 热路径局部化:profile 中本函数被调 35,240 次(cum 1893s),内部
|
||||
# SymbolTable.lookup 15.9M 次(16.7s)+ 真值判断触发的 __len__ 15.9M 次
|
||||
@@ -569,7 +569,7 @@ class StructGenMixin:
|
||||
# 治本修复:检查 struct body 是否不完整(元素数少于 class_members + vtable 预期)。
|
||||
# 常见于跨模块继承:子类 struct 在父类 class_members 加载前从 stub 生成,
|
||||
# stub 中的定义可能不完整或类型不正确(如 GSList* 代替 AST*、i8* 代替 i32)。
|
||||
# 此处检测到不完整后清除 elements(公开属性,见下方 Step 4 说明)和
|
||||
# 此处检测到不完整后清除 elements(公开属性,见下方 Step 4 说明)和
|
||||
# stub 缓存,让后续代码重新从 stub 加载。
|
||||
_has_vtable_precheck: bool = ClassName in self.class_vtable or ClassName in self._cross_module_vtable_classes
|
||||
if not _has_vtable_precheck:
|
||||
@@ -774,7 +774,7 @@ class StructGenMixin:
|
||||
# 优先从 stub.ll 加载完整定义。set_body 只能对 opaque struct 调用一次,
|
||||
# 若用不完整 class_members 设置 body,后续无法修正,会导致 GEP 越界。
|
||||
# 但本地定义的类(_classes_in_progress)不从 stub 加载,因为 stub 可能
|
||||
# 来自同名导入类,其 vtable 状态与本地定义不同(@t.NoVTable 冲突)
|
||||
# 来自同名导入类,其 vtable 状态与本地定义不同(@NoVTable 冲突)
|
||||
import_handler: Any = self._import_handler_ref
|
||||
if import_handler is not None and ClassName not in self._classes_in_progress:
|
||||
try:
|
||||
@@ -924,7 +924,7 @@ class StructGenMixin:
|
||||
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):
|
||||
if any(hasattr(c, 'constant') and isinstance(constant, _Undefined) for c in gv.initializer.constant):
|
||||
needs_fix = True
|
||||
if not needs_fix:
|
||||
continue
|
||||
|
||||
Reference in new issue
Block a user