refactor(tpv): 新语法 R10 括号内隐式续行并一行(1140 处 / 67 文件)
This commit is contained in:
1 parent
4a685d478f
commit
f2ef1bb240
67 files changed
+1140
-3775
No files matched your search
@@ -153,8 +153,7 @@ def _pyi_cdefine_found() -> int:
|
||||
# 将 text 追加到 buf 的 pos 位置,返回新的 pos。
|
||||
# 自动处理缓冲区溢出(截断)。
|
||||
# ============================================================
|
||||
def _PyiEmit(buf: bytes, buf_size: sizet, pos: sizet,
|
||||
text: str) -> sizet:
|
||||
def _PyiEmit(buf: bytes, buf_size: sizet, pos: sizet, text: str) -> sizet:
|
||||
"""追加 text 到 buf 的 pos 位置,返回新的 pos"""
|
||||
if buf is None or text is None or pos >= buf_size: return pos
|
||||
tlen: sizet = string.strlen(text)
|
||||
@@ -170,8 +169,7 @@ def _PyiEmit(buf: bytes, buf_size: sizet, pos: sizet,
|
||||
#
|
||||
# 追加 level*4 个空格到 buf 的 pos 位置。
|
||||
# ============================================================
|
||||
def _PyiIndent(buf: bytes, buf_size: sizet, pos: sizet,
|
||||
level: int) -> sizet:
|
||||
def _PyiIndent(buf: bytes, buf_size: sizet, pos: sizet, level: int) -> sizet:
|
||||
"""追加 level*4 个空格到 buf,返回新的 pos"""
|
||||
i: int = 0
|
||||
while i < level:
|
||||
@@ -191,8 +189,7 @@ def _PyiIndent(buf: bytes, buf_size: sizet, pos: sizet,
|
||||
# 表外运算符 fail-fast:静默写错运算符会生成错误的类型/长度文本,
|
||||
# 让下游按错误结果解析(与 TPC 落到未知节点 fail-fast 同语义)。
|
||||
# ============================================================
|
||||
def _PyiBinOpOpText(buf: bytes, buf_size: sizet, pos: sizet,
|
||||
op: int, node: ast.AST*) -> sizet:
|
||||
def _PyiBinOpOpText(buf: bytes, buf_size: sizet, pos: sizet, op: int, node: ast.AST*) -> sizet:
|
||||
"""按运算符种类输出 " OP " 文本,表外运算符 fail-fast"""
|
||||
if op == ast.OpKind.BitOr: return _PyiEmit(buf, buf_size, pos, " | ")
|
||||
if op == ast.OpKind.Add: return _PyiEmit(buf, buf_size, pos, " + ")
|
||||
@@ -216,9 +213,7 @@ def _PyiBinOpOpText(buf: bytes, buf_size: sizet, pos: sizet,
|
||||
# 差异项:TPV 额外支持裸 Tuple(TPC 仅在 Subscript.slice 位置接受 Tuple);
|
||||
# TPC 额外有 Index 分支(vast 遗留类,解析器不产出该节点)。
|
||||
# ============================================================
|
||||
def _PyiTypeStr(buf: bytes, buf_size: sizet, pos: sizet,
|
||||
annot: ast.AST*,
|
||||
depth: int = 0) -> sizet:
|
||||
def _PyiTypeStr(buf: bytes, buf_size: sizet, pos: sizet, annot: ast.AST*, depth: int = 0) -> sizet:
|
||||
"""递归生成类型注解字符串,返回新的 pos"""
|
||||
# 递归深度守卫:AST 损坏成自引用环(Attribute.value/Subscript.slice/
|
||||
# BinOp.left 等回指祖先)时无限递归直至栈耗尽(Phase1 vpi 生成最先
|
||||
@@ -404,9 +399,7 @@ def _PyiTypeStr(buf: bytes, buf_size: sizet, pos: sizet,
|
||||
# 用默认值填充,否则被调函数读到栈垃圾(假报递归过深/崩溃)。
|
||||
# 支持: Constant(int/str/bool/None), Name(CDefine 常量), UnaryOp。
|
||||
# ============================================================
|
||||
def _PyiDefaultStr(buf: bytes, buf_size: sizet, pos: sizet,
|
||||
node: ast.AST*,
|
||||
depth: int = 0) -> sizet:
|
||||
def _PyiDefaultStr(buf: bytes, buf_size: sizet, pos: sizet, node: ast.AST*, depth: int = 0) -> sizet:
|
||||
"""生成默认值表达式文本到 buf,返回新的 pos"""
|
||||
# 递归深度守卫:AST 损坏成自引用环时 fail-fast 终止(同 _PyiTypeStr)
|
||||
if depth > 64:
|
||||
@@ -462,8 +455,7 @@ def _PyiDefaultStr(buf: bytes, buf_size: sizet, pos: sizet,
|
||||
# (既有 tuple → struct 通路保留)。vpi 里仍带该装饰器意味着存根过旧,
|
||||
# fail-fast 提示重新生成,不静默忽略。返回 0 = 装饰器列表里没有 CReturn。
|
||||
# ============================================================
|
||||
def _PyiRejectCReturnDecorator(node: ast.AST*,
|
||||
decorators: list[ast.AST*]*) -> int:
|
||||
def _PyiRejectCReturnDecorator(node: ast.AST*, decorators: list[ast.AST*]*) -> int:
|
||||
"""装饰器列表里出现 @c.CReturn 即 fatal_error(返回 0 = 无该装饰器)"""
|
||||
if decorators is None: return 0
|
||||
dn: sizet = len(decorators)
|
||||
@@ -490,9 +482,7 @@ def _PyiRejectCReturnDecorator(node: ast.AST*,
|
||||
#
|
||||
# 格式: def name(param: Type, ...) -> ReturnType: pass
|
||||
# ============================================================
|
||||
def _PyiFunction(buf: bytes, buf_size: sizet, pos: sizet,
|
||||
fn: ast.FunctionDef*,
|
||||
indent_level: int, class_name: str) -> sizet:
|
||||
def _PyiFunction(buf: bytes, buf_size: sizet, pos: sizet, fn: ast.FunctionDef*, indent_level: int, class_name: str) -> sizet:
|
||||
"""生成函数签名到 buf,返回新的 pos"""
|
||||
# 装饰器
|
||||
if fn.decorator_list is not None:
|
||||
@@ -584,8 +574,7 @@ def _PyiFunction(buf: bytes, buf_size: sizet, pos: sizet,
|
||||
# field: Type
|
||||
# def method(self: Name, ...) -> RetType: pass
|
||||
# ============================================================
|
||||
def _PyiClass(buf: bytes, buf_size: sizet, pos: sizet,
|
||||
cls: ast.ClassDef*, indent_level: int) -> sizet:
|
||||
def _PyiClass(buf: bytes, buf_size: sizet, pos: sizet, cls: ast.ClassDef*, indent_level: int) -> sizet:
|
||||
"""生成类定义到 buf,返回新的 pos"""
|
||||
# 装饰器
|
||||
if cls.decorator_list is not None:
|
||||
@@ -720,9 +709,7 @@ def _PyiClass(buf: bytes, buf_size: sizet, pos: sizet,
|
||||
# Args: mb 内存池(保留以符合调用约定,实际未使用);tree AST Module 根节点;rel_path 源文件路径(仅用于报错归因的"当前文件",应传绝对路径以便 fatal_error 读取源码行);buf 输出缓冲区;buf_size 缓冲区大小
|
||||
# Returns: 写入的字节数(0 表示失败)
|
||||
# ============================================================
|
||||
def _GeneratePyiFromAst(mb: memhub.MemBuddy*, tree: ast.AST*,
|
||||
rel_path: str, buf: bytes,
|
||||
buf_size: sizet) -> sizet:
|
||||
def _GeneratePyiFromAst(mb: memhub.MemBuddy*, tree: ast.AST*, rel_path: str, buf: bytes, buf_size: sizet) -> sizet:
|
||||
"""从 AST 生成 .vpi 存根文件内容到 buf"""
|
||||
if tree is None or buf is None or buf_size == 0: return 0
|
||||
|
||||
@@ -822,9 +809,7 @@ def _GeneratePyiFromAst(mb: memhub.MemBuddy*, tree: ast.AST*,
|
||||
# fail-fast:别名列表为空 ⇒ 写出 `import ` 这种残缺行,import 名字
|
||||
# 全丢,包重导出注册随之失效(与下面逐个别名为空的检查互补)。
|
||||
if imp2.names is None or len(imp2.names) == 0:
|
||||
GenApi.fatal_error(stmt,
|
||||
"vpi 生成:import 语句别名列表为空(应为 ≥1 个别名)——AST 构造/解析异常",
|
||||
"NameError")
|
||||
GenApi.fatal_error(stmt, "vpi 生成:import 语句别名列表为空(应为 ≥1 个别名)——AST 构造/解析异常", "NameError")
|
||||
if imp2.names is not None:
|
||||
imp2_names: list[ast.AST*]* = imp2.names
|
||||
an2: sizet = len(imp2_names)
|
||||
@@ -842,15 +827,9 @@ def _GeneratePyiFromAst(mb: memhub.MemBuddy*, tree: ast.AST*,
|
||||
# 两种成因分开报,便于一次定位:节点指针为空 = Alias 构造失败;
|
||||
# 节点在而 name 为空 = _copy_str/__init__ 未生效。
|
||||
if al2 is None:
|
||||
GenApi.fatal_error(stmt,
|
||||
"vpi 生成:import 别名**节点指针为空**(Alias(...) 构造未产出对象:"
|
||||
"pool.alloc 失败或 __init__ 未执行)——import 名字丢失会破坏包重导出注册",
|
||||
"NameError")
|
||||
GenApi.fatal_error(stmt, "vpi 生成:import 别名**节点指针为空**(Alias(...) 构造未产出对象:" "pool.alloc 失败或 __init__ 未执行)——import 名字丢失会破坏包重导出注册", "NameError")
|
||||
if al2.name is None or al2.name[0] == '\0':
|
||||
GenApi.fatal_error(stmt,
|
||||
"vpi 生成:import 别名节点存在但 **name 为空**(_copy_str 返回 None / "
|
||||
"__init__ 未赋值 name)——import 名字丢失会破坏包重导出注册",
|
||||
"NameError")
|
||||
GenApi.fatal_error(stmt, "vpi 生成:import 别名节点存在但 **name 为空**(_copy_str 返回 None / " "__init__ 未赋值 name)——import 名字丢失会破坏包重导出注册", "NameError")
|
||||
pos = _PyiEmit(buf, buf_size, pos, al2.name)
|
||||
if al2.asname is not None and string.strlen(al2.asname) > 0:
|
||||
pos = _PyiEmit(buf, buf_size, pos, " as ")
|
||||
@@ -872,10 +851,7 @@ def _GeneratePyiFromAst(mb: memhub.MemBuddy*, tree: ast.AST*,
|
||||
# 列表为空或名字为空都说明 AST 坏;静默写出 `from X import ` 会让
|
||||
# 包重导出注册失效(star 也用于 re-export 判断)。
|
||||
if ifr.names is None or len(ifr.names) == 0:
|
||||
GenApi.fatal_error(stmt,
|
||||
"vpi 生成:from-import 语句别名列表为空(应为 ≥1 个别名,含 '*')"
|
||||
"——AST 构造/解析异常",
|
||||
"NameError")
|
||||
GenApi.fatal_error(stmt, "vpi 生成:from-import 语句别名列表为空(应为 ≥1 个别名,含 '*')" "——AST 构造/解析异常", "NameError")
|
||||
if ifr.names is not None:
|
||||
ifr_names: list[ast.AST*]* = ifr.names
|
||||
an3: sizet = len(ifr_names)
|
||||
@@ -885,15 +861,9 @@ def _GeneratePyiFromAst(mb: memhub.MemBuddy*, tree: ast.AST*,
|
||||
al3: ast.Alias* = ast.Alias*(ifr_names.get(ai3))
|
||||
# fail-fast:同 Import 分支(两种成因分开报,一次定位)。
|
||||
if al3 is None:
|
||||
GenApi.fatal_error(stmt,
|
||||
"vpi 生成:from-import 别名**节点指针为空**(Alias(...) 构造未产出对象:"
|
||||
"pool.alloc 失败或 __init__ 未执行)——包重导出注册会因此失效",
|
||||
"NameError")
|
||||
GenApi.fatal_error(stmt, "vpi 生成:from-import 别名**节点指针为空**(Alias(...) 构造未产出对象:" "pool.alloc 失败或 __init__ 未执行)——包重导出注册会因此失效", "NameError")
|
||||
if al3.name is None or al3.name[0] == '\0':
|
||||
GenApi.fatal_error(stmt,
|
||||
"vpi 生成:from-import 别名节点存在但 **name 为空**(_copy_str 返回 None / "
|
||||
"__init__ 未赋值 name)——包重导出注册会因此失效",
|
||||
"NameError")
|
||||
GenApi.fatal_error(stmt, "vpi 生成:from-import 别名节点存在但 **name 为空**(_copy_str 返回 None / " "__init__ 未赋值 name)——包重导出注册会因此失效", "NameError")
|
||||
pos = _PyiEmit(buf, buf_size, pos, al3.name)
|
||||
if al3.asname is not None and string.strlen(al3.asname) > 0:
|
||||
pos = _PyiEmit(buf, buf_size, pos, " as ")
|
||||
@@ -958,8 +928,7 @@ def _GeneratePyiFromAst(mb: memhub.MemBuddy*, tree: ast.AST*,
|
||||
# 字符串 CDefine(pyzlib.ZLIB_VERSION = "1.3.2" 等)必须输出值,让 stub 自包含(读回端按目标名判定会回退源文件)
|
||||
sbuf_c: bytes = mb.alloc(string.strlen(cv.str_val) + 6)
|
||||
if sbuf_c is not None:
|
||||
viperlib.snprintf(sbuf_c, string.strlen(cv.str_val) + 6,
|
||||
" = \"%s\"", cv.str_val)
|
||||
viperlib.snprintf(sbuf_c, string.strlen(cv.str_val) + 6, " = \"%s\"", cv.str_val)
|
||||
pos = _PyiEmit(buf, buf_size, pos, sbuf_c)
|
||||
elif cv.const_kind == ast.CONST_NONE: pos = _PyiEmit(buf, buf_size, pos, " = None")
|
||||
elif aa.value is not None and aa.value.kind() == ast.ASTKind.UnaryOp:
|
||||
|
||||
@@ -169,8 +169,7 @@ def _vpi_idx_slot(idx_base: bytes, si: sizet) -> sizet*:
|
||||
return (sizet*)(uint64(idx_base) + uint64(si) * 8)
|
||||
|
||||
|
||||
def _vpi_idx_find(keys: bytes, key_stride: int, idx_base: bytes,
|
||||
cap: int, key: bytes) -> int:
|
||||
def _vpi_idx_find(keys: bytes, key_stride: int, idx_base: bytes, cap: int, key: bytes) -> int:
|
||||
"""在索引中探测 key,返回命中槽下标(>=0);未命中/索引不可用返回 -1
|
||||
|
||||
命中判据是"当前键相等"(strcmp),不能只比哈希。
|
||||
@@ -235,8 +234,7 @@ def _vpi_rebuild_ret_idx(new_cap: int) -> int:
|
||||
fail: int = 0
|
||||
ri: int
|
||||
for ri in range(_g_vpi_ret_count):
|
||||
if _vpi_idx_insert(new_idx, new_cap, ri,
|
||||
_g_vpi_ret_keys + ri * VPI_KEY_LEN) != 0:
|
||||
if _vpi_idx_insert(new_idx, new_cap, ri, _g_vpi_ret_keys + ri * VPI_KEY_LEN) != 0:
|
||||
fail = 1
|
||||
break
|
||||
if fail != 0:
|
||||
@@ -268,8 +266,7 @@ def _vpi_rebuild_param_idx(new_cap: int) -> int:
|
||||
fail: int = 0
|
||||
ri: int
|
||||
for ri in range(_g_vpi_param_count):
|
||||
if _vpi_idx_insert(new_idx, new_cap, ri,
|
||||
_g_vpi_param_keys + ri * VPI_PARAM_KEY_LEN) != 0:
|
||||
if _vpi_idx_insert(new_idx, new_cap, ri, _g_vpi_param_keys + ri * VPI_PARAM_KEY_LEN) != 0:
|
||||
fail = 1
|
||||
break
|
||||
if fail != 0:
|
||||
@@ -389,8 +386,7 @@ def _cache_vpi_return_annots_text(vpi_buf: bytes, src_sha1: str) -> int:
|
||||
mname_buf[mname_len] = '\0'
|
||||
# 无注解的特殊方法(构造/析构)跳过:它们有专门调用路径
|
||||
skip_def: int = 0
|
||||
if arrow_pos >= le and (
|
||||
string.strcmp(mname_buf, "__init__") == 0 or string.strcmp(mname_buf, "__new__") == 0 or string.strcmp(mname_buf, "__before_init__") == 0 or string.strcmp(mname_buf, "__after_init__") == 0):
|
||||
if arrow_pos >= le and (string.strcmp(mname_buf, "__init__") == 0 or string.strcmp(mname_buf, "__new__") == 0 or string.strcmp(mname_buf, "__before_init__") == 0 or string.strcmp(mname_buf, "__after_init__") == 0):
|
||||
skip_def = 1
|
||||
if skip_def == 0:
|
||||
key_buf: bytes = stdlib.malloc(key_len + 1)
|
||||
@@ -404,8 +400,7 @@ def _cache_vpi_return_annots_text(vpi_buf: bytes, src_sha1: str) -> int:
|
||||
# 重复(命中即"首个注册优先"= 原线性扫描首个同名);
|
||||
# 未命中 | 索引不可信 → 回退原线性扫描(正确性保证)。
|
||||
if _g_vpi_ret_idx_built == _g_vpi_ret_count and _g_vpi_ret_idx is not None and _g_vpi_ret_idx_cap > 0:
|
||||
if _vpi_idx_find(_g_vpi_ret_keys, VPI_KEY_LEN,
|
||||
_g_vpi_ret_idx, _g_vpi_ret_idx_cap, key_buf) >= 0:
|
||||
if _vpi_idx_find(_g_vpi_ret_keys, VPI_KEY_LEN, _g_vpi_ret_idx, _g_vpi_ret_idx_cap, key_buf) >= 0:
|
||||
dup_key = 1
|
||||
else:
|
||||
# 快速路径:重复键必首字节相同(strcmp 判等蕴含首字节
|
||||
@@ -420,14 +415,12 @@ def _cache_vpi_return_annots_text(vpi_buf: bytes, src_sha1: str) -> int:
|
||||
if dup_key == 0 and _g_vpi_ret_count >= _g_vpi_ret_cap: grow_ok = _grow_vpi_ret_cache()
|
||||
if dup_key == 0 and grow_ok != 0:
|
||||
string.strcpy(_g_vpi_ret_keys + _g_vpi_ret_count * VPI_KEY_LEN, key_buf)
|
||||
string.strncpy(_g_vpi_ret_strs + _g_vpi_ret_count * VPI_RET_LEN,
|
||||
ret_src, rtype_len)
|
||||
string.strncpy(_g_vpi_ret_strs + _g_vpi_ret_count * VPI_RET_LEN, ret_src, rtype_len)
|
||||
(_g_vpi_ret_strs + _g_vpi_ret_count * VPI_RET_LEN)[rtype_len] = '\0'
|
||||
_g_vpi_ret_count += 1
|
||||
# 同步索引:仅当插入前可信(Built==Count-1,含扩容
|
||||
# 重建后)且插入成功;否则标记不可信(查找回退扫描)。
|
||||
if _g_vpi_ret_idx_built == _g_vpi_ret_count - 1 and _vpi_idx_insert(_g_vpi_ret_idx, _g_vpi_ret_idx_cap,
|
||||
_g_vpi_ret_count - 1, key_buf) == 0:
|
||||
if _g_vpi_ret_idx_built == _g_vpi_ret_count - 1 and _vpi_idx_insert(_g_vpi_ret_idx, _g_vpi_ret_idx_cap, _g_vpi_ret_count - 1, key_buf) == 0:
|
||||
_g_vpi_ret_idx_built = _g_vpi_ret_count
|
||||
else: _g_vpi_ret_idx_built = -1
|
||||
stdlib.free(key_buf)
|
||||
@@ -598,8 +591,7 @@ def _cache_vpi_param_annots_text(vpi_buf: bytes, src_sha1: str) -> int:
|
||||
# 重复(命中即"首个注册优先"= 原线性扫描首个同名);
|
||||
# 未命中 | 索引不可信 → 回退原线性扫描(正确性保证)。
|
||||
if _g_vpi_param_idx_built == _g_vpi_param_count and _g_vpi_param_idx is not None and _g_vpi_param_idx_cap > 0:
|
||||
if _vpi_idx_find(_g_vpi_param_keys, VPI_PARAM_KEY_LEN,
|
||||
_g_vpi_param_idx, _g_vpi_param_idx_cap, key_buf) >= 0:
|
||||
if _vpi_idx_find(_g_vpi_param_keys, VPI_PARAM_KEY_LEN, _g_vpi_param_idx, _g_vpi_param_idx_cap, key_buf) >= 0:
|
||||
dup_key = 1
|
||||
else:
|
||||
# 快速路径:重复键必首字节相同(strcmp 判等蕴含首字节
|
||||
@@ -614,14 +606,12 @@ def _cache_vpi_param_annots_text(vpi_buf: bytes, src_sha1: str) -> int:
|
||||
if dup_key == 0 and _g_vpi_param_count >= _g_vpi_param_cap: grow_ok = _grow_vpi_param_cache()
|
||||
if dup_key == 0 and grow_ok != 0:
|
||||
string.strcpy(_g_vpi_param_keys + _g_vpi_param_count * VPI_PARAM_KEY_LEN, key_buf)
|
||||
string.strncpy(_g_vpi_param_strs + _g_vpi_param_count * VPI_PARAM_LEN,
|
||||
plist, plist_pos)
|
||||
string.strncpy(_g_vpi_param_strs + _g_vpi_param_count * VPI_PARAM_LEN, plist, plist_pos)
|
||||
(_g_vpi_param_strs + _g_vpi_param_count * VPI_PARAM_LEN)[plist_pos] = '\0'
|
||||
_g_vpi_param_count += 1
|
||||
# 同步索引:仅当插入前可信(Built==Count-1,含扩容
|
||||
# 重建后)且插入成功;否则标记不可信(查找回退扫描)。
|
||||
if _g_vpi_param_idx_built == _g_vpi_param_count - 1 and _vpi_idx_insert(_g_vpi_param_idx, _g_vpi_param_idx_cap,
|
||||
_g_vpi_param_count - 1, key_buf) == 0:
|
||||
if _g_vpi_param_idx_built == _g_vpi_param_count - 1 and _vpi_idx_insert(_g_vpi_param_idx, _g_vpi_param_idx_cap, _g_vpi_param_count - 1, key_buf) == 0:
|
||||
_g_vpi_param_idx_built = _g_vpi_param_count
|
||||
else: _g_vpi_param_idx_built = -1
|
||||
stdlib.free(key_buf)
|
||||
@@ -676,8 +666,7 @@ def _lookup_vpi_param_annots(src_sha1: str, cls_name: str, method_name: str) ->
|
||||
# 索引随扩容整体重建且覆盖全表)⇒ 无需再线性扫描;索引不可信 → 回退线性扫描。
|
||||
hit_p: int = -1
|
||||
if _g_vpi_param_idx_built == _g_vpi_param_count and _g_vpi_param_idx is not None and _g_vpi_param_idx_cap > 0:
|
||||
hit_p = _vpi_idx_find(_g_vpi_param_keys, VPI_PARAM_KEY_LEN,
|
||||
_g_vpi_param_idx, _g_vpi_param_idx_cap, key_buf)
|
||||
hit_p = _vpi_idx_find(_g_vpi_param_keys, VPI_PARAM_KEY_LEN, _g_vpi_param_idx, _g_vpi_param_idx_cap, key_buf)
|
||||
else:
|
||||
# 回退原线性扫描:strcmp 判等蕴含首字节相等;键首字节 = src_sha1[0],缓存含
|
||||
# 多模块条目,首字节不同者必不相等,直接跳过其 strcmp(仅做否定判定,不改命中)。
|
||||
@@ -699,13 +688,7 @@ def _lookup_vpi_param_annots(src_sha1: str, cls_name: str, method_name: str) ->
|
||||
# 调用点 declare 停在调用点实参宽度(如 elem_size 字面量 i32 把定义侧 sizet(i64) 固化窄)。本函数按 {sha1}.{base}[T].{method} 形态定位模板条目,
|
||||
# 把段内独立的类型形参 token 用特化实参(cls_name 的 [...] 内容)替换后再解析;未命中/多参模板(键段含空格被截断)返回 None,不做兜底推断。
|
||||
# ============================================================
|
||||
def _resolve_vpi_param_annot_seg_template(pool: memhub.MemBuddy*,
|
||||
src_sha1: str,
|
||||
cls_name: str,
|
||||
method_name: str,
|
||||
seg_idx: int,
|
||||
i32_ty: mlirlite.LLVMType*,
|
||||
i8_ptr_ty: mlirlite.LLVMType*) -> mlirlite.LLVMType*:
|
||||
def _resolve_vpi_param_annot_seg_template(pool: memhub.MemBuddy*, src_sha1: str, cls_name: str, method_name: str, seg_idx: int, i32_ty: mlirlite.LLVMType*, i8_ptr_ty: mlirlite.LLVMType*) -> mlirlite.LLVMType*:
|
||||
"""特化类 X[arg] 的参数注解段解析(模板 X[T] 注解 + T→arg 替换);未命中 None"""
|
||||
if pool is None or src_sha1 is None or cls_name is None or method_name is None or _g_vpi_param_keys is None: return None
|
||||
lbkt_t: str = string.strchr(cls_name, 91) # '[' = 91
|
||||
@@ -783,14 +766,7 @@ def _resolve_vpi_param_annot_seg_template(pool: memhub.MemBuddy*,
|
||||
# vpi tree 参数列表被覆盖损坏时(param_count 偏小,尾部默认参数丢失),用 _cache_vpi_param_annots_text 的文本缓存补全:参数位置 p 对应缓存段 p(含首参空串占位)。
|
||||
# 补全后 declare 参数数与 define 一致,调用点默认参数填充才能生效,避免被调函数读栈垃圾。
|
||||
# ============================================================
|
||||
def _repair_declare_params_from_text(pool: memhub.MemBuddy*,
|
||||
func: mlirlite.Function*,
|
||||
src_sha1: str,
|
||||
cls_name: str,
|
||||
method_name: str,
|
||||
param_count: int,
|
||||
i32_ty: mlirlite.LLVMType*,
|
||||
i8_ptr_ty: mlirlite.LLVMType*) -> int:
|
||||
def _repair_declare_params_from_text(pool: memhub.MemBuddy*, func: mlirlite.Function*, src_sha1: str, cls_name: str, method_name: str, param_count: int, i32_ty: mlirlite.LLVMType*, i8_ptr_ty: mlirlite.LLVMType*) -> int:
|
||||
"""用 vpi 文本缓存的参数注解补全 declare 参数;返回补全后参数数"""
|
||||
if func is None or src_sha1 is None or method_name is None: return param_count
|
||||
prm_annots: str = _lookup_vpi_param_annots(src_sha1, cls_name, method_name)
|
||||
@@ -817,8 +793,7 @@ def _repair_declare_params_from_text(pool: memhub.MemBuddy*,
|
||||
if seg_buf_r is not None:
|
||||
string.strncpy(seg_buf_r, prm_annots + seg_start2, seg_len2)
|
||||
seg_buf_r[seg_len2] = '\0'
|
||||
rt: mlirlite.LLVMType* = _resolve_vpi_ret_annot_str(
|
||||
pool, seg_buf_r, i32_ty, i8_ptr_ty)
|
||||
rt: mlirlite.LLVMType* = _resolve_vpi_ret_annot_str(pool, seg_buf_r, i32_ty, i8_ptr_ty)
|
||||
if rt is not None: param_ty_r = rt
|
||||
stdlib.free(seg_buf_r)
|
||||
mlirlite.add_param(pool, func, param_ty_r, "arg")
|
||||
@@ -834,13 +809,7 @@ def _repair_declare_params_from_text(pool: memhub.MemBuddy*,
|
||||
# 参数类型错会导致调用侧 trunc 传参、callee 按 i64 读栈残留高位 → can=巨值读未写槽位崩溃(SlotsBugTest 根因)。
|
||||
# 从 @-joined 注解串取第 seg_idx 段(0=self 空段),用 _resolve_vpi_ret_annot_str 解析;空段/未命中返回 None(走 AST 兜底)。
|
||||
# ============================================================
|
||||
def _resolve_vpi_param_annot_seg(pool: memhub.MemBuddy*,
|
||||
src_sha1: str,
|
||||
cls_name: str,
|
||||
method_name: str,
|
||||
seg_idx: int,
|
||||
i32_ty: mlirlite.LLVMType*,
|
||||
i8_ptr_ty: mlirlite.LLVMType*) -> mlirlite.LLVMType*:
|
||||
def _resolve_vpi_param_annot_seg(pool: memhub.MemBuddy*, src_sha1: str, cls_name: str, method_name: str, seg_idx: int, i32_ty: mlirlite.LLVMType*, i8_ptr_ty: mlirlite.LLVMType*) -> mlirlite.LLVMType*:
|
||||
"""按段索引解析 vpi 参数注解段为 LLVMType,空段/失败返回 None"""
|
||||
if pool is None or src_sha1 is None or method_name is None: return None
|
||||
prm_annots_p: str = _lookup_vpi_param_annots(src_sha1, cls_name, method_name)
|
||||
@@ -859,8 +828,7 @@ def _resolve_vpi_param_annot_seg(pool: memhub.MemBuddy*,
|
||||
if seg_buf_p is None: return None
|
||||
string.strncpy(seg_buf_p, prm_annots_p + seg_start_p, seg_len_p)
|
||||
seg_buf_p[seg_len_p] = '\0'
|
||||
seg_ty_p: mlirlite.LLVMType* = _resolve_vpi_ret_annot_str(
|
||||
pool, seg_buf_p, i32_ty, i8_ptr_ty)
|
||||
seg_ty_p: mlirlite.LLVMType* = _resolve_vpi_ret_annot_str(pool, seg_buf_p, i32_ty, i8_ptr_ty)
|
||||
stdlib.free(seg_buf_p)
|
||||
return seg_ty_p
|
||||
|
||||
@@ -945,8 +913,7 @@ def _ensure_vpi_ret_annot_loaded(src_sha1: str, temp_dir: str) -> int:
|
||||
# ============================================================
|
||||
# _vpi_param_annot_seg_is - 形参注解段等值判定(供"str/bytes 不是通用指针通配"规则)
|
||||
# ============================================================
|
||||
def _vpi_param_annot_seg_is(src_sha1: str, cls_name: str, method_name: str,
|
||||
seg_idx: int, want: str) -> int:
|
||||
def _vpi_param_annot_seg_is(src_sha1: str, cls_name: str, method_name: str, seg_idx: int, want: str) -> int:
|
||||
"""vpi 定义侧第 seg_idx 个形参注解段是否**恰等于** want(1=是 / 0=否)
|
||||
|
||||
注解串格式(见 _lookup_vpi_param_annots):以 '@' 分隔的段序列,段 0 是
|
||||
@@ -1105,8 +1072,7 @@ def _lookup_vpi_ret_annot(src_sha1: str, cls_name: str, method_name: str) -> str
|
||||
# 匹配兜底仍保留,其键形态不同、不依赖精确键命中);索引不可信 → 回退线性扫描。
|
||||
hit_r: int = -1
|
||||
if _g_vpi_ret_idx_built == _g_vpi_ret_count and _g_vpi_ret_idx is not None and _g_vpi_ret_idx_cap > 0:
|
||||
hit_r = _vpi_idx_find(_g_vpi_ret_keys, VPI_KEY_LEN,
|
||||
_g_vpi_ret_idx, _g_vpi_ret_idx_cap, key_buf)
|
||||
hit_r = _vpi_idx_find(_g_vpi_ret_keys, VPI_KEY_LEN, _g_vpi_ret_idx, _g_vpi_ret_idx_cap, key_buf)
|
||||
else:
|
||||
# 回退原线性扫描:strcmp 判等蕴含首字节相等(键首字节 = src_sha1[0]),跳过首字节不同者。
|
||||
key_first: int = key_buf[0]
|
||||
@@ -1143,16 +1109,14 @@ def _lookup_vpi_ret_annot(src_sha1: str, cls_name: str, method_name: str) -> str
|
||||
if string.strncmp(gk, src_sha1, sha1_len) == 0 and gk[sha1_len] == '.' and string.strncmp(gk + sha1_len + 1, base_v, base_len_v) == 0 and gk[sha1_len + 1 + base_len_v] == '[':
|
||||
gklb: str = string.strchr(gk + sha1_len + 1 + base_len_v, ']')
|
||||
if gklb is not None:
|
||||
tparam_len_v: sizet = sizet(
|
||||
uint64(gklb) - uint64(gk + sha1_len + 1 + base_len_v) - 1)
|
||||
tparam_len_v: sizet = sizet(uint64(gklb) - uint64(gk + sha1_len + 1 + base_len_v) - 1)
|
||||
meth_start_v: str = gklb + 2 # 跳过 ']' 和 '.'
|
||||
if tparam_len_v > 0 and string.strcmp(meth_start_v, method_name) == 0:
|
||||
tparam_v: str = stdlib.malloc(tparam_len_v + 1)
|
||||
if tparam_v is not None:
|
||||
string.strncpy(tparam_v, gk + sha1_len + 1 + base_len_v + 1, tparam_len_v)
|
||||
tparam_v[tparam_len_v] = '\0'
|
||||
new_annot_v: str = _subst_template_arg(
|
||||
_g_vpi_ret_strs + gi * VPI_RET_LEN, tparam_v, param_v)
|
||||
new_annot_v: str = _subst_template_arg(_g_vpi_ret_strs + gi * VPI_RET_LEN, tparam_v, param_v)
|
||||
stdlib.free(tparam_v)
|
||||
stdlib.free(base_v)
|
||||
stdlib.free(param_v)
|
||||
@@ -1169,8 +1133,7 @@ def _lookup_vpi_ret_annot(src_sha1: str, cls_name: str, method_name: str) -> str
|
||||
#
|
||||
# 纯字符串解析,不构造 AST 节点。
|
||||
# ============================================================
|
||||
def _resolve_single_vpi_type_str(pool: memhub.MemBuddy*,
|
||||
seg: str) -> mlirlite.LLVMType*:
|
||||
def _resolve_single_vpi_type_str(pool: memhub.MemBuddy*, seg: str) -> mlirlite.LLVMType*:
|
||||
"""解析单个类型段为 LLVMType,无法识别返回 None"""
|
||||
if seg is None or pool is None: return None
|
||||
# 【指针实参唯一规范形 `T*`(用户定口径,2026-09-30)】`rawptr[T]` ≡
|
||||
@@ -1266,8 +1229,7 @@ def _resolve_single_vpi_type_str(pool: memhub.MemBuddy*,
|
||||
if inner_buf_cp is not None:
|
||||
string.strncpy(inner_buf_cp, seg + cptr_sub_pfx, inner_len_cp)
|
||||
inner_buf_cp[inner_len_cp] = '\0'
|
||||
inner_ty_cp: mlirlite.LLVMType* = _resolve_single_vpi_type_str(
|
||||
pool, inner_buf_cp)
|
||||
inner_ty_cp: mlirlite.LLVMType* = _resolve_single_vpi_type_str(pool, inner_buf_cp)
|
||||
stdlib.free(inner_buf_cp)
|
||||
if inner_ty_cp is not None: return mlirlite.Ptr(pool, inner_ty_cp)
|
||||
return None
|
||||
@@ -1318,10 +1280,7 @@ def _resolve_single_vpi_type_str(pool: memhub.MemBuddy*,
|
||||
#
|
||||
# 支持: "str"/"bytes" → i8*; "int" → i32; "bool" → i1; "char" 等 → map_t_type 映射; "X*" → Ptr(Struct X); "t.CPtr" → i8*; "memhub.MemBuddy*" → Ptr(Struct MemBuddy)。
|
||||
# ============================================================
|
||||
def _resolve_vpi_ret_annot_str(pool: memhub.MemBuddy*,
|
||||
ret_annot: str,
|
||||
i32_ty: mlirlite.LLVMType*,
|
||||
i8_ptr_ty: mlirlite.LLVMType*) -> mlirlite.LLVMType*:
|
||||
def _resolve_vpi_ret_annot_str(pool: memhub.MemBuddy*, ret_annot: str, i32_ty: mlirlite.LLVMType*, i8_ptr_ty: mlirlite.LLVMType*) -> mlirlite.LLVMType*:
|
||||
"""直接解析 vpi 返回注解字符串为 LLVMType(不构造 AST 节点)"""
|
||||
if ret_annot is None or pool is None: return None
|
||||
|
||||
@@ -1656,8 +1615,7 @@ def _vpi_typedef_visited_mark(sha1: str) -> None:
|
||||
new_cap: int = old_cap * 2
|
||||
nb: bytes = stdlib.realloc(_g_vpi_typedef_visited, new_cap * 17)
|
||||
if nb is None:
|
||||
stdio.printf("[VPI] 防环访问表扩容失败 cap=%d(丢标记引发重解析爆炸,终止)\n",
|
||||
old_cap)
|
||||
stdio.printf("[VPI] 防环访问表扩容失败 cap=%d(丢标记引发重解析爆炸,终止)\n", old_cap)
|
||||
stdio.fflush(None)
|
||||
stdlib.exit(1)
|
||||
_g_vpi_typedef_visited = nb
|
||||
@@ -1667,10 +1625,7 @@ def _vpi_typedef_visited_mark(sha1: str) -> None:
|
||||
_g_vpi_typedef_visited_count += 1
|
||||
|
||||
|
||||
def _vpi_register_typedef_closure(pool: memhub.MemBuddy*,
|
||||
import_mods: str,
|
||||
temp_dir: str,
|
||||
depth: int) -> int:
|
||||
def _vpi_register_typedef_closure(pool: memhub.MemBuddy*, import_mods: str, temp_dir: str, depth: int) -> int:
|
||||
"""递归注册 import 闭包模块的 CTypedef/CDefine,返回 0 恒(副作用注册)
|
||||
|
||||
仅注册 AnnAssign 的 t.CTypedef/t.CDefine,不注入函数 declare(避免
|
||||
@@ -1825,10 +1780,7 @@ def _vpi_register_typedef_closure(pool: memhub.MemBuddy*,
|
||||
# Args: pool 内存池;mod 当前 LLVM 模块;vpi_path .vpi 文件路径;trans 翻译器对象
|
||||
# Returns: 1=成功,0=失败
|
||||
# ============================================================
|
||||
def ParseVpiIntoModule(pool: memhub.MemBuddy*,
|
||||
mod: mlirlite.LLVMModule*,
|
||||
vpi_path: str,
|
||||
trans: HT.Translator*) -> int:
|
||||
def ParseVpiIntoModule(pool: memhub.MemBuddy*, mod: mlirlite.LLVMModule*, vpi_path: str, trans: HT.Translator*) -> int:
|
||||
"""解析 .vpi 文件,将函数声明注入到当前模块
|
||||
|
||||
解析 stub 期间临时将错误归因切换到被读 stub 文件(.vpi):
|
||||
@@ -1843,10 +1795,7 @@ def ParseVpiIntoModule(pool: memhub.MemBuddy*,
|
||||
return ret
|
||||
|
||||
|
||||
def _ParseVpiIntoModuleImpl(pool: memhub.MemBuddy*,
|
||||
mod: mlirlite.LLVMModule*,
|
||||
vpi_path: str,
|
||||
trans: HT.Translator*) -> int:
|
||||
def _ParseVpiIntoModuleImpl(pool: memhub.MemBuddy*, mod: mlirlite.LLVMModule*, vpi_path: str, trans: HT.Translator*) -> int:
|
||||
"""解析 .vpi 文件,将函数声明注入到当前模块(ParseVpiIntoModule 实际实现)"""
|
||||
if pool is None or mod is None or vpi_path is None or trans is None: return 0
|
||||
|
||||
@@ -1985,8 +1934,7 @@ def _ParseVpiIntoModuleImpl(pool: memhub.MemBuddy*,
|
||||
sifr_mod_q = qbuf_r
|
||||
if sifr_mod is not None:
|
||||
if stub_ctx is not None:
|
||||
stub_ctx.ImportedModules = StubMergerStore.AppendImportedModule(
|
||||
pool, stub_ctx.ImportedModules, sifr_mod_q)
|
||||
stub_ctx.ImportedModules = StubMergerStore.AppendImportedModule(pool, stub_ctx.ImportedModules, sifr_mod_q)
|
||||
# 方案A:包 __init__.vpi 的重导出类以包 sha1 注册别名 entry
|
||||
# (ast.Attribute 定义在 ast.exprs 但归属 ast 包;查找端按包
|
||||
# sha1 匹配,注册端按定义文件 sha1 → name+sha1 错位 fail-fast。
|
||||
@@ -2032,13 +1980,7 @@ def _ParseVpiIntoModuleImpl(pool: memhub.MemBuddy*,
|
||||
# Expression 定义在 ast.stmts,真因是子模块 sha1 查找/注入失败)。
|
||||
# 此处直接给出包名与子模块名(含补前缀后的精确名)便于定位。
|
||||
if is_pkg_init_rt != 0 and sub_sha1_rt is None and sifr_mod is not None and sifr_mod[0] != '\0':
|
||||
GenApi.fatal_error(
|
||||
sifr,
|
||||
f"包 stub 的 from-import 子模块 sha1 查找失败:"
|
||||
f"包={rel_path_rt if rel_path_rt is not None else '?'},"
|
||||
f"子模块='{sifr_mod}'(补前缀后='{sifr_mod_q}');"
|
||||
f"该子模块的类无法注册,引用它们的注解会在后续解析时落空",
|
||||
"NameError")
|
||||
GenApi.fatal_error(sifr, f"包 stub 的 from-import 子模块 sha1 查找失败:" f"包={rel_path_rt if rel_path_rt is not None else '?'}," f"子模块='{sifr_mod}'(补前缀后='{sifr_mod_q}');" f"该子模块的类无法注册,引用它们的注解会在后续解析时落空", "NameError")
|
||||
if sifr.names is not None:
|
||||
sifr_nn: sizet = len(sifr.names)
|
||||
sifri: sizet
|
||||
@@ -2056,15 +1998,12 @@ def _ParseVpiIntoModuleImpl(pool: memhub.MemBuddy*,
|
||||
# 在此跳过 ⇒ stub 上下文里 star 回退恒失效(同一份约定
|
||||
# 的两处 loop 又一处不一致)。
|
||||
if stub_ctx is not None:
|
||||
stub_ctx.FromImports = StubMergerStore.AppendFromImport(
|
||||
pool, stub_ctx.FromImports, slocal, sifr_mod_q, sorig)
|
||||
stub_ctx.FromImports = StubMergerStore.AppendFromImport(pool, stub_ctx.FromImports, slocal, sifr_mod_q, sorig)
|
||||
# 重导出类以包 sha1 注册(asname 时按别名注册);star 无
|
||||
# 具体类名,不参与重导出(仅记账,见上)。
|
||||
if string.strcmp(sial.name, "*") != 0:
|
||||
if is_pkg_init_rt != 0 and sub_sha1_rt is not None:
|
||||
_inject_reexport_class_declare(
|
||||
pool, mod, sial.name, slocal,
|
||||
sub_sha1_rt, src_sha1, trans)
|
||||
_inject_reexport_class_declare(pool, mod, sial.name, slocal, sub_sha1_rt, src_sha1, trans)
|
||||
|
||||
# 用 stub 自己的 imports 替代当前模块的(stub 注解解析上下文正确性)
|
||||
if stub_ctx is not None:
|
||||
@@ -2094,8 +2033,7 @@ def _ParseVpiIntoModuleImpl(pool: memhub.MemBuddy*,
|
||||
if ch_src == '/' or ch_src == '\\': src_mod_buf[sri_src] = '.'
|
||||
else: src_mod_buf[sri_src] = ch_src
|
||||
src_mod_buf[sr_len_src] = '\0'
|
||||
imported_modules = StubMergerStore.AppendImportedModule(
|
||||
pool, imported_modules, src_mod_buf)
|
||||
imported_modules = StubMergerStore.AppendImportedModule(pool, imported_modules, src_mod_buf)
|
||||
stdlib.free(src_mod_buf)
|
||||
|
||||
# 递归预注册 stub import 闭包的 CTypedef/CDefine:注解(如 codepage:
|
||||
@@ -2119,8 +2057,7 @@ def _ParseVpiIntoModuleImpl(pool: memhub.MemBuddy*,
|
||||
# 虚表恢复"段;批处理该标志恒 0,本块不执行。
|
||||
# ============================================================
|
||||
if ReplStubLayoutMode != 0:
|
||||
_repl_stub_collect_module(pool, mod, ch, n, trans, src_sha1,
|
||||
stub_imported_modules, stub_from_imports)
|
||||
_repl_stub_collect_module(pool, mod, ch, n, trans, src_sha1, stub_imported_modules, stub_from_imports)
|
||||
|
||||
# ============================================================
|
||||
# 第一遍 A:先注册**所有** ClassDef(字段 + 结构体),不处理方法。
|
||||
@@ -2139,8 +2076,7 @@ def _ParseVpiIntoModuleImpl(pool: memhub.MemBuddy*,
|
||||
# T 无法确定;特化方法 define 已在 Phase1 生成,无需 stub 模板 declare。
|
||||
tp_stub0: list[str]* = class_cd0.type_params
|
||||
if tp_stub0 is not None and len(tp_stub0) > 0: continue
|
||||
_inject_class_struct_declare(pool, mod, class_cd0, cls_name_v0, trans,
|
||||
src_sha1, imported_modules, from_imports)
|
||||
_inject_class_struct_declare(pool, mod, class_cd0, cls_name_v0, trans, src_sha1, imported_modules, from_imports)
|
||||
|
||||
# App 预注册(Phase A-pre,_pre_allow_dep_inject)**跳过方法/函数 declare 注入**:
|
||||
# 预注册的唯一目的是注册 struct/enum/union(第一遍 A)与包重导出别名(上方
|
||||
@@ -2180,9 +2116,7 @@ def _ParseVpiIntoModuleImpl(pool: memhub.MemBuddy*,
|
||||
if m_fd1 is None or m_fd1.name is None: continue
|
||||
# App 预注册跳过方法 declare(原因见上方 pre_skip_fn_declares 注释)。
|
||||
if pre_skip_fn_declares == 0:
|
||||
_inject_method_declare(pool, mod, m_fd1, cls_name_v1, trans,
|
||||
src_sha1, imported_modules, from_imports,
|
||||
i32_ty, i8_ptr_ty, funcs_ptr, max_funcs)
|
||||
_inject_method_declare(pool, mod, m_fd1, cls_name_v1, trans, src_sha1, imported_modules, from_imports, i32_ty, i8_ptr_ty, funcs_ptr, max_funcs)
|
||||
|
||||
i: sizet
|
||||
for i in range(n):
|
||||
@@ -2199,10 +2133,7 @@ def _ParseVpiIntoModuleImpl(pool: memhub.MemBuddy*,
|
||||
# 打断多遍收敛(现场 Translator.vpi 的 InjectTracebackInstallCtor
|
||||
# 形参 rawptr[Translator])。
|
||||
if pre_skip_fn_declares != 0: continue
|
||||
_inject_function_declare(pool, mod, fd, trans, src_sha1,
|
||||
imported_modules, from_imports,
|
||||
i32_ty, i8_ptr_ty,
|
||||
funcs_ptr, max_funcs)
|
||||
_inject_function_declare(pool, mod, fd, trans, src_sha1, imported_modules, from_imports, i32_ty, i8_ptr_ty, funcs_ptr, max_funcs)
|
||||
continue
|
||||
|
||||
# AnnAssign with t.CTypedef → 注册 CTypedef;
|
||||
@@ -2243,9 +2174,7 @@ def _ParseVpiIntoModuleImpl(pool: memhub.MemBuddy*,
|
||||
cdef_val: int64 = GenApi.extract_cdefine_int_value(aa.value)
|
||||
GenApi.register_cdefine_constant(pool, cdef_tgt.id, cdef_val)
|
||||
else:
|
||||
_inject_global_variable_declare(pool, mod, aa, trans,
|
||||
stub_imported_modules, stub_from_imports,
|
||||
i32_ty, i8_ptr_ty, src_sha1)
|
||||
_inject_global_variable_declare(pool, mod, aa, trans, stub_imported_modules, stub_from_imports, i32_ty, i8_ptr_ty, src_sha1)
|
||||
continue
|
||||
|
||||
# ClassDef → 已在第一遍统一注册(含字段 + 方法 declare),此处跳过
|
||||
@@ -2291,10 +2220,7 @@ def ResetVpiInjectVisited() -> None:
|
||||
_vpi_inj_depth = 0
|
||||
|
||||
|
||||
def _ensure_dep_vpi_injected(pool: memhub.MemBuddy*,
|
||||
mod: mlirlite.LLVMModule*,
|
||||
dep_sha1: str,
|
||||
trans: HT.Translator*) -> int:
|
||||
def _ensure_dep_vpi_injected(pool: memhub.MemBuddy*, mod: mlirlite.LLVMModule*, dep_sha1: str, trans: HT.Translator*) -> int:
|
||||
"""按需注入 dep_sha1 对应的 .vpi 到当前模块(防重入),1=就绪 / 0=失败"""
|
||||
global _vpi_inj_sha1s, _vpi_inj_count, _vpi_inj_depth
|
||||
if pool is None or mod is None or dep_sha1 is None or trans is None: return 0
|
||||
@@ -2340,8 +2266,7 @@ def _ensure_dep_vpi_injected(pool: memhub.MemBuddy*,
|
||||
# 错误却表现为远处注解解析失败。
|
||||
_vpi_inj_count -= 1
|
||||
if my_idx_i != _vpi_inj_count:
|
||||
string.strcpy(_vpi_inj_sha1s + sizet(my_idx_i) * 17,
|
||||
_vpi_inj_sha1s + sizet(_vpi_inj_count) * 17)
|
||||
string.strcpy(_vpi_inj_sha1s + sizet(my_idx_i) * 17, _vpi_inj_sha1s + sizet(_vpi_inj_count) * 17)
|
||||
return 0
|
||||
return 1
|
||||
|
||||
@@ -2356,13 +2281,7 @@ def _ensure_dep_vpi_injected(pool: memhub.MemBuddy*,
|
||||
#
|
||||
# Args: src_name 子模块中的原类名;local_name 包命名空间中的名字(或 as 别名);sub_sha1 子模块(定义文件)sha1;pkg_sha1 当前包 __init__ 的 sha1;trans 翻译器对象(源 entry 缺失时按需注入子模块 vpi 需要)
|
||||
# ============================================================
|
||||
def _inject_reexport_class_declare(pool: memhub.MemBuddy*,
|
||||
mod: mlirlite.LLVMModule*,
|
||||
src_name: str,
|
||||
local_name: str,
|
||||
sub_sha1: str,
|
||||
pkg_sha1: str,
|
||||
trans: HT.Translator*) -> int:
|
||||
def _inject_reexport_class_declare(pool: memhub.MemBuddy*, mod: mlirlite.LLVMModule*, src_name: str, local_name: str, sub_sha1: str, pkg_sha1: str, trans: HT.Translator*) -> int:
|
||||
"""把包子模块重导出的类以包 sha1 注册别名 entry(方案A:ast.Attribute 归属 ast 包)"""
|
||||
if pool is None or mod is None or src_name is None or local_name is None: return 0
|
||||
if sub_sha1 is None or sub_sha1[0] == '\0' or pkg_sha1 is None or pkg_sha1[0] == '\0': return 0
|
||||
@@ -2462,15 +2381,7 @@ def _vpi_class_is_renum(class_cd: ast.ClassDef*) -> int:
|
||||
# 2) 未注册 → 解析字段类型 → 创建命名 StructType("sha1.ClassName") → register_struct + add_visible_struct。
|
||||
# 字段解析失败不 fatal(不注册该类,留给源模块编译注册,后续裸类名引用由调用侧 fail-fast 暴露)。
|
||||
# ============================================================
|
||||
def _inject_class_struct_declare(pool: memhub.MemBuddy*,
|
||||
mod: mlirlite.LLVMModule*,
|
||||
class_cd: ast.ClassDef*,
|
||||
cls_name: str,
|
||||
trans: HT.Translator*,
|
||||
src_sha1: str,
|
||||
imported_modules: str,
|
||||
from_imports: str,
|
||||
name_prefix: str = None) -> int:
|
||||
def _inject_class_struct_declare(pool: memhub.MemBuddy*, mod: mlirlite.LLVMModule*, class_cd: ast.ClassDef*, cls_name: str, trans: HT.Translator*, src_sha1: str, imported_modules: str, from_imports: str, name_prefix: str = None) -> int:
|
||||
"""从 vpi ClassDef 注册类为 struct 类型(含字段),使同 vpi 内裸类名注解可解析
|
||||
|
||||
name_prefix:非 None 表示"本类是 prefix 类的嵌套类",注册名取扁平名
|
||||
@@ -2496,8 +2407,7 @@ def _inject_class_struct_declare(pool: memhub.MemBuddy*,
|
||||
# 不登记(片段侧字段访问明确失败,绝不按错偏移静默访问)。
|
||||
# State=EMPTY 的类(无父类/无虚表/字段类型不可解析)不在此列,仍走下方既有口径。
|
||||
if ReplStubLayoutMode != 0:
|
||||
se: rawptr[ReplStubClass] = _repl_stub_find(
|
||||
_repl_stub_key(pool, src_sha1, real_name))
|
||||
se: rawptr[ReplStubClass] = _repl_stub_find(_repl_stub_key(pool, src_sha1, real_name))
|
||||
if se is not None and se.State != _REPL_SS_EMPTY:
|
||||
if se.State == _REPL_SS_PENDING: _repl_stub_try(se, mod)
|
||||
if se.State == _REPL_SS_OK: GenApi.add_visible_struct(pool, real_name)
|
||||
@@ -2540,8 +2450,7 @@ def _inject_class_struct_declare(pool: memhub.MemBuddy*,
|
||||
# (ClassGenDef._translate_nested_classdefs)⇒ 此处按同一命名**先**递归登记。
|
||||
# 必须早于下方字段注解解析:外层字段可能写成 `外类.内类`,只有扁平名条目已在
|
||||
# 结构体表里,TypeGenResolve._resolve_nested_class_type 才解析得出类型。
|
||||
_inject_nested_class_declares(pool, mod, class_cd, real_name, trans,
|
||||
src_sha1, imported_modules, from_imports)
|
||||
_inject_nested_class_declares(pool, mod, class_cd, real_name, trans, src_sha1, imported_modules, from_imports)
|
||||
# 还原"正在定义类"窗口:嵌套递归内的 mark_module_class 会把 CurDefClassName 改成
|
||||
# 嵌套类名(A_B)。不还原会让外层字段注解的规则 5.5 自引用证据判错(裸类名票名冻结
|
||||
# 成裸名版本、与定义侧带前缀形式分裂),也会让 `外类.内类` 的守卫①(CurDefClassName
|
||||
@@ -2566,8 +2475,7 @@ def _inject_class_struct_declare(pool: memhub.MemBuddy*,
|
||||
if m_aa_c.target.kind() != ast.ASTKind.Name: continue
|
||||
m_tgt_c: ast.Name* = ast.Name*(m_aa_c.target)
|
||||
if m_tgt_c.id is None: continue
|
||||
field_ty_c: mlirlite.LLVMType* = GenApi.resolve_annotation_type(
|
||||
pool, m_aa_c.annotation, imported_modules, from_imports, trans, 0)
|
||||
field_ty_c: mlirlite.LLVMType* = GenApi.resolve_annotation_type(pool, m_aa_c.annotation, imported_modules, from_imports, trans, 0)
|
||||
if field_ty_c is None:
|
||||
# 字段类型解析失败:不注册该类(留给源模块编译注册),不 fatal
|
||||
return 0
|
||||
@@ -2607,14 +2515,12 @@ def _inject_class_struct_declare(pool: memhub.MemBuddy*,
|
||||
name_buf_c[sh_len_c] = '.'
|
||||
string.strcpy(name_buf_c + sh_len_c + 1, real_name)
|
||||
type_name_c = name_buf_c
|
||||
struct_ty_c: mlirlite.LLVMType* = mlirlite.Struct(
|
||||
pool, first_node_c, field_count, type_name_c)
|
||||
struct_ty_c: mlirlite.LLVMType* = mlirlite.Struct(pool, first_node_c, field_count, type_name_c)
|
||||
if struct_ty_c is None: return 0
|
||||
# 5. StdlibAlloc(Phase B)时深拷贝到 perm_pool,跨文件 reset 存活
|
||||
# (对齐 ClassGenDef.translate_class_def L489-494)
|
||||
if GenApi.get_stdlib_alloc() != 0:
|
||||
st_copy_c: mlirlite.LLVMType* = mlirlite.DeepCopyType(
|
||||
CompilerFactory.factory.PermPool, struct_ty_c)
|
||||
st_copy_c: mlirlite.LLVMType* = mlirlite.DeepCopyType(CompilerFactory.factory.PermPool, struct_ty_c)
|
||||
if st_copy_c is not None: struct_ty_c = st_copy_c
|
||||
# 5.5 前向声明占位命中 ⇒ **占位 Ty 原地写入**(与 ClassGenDef.translate_class_def
|
||||
# 的 fill_fwd 段逐句同款):给已存在的类型对象 `*existing.Ty` 赋入刚构建的
|
||||
@@ -2640,8 +2546,7 @@ def _inject_class_struct_declare(pool: memhub.MemBuddy*,
|
||||
if _vpi_class_has_packed(class_cd.decorator_list) != 0: mlirlite.module_set_named_type_packed(mod, pool, struct_ty_c, 1)
|
||||
# 注册名用扁平名 real_name:跨模块引用 `外类.内类` 时 TypeGenResolve 查的是
|
||||
# 扁平名条目(与定义端 StructGen 的登记名同源)。
|
||||
entry_c: GenTypes.StructEntry* = GenApi.register_struct(
|
||||
pool, real_name, struct_ty_c, src_sha1)
|
||||
entry_c: GenTypes.StructEntry* = GenApi.register_struct(pool, real_name, struct_ty_c, src_sha1)
|
||||
if entry_c is None: return 0
|
||||
# B5:vpi 注入注册的 entry 同步 IsPacked——后续跨模块 stub 注入
|
||||
# (ensure_struct_def_in_module)按 entry.IsPacked 判定 packed,否则读 0
|
||||
@@ -2674,14 +2579,7 @@ def _inject_class_struct_declare(pool: memhub.MemBuddy*,
|
||||
# mark_module_class 窗口留在嵌套类上;故外层调用点在其后**再调一次**
|
||||
# mark_module_class 还原(见 _inject_class_struct_declare 内注释)。
|
||||
# ============================================================
|
||||
def _inject_nested_class_declares(pool: memhub.MemBuddy*,
|
||||
mod: mlirlite.LLVMModule*,
|
||||
class_cd: ast.ClassDef*,
|
||||
prefix_name: str,
|
||||
trans: HT.Translator*,
|
||||
src_sha1: str,
|
||||
imported_modules: str,
|
||||
from_imports: str) -> None:
|
||||
def _inject_nested_class_declares(pool: memhub.MemBuddy*, mod: mlirlite.LLVMModule*, class_cd: ast.ClassDef*, prefix_name: str, trans: HT.Translator*, src_sha1: str, imported_modules: str, from_imports: str) -> None:
|
||||
"""递归登记 class_cd 的所有嵌套 ClassDef 为扁平名类型(前缀 = prefix_name)"""
|
||||
if pool is None or mod is None or class_cd is None or prefix_name is None: return
|
||||
children: list[ast.AST*]* = class_cd.children
|
||||
@@ -2693,9 +2591,7 @@ def _inject_nested_class_declares(pool: memhub.MemBuddy*,
|
||||
if child_ast.kind() != ast.ASTKind.ClassDef: continue
|
||||
child_cd: ast.ClassDef* = ast.ClassDef*(child_ast)
|
||||
if child_cd is None or child_cd.name is None or child_cd.name[0] == '\0': continue
|
||||
_inject_class_struct_declare(pool, mod, child_cd, child_cd.name, trans,
|
||||
src_sha1, imported_modules, from_imports,
|
||||
prefix_name)
|
||||
_inject_class_struct_declare(pool, mod, child_cd, child_cd.name, trans, src_sha1, imported_modules, from_imports, prefix_name)
|
||||
|
||||
|
||||
# ============================================================
|
||||
@@ -2705,9 +2601,7 @@ def _inject_nested_class_declares(pool: memhub.MemBuddy*,
|
||||
# 均报 "use of undefined type"(值类型大小需已知)。vpi 注入类已 add_field 含字段(完整 Ty),在注册表可查时注册完整定义;
|
||||
# 指针引用(Ptr(Struct))无需——_scan_type_for_cross_module_refs 的 Ptr 分支添加 opaque 即可。
|
||||
# ============================================================
|
||||
def _ensure_full_value_types(mod: mlirlite.LLVMModule*,
|
||||
pool: memhub.MemBuddy*,
|
||||
ty: mlirlite.LLVMType*) -> None:
|
||||
def _ensure_full_value_types(mod: mlirlite.LLVMModule*, pool: memhub.MemBuddy*, ty: mlirlite.LLVMType*) -> None:
|
||||
"""递归为值 struct / 数组元素 struct 注册完整定义(递归深度守卫)"""
|
||||
if mod is None or pool is None or ty is None: return
|
||||
match ty:
|
||||
@@ -2740,10 +2634,7 @@ def _ensure_full_value_types(mod: mlirlite.LLVMModule*,
|
||||
# Windows x64 ABI 小结构体(≤8 字节)按整数寄存器传、位兼容,且与定义侧同样降级 ⇒ 同符号签名仍逐字一致)。
|
||||
# * TPV 内部函数/方法(存在 define 侧)→ Ptr(struct):与定义侧逐字一致,指针目标只需 opaque 声明(module_ensure_opaque_for_type)。
|
||||
# ============================================================
|
||||
def _AggregateParamTy(mod: mlirlite.LLVMModule*,
|
||||
pool: memhub.MemBuddy*,
|
||||
ty: mlirlite.LLVMType*,
|
||||
is_c_abi: int) -> mlirlite.LLVMType*:
|
||||
def _AggregateParamTy(mod: mlirlite.LLVMModule*, pool: memhub.MemBuddy*, ty: mlirlite.LLVMType*, is_c_abi: int) -> mlirlite.LLVMType*:
|
||||
"""裸结构体形参类型(C ABI 按值 / 内部 Ptr(struct),见上方注释)"""
|
||||
if mod is None or pool is None or ty is None: return ty
|
||||
if is_c_abi != 0:
|
||||
@@ -2769,15 +2660,7 @@ def _AggregateParamTy(mod: mlirlite.LLVMModule*,
|
||||
# vpi 里模块级全局变量(如 tokens.vp 的 _op_head: OpEntry* = None)需在当前模块创建 external global 声明(短名 @name,COFF 按名链接),
|
||||
# 否则跨模块 from-import 读取全局变量时 find_global_in_module 找不到 → 误杀「跨模块全局变量类型未知(stub 未注入)」。
|
||||
# ============================================================
|
||||
def _inject_global_variable_declare(pool: memhub.MemBuddy*,
|
||||
mod: mlirlite.LLVMModule*,
|
||||
aa: ast.AnnAssign*,
|
||||
trans: HT.Translator*,
|
||||
imported_modules: str,
|
||||
from_imports: str,
|
||||
i32_ty: mlirlite.LLVMType*,
|
||||
i8_ptr_ty: mlirlite.LLVMType*,
|
||||
src_sha1: str) -> None:
|
||||
def _inject_global_variable_declare(pool: memhub.MemBuddy*, mod: mlirlite.LLVMModule*, aa: ast.AnnAssign*, trans: HT.Translator*, imported_modules: str, from_imports: str, i32_ty: mlirlite.LLVMType*, i8_ptr_ty: mlirlite.LLVMType*, src_sha1: str) -> None:
|
||||
"""从 vpi AnnAssign 创建模块级全局变量 external declare(mangled 名 @<src_sha1>.<name>)"""
|
||||
if pool is None or mod is None or aa is None or trans is None: return
|
||||
tgt_v: ast.AST* = aa.target
|
||||
@@ -2818,8 +2701,7 @@ def _inject_global_variable_declare(pool: memhub.MemBuddy*,
|
||||
# 解析注解类型(裸类 → Ptr(struct),CArray → 元素指针)
|
||||
resolved_v: mlirlite.LLVMType* = None
|
||||
if aa.annotation is not None:
|
||||
resolved_v = GenApi.resolve_annotation_type(
|
||||
pool, aa.annotation, imported_modules, from_imports, trans)
|
||||
resolved_v = GenApi.resolve_annotation_type(pool, aa.annotation, imported_modules, from_imports, trans)
|
||||
if resolved_v is None:
|
||||
return # 类型解析失败跳过:调用侧有 fail-fast 定位
|
||||
gv_ty_v: mlirlite.LLVMType* = resolved_v
|
||||
@@ -2863,17 +2745,7 @@ def _inject_global_variable_declare(pool: memhub.MemBuddy*,
|
||||
# 用 find_func_in_module 去重,创建 declare 并添加参数,
|
||||
# 注册到函数表。
|
||||
# ============================================================
|
||||
def _inject_function_declare(pool: memhub.MemBuddy*,
|
||||
mod: mlirlite.LLVMModule*,
|
||||
fd: ast.FunctionDef*,
|
||||
trans: HT.Translator*,
|
||||
src_sha1: str,
|
||||
imported_modules: str,
|
||||
from_imports: str,
|
||||
i32_ty: mlirlite.LLVMType*,
|
||||
i8_ptr_ty: mlirlite.LLVMType*,
|
||||
funcs_ptr: GenTypes.FuncEntry*,
|
||||
max_funcs: int) -> None:
|
||||
def _inject_function_declare(pool: memhub.MemBuddy*, mod: mlirlite.LLVMModule*, fd: ast.FunctionDef*, trans: HT.Translator*, src_sha1: str, imported_modules: str, from_imports: str, i32_ty: mlirlite.LLVMType*, i8_ptr_ty: mlirlite.LLVMType*, funcs_ptr: GenTypes.FuncEntry*, max_funcs: int) -> None:
|
||||
"""为 FunctionDef 创建 declare 声明并注入到模块"""
|
||||
if fd.name is None: return
|
||||
|
||||
@@ -2938,8 +2810,7 @@ def _inject_function_declare(pool: memhub.MemBuddy*,
|
||||
ret_annot_fd: str = _lookup_vpi_ret_annot(src_sha1, None, fd.name)
|
||||
if ret_annot_fd is not None: ret_ty = _resolve_vpi_ret_annot_str(pool, ret_annot_fd, i32_ty, i8_ptr_ty)
|
||||
if ret_ty is None and fd.returns is not None:
|
||||
ret_ty = GenApi.resolve_annotation_type(
|
||||
pool, fd.returns, imported_modules, from_imports, trans)
|
||||
ret_ty = GenApi.resolve_annotation_type(pool, fd.returns, imported_modules, from_imports, trans)
|
||||
# 如果返回类型是纯 t.State(无实际类型),用 Void
|
||||
if ret_ty is None and fd.returns is not None:
|
||||
# t.State/t.CExtern 是存储类装饰器标记,非真实返回类型。
|
||||
@@ -2952,9 +2823,7 @@ def _inject_function_declare(pool: memhub.MemBuddy*,
|
||||
if rk2_rt == ast.ASTKind.Name or rk2_rt == ast.ASTKind.Constant: is_pure_marker_rt = 1
|
||||
elif rk2_rt == ast.ASTKind.Attribute:
|
||||
pm_at: ast.Attribute* = ast.Attribute*(fd.returns)
|
||||
if pm_at.attr is not None and (string.strcmp(pm_at.attr, "State") == 0
|
||||
or string.strcmp(pm_at.attr, "CExtern") == 0
|
||||
or string.strcmp(pm_at.attr, "CExport") == 0):
|
||||
if pm_at.attr is not None and (string.strcmp(pm_at.attr, "State") == 0 or string.strcmp(pm_at.attr, "CExtern") == 0 or string.strcmp(pm_at.attr, "CExport") == 0):
|
||||
is_pure_marker_rt = 1
|
||||
if is_pure_marker_rt != 0: ret_ty = mlirlite.Void(pool)
|
||||
elif has_state != 0 or has_extern != 0 or has_export != 0:
|
||||
@@ -2965,9 +2834,7 @@ def _inject_function_declare(pool: memhub.MemBuddy*,
|
||||
# [S4 fail-fast] 有返回注解却解析不出类型 → 不再静默退 i32;
|
||||
# 无注解(fd.returns is None)是合法默认,保持下方 i32。
|
||||
if ret_ty is None and fd.returns is not None:
|
||||
GenApi.fatal_error(
|
||||
fd.returns, f"extern 声明 '{fd.name}' 返回类型注解解析失败",
|
||||
"NameError")
|
||||
GenApi.fatal_error(fd.returns, f"extern 声明 '{fd.name}' 返回类型注解解析失败", "NameError")
|
||||
# 默认返回 i32
|
||||
if ret_ty is None: ret_ty = i32_ty
|
||||
|
||||
@@ -2977,8 +2844,7 @@ def _inject_function_declare(pool: memhub.MemBuddy*,
|
||||
mlirlite.module_ensure_opaque_for_type(mod, pool, ret_ty)
|
||||
|
||||
# 创建 declare
|
||||
func: mlirlite.Function* = mlirlite.create_declare(
|
||||
pool, mod, mangled_name, ret_ty)
|
||||
func: mlirlite.Function* = mlirlite.create_declare(pool, mod, mangled_name, ret_ty)
|
||||
if func is None: return
|
||||
|
||||
# 提取参数并添加到 declare
|
||||
@@ -2995,9 +2861,7 @@ def _inject_function_declare(pool: memhub.MemBuddy*,
|
||||
# 返回垃圾大数 → for 循环 add_param 海量次 → Params 链超长,
|
||||
# dump 时步数哨兵误报"链表成环"。超限立即报错定位。
|
||||
if param_count < 0 or param_count > 128:
|
||||
stdio.printf(
|
||||
"[VPIS] 参数数异常: 函数名=%s param_count=%d(fd.args=%llu,tree 可能被覆盖,终止)\n",
|
||||
fd.name, param_count, uint64(fd.args))
|
||||
stdio.printf("[VPIS] 参数数异常: 函数名=%s param_count=%d(fd.args=%llu,tree 可能被覆盖,终止)\n", fd.name, param_count, uint64(fd.args))
|
||||
# 终止点收敛:REPL 会话内 longjmp 回 REPL 循环(诊断已打印)
|
||||
VLogger.repl_abort()
|
||||
pi: sizet
|
||||
@@ -3013,8 +2877,7 @@ def _inject_function_declare(pool: memhub.MemBuddy*,
|
||||
# sizet→i32,跨模块 declare 参数宽错 → 调用侧 trunc 传参、
|
||||
# callee 按宽类型读栈残留垃圾高位 → 参数巨值崩溃(SlotsBugTest
|
||||
# 根因)。段索引 = pi(模块级函数无 self,0=首参)。
|
||||
pseg_ty: mlirlite.LLVMType* = _resolve_vpi_param_annot_seg(
|
||||
pool, src_sha1, None, fd.name, pi, i32_ty, i8_ptr_ty)
|
||||
pseg_ty: mlirlite.LLVMType* = _resolve_vpi_param_annot_seg(pool, src_sha1, None, fd.name, pi, i32_ty, i8_ptr_ty)
|
||||
if pseg_ty is not None:
|
||||
match pseg_ty:
|
||||
case mlirlite.LLVMType.Struct(_, _, _):
|
||||
@@ -3026,8 +2889,7 @@ def _inject_function_declare(pool: memhub.MemBuddy*,
|
||||
case _:
|
||||
param_ty = pseg_ty
|
||||
elif ag.annotation is not None:
|
||||
resolved_ty: mlirlite.LLVMType* = GenApi.resolve_annotation_type(
|
||||
pool, ag.annotation, imported_modules, from_imports, trans)
|
||||
resolved_ty: mlirlite.LLVMType* = GenApi.resolve_annotation_type(pool, ag.annotation, imported_modules, from_imports, trans)
|
||||
if resolved_ty is not None:
|
||||
# CArray 参数 → 元素指针 ty*(C 数组衰减,与编译侧一致)。
|
||||
# 裸结构体参数 → _AggregateParamTy(同一判据)。
|
||||
@@ -3041,16 +2903,12 @@ def _inject_function_declare(pool: memhub.MemBuddy*,
|
||||
else:
|
||||
# [S4 fail-fast] 有注解却解析不出类型 → 不再静默退 i8*
|
||||
# (无注解 ag.annotation is None 是合法默认,保持 i8*)
|
||||
GenApi.fatal_error(
|
||||
ag.annotation,
|
||||
f"extern 声明 '{fd.name}' 形参 '{pname}' 类型注解解析失败",
|
||||
"NameError")
|
||||
GenApi.fatal_error(ag.annotation, f"extern 声明 '{fd.name}' 形参 '{pname}' 类型注解解析失败", "NameError")
|
||||
mlirlite.add_param(pool, func, param_ty, pname)
|
||||
# 文本缓存校验/修复:vpi tree args 可能被覆盖损坏(尾部默认参数丢失)
|
||||
# → declare 参数数不足 → 调用点缺参 → 被调函数读栈垃圾。用 vpi 文本
|
||||
# 缓存的参数注解补全 declare 参数(与 define 参数数一致)。
|
||||
param_count = _repair_declare_params_from_text(
|
||||
pool, func, src_sha1, None, fd.name, param_count, i32_ty, i8_ptr_ty)
|
||||
param_count = _repair_declare_params_from_text(pool, func, src_sha1, None, fd.name, param_count, i32_ty, i8_ptr_ty)
|
||||
# *args 变长参数:标记 IsVarArg=1,使调用侧走 C ABI 参数提升
|
||||
# (i8/i16 → i32,float → double),避免 %d/%x 等格式因参数按 i64
|
||||
# 传递而读错(第二个 %x 读到第一个 i64 槽的高 4 字节)。
|
||||
@@ -3067,9 +2925,7 @@ def _inject_function_declare(pool: memhub.MemBuddy*,
|
||||
# 越界写 perm_pool(覆盖当前模块 AST/表,SlotsBugTest 崩溃根因
|
||||
# 候选)。与 param_count 哨兵(L1493-1497)对齐:垃圾值放弃
|
||||
# 注册默认值(跨模块缺参调用走零值兜底),阻断越界写。
|
||||
stdio.printf(
|
||||
"[VPIS] 默认参数数异常: 函数名=%s default_count=%d(tree 可能被覆盖,跳过默认值注册)\n",
|
||||
fd.name, fd_default_count)
|
||||
stdio.printf("[VPIS] 默认参数数异常: 函数名=%s default_count=%d(tree 可能被覆盖,跳过默认值注册)\n", fd.name, fd_default_count)
|
||||
fd_defaults = None
|
||||
fd_default_count = 0
|
||||
else: fd_defaults = fd_dlist
|
||||
@@ -3077,8 +2933,7 @@ def _inject_function_declare(pool: memhub.MemBuddy*,
|
||||
# 注册到函数表(用裸名 fd.name,不是 mangled_name)
|
||||
if funcs_ptr is not None:
|
||||
cur_count: int = trans._func_count
|
||||
if GenApi.add_func_to_table(funcs_ptr, cur_count, fd.name, func, max_funcs,
|
||||
fd_defaults, fd_default_count, param_count, None, src_sha1) == 0:
|
||||
if GenApi.add_func_to_table(funcs_ptr, cur_count, fd.name, func, max_funcs, fd_defaults, fd_default_count, param_count, None, src_sha1) == 0:
|
||||
trans._func_count = cur_count + 1
|
||||
# 补全全局函数表 Spec(参数已全部添加,对齐 FuncGenDef 行为):
|
||||
# vpi 注入路径若不补全,跨模块 vtable 生成 find_func_entry_global()
|
||||
@@ -3092,18 +2947,7 @@ def _inject_function_declare(pool: memhub.MemBuddy*,
|
||||
# 方法混淆名 {src_sha1}.{ClassName}.{method};参数类型从 vpi 注解解析(self 无注解时默认为 i8*)。
|
||||
# 注入正确签名可避免调用时 _ensure_method_declare 用实参类型创建错误 declare(如 size: sizet 被写成 i32 而非 i64)。
|
||||
# ============================================================
|
||||
def _inject_method_declare(pool: memhub.MemBuddy*,
|
||||
mod: mlirlite.LLVMModule*,
|
||||
m_fd: ast.FunctionDef*,
|
||||
cls_name: str,
|
||||
trans: HT.Translator*,
|
||||
src_sha1: str,
|
||||
imported_modules: str,
|
||||
from_imports: str,
|
||||
i32_ty: mlirlite.LLVMType*,
|
||||
i8_ptr_ty: mlirlite.LLVMType*,
|
||||
funcs_ptr: GenTypes.FuncEntry*,
|
||||
max_funcs: int) -> None:
|
||||
def _inject_method_declare(pool: memhub.MemBuddy*, mod: mlirlite.LLVMModule*, m_fd: ast.FunctionDef*, cls_name: str, trans: HT.Translator*, src_sha1: str, imported_modules: str, from_imports: str, i32_ty: mlirlite.LLVMType*, i8_ptr_ty: mlirlite.LLVMType*, funcs_ptr: GenTypes.FuncEntry*, max_funcs: int) -> None:
|
||||
"""为 ClassDef 内方法创建 declare 声明并注入到模块"""
|
||||
if m_fd is None or m_fd.name is None or cls_name is None: return
|
||||
if src_sha1 is None: return
|
||||
@@ -3141,8 +2985,7 @@ def _inject_method_declare(pool: memhub.MemBuddy*,
|
||||
ret_annot: str = _lookup_vpi_ret_annot(src_sha1, cls_name, m_fd.name)
|
||||
if ret_annot is not None: ret_ty = _resolve_vpi_ret_annot_str(pool, ret_annot, i32_ty, i8_ptr_ty)
|
||||
if ret_ty is None and m_fd.returns is not None:
|
||||
ret_ty = GenApi.resolve_annotation_type(
|
||||
pool, m_fd.returns, imported_modules, from_imports, trans)
|
||||
ret_ty = GenApi.resolve_annotation_type(pool, m_fd.returns, imported_modules, from_imports, trans)
|
||||
# __new__ 无返回注解时推断为类指针(__new__ 返回 self 指针,默认 i32 会截断指针)
|
||||
if ret_ty is None and string.strcmp(m_fd.name, "__new__") == 0:
|
||||
cls_ty: mlirlite.LLVMType* = GenApi.get_struct_type(cls_name)
|
||||
@@ -3150,10 +2993,7 @@ def _inject_method_declare(pool: memhub.MemBuddy*,
|
||||
# [S4 fail-fast] 有返回注解却解析不出类型 → 不再静默退 i32;
|
||||
# __new__ 无注解、普通方法无注解均走下方 i32 合法默认。
|
||||
if ret_ty is None and m_fd.returns is not None:
|
||||
GenApi.fatal_error(
|
||||
m_fd.returns,
|
||||
f"extern 方法 '{cls_name}.{m_fd.name}' 返回类型注解解析失败",
|
||||
"NameError")
|
||||
GenApi.fatal_error(m_fd.returns, f"extern 方法 '{cls_name}.{m_fd.name}' 返回类型注解解析失败", "NameError")
|
||||
# __init__ 无返回注解 → 与定义端一致取 Void(定义端
|
||||
# ClassGenVTable._translate_method 对 __init__ 恒 Void)。若按"普通方法无注解"
|
||||
# 退成下方 i32 默认,就会出现 declare i32 / define void 的返回类型分裂:
|
||||
@@ -3162,8 +3002,7 @@ def _inject_method_declare(pool: memhub.MemBuddy*,
|
||||
if ret_ty is None: ret_ty = i32_ty
|
||||
|
||||
# 创建 declare
|
||||
func: mlirlite.Function* = mlirlite.create_declare(
|
||||
pool, mod, mangled_name, ret_ty)
|
||||
func: mlirlite.Function* = mlirlite.create_declare(pool, mod, mangled_name, ret_ty)
|
||||
if func is None: return
|
||||
|
||||
# 提取参数并添加到 declare
|
||||
@@ -3178,9 +3017,7 @@ def _inject_method_declare(pool: memhub.MemBuddy*,
|
||||
# 参数数上限哨兵(fail-fast):与 _inject_function_declare 同因
|
||||
# (vpi tree 深层节点被覆盖损坏时 __len__() 返回垃圾大数)。
|
||||
if param_count < 0 or param_count > 128:
|
||||
stdio.printf(
|
||||
"[VPIS] 参数数异常: 方法名=%s.%s param_count=%d(m_fd.args=%llu,tree 可能被覆盖,终止)\n",
|
||||
cls_name, m_fd.name, param_count, uint64(m_fd.args))
|
||||
stdio.printf("[VPIS] 参数数异常: 方法名=%s.%s param_count=%d(m_fd.args=%llu,tree 可能被覆盖,终止)\n", cls_name, m_fd.name, param_count, uint64(m_fd.args))
|
||||
# 终止点收敛:REPL 会话内 longjmp 回 REPL 循环(诊断已打印)
|
||||
VLogger.repl_abort()
|
||||
pi: sizet
|
||||
@@ -3194,8 +3031,7 @@ def _inject_method_declare(pool: memhub.MemBuddy*,
|
||||
# 签名一致,消除跨模块声明/定义歧义。调用侧按形参 coerce 自动
|
||||
# bitcast(见 _call_method_on_ptr/_translate_method_call 的 coerce
|
||||
# 块)。类类型未注册时兜底走下方注解解析/i8*(保持原行为)。
|
||||
if pi == 0 and (string.strcmp(pname, "self") == 0
|
||||
or string.strcmp(pname, "cls") == 0):
|
||||
if pi == 0 and (string.strcmp(pname, "self") == 0 or string.strcmp(pname, "cls") == 0):
|
||||
cls_ty_sd: mlirlite.LLVMType* = GenApi.get_struct_type(cls_name)
|
||||
if cls_ty_sd is not None:
|
||||
mlirlite.add_param(pool, func, mlirlite.Ptr(pool, cls_ty_sd), pname)
|
||||
@@ -3206,8 +3042,7 @@ def _inject_method_declare(pool: memhub.MemBuddy*,
|
||||
# sizet→i32,declare 参数宽错 → 调用侧 trunc i64→i32 传参、
|
||||
# callee 按 i64 读栈残留垃圾高位 → can=巨值读未写槽位崩溃,
|
||||
# SlotsBugTest 根因)。段索引 = pi(0=self 空段)。
|
||||
pseg_ty: mlirlite.LLVMType* = _resolve_vpi_param_annot_seg(
|
||||
pool, src_sha1, cls_name, m_fd.name, pi, i32_ty, i8_ptr_ty)
|
||||
pseg_ty: mlirlite.LLVMType* = _resolve_vpi_param_annot_seg(pool, src_sha1, cls_name, m_fd.name, pi, i32_ty, i8_ptr_ty)
|
||||
if pseg_ty is not None:
|
||||
match pseg_ty:
|
||||
case mlirlite.LLVMType.Struct(_, _, _):
|
||||
@@ -3221,8 +3056,7 @@ def _inject_method_declare(pool: memhub.MemBuddy*,
|
||||
case _:
|
||||
param_ty = pseg_ty
|
||||
elif ag.annotation is not None:
|
||||
resolved_ty: mlirlite.LLVMType* = GenApi.resolve_annotation_type(
|
||||
pool, ag.annotation, imported_modules, from_imports, trans)
|
||||
resolved_ty: mlirlite.LLVMType* = GenApi.resolve_annotation_type(pool, ag.annotation, imported_modules, from_imports, trans)
|
||||
if resolved_ty is not None:
|
||||
# CArray 参数 → 元素指针 ty*(C 数组衰减,与编译侧一致)。
|
||||
# 裸结构体参数 → _AggregateParamTy(同一判据,is_c_abi=0)。
|
||||
@@ -3236,18 +3070,14 @@ def _inject_method_declare(pool: memhub.MemBuddy*,
|
||||
else:
|
||||
# [S4 fail-fast] 有注解却解析不出类型 → 不再静默退 i8*
|
||||
# (无注解 ag.annotation is None 是合法默认,保持 i8*)
|
||||
GenApi.fatal_error(
|
||||
ag.annotation,
|
||||
f"extern 方法 '{cls_name}.{m_fd.name}' 形参 '{pname}' 类型注解解析失败",
|
||||
"NameError")
|
||||
GenApi.fatal_error(ag.annotation, f"extern 方法 '{cls_name}.{m_fd.name}' 形参 '{pname}' 类型注解解析失败", "NameError")
|
||||
mlirlite.add_param(pool, func, param_ty, pname)
|
||||
|
||||
# 文本缓存校验/修复:vpi tree args 可能被覆盖损坏(尾部默认参数丢失)
|
||||
# → declare 参数数不足 → 调用点缺参 → 被调函数读栈垃圾(跨模块 CDefine
|
||||
# 查找 depth=160 假递归根因)。用 vpi 文本缓存的参数注解补全 declare
|
||||
# 参数(与 define 参数数一致,调用点默认参数填充才能生效)。
|
||||
param_count = _repair_declare_params_from_text(
|
||||
pool, func, src_sha1, cls_name, m_fd.name, param_count, i32_ty, i8_ptr_ty)
|
||||
param_count = _repair_declare_params_from_text(pool, func, src_sha1, cls_name, m_fd.name, param_count, i32_ty, i8_ptr_ty)
|
||||
|
||||
# OOP iter 协议:__next__ 方法 stub 声明带隐藏 __stop_iter_flag__(i1*),
|
||||
# 与 _translate_method 的 define 签名一致(对齐 TPC HandlesFunctions.py
|
||||
@@ -3268,9 +3098,7 @@ def _inject_method_declare(pool: memhub.MemBuddy*,
|
||||
if md_default_count < 0 or md_default_count > 128:
|
||||
# 同 _inject_function_declare:vpi tree 深层节点被覆盖时
|
||||
# defaults len 可能为垃圾大数 → 越界写 perm_pool。放弃注册。
|
||||
stdio.printf(
|
||||
"[VPIS] 默认参数数异常: 方法名=%s.%s default_count=%d(tree 可能被覆盖,跳过默认值注册)\n",
|
||||
cls_name, m_fd.name, md_default_count)
|
||||
stdio.printf("[VPIS] 默认参数数异常: 方法名=%s.%s default_count=%d(tree 可能被覆盖,跳过默认值注册)\n", cls_name, m_fd.name, md_default_count)
|
||||
md_defaults = None
|
||||
md_default_count = 0
|
||||
else: md_defaults = md_dlist
|
||||
@@ -3283,8 +3111,7 @@ def _inject_method_declare(pool: memhub.MemBuddy*,
|
||||
cur_count: int = trans._func_count
|
||||
param_count_no_self: int = param_count
|
||||
if param_count_no_self > 0: param_count_no_self -= 1
|
||||
if GenApi.add_func_to_table(funcs_ptr, cur_count, lookup_name, func, max_funcs,
|
||||
md_defaults, md_default_count, param_count_no_self, None, src_sha1) == 0:
|
||||
if GenApi.add_func_to_table(funcs_ptr, cur_count, lookup_name, func, max_funcs, md_defaults, md_default_count, param_count_no_self, None, src_sha1) == 0:
|
||||
trans._func_count = cur_count + 1
|
||||
# 补全全局函数表 Spec(参数已全部添加,对齐 ClassGenVTable 行为):
|
||||
# vpi 注入的方法声明若不补全 Spec,跨模块继承 vtable 生成时
|
||||
@@ -3299,8 +3126,7 @@ def _inject_method_declare(pool: memhub.MemBuddy*,
|
||||
# 提取 NAME: t.CTypedef = Type 中的名称和类型表达式字符串,
|
||||
# 调用 register_ctypedef 注册到动态 CTypedef 表。
|
||||
# ============================================================
|
||||
def _register_ctypedef_from_annassign(pool: memhub.MemBuddy*,
|
||||
aa: ast.AnnAssign*) -> None:
|
||||
def _register_ctypedef_from_annassign(pool: memhub.MemBuddy*, aa: ast.AnnAssign*) -> None:
|
||||
"""从 AnnAssign 节点提取并注册 CTypedef"""
|
||||
if aa is None or pool is None: return
|
||||
# 提取目标名称(必须是 Name 节点)
|
||||
@@ -3610,8 +3436,7 @@ def _repl_stub_deco_flags(deco_list: list[ast.AST*]*) -> int:
|
||||
return flags
|
||||
|
||||
|
||||
def _repl_stub_is_virtual(e: rawptr[ReplStubClass], mi: int,
|
||||
first: rawptr[ReplStubClass]) -> int:
|
||||
def _repl_stub_is_virtual(e: rawptr[ReplStubClass], mi: int, first: rawptr[ReplStubClass]) -> int:
|
||||
"""本类第 mi 个方法是否进虚表(转写 ClassGenBase._should_method_be_virtual)"""
|
||||
if e is None or e.MethodFlags is None or mi < 0 or mi >= e.MethodCount: return 0
|
||||
mf: int = int(e.MethodFlags[mi])
|
||||
@@ -3630,10 +3455,7 @@ def _repl_stub_warn_refuse(e: rawptr[ReplStubClass], why: str, a: int, b: int) -
|
||||
ReplStubRefused += 1
|
||||
if ReplStubWarnLeft <= 0: return
|
||||
ReplStubWarnLeft -= 1
|
||||
stdio.printf("includes 类布局: %s.%s 布局不可信 ⇒ 明确拒绝(原因=判据拒绝:%s;"
|
||||
"存根字段数=%d ≠ 展平字段数+虚表位=%d)。该类字段访问被明确拒绝"
|
||||
"(方法调用不受影响)\n",
|
||||
e.Sha1, e.ClassName, why, a, b)
|
||||
stdio.printf("includes 类布局: %s.%s 布局不可信 ⇒ 明确拒绝(原因=判据拒绝:%s;" "存根字段数=%d ≠ 展平字段数+虚表位=%d)。该类字段访问被明确拒绝" "(方法调用不受影响)\n", e.Sha1, e.ClassName, why, a, b)
|
||||
|
||||
|
||||
def _repl_stub_warn_nodata(e: rawptr[ReplStubClass], cause: int) -> None:
|
||||
@@ -3655,25 +3477,13 @@ def _repl_stub_warn_nodata(e: rawptr[ReplStubClass], cause: int) -> None:
|
||||
ReplStubWarnLeft -= 1
|
||||
if cause == _REPL_SU_NOSTUB:
|
||||
# 数据缺失:连模块布局元数据都没有(LayoutCount = -1 只是"没读到"的哨兵)
|
||||
stdio.printf("includes 类布局: %s.%s 布局不可用 ⇒ 明确拒绝(原因=『数据缺失』:"
|
||||
"模块 %s 没有 {sha1}.meta 布局元数据;meta 字段数=无 / 推断字段数=未计算 ⇒ "
|
||||
"两侧都没数据,『未做比较』,不是字段数不符)。该类字段访问被"
|
||||
"拒绝(方法调用不受影响);补上该模块 meta(同一工程先跑一次批处理,"
|
||||
"Phase A/B 会落盘 {sha1}.meta)后用同一 --project 重跑 REPL 即恢复\n",
|
||||
e.Sha1, e.ClassName, e.Sha1)
|
||||
stdio.printf("includes 类布局: %s.%s 布局不可用 ⇒ 明确拒绝(原因=『数据缺失』:" "模块 %s 没有 {sha1}.meta 布局元数据;meta 字段数=无 / 推断字段数=未计算 ⇒ " "两侧都没数据,『未做比较』,不是字段数不符)。该类字段访问被" "拒绝(方法调用不受影响);补上该模块 meta(同一工程先跑一次批处理," "Phase A/B 会落盘 {sha1}.meta)后用同一 --project 重跑 REPL 即恢复\n", e.Sha1, e.ClassName, e.Sha1)
|
||||
elif cause == _REPL_SU_OPAQUE:
|
||||
# 判据拒绝:meta 里该 key 是 OPAQUE(无 body ⇒ 无字段数可比)
|
||||
stdio.printf("includes 类布局: %s.%s 布局不可用 ⇒ 明确拒绝(原因=『判据拒绝』:"
|
||||
"meta %s.meta 里键 %s 为 OPAQUE 声明(无 body);meta 字段数=不可得 / "
|
||||
"推断字段数=未计算 ⇒ 『未做比较』)。该类字段访问被拒绝"
|
||||
"(方法调用不受影响)\n", e.Sha1, e.ClassName, e.Sha1, e.Key)
|
||||
stdio.printf("includes 类布局: %s.%s 布局不可用 ⇒ 明确拒绝(原因=『判据拒绝』:" "meta %s.meta 里键 %s 为 OPAQUE 声明(无 body);meta 字段数=不可得 / " "推断字段数=未计算 ⇒ 『未做比较』)。该类字段访问被拒绝" "(方法调用不受影响)\n", e.Sha1, e.ClassName, e.Sha1, e.Key)
|
||||
else:
|
||||
# 判据拒绝:meta 在,但没有该类的 STRUCT 行(LayoutCount = -1 只是"未找到"的哨兵)
|
||||
stdio.printf("includes 类布局: %s.%s 布局不可用 ⇒ 明确拒绝(原因=『判据拒绝』:"
|
||||
"meta %s.meta 存在但其中没有键 %s 的 `STRUCT … FIELDS n / OPAQUE` 记录;"
|
||||
"meta 字段数=未找到 / 推断字段数=未计算 ⇒ 『未做比较』)。该类字段访问"
|
||||
"被拒绝(方法调用不受影响);若该类确实定义于该模块,说明 meta 陈旧/"
|
||||
"不完整,请重建\n", e.Sha1, e.ClassName, e.Sha1, e.Key)
|
||||
stdio.printf("includes 类布局: %s.%s 布局不可用 ⇒ 明确拒绝(原因=『判据拒绝』:" "meta %s.meta 存在但其中没有键 %s 的 `STRUCT … FIELDS n / OPAQUE` 记录;" "meta 字段数=未找到 / 推断字段数=未计算 ⇒ 『未做比较』)。该类字段访问" "被拒绝(方法调用不受影响);若该类确实定义于该模块,说明 meta 陈旧/" "不完整,请重建\n", e.Sha1, e.ClassName, e.Sha1, e.Key)
|
||||
|
||||
|
||||
def _repl_stub_warn_parent(e: rawptr[ReplStubClass], detail: str, pname: str) -> None:
|
||||
@@ -3683,9 +3493,7 @@ def _repl_stub_warn_parent(e: rawptr[ReplStubClass], detail: str, pname: str) ->
|
||||
ReplStubRefusedParent += 1
|
||||
if ReplStubWarnLeft <= 0: return
|
||||
ReplStubWarnLeft -= 1
|
||||
stdio.printf("includes 类布局: %s.%s 布局不可用 ⇒ 明确拒绝(原因=『上游无数据』:%s,"
|
||||
"父类=%s;父类字段与虚表位无法展平 ⇒ 本类未做字段数比较)。该类字段访问"
|
||||
"被拒绝(方法调用不受影响)\n", e.Sha1, e.ClassName, detail, pname)
|
||||
stdio.printf("includes 类布局: %s.%s 布局不可用 ⇒ 明确拒绝(原因=『上游无数据』:%s," "父类=%s;父类字段与虚表位无法展平 ⇒ 本类未做字段数比较)。该类字段访问" "被拒绝(方法调用不受影响)\n", e.Sha1, e.ClassName, detail, pname)
|
||||
|
||||
|
||||
def _repl_stub_try(e: rawptr[ReplStubClass], mod: mlirlite.LLVMModule*) -> int:
|
||||
@@ -3714,8 +3522,7 @@ def _repl_stub_try(e: rawptr[ReplStubClass], mod: mlirlite.LLVMModule*) -> int:
|
||||
# ⇒ 展平出来的本类字段数不可用:既不比较(避免误报"字段数不符")、也不放行
|
||||
# (M4.2:布局不可信 ⇒ 明确拒绝)。
|
||||
e.State = _REPL_SS_REFUSED
|
||||
_repl_stub_warn_parent(e, "父类的字段类型未全部解析(其字段数不完整)",
|
||||
pe.ClassName)
|
||||
_repl_stub_warn_parent(e, "父类的字段类型未全部解析(其字段数不完整)", pe.ClassName)
|
||||
return -1
|
||||
first: rawptr[ReplStubClass] = None
|
||||
if e.BaseCount > 0: first = _repl_stub_find_base(e, 0)
|
||||
@@ -3788,9 +3595,7 @@ def _repl_stub_try(e: rawptr[ReplStubClass], mod: mlirlite.LLVMModule*) -> int:
|
||||
if vn == e.VtArity: e.VtTrust = 1
|
||||
elif ReplStubWarnLeft > 0:
|
||||
ReplStubWarnLeft -= 1
|
||||
stdio.printf("includes 类布局: %s.%s 的虚表槽数与存根不符(%d vs %d)"
|
||||
"——该类不做虚分派(退化为直接调用,会话继续)\n",
|
||||
e.Sha1, e.ClassName, vn, e.VtArity)
|
||||
stdio.printf("includes 类布局: %s.%s 的虚表槽数与存根不符(%d vs %d)" "——该类不做虚分派(退化为直接调用,会话继续)\n", e.Sha1, e.ClassName, vn, e.VtArity)
|
||||
# ⑥ 建 LLVM 结构体(命名 "%<sha1>.<类名>",与定义侧同口径)
|
||||
total: int = cn + hv
|
||||
i8_ptr: mlirlite.LLVMType* = mlirlite.Ptr(pool, mlirlite.Int8(pool))
|
||||
@@ -3818,8 +3623,7 @@ def _repl_stub_try(e: rawptr[ReplStubClass], mod: mlirlite.LLVMModule*) -> int:
|
||||
struct_ty: mlirlite.LLVMType* = mlirlite.Struct(pool, first_node, total, e.Key)
|
||||
if struct_ty is None: return 0
|
||||
# ⑦ 登记(StdlibAlloc=1 期间的注册走 PermPool,跨片段存活)
|
||||
entry: GenTypes.StructEntry* = GenApi.register_struct(
|
||||
pool, e.ClassName, struct_ty, e.Sha1)
|
||||
entry: GenTypes.StructEntry* = GenApi.register_struct(pool, e.ClassName, struct_ty, e.Sha1)
|
||||
if entry is None:
|
||||
e.State = _REPL_SS_REFUSED
|
||||
return -1
|
||||
@@ -3863,15 +3667,7 @@ def _repl_stub_try(e: rawptr[ReplStubClass], mod: mlirlite.LLVMModule*) -> int:
|
||||
return 1
|
||||
|
||||
|
||||
def _repl_stub_add_class(pool: memhub.MemBuddy*,
|
||||
mod: mlirlite.LLVMModule*,
|
||||
cd: ast.ClassDef*,
|
||||
sha1: str,
|
||||
txt: str,
|
||||
have_stub: int,
|
||||
trans: HT.Translator*,
|
||||
imported_modules: str,
|
||||
from_imports: str) -> int:
|
||||
def _repl_stub_add_class(pool: memhub.MemBuddy*, mod: mlirlite.LLVMModule*, cd: ast.ClassDef*, sha1: str, txt: str, have_stub: int, trans: HT.Translator*, imported_modules: str, from_imports: str) -> int:
|
||||
"""收集单个 vpi ClassDef 的布局要素并尝试登记(1=已登记/推迟处理,0=跳过)
|
||||
|
||||
have_stub:本模块是否读到了 {sha1}.meta 布局元数据(0 时本模块带父类/虚表的类按
|
||||
@@ -3918,8 +3714,7 @@ def _repl_stub_add_class(pool: memhub.MemBuddy*,
|
||||
bcnt: int = 0
|
||||
if pb is not None and GenApi._g_gen is not None:
|
||||
string.memset(pb, 0, 8 * GenTypes.PARENT_MAX)
|
||||
bcnt = GenApi._g_gen.ClassGenBase._collect_parents(
|
||||
pool, cd, pb, GenTypes.PARENT_MAX, trans)
|
||||
bcnt = GenApi._g_gen.ClassGenBase._collect_parents(pool, cd, pb, GenTypes.PARENT_MAX, trans)
|
||||
if bcnt > 0:
|
||||
if bcnt > _REPL_STUB_FIELD_MAX: bcnt = _REPL_STUB_FIELD_MAX
|
||||
bi: int
|
||||
@@ -3945,8 +3740,7 @@ def _repl_stub_add_class(pool: memhub.MemBuddy*,
|
||||
if aa2.target.kind() != ast.ASTKind.Name: continue
|
||||
tg: ast.Name* = ast.Name*(aa2.target)
|
||||
if tg.id is None or tg.id[0] == '\0': continue
|
||||
fty2: mlirlite.LLVMType* = GenApi.resolve_annotation_type(
|
||||
pool, aa2.annotation, imported_modules, from_imports, trans, 0)
|
||||
fty2: mlirlite.LLVMType* = GenApi.resolve_annotation_type(pool, aa2.annotation, imported_modules, from_imports, trans, 0)
|
||||
if fty2 is None:
|
||||
own_fail = 1
|
||||
continue
|
||||
@@ -4010,14 +3804,7 @@ def _repl_stub_add_class(pool: memhub.MemBuddy*,
|
||||
return 1
|
||||
|
||||
|
||||
def _repl_stub_collect_module(pool: memhub.MemBuddy*,
|
||||
mod: mlirlite.LLVMModule*,
|
||||
ch: list[ast.AST*]*,
|
||||
n: sizet,
|
||||
trans: HT.Translator*,
|
||||
src_sha1: str,
|
||||
imported_modules: str,
|
||||
from_imports: str) -> int:
|
||||
def _repl_stub_collect_module(pool: memhub.MemBuddy*, mod: mlirlite.LLVMModule*, ch: list[ast.AST*]*, n: sizet, trans: HT.Translator*, src_sha1: str, imported_modules: str, from_imports: str) -> int:
|
||||
"""(REPL)为当前模块的类收集布局要素 + 尝试登记;返回处理的类数"""
|
||||
global ReplStubNoStub, ReplStubWarnLeft
|
||||
if ReplStubLayoutMode == 0 or pool is None or ch is None: return 0
|
||||
@@ -4034,11 +3821,7 @@ def _repl_stub_collect_module(pool: memhub.MemBuddy*,
|
||||
ReplStubNoStub += 1
|
||||
if ReplStubWarnLeft > 0:
|
||||
ReplStubWarnLeft -= 1
|
||||
stdio.printf("includes 类布局: 模块 %s 无 .meta 存根(数据缺失)—— 该模块"
|
||||
"带父类/虚表的类将逐个按『数据缺失』明确拒绝(读不到布局元数据 ⇒ 无"
|
||||
"字段数可比,不是字段数不符)。用同一工程先跑一次批处理生成存根,"
|
||||
"再 `--project .\\project.vpj --repl`(TransPyV 目录)即可复用\n",
|
||||
src_sha1)
|
||||
stdio.printf("includes 类布局: 模块 %s 无 .meta 存根(数据缺失)—— 该模块" "带父类/虚表的类将逐个按『数据缺失』明确拒绝(读不到布局元数据 ⇒ 无" "字段数可比,不是字段数不符)。用同一工程先跑一次批处理生成存根," "再 `--project .\\project.vpj --repl`(TransPyV 目录)即可复用\n", src_sha1)
|
||||
cnt: int = 0
|
||||
i: sizet
|
||||
for i in range(n):
|
||||
@@ -4057,8 +3840,7 @@ def _repl_stub_collect_module(pool: memhub.MemBuddy*,
|
||||
continue
|
||||
# REnum 类:布局 {i32 tag, payload} 由 ClassGenEnum 计算,既有路径整体跳过
|
||||
if _vpi_class_is_renum(cd) != 0: continue
|
||||
if _repl_stub_add_class(pool, mod, cd, src_sha1, txt, have_stub, trans,
|
||||
imported_modules, from_imports) != 0:
|
||||
if _repl_stub_add_class(pool, mod, cd, src_sha1, txt, have_stub, trans, imported_modules, from_imports) != 0:
|
||||
cnt += 1
|
||||
if txt is not None: stdlib.free(txt)
|
||||
return cnt
|
||||
@@ -4092,30 +3874,14 @@ def ReplStubLayoutFinish() -> int:
|
||||
if peb is not None and peb.ClassName is not None: pbad = peb.ClassName
|
||||
break
|
||||
_repl_stub_warn_parent(e2, "父类未在会话注册或其布局被拒", pbad)
|
||||
stdio.printf("includes 类布局: 完整布局 %d 个(其中虚表索引可用 %d 个)/ "
|
||||
"被拒 %d 个 / 缺布局元数据模块 %d 个\n",
|
||||
ReplStubOk, ReplStubVtOk, ReplStubRefused, ReplStubNoStub)
|
||||
stdio.printf(" 拒绝原因分布(自证数据来源):数据缺失-模块无 {sha1}.meta %d 个类 / "
|
||||
"判据拒绝-meta 无此类 %d 个 / 判据拒绝-meta 为 opaque %d 个 / "
|
||||
"上游无数据-父类不可用 %d 个\n",
|
||||
ReplStubRefusedNoStub, ReplStubRefusedNoClass,
|
||||
ReplStubRefusedOpaque, ReplStubRefusedParent)
|
||||
stdio.printf("includes 类布局: 完整布局 %d 个(其中虚表索引可用 %d 个)/ " "被拒 %d 个 / 缺布局元数据模块 %d 个\n", ReplStubOk, ReplStubVtOk, ReplStubRefused, ReplStubNoStub)
|
||||
stdio.printf(" 拒绝原因分布(自证数据来源):数据缺失-模块无 {sha1}.meta %d 个类 / " "判据拒绝-meta 无此类 %d 个 / 判据拒绝-meta 为 opaque %d 个 / " "上游无数据-父类不可用 %d 个\n", ReplStubRefusedNoStub, ReplStubRefusedNoClass, ReplStubRefusedOpaque, ReplStubRefusedParent)
|
||||
if ReplStubRefused > 0 or ReplStubNoStub > 0:
|
||||
stdio.printf(" 说明:被拒类的字段访问会报『类未注册/属性访问失败』"
|
||||
"(不按错偏移静默访问);方法调用不受影响。\n")
|
||||
stdio.printf(" 说明:被拒类的字段访问会报『类未注册/属性访问失败』" "(不按错偏移静默访问);方法调用不受影响。\n")
|
||||
if ReplStubRefusedNoStub > 0:
|
||||
stdio.printf(" 其中『数据缺失』的 %d 个类只是没读到模块布局元数据(本会话临时目录 %s "
|
||||
"缺这些 {sha1}.meta):批处理才会落盘 meta(REPL 分支在 Phase1 之前"
|
||||
"返回,故 --repl 自身不生成存根)。修法:用同一个工程跑一次批处理"
|
||||
"(TransPyV 目录:.\\tpv_build\\output\\TransPyV.exe --project "
|
||||
".\\project.vpj;includes 有改动时加 --rebuild-includes),随后 "
|
||||
"--project .\\project.vpj --repl 复用其临时目录即可\n", ReplStubRefusedNoStub,
|
||||
ReplStubTempDir)
|
||||
stdio.printf(" 其中『数据缺失』的 %d 个类只是没读到模块布局元数据(本会话临时目录 %s " "缺这些 {sha1}.meta):批处理才会落盘 meta(REPL 分支在 Phase1 之前" "返回,故 --repl 自身不生成存根)。修法:用同一个工程跑一次批处理" "(TransPyV 目录:.\\tpv_build\\output\\TransPyV.exe --project " ".\\project.vpj;includes 有改动时加 --rebuild-includes),随后 " "--project .\\project.vpj --repl 复用其临时目录即可\n", ReplStubRefusedNoStub, ReplStubTempDir)
|
||||
if ReplStubRefusedNoClass + ReplStubRefusedOpaque > 0:
|
||||
stdio.printf(" 其中『判据拒绝』的 %d 个类:数据在但不可信(存根里没有该类的字段数、"
|
||||
"或其声明为 opaque),按 M4.2 一律不放行——请确认该类是否本应按结构体"
|
||||
"登记:应按结构体登记而存根里查不到 ⇒ 存根陈旧/不完整(重建 includes "
|
||||
"存根)\n", ReplStubRefusedNoClass + ReplStubRefusedOpaque)
|
||||
stdio.printf(" 其中『判据拒绝』的 %d 个类:数据在但不可信(存根里没有该类的字段数、" "或其声明为 opaque),按 M4.2 一律不放行——请确认该类是否本应按结构体" "登记:应按结构体登记而存根里查不到 ⇒ 存根陈旧/不完整(重建 includes " "存根)\n", ReplStubRefusedNoClass + ReplStubRefusedOpaque)
|
||||
return ReplStubOk
|
||||
|
||||
|
||||
|
||||
@@ -53,8 +53,7 @@ def _IsAppModule(mod_name: str) -> int:
|
||||
# Args: worklist 队列缓冲(原地修改);wl_len 当前长度(值);deps_str 要追加的模块名(空格分隔);processed 已处理集合(空格分隔,查重)
|
||||
# Returns: 追加后的新长度(>=0);溢出/参数错误返回 -1(调用方 fail-fast)
|
||||
# ============================================================
|
||||
def _AppendDepsToWorklist(worklist: bytes, wl_len: sizet,
|
||||
deps_str: str, processed: str) -> int:
|
||||
def _AppendDepsToWorklist(worklist: bytes, wl_len: sizet, deps_str: str, processed: str) -> int:
|
||||
if worklist is None or deps_str is None: return -1
|
||||
cur_len: sizet = wl_len
|
||||
dl: sizet = string.strlen(deps_str)
|
||||
@@ -103,11 +102,7 @@ def _AppendDepsToWorklist(worklist: bytes, wl_len: sizet,
|
||||
# Args: mb 内存池;source_dir App 源文件目录(Config.SourceDir);temp_dir 临时目录(deps.txt 所在位置);reachable_set 输出参数,可达 SHA1 集合缓冲区(MAX_INCLUDES_SHA1 * 17 字节);app_deps App 源文件直接依赖模块名(空格分隔),非空则跳过 App 扫描;includes_dirs includes 根目录(空格分隔)
|
||||
# Returns: 可达 SHA1 数量(>0 成功;0 无 includes 依赖;<0 失败)
|
||||
# ============================================================
|
||||
def _BuildReachableSha1Set(mb: memhub.MemBuddy*, source_dir: str,
|
||||
temp_dir: str,
|
||||
reachable_set: str,
|
||||
app_deps: str = None,
|
||||
includes_dirs: str = None) -> int:
|
||||
def _BuildReachableSha1Set(mb: memhub.MemBuddy*, source_dir: str, temp_dir: str, reachable_set: str, app_deps: str = None, includes_dirs: str = None) -> int:
|
||||
"""构建可达 SHA1 集合(依赖图按需扫描,App 优先)"""
|
||||
if source_dir is None or temp_dir is None or reachable_set is None: return -1
|
||||
if includes_dirs is None:
|
||||
@@ -241,8 +236,7 @@ def _BuildReachableSha1Set(mb: memhub.MemBuddy*, source_dir: str,
|
||||
tb_abs_slot[0] = 0
|
||||
tb_rel_slot[0] = 0
|
||||
tb_inc_slot[0] = 0
|
||||
tb_found = IncludesScanner.ResolveModuleToPath(
|
||||
includes_dirs, "traceback", tb_abs, tb_rel, tb_inc)
|
||||
tb_found = IncludesScanner.ResolveModuleToPath(includes_dirs, "traceback", tb_abs, tb_rel, tb_inc)
|
||||
if tb_abs is not None: stdlib.free(tb_abs)
|
||||
if tb_rel is not None: stdlib.free(tb_rel)
|
||||
if tb_inc is not None: stdlib.free(tb_inc)
|
||||
@@ -344,8 +338,7 @@ def _BuildReachableSha1Set(mb: memhub.MemBuddy*, source_dir: str,
|
||||
abs_slot[0] = 0
|
||||
rel_slot[0] = 0
|
||||
inc_slot[0] = 0
|
||||
rcode: int = IncludesScanner.ResolveModuleToPath(
|
||||
includes_dirs, mod_buf, out_abs, out_rel, out_inc)
|
||||
rcode: int = IncludesScanner.ResolveModuleToPath(includes_dirs, mod_buf, out_abs, out_rel, out_inc)
|
||||
if rcode != 0:
|
||||
# 内建模块(t/c/builtins 等内部库)或未找到:静默跳过
|
||||
stdlib.free(out_abs)
|
||||
@@ -542,8 +535,7 @@ def _BuildReachableSha1Set(mb: memhub.MemBuddy*, source_dir: str,
|
||||
# (类型定义 + external 声明 + 定义 + DI 一次齐全,类型定义天然在声明之前),
|
||||
# 无需再把 stub + 依赖 stub/text 文本合并。
|
||||
# ============================================================
|
||||
def LoadFullIR(temp_dir: str, sha1: str,
|
||||
out_buf: bytes, out_size: sizet) -> sizet:
|
||||
def LoadFullIR(temp_dir: str, sha1: str, out_buf: bytes, out_size: sizet) -> sizet:
|
||||
"""读取 {sha1}.full.ll 到 out_buf;返回长度(0=失败)"""
|
||||
if temp_dir is None or sha1 is None or out_buf is None or out_size == 0: return 0
|
||||
td_len: sizet = string.strlen(temp_dir)
|
||||
@@ -573,12 +565,7 @@ def LoadFullIR(temp_dir: str, sha1: str,
|
||||
# Args: pool 内存池;mod 当前 LLVM 模块;imported_modules 已导入模块名字符串(空格分隔);from_imports from-import 映射字符串("name:module name:module" 格式);temp_dir temp 目录路径;trans 翻译器对象
|
||||
# Returns: 成功加载的 .vpi 文件数
|
||||
# ============================================================
|
||||
def LoadDepVpiIntoModule(pool: memhub.MemBuddy*,
|
||||
mod: mlirlite.LLVMModule*,
|
||||
imported_modules: str,
|
||||
from_imports: str,
|
||||
temp_dir: str,
|
||||
trans: rawptr[HandlesTranslator.Translator]) -> int:
|
||||
def LoadDepVpiIntoModule(pool: memhub.MemBuddy*, mod: mlirlite.LLVMModule*, imported_modules: str, from_imports: str, temp_dir: str, trans: rawptr[HandlesTranslator.Translator]) -> int:
|
||||
"""加载依赖模块的 .vpi 文件,将函数声明注入到当前模块"""
|
||||
if pool is None or mod is None or temp_dir is None or trans is None: return 0
|
||||
if imported_modules is None: return 0
|
||||
|
||||
@@ -84,9 +84,7 @@ def _sliced_path(temp_dir: str, td_len: sizet, sha1: str, ext: str) -> str:
|
||||
# 数据来源是 PopulateSha1MapStore 填充的全局存储器(不读取 _sha1_map.txt)。
|
||||
# 用于过滤 stub 文件,避免加载 TransPyV 自身源文件(lib/*)的 stub 导致链接失败。
|
||||
# ============================================================
|
||||
def _load_includes_sha1_set(pool: memhub.MemBuddy*,
|
||||
temp_dir: str,
|
||||
sha1_set: str) -> int:
|
||||
def _load_includes_sha1_set(pool: memhub.MemBuddy*, temp_dir: str, sha1_set: str) -> int:
|
||||
"""从全局内存存储器将 includes 的 SHA1 写入 sha1_set
|
||||
|
||||
pool/temp_dir 参数保留以兼容现有调用者,但不再使用。
|
||||
@@ -118,10 +116,7 @@ def _is_in_sha1_set(sha1: str, sha1_set: str, set_count: int) -> int:
|
||||
# Args: mb 内存池;temp_dir 临时目录(_sha1_map.txt 写入位置);scan_result IncludesScanner 扫描结果
|
||||
# Returns: 0 成功,非 0 失败
|
||||
# ============================================================
|
||||
def WriteIncludesSha1Map(mb: memhub.MemBuddy*, temp_dir: str,
|
||||
scan_result: rawptr[IncludesScanner.ScanResult],
|
||||
filter_set: str,
|
||||
filter_count: int) -> int:
|
||||
def WriteIncludesSha1Map(mb: memhub.MemBuddy*, temp_dir: str, scan_result: rawptr[IncludesScanner.ScanResult], filter_set: str, filter_count: int) -> int:
|
||||
"""将 includes 扫描结果写入 _sha1_map.txt(人类可读输出,程序内部使用内存存储器)
|
||||
|
||||
若 filter_set 不为 None 且 filter_count > 0,只写入 filter_set 中的条目。
|
||||
|
||||
@@ -47,8 +47,7 @@ import lib.Stub.StubMerger as StubMerger
|
||||
# Args: mod 已翻译完成的 LLVM 模块;temp_dir 基础目录;td_len temp_dir 长度;sha1 模块 SHA1
|
||||
# Returns: 0=成功(失败经 VLogger.error 终止进程)
|
||||
# ============================================================
|
||||
def WriteModuleMeta(mod: mlirlite.LLVMModule*, temp_dir: str,
|
||||
td_len: sizet, sha1: str) -> int:
|
||||
def WriteModuleMeta(mod: mlirlite.LLVMModule*, temp_dir: str, td_len: sizet, sha1: str) -> int:
|
||||
"""把本模块的函数定义/结构体布局/虚表清单写入 {sha1}.meta"""
|
||||
if mod is None or temp_dir is None or sha1 is None:
|
||||
VLogger.error("meta 写出:参数为空", "Meta")
|
||||
@@ -216,9 +215,7 @@ def _is_submodule_of_imported(deps_buf: str, mod_name: str) -> int:
|
||||
# 返回两个数组(sha1_list 和 mod_list),长度存储在 count 中。
|
||||
# 所有内存由 stdlib.malloc 分配,调用者负责释放。
|
||||
# ============================================================
|
||||
def _BuildIncludesSha1Map(temp_dir: str, td_len: sizet,
|
||||
sha1_list: str,
|
||||
mod_list: str) -> int:
|
||||
def _BuildIncludesSha1Map(temp_dir: str, td_len: sizet, sha1_list: str, mod_list: str) -> int:
|
||||
"""从全局内存存储器复制 sha1→module_name 映射到调用者数组
|
||||
|
||||
temp_dir/td_len 参数保留以兼容现有调用者,但不再使用。
|
||||
@@ -241,8 +238,7 @@ def _BuildIncludesSha1Map(temp_dir: str, td_len: sizet,
|
||||
# Args: sha1_arr SHA1 数组(每个 17 字节);mod_arr 模块名数组(每个 64 字节);count 映射条目数;mod_name 要查找的模块名
|
||||
# Returns: SHA1 字符串指针(指向 sha1_arr 内部,无需释放),未找到返回 None
|
||||
# ============================================================
|
||||
def _FindSha1ByModName(sha1_arr: str, mod_arr: str,
|
||||
count: int, mod_name: str) -> str:
|
||||
def _FindSha1ByModName(sha1_arr: str, mod_arr: str, count: int, mod_name: str) -> str:
|
||||
"""从模块名查找 SHA1(精确匹配 + 包名回退)
|
||||
|
||||
精确匹配失败时,尝试 "{mod_name}.__init__" 回退,
|
||||
|
||||
@@ -80,8 +80,7 @@ def AppendImportedModule(pool: memhub.MemBuddy*, cur: str, name: str) -> str:
|
||||
# 该条目在查找侧仍被当作合法条目解析出错误的 local/mod/orig ⇒ 跨模块类名/
|
||||
# 别名还原取到错名字(污染 Spec.SourceName)。此处按精确长度分配,无上限。
|
||||
# ============================================================
|
||||
def AppendFromImport(pool: memhub.MemBuddy*, cur: str,
|
||||
local: str, mod: str, orig: str) -> str:
|
||||
def AppendFromImport(pool: memhub.MemBuddy*, cur: str, local: str, mod: str, orig: str) -> str:
|
||||
"""追加 from-import 映射(pool 分配),返回新列表"""
|
||||
if local is None or mod is None: return cur
|
||||
llen: sizet = string.strlen(local)
|
||||
@@ -116,8 +115,7 @@ def AppendFromImport(pool: memhub.MemBuddy*, cur: str,
|
||||
# ============================================================
|
||||
# AllocImportCtx - 用两个既有上下文串构造记账容器
|
||||
# ============================================================
|
||||
def AllocImportCtx(pool: memhub.MemBuddy*,
|
||||
imported_modules: str, from_imports: str) -> ImportCtx*:
|
||||
def AllocImportCtx(pool: memhub.MemBuddy*, imported_modules: str, from_imports: str) -> ImportCtx*:
|
||||
"""构造导入上下文容器(pool 分配);两串可为 None"""
|
||||
ctx: ImportCtx* = pool.alloc(ImportCtx.__sizeof__())
|
||||
if ctx is None: return None
|
||||
@@ -134,8 +132,7 @@ def AllocImportCtx(pool: memhub.MemBuddy*,
|
||||
# 无别名:`import a.b.c` 时把顶层包名 `a` 也追加(使 a.b.c 作为属性访问 base
|
||||
# 时 is_module_imported("a") 放行)。
|
||||
# ============================================================
|
||||
def NotePlainImport(pool: memhub.MemBuddy*, ctx: ImportCtx*,
|
||||
name: str, asname: str) -> int:
|
||||
def NotePlainImport(pool: memhub.MemBuddy*, ctx: ImportCtx*, name: str, asname: str) -> int:
|
||||
"""记账单条 import(就地更新 ctx),返回 0"""
|
||||
if ctx is None or name is None: return 1
|
||||
ctx.ImportedModules = AppendImportedModule(pool, ctx.ImportedModules, name)
|
||||
@@ -151,8 +148,7 @@ def NotePlainImport(pool: memhub.MemBuddy*, ctx: ImportCtx*,
|
||||
if pkg_buf is not None:
|
||||
string.strncpy(pkg_buf, name, pkg_len)
|
||||
pkg_buf[pkg_len] = '\0'
|
||||
ctx.ImportedModules = AppendImportedModule(
|
||||
pool, ctx.ImportedModules, pkg_buf)
|
||||
ctx.ImportedModules = AppendImportedModule(pool, ctx.ImportedModules, pkg_buf)
|
||||
return 0
|
||||
|
||||
|
||||
|
||||
@@ -41,10 +41,7 @@ import lib.Stub.StubMerger as StubMerger
|
||||
# Args: store_count / store_sha1_arr / store_mod_arr store 元数据;reachable_set / reachable_count 可达集合(_BuildReachableSha1Set 输出);sorted_idx 输出数组(store_count+1 个 8 字节槽),前 N 个为拓扑序 store 索引
|
||||
# Returns: 拓扑序条数;有环时剩余条目按 store 顺序补齐(避免漏编译)
|
||||
# ============================================================
|
||||
def BuildTopoSortedIndices(store_count: int, store_sha1_arr: bytes,
|
||||
store_mod_arr: bytes, reachable_set: bytes,
|
||||
reachable_count: int,
|
||||
sorted_idx: sizet*) -> int:
|
||||
def BuildTopoSortedIndices(store_count: int, store_sha1_arr: bytes, store_mod_arr: bytes, reachable_set: bytes, reachable_count: int, sorted_idx: sizet*) -> int:
|
||||
"""对可达 includes 逆拓扑排序(被依赖者先),store 索引写入 sorted_idx"""
|
||||
if store_count <= 0 or store_sha1_arr is None or store_mod_arr is None or sorted_idx is None: return 0
|
||||
indegree: sizet* = (sizet*)(stdlib.malloc(8 * (store_count + 1)))
|
||||
|
||||
Reference in new issue
Block a user