修正 Stub 的 define 导入

This commit is contained in:
TermiNexus committed 2026-08-22 10:36:05 +08:00
1 parent f4fee79d4d
commit 748eda9c69
11 files changed
+141 -188

No files matched your search

-6
View File
@@ -46,12 +46,6 @@ IncludesDirs: str = None # 全部 includes 目录(空格分隔,多
_inc_bin_suffix: str = ".binary"
def set_inc_bin_suffix(suffix: str) -> None:
"""设置 includes.binary 缓存目录后缀(如 ".binary_asan")"""
global _inc_bin_suffix
_inc_bin_suffix = suffix
def Load_project_config(path: str) -> int:
"""加载工程配置文件(project.vpj)
-1
View File
@@ -148,7 +148,6 @@ def _lookup_cdefine_for_pyi(name: str) -> t.CInt64T:
if pnm is not None and string.strcmp(pnm, name) == 0:
_g_pyi_cdefine_found = 1
return _g_pyi_cdef_vals[pi]
import lib.core.Handles.HandlesType as HandlesType
val: t.CInt64T = GenApi.lookup_cdefine_constant(name)
if GenApi.is_cdefine_found() != 0:
_g_pyi_cdefine_found = 1
-1
View File
@@ -881,7 +881,6 @@ def _ParseVpiIntoModuleImpl(pool: memhub.MemBuddy | t.CPtr,
# (imported_modules 无 __sha512)→ t.CArray count 报"必须是整数常量"。
# 示例:RelPath "hashlib/__sha512.vp" → 模块名 "hashlib.__sha512"。
if src_sha1 is not None:
import lib.core.StubMerger as StubMerger
stub_rel_src: str = StubMergerStore.LookupSha1RelPath(src_sha1)
if stub_rel_src is not None:
sr_len_src: t.CSizeT = string.strlen(stub_rel_src)
-3
View File
@@ -1,6 +1,3 @@
# ============================================================
# StubGen 包入口
#
# 子模块通过绝对导入使用(import lib.StubGen.Converter as Converter),
# 此 __init__.vp 不做 re-export,避免引入未使用的依赖。
# ============================================================
+30 -31
View File
@@ -19,7 +19,6 @@ import lib.Stub.StubGen.VpiReader as VpiReader
import lib.Projectrans.Utils as Utils
import lib.Projectrans.Config as Config
import lib.Stub.StubMerger.StubMergerCollect as StubMergerCollect
import lib.Stub.StubMerger.StubMergerStore as StubMergerStore
import lib.Stub.StubMerger.StubMergerTopo as StubMergerTopo
@@ -61,17 +60,17 @@ def _LoadAndAppendStub(temp_dir: str, td_len: t.CSizeT, dep_sha1: str,
viperlib.snprintf(fb_ls, 1024, "依赖 stub 缺失: %s", dep_sha1)
VLogger.error(fb_ls, "StubMerger")
return out_pos
dep_br_ls: t.CInt64T = df_ls.read_all(dep_buf, STUB_READ_BUF_SIZE)
dep_br_ls: t.CInt64T = df_ls.read_all(dep_buf, StubMerger.STUB_READ_BUF_SIZE)
df_ls.close()
stdlib.free(dep_path)
if dep_br_ls <= 0:
# 依赖 stub 为空:纯声明/纯常量模块(如 stdio.vp 全 pass、CDefine 模块)
# 无可声明符号,stub.ll 为空属合法形态,静默跳过
return out_pos
if dep_br_ls < STUB_READ_BUF_SIZE:
if dep_br_ls < StubMerger.STUB_READ_BUF_SIZE:
dep_buf[dep_br_ls] = '\0'
else:
dep_buf[STUB_READ_BUF_SIZE - 1] = '\0'
dep_buf[StubMerger.STUB_READ_BUF_SIZE - 1] = '\0'
# 注释掉依赖 stub 中的字符串常量行(模块内部的,不需要)
# 简单方案:搜索 "= external unnamed_addr constant" 并将行首的 @ 改为 ;@
@@ -226,17 +225,17 @@ def _LoadAndAppendTextDeclares(temp_dir: str, td_len: t.CSizeT, dep_sha1: str,
viperlib.snprintf(fb_lt, 1024, "依赖 text 缺失: %s", dep_sha1)
VLogger.error(fb_lt, "StubMerger")
return out_pos
text_br: t.CInt64T = tf_lt.read_all(dep_buf, STUB_READ_BUF_SIZE)
text_br: t.CInt64T = tf_lt.read_all(dep_buf, StubMerger.STUB_READ_BUF_SIZE)
tf_lt.close()
stdlib.free(text_path)
if text_br <= 0:
# 依赖 text 为空:纯 stub 模块(如 stdio.vp 全 pass 声明)无函数体,
# text.ll 为空属合法形态,无可提取 declare,静默跳过
return out_pos
if text_br < STUB_READ_BUF_SIZE:
if text_br < StubMerger.STUB_READ_BUF_SIZE:
dep_buf[text_br] = '\0'
else:
dep_buf[STUB_READ_BUF_SIZE - 1] = '\0'
dep_buf[StubMerger.STUB_READ_BUF_SIZE - 1] = '\0'
dep_pos_lt: t.CSizeT = 0
in_body: int = 0
@@ -457,8 +456,8 @@ def _BuildReachableSha1Set(mb: memhub.MemBuddy | t.CPtr, source_dir: str,
# 1. 构建 SHA1→module_name 映射
td_len_r: t.CSizeT = string.strlen(temp_dir)
sha1_arr: bytes = stdlib.malloc(MAX_INCLUDES * 17)
mod_arr: bytes = stdlib.malloc(MAX_INCLUDES * 64)
sha1_arr: bytes = stdlib.malloc(StubMerger.MAX_INCLUDES * 17)
mod_arr: bytes = stdlib.malloc(StubMerger.MAX_INCLUDES * 64)
if sha1_arr is None or mod_arr is None:
if sha1_arr is not None:
stdlib.free(sha1_arr)
@@ -477,7 +476,7 @@ def _BuildReachableSha1Set(mb: memhub.MemBuddy | t.CPtr, source_dir: str,
VLogger.debug(fb, "Reachable")
# 工作列表(空格分隔的模块名)
worklist: bytes = stdlib.malloc(REACH_WORKLIST_BUF)
worklist: bytes = stdlib.malloc(StubMerger.REACH_WORKLIST_BUF)
if worklist is None:
stdlib.free(sha1_arr)
stdlib.free(mod_arr)
@@ -491,7 +490,7 @@ def _BuildReachableSha1Set(mb: memhub.MemBuddy | t.CPtr, source_dir: str,
# 否则,回退到自己的非递归扫描(source_dir/*.py,只扫描顶层)
if app_deps is not None and app_deps[0] != '\0':
ad_len: t.CSizeT = string.strlen(app_deps)
if ad_len > 0 and ad_len < REACH_WORKLIST_BUF:
if ad_len > 0 and ad_len < StubMerger.REACH_WORKLIST_BUF:
string.strcpy(worklist, app_deps)
wl_len = ad_len
else:
@@ -557,7 +556,7 @@ def _BuildReachableSha1Set(mb: memhub.MemBuddy | t.CPtr, source_dir: str,
if wl_len > 0 and GenApi.is_module_imported(worklist, im_buf) != 0:
stdlib.free(im_buf)
continue
if wl_len + im_mod_len + 2 < REACH_WORKLIST_BUF:
if wl_len + im_mod_len + 2 < StubMerger.REACH_WORKLIST_BUF:
if wl_len > 0:
worklist[wl_len] = ' '
wl_len += 1
@@ -597,7 +596,7 @@ def _BuildReachableSha1Set(mb: memhub.MemBuddy | t.CPtr, source_dir: str,
if GenApi.is_module_imported(worklist, "builtins") == 0:
bsha1_b: str = StubMergerIR._FindSha1ByModName(sha1_arr, mod_arr, map_count, "builtins")
if bsha1_b is not None:
if wl_len + 9 < REACH_WORKLIST_BUF:
if wl_len + 9 < StubMerger.REACH_WORKLIST_BUF:
if wl_len > 0:
worklist[wl_len] = ' '
wl_len += 1
@@ -612,7 +611,7 @@ def _BuildReachableSha1Set(mb: memhub.MemBuddy | t.CPtr, source_dir: str,
VLogger.debug(fb, "Reachable")
# 3. 工作列表算法:递归收集可达 SHA1
processed: bytes = stdlib.malloc(REACH_WORKLIST_BUF)
processed: bytes = stdlib.malloc(StubMerger.REACH_WORKLIST_BUF)
if processed is None:
stdlib.free(sha1_arr)
stdlib.free(mod_arr)
@@ -649,7 +648,7 @@ def _BuildReachableSha1Set(mb: memhub.MemBuddy | t.CPtr, source_dir: str,
if already == 0:
# 加入 processed(嵌套 if 拆分 + 用 = 代替 += 绕过 TPC AUGASGN bug)
if processed is not None:
if proc_len + name_len + 1 < REACH_WORKLIST_BUF:
if proc_len + name_len + 1 < StubMerger.REACH_WORKLIST_BUF:
string.strcpy(processed + proc_len, mod_buf)
proc_len = proc_len + name_len
processed[proc_len] = ' '
@@ -671,7 +670,7 @@ def _BuildReachableSha1Set(mb: memhub.MemBuddy | t.CPtr, source_dir: str,
for ai_r in range(StubMerger._sha1_store_count):
asi_r: t.CSizeT = t.CSizeT(ai_r) * 17
if string.strcmp(StubMerger._sha1_store_arr + asi_r, found_sha1) == 0:
aii_r: t.CSizeT = t.CSizeT(ai_r) * MAX_INC_DIR_LEN
aii_r: t.CSizeT = t.CSizeT(ai_r) * StubMerger.MAX_INC_DIR_LEN
if StubMerger._sha1_store_incdir[aii_r] == '\0':
is_app_r = 1
break
@@ -710,7 +709,7 @@ def _BuildReachableSha1Set(mb: memhub.MemBuddy | t.CPtr, source_dir: str,
if GenApi.is_module_imported(processed, dmod) != 0:
in_wl = 1
if in_wl == 0:
if wl_len + dlen + 2 < REACH_WORKLIST_BUF:
if wl_len + dlen + 2 < StubMerger.REACH_WORKLIST_BUF:
if wl_len > 0 and worklist[wl_len - 1] != ' ':
worklist[wl_len] = ' '
wl_len = wl_len + 1
@@ -794,21 +793,21 @@ def BuildCombinedIR(temp_dir: str, local_sha1: str,
if sf.closed:
stdlib.free(stub_path)
return 0
stub_content: bytes = stdlib.malloc(STUB_READ_BUF_SIZE)
stub_content: bytes = stdlib.malloc(StubMerger.STUB_READ_BUF_SIZE)
if stub_content is None:
sf.close()
stdlib.free(stub_path)
return 0
stub_br: t.CInt64T = sf.read_all(stub_content, STUB_READ_BUF_SIZE)
stub_br: t.CInt64T = sf.read_all(stub_content, StubMerger.STUB_READ_BUF_SIZE)
sf.close()
stdlib.free(stub_path)
if stub_br <= 0:
stdlib.free(stub_content)
return 0
if stub_br < STUB_READ_BUF_SIZE:
if stub_br < StubMerger.STUB_READ_BUF_SIZE:
stub_content[stub_br] = '\0'
else:
stub_content[STUB_READ_BUF_SIZE - 1] = '\0'
stub_content[StubMerger.STUB_READ_BUF_SIZE - 1] = '\0'
slen: t.CSizeT = stub_br
# 修复本地 stub.ll 中字符串常量的非法 IR:
# llvmlite OUTPUT_STUB 模式输出 "= external unnamed_addr constant" 的非法形式。
@@ -844,8 +843,8 @@ def BuildCombinedIR(temp_dir: str, local_sha1: str,
# 2. 按需加载依赖 stubs(根据 deps.txt 过滤,而非扫描全部)
# 先加载依赖 stub(含 type 定义),确保 type 定义在本地 text.ll 的 define 块之前
# 2a. 构建 includes SHA1 → module_name 映射(从全局内存存储器)
sha1_arr: bytes = stdlib.malloc(MAX_INCLUDES * 17)
mod_arr: bytes = stdlib.malloc(MAX_INCLUDES * 64)
sha1_arr: bytes = stdlib.malloc(StubMerger.MAX_INCLUDES * 17)
mod_arr: bytes = stdlib.malloc(StubMerger.MAX_INCLUDES * 64)
inc_count: int = 0
if sha1_arr is not None and mod_arr is not None:
inc_count = StubMergerIR._BuildIncludesSha1Map(temp_dir, td_len, sha1_arr, mod_arr)
@@ -890,11 +889,11 @@ def BuildCombinedIR(temp_dir: str, local_sha1: str,
if string.strcmp(StubMerger._stub_scan_cache_dir, temp_dir) == 0:
cache_valid_sc = 1
if cache_valid_sc == 0:
new_scan_arr: str = stdlib.malloc(MAX_INCLUDES_SHA1 * 17)
new_scan_arr: str = stdlib.malloc(StubMerger.MAX_INCLUDES_SHA1 * 17)
if new_scan_arr is not None:
string.memset(new_scan_arr, 0, MAX_INCLUDES_SHA1 * 17)
string.memset(new_scan_arr, 0, StubMerger.MAX_INCLUDES_SHA1 * 17)
new_scan_count: int = StubMergerCollect._collect_stub_sha1s(
temp_dir, td_len, Config.Sha1SliceLevel, new_scan_arr, 0, MAX_INCLUDES_SHA1)
temp_dir, td_len, Config.Sha1SliceLevel, new_scan_arr, 0, StubMerger.MAX_INCLUDES_SHA1)
if new_scan_count > 0:
# 缓存目录键(stdlib 深拷贝,跨调用存活)
dir_buf_sc: str = stdlib.malloc(td_len + 1)
@@ -916,7 +915,7 @@ def BuildCombinedIR(temp_dir: str, local_sha1: str,
all_sha1_arr: str = StubMerger._stub_scan_cache_arr
all_count: int = StubMerger._stub_scan_cache_count
if all_sha1_arr is not None and all_count > 0:
dep_buf: bytes = stdlib.malloc(STUB_READ_BUF_SIZE)
dep_buf: bytes = stdlib.malloc(StubMerger.STUB_READ_BUF_SIZE)
if dep_buf is not None:
si: int = 0
while si < all_count:
@@ -1020,19 +1019,19 @@ def BuildCombinedIR(temp_dir: str, local_sha1: str,
VLogger.error(fb_tlp, "StubMerger")
stdlib.free(text_path)
else:
text_content: bytes = stdlib.malloc(STUB_READ_BUF_SIZE)
text_content: bytes = stdlib.malloc(StubMerger.STUB_READ_BUF_SIZE)
if text_content is None:
tf.close()
stdlib.free(text_path)
else:
text_br: t.CInt64T = tf.read_all(text_content, STUB_READ_BUF_SIZE)
text_br: t.CInt64T = tf.read_all(text_content, StubMerger.STUB_READ_BUF_SIZE)
tf.close()
stdlib.free(text_path)
if text_br > 0:
if text_br < STUB_READ_BUF_SIZE:
if text_br < StubMerger.STUB_READ_BUF_SIZE:
text_content[text_br] = '\0'
else:
text_content[STUB_READ_BUF_SIZE - 1] = '\0'
text_content[StubMerger.STUB_READ_BUF_SIZE - 1] = '\0'
# 行级去重追加(与 _LoadAndAppendStub 相同逻辑)
tx_pos: t.CSizeT = 0
tx_skip: int = 1
+1 -1
View File
@@ -204,7 +204,7 @@ def _load_includes_sha1_set(pool: memhub.MemBuddy | t.CPtr,
return -1
count: int = 0
for i in range(StubMerger._sha1_store_count):
if count >= MAX_INCLUDES_SHA1:
if count >= StubMerger.MAX_INCLUDES_SHA1:
break
idx: t.CSizeT = t.CSizeT(i) * 17
string.strcpy(sha1_set + t.CSizeT(count) * 17, StubMerger._sha1_store_arr + idx)
+6 -6
View File
@@ -56,10 +56,10 @@ def IsDeclOnlyModule(temp_dir: str, td_len: t.CSizeT, sha1: str) -> int:
stdlib.free(tpath)
if tf_d.closed:
return -1
tbuf_d: bytes = stdlib.malloc(STUB_READ_BUF_SIZE)
tbuf_d: bytes = stdlib.malloc(StubMerger.STUB_READ_BUF_SIZE)
tbr_d: t.CInt64T = 0
if tbuf_d is not None:
tbr_d = tf_d.read_all(tbuf_d, STUB_READ_BUF_SIZE)
tbr_d = tf_d.read_all(tbuf_d, StubMerger.STUB_READ_BUF_SIZE)
tf_d.close()
if tbuf_d is None:
return -1
@@ -67,10 +67,10 @@ def IsDeclOnlyModule(temp_dir: str, td_len: t.CSizeT, sha1: str) -> int:
# 空 text.ll:无函数体,纯声明
stdlib.free(tbuf_d)
return 1
if tbr_d < STUB_READ_BUF_SIZE:
if tbr_d < StubMerger.STUB_READ_BUF_SIZE:
tbuf_d[tbr_d] = '\0'
else:
tbuf_d[STUB_READ_BUF_SIZE - 1] = '\0'
tbuf_d[StubMerger.STUB_READ_BUF_SIZE - 1] = '\0'
# 逐行扫描:找 "define " 行即为实现文件
tpos_d: t.CSizeT = 0
while tpos_d < tbr_d:
@@ -334,7 +334,7 @@ def _BuildIncludesSha1Map(temp_dir: str, td_len: t.CSizeT,
return 0
count: int = 0
for i in range(StubMerger._sha1_store_count):
if count >= MAX_INCLUDES:
if count >= StubMerger.MAX_INCLUDES:
break
idx: t.CSizeT = t.CSizeT(i) * 17
idx2: t.CSizeT = t.CSizeT(i) * 64
@@ -408,7 +408,7 @@ def _AddSha1ToSet(set_buf: str, count: int, sha1: str) -> int:
idx: t.CSizeT = t.CSizeT(i) * 17
if string.strcmp(set_buf + idx, sha1) == 0:
return count
if count < MAX_INCLUDES_SHA1:
if count < StubMerger.MAX_INCLUDES_SHA1:
idx: t.CSizeT = t.CSizeT(count) * 17
string.strcpy(set_buf + idx, sha1)
return count + 1
+45 -45
View File
@@ -64,21 +64,21 @@ def PopulateSha1MapStore(scan_result: IncludesScanner.ScanResult | t.CPtr) -> in
stdlib.free(StubMerger._sha1_store_rel)
if StubMerger._sha1_store_incdir is not None:
stdlib.free(StubMerger._sha1_store_incdir)
StubMerger._sha1_store_arr = stdlib.malloc(MAX_INCLUDES * 17)
StubMerger._sha1_store_mod = stdlib.malloc(MAX_INCLUDES * 64)
StubMerger._sha1_store_rel = stdlib.malloc(MAX_INCLUDES * MAX_REL_PATH_LEN)
StubMerger._sha1_store_incdir = stdlib.malloc(MAX_INCLUDES * MAX_INC_DIR_LEN)
StubMerger._sha1_store_arr = stdlib.malloc(StubMerger.MAX_INCLUDES * 17)
StubMerger._sha1_store_mod = stdlib.malloc(StubMerger.MAX_INCLUDES * 64)
StubMerger._sha1_store_rel = stdlib.malloc(StubMerger.MAX_INCLUDES * StubMerger.MAX_REL_PATH_LEN)
StubMerger._sha1_store_incdir = stdlib.malloc(StubMerger.MAX_INCLUDES * StubMerger.MAX_INC_DIR_LEN)
if StubMerger._sha1_store_arr is None or StubMerger._sha1_store_mod is None or StubMerger._sha1_store_rel is None or StubMerger._sha1_store_incdir is None:
return -1
string.memset(StubMerger._sha1_store_arr, 0, MAX_INCLUDES * 17)
string.memset(StubMerger._sha1_store_mod, 0, MAX_INCLUDES * 64)
string.memset(StubMerger._sha1_store_rel, 0, MAX_INCLUDES * MAX_REL_PATH_LEN)
string.memset(StubMerger._sha1_store_incdir, 0, MAX_INCLUDES * MAX_INC_DIR_LEN)
string.memset(StubMerger._sha1_store_arr, 0, StubMerger.MAX_INCLUDES * 17)
string.memset(StubMerger._sha1_store_mod, 0, StubMerger.MAX_INCLUDES * 64)
string.memset(StubMerger._sha1_store_rel, 0, StubMerger.MAX_INCLUDES * StubMerger.MAX_REL_PATH_LEN)
string.memset(StubMerger._sha1_store_incdir, 0, StubMerger.MAX_INCLUDES * StubMerger.MAX_INC_DIR_LEN)
StubMerger._sha1_store_count = 0
p_bad: int = 0
entry_size_p: t.CSizeT = IncludesScanner.FileEntry.__sizeof__()
for i in range(scan_result.Count):
if StubMerger._sha1_store_count >= MAX_INCLUDES:
if StubMerger._sha1_store_count >= StubMerger.MAX_INCLUDES:
VLogger.error("includes SHA1 存储超上限,终止", "StubMerger")
ea: t.CUInt64T = t.CUInt64T(scan_result.Entries) + i * entry_size_p
ent: IncludesScanner.FileEntry | t.CPtr = (IncludesScanner.FileEntry | t.CPtr)(t.CVoid(ea, t.CPtr))
@@ -106,21 +106,21 @@ def PopulateSha1MapStore(scan_result: IncludesScanner.ScanResult | t.CPtr) -> in
StubMerger._sha1_store_mod[idx2 + 63] = '\0'
stdlib.free(mod_name)
# 保存 rel_path(供 Phase2 3.5 编译缺失 includes 使用)
idx3: t.CSizeT = t.CSizeT(StubMerger._sha1_store_count) * MAX_REL_PATH_LEN
if rp_len < MAX_REL_PATH_LEN:
idx3: t.CSizeT = t.CSizeT(StubMerger._sha1_store_count) * StubMerger.MAX_REL_PATH_LEN
if rp_len < StubMerger.MAX_REL_PATH_LEN:
string.strcpy(StubMerger._sha1_store_rel + idx3, ent.RelPath)
else:
string.strncpy(StubMerger._sha1_store_rel + idx3, ent.RelPath, MAX_REL_PATH_LEN - 1)
StubMerger._sha1_store_rel[idx3 + MAX_REL_PATH_LEN - 1] = '\0'
string.strncpy(StubMerger._sha1_store_rel + idx3, ent.RelPath, StubMerger.MAX_REL_PATH_LEN - 1)
StubMerger._sha1_store_rel[idx3 + StubMerger.MAX_REL_PATH_LEN - 1] = '\0'
# 保存所属 includes 根目录(Phase2 预注册/按需编译拼路径用)
idx_inc: t.CSizeT = t.CSizeT(StubMerger._sha1_store_count) * MAX_INC_DIR_LEN
idx_inc: t.CSizeT = t.CSizeT(StubMerger._sha1_store_count) * StubMerger.MAX_INC_DIR_LEN
if ent.IncDir is not None:
icd_len: t.CSizeT = string.strlen(ent.IncDir)
if icd_len < MAX_INC_DIR_LEN:
if icd_len < StubMerger.MAX_INC_DIR_LEN:
string.strcpy(StubMerger._sha1_store_incdir + idx_inc, ent.IncDir)
else:
string.strncpy(StubMerger._sha1_store_incdir + idx_inc, ent.IncDir, MAX_INC_DIR_LEN - 1)
StubMerger._sha1_store_incdir[idx_inc + MAX_INC_DIR_LEN - 1] = '\0'
string.strncpy(StubMerger._sha1_store_incdir + idx_inc, ent.IncDir, StubMerger.MAX_INC_DIR_LEN - 1)
StubMerger._sha1_store_incdir[idx_inc + StubMerger.MAX_INC_DIR_LEN - 1] = '\0'
StubMerger._sha1_store_count += 1
if p_bad > 0:
fb_pbad: str = VLogger.fmt_buf()
@@ -134,7 +134,7 @@ def PopulateSha1MapStore(scan_result: IncludesScanner.ScanResult | t.CPtr) -> in
# Phase1 调用 PopulateSha1MapStore 填充 includes 文件,
# Phase2 扫描 App 源文件后调用此函数追加 App 模块条目,
# 确保编译 App 自身时跨模块 CDefine 查找能命中 App 模块
# (如 StubMerger.MAX_INCLUDES 在编译 Phase2 时通过
# (如 StubMerger.StubMerger.MAX_INCLUDES 在编译 Phase2 时通过
# _build_source_path_from_sha1 查找 StubMerger 的源路径)。
#
# 若存储器未初始化(PopulateSha1MapStore 未调用),自动初始化。
@@ -154,18 +154,18 @@ def AppendToSha1MapStore(sha1: str, rel_path: str) -> int:
return 1
# 存储器未初始化:自动初始化(Phase2 可能先于 Phase1 调用)
if StubMerger._sha1_store_arr is None:
StubMerger._sha1_store_arr = stdlib.malloc(MAX_INCLUDES * 17)
StubMerger._sha1_store_mod = stdlib.malloc(MAX_INCLUDES * 64)
StubMerger._sha1_store_rel = stdlib.malloc(MAX_INCLUDES * MAX_REL_PATH_LEN)
StubMerger._sha1_store_incdir = stdlib.malloc(MAX_INCLUDES * MAX_INC_DIR_LEN)
StubMerger._sha1_store_arr = stdlib.malloc(StubMerger.MAX_INCLUDES * 17)
StubMerger._sha1_store_mod = stdlib.malloc(StubMerger.MAX_INCLUDES * 64)
StubMerger._sha1_store_rel = stdlib.malloc(StubMerger.MAX_INCLUDES * StubMerger.MAX_REL_PATH_LEN)
StubMerger._sha1_store_incdir = stdlib.malloc(StubMerger.MAX_INCLUDES * StubMerger.MAX_INC_DIR_LEN)
if StubMerger._sha1_store_arr is None or StubMerger._sha1_store_mod is None or StubMerger._sha1_store_rel is None or StubMerger._sha1_store_incdir is None:
return 1
string.memset(StubMerger._sha1_store_arr, 0, MAX_INCLUDES * 17)
string.memset(StubMerger._sha1_store_mod, 0, MAX_INCLUDES * 64)
string.memset(StubMerger._sha1_store_rel, 0, MAX_INCLUDES * MAX_REL_PATH_LEN)
string.memset(StubMerger._sha1_store_incdir, 0, MAX_INCLUDES * MAX_INC_DIR_LEN)
string.memset(StubMerger._sha1_store_arr, 0, StubMerger.MAX_INCLUDES * 17)
string.memset(StubMerger._sha1_store_mod, 0, StubMerger.MAX_INCLUDES * 64)
string.memset(StubMerger._sha1_store_rel, 0, StubMerger.MAX_INCLUDES * StubMerger.MAX_REL_PATH_LEN)
string.memset(StubMerger._sha1_store_incdir, 0, StubMerger.MAX_INCLUDES * StubMerger.MAX_INC_DIR_LEN)
StubMerger._sha1_store_count = 0
if StubMerger._sha1_store_count >= MAX_INCLUDES:
if StubMerger._sha1_store_count >= StubMerger.MAX_INCLUDES:
return 1
# 去重:若 SHA1 已存在则跳过
for i in range(StubMerger._sha1_store_count):
@@ -194,15 +194,15 @@ def AppendToSha1MapStore(sha1: str, rel_path: str) -> int:
StubMerger._sha1_store_mod[idx_m + 63] = '\0'
stdlib.free(mod_name)
# 写入相对路径
idx_r: t.CSizeT = t.CSizeT(StubMerger._sha1_store_count) * MAX_REL_PATH_LEN
idx_r: t.CSizeT = t.CSizeT(StubMerger._sha1_store_count) * StubMerger.MAX_REL_PATH_LEN
rp_len: t.CSizeT = string.strlen(rel_path)
if rp_len < MAX_REL_PATH_LEN:
if rp_len < StubMerger.MAX_REL_PATH_LEN:
string.strcpy(StubMerger._sha1_store_rel + idx_r, rel_path)
else:
string.strncpy(StubMerger._sha1_store_rel + idx_r, rel_path, MAX_REL_PATH_LEN - 1)
StubMerger._sha1_store_rel[idx_r + MAX_REL_PATH_LEN - 1] = '\0'
string.strncpy(StubMerger._sha1_store_rel + idx_r, rel_path, StubMerger.MAX_REL_PATH_LEN - 1)
StubMerger._sha1_store_rel[idx_r + StubMerger.MAX_REL_PATH_LEN - 1] = '\0'
# App 源文件不属于任何 includes 目录:IncDir 留空(Phase2 回退 includes_dir 参数)
idx_inc_a: t.CSizeT = t.CSizeT(StubMerger._sha1_store_count) * MAX_INC_DIR_LEN
idx_inc_a: t.CSizeT = t.CSizeT(StubMerger._sha1_store_count) * StubMerger.MAX_INC_DIR_LEN
StubMerger._sha1_store_incdir[idx_inc_a] = '\0'
StubMerger._sha1_store_count += 1
return 0
@@ -291,14 +291,14 @@ def PopulateIncludesDeps(sha1: str, deps_str: str) -> int:
return 1
# 延迟初始化
if StubMerger._includes_deps_sha1 is None:
StubMerger._includes_deps_sha1 = stdlib.malloc(MAX_INCLUDES * 17)
StubMerger._includes_deps_str = stdlib.malloc(MAX_INCLUDES * MAX_DEPS_STR_LEN)
StubMerger._includes_deps_sha1 = stdlib.malloc(StubMerger.MAX_INCLUDES * 17)
StubMerger._includes_deps_str = stdlib.malloc(StubMerger.MAX_INCLUDES * StubMerger.MAX_DEPS_STR_LEN)
if StubMerger._includes_deps_sha1 is None or StubMerger._includes_deps_str is None:
return 1
string.memset(StubMerger._includes_deps_sha1, 0, MAX_INCLUDES * 17)
string.memset(StubMerger._includes_deps_str, 0, MAX_INCLUDES * MAX_DEPS_STR_LEN)
string.memset(StubMerger._includes_deps_sha1, 0, StubMerger.MAX_INCLUDES * 17)
string.memset(StubMerger._includes_deps_str, 0, StubMerger.MAX_INCLUDES * StubMerger.MAX_DEPS_STR_LEN)
StubMerger._includes_deps_count = 0
if StubMerger._includes_deps_count >= MAX_INCLUDES:
if StubMerger._includes_deps_count >= StubMerger.MAX_INCLUDES:
return 1
# 去重:若 SHA1 已存在则跳过
for i in range(StubMerger._includes_deps_count):
@@ -309,13 +309,13 @@ def PopulateIncludesDeps(sha1: str, deps_str: str) -> int:
idx: t.CSizeT = t.CSizeT(StubMerger._includes_deps_count) * 17
string.strcpy(StubMerger._includes_deps_sha1 + idx, sha1)
# 写入依赖字符串
idx2: t.CSizeT = t.CSizeT(StubMerger._includes_deps_count) * MAX_DEPS_STR_LEN
idx2: t.CSizeT = t.CSizeT(StubMerger._includes_deps_count) * StubMerger.MAX_DEPS_STR_LEN
if deps_str is not None:
dl: t.CSizeT = string.strlen(deps_str)
if dl < MAX_DEPS_STR_LEN:
if dl < StubMerger.MAX_DEPS_STR_LEN:
string.strcpy(StubMerger._includes_deps_str + idx2, deps_str)
else:
string.strncpy(StubMerger._includes_deps_str + idx2, deps_str, MAX_DEPS_STR_LEN - 1)
string.strncpy(StubMerger._includes_deps_str + idx2, deps_str, StubMerger.MAX_DEPS_STR_LEN - 1)
else:
StubMerger._includes_deps_str[idx2] = '\0'
StubMerger._includes_deps_count = StubMerger._includes_deps_count + 1
@@ -338,7 +338,7 @@ def LookupIncludesDeps(sha1: str) -> str:
for i in range(StubMerger._includes_deps_count):
sidx: t.CSizeT = t.CSizeT(i) * 17
if string.strcmp(StubMerger._includes_deps_sha1 + sidx, sha1) == 0:
idx2: t.CSizeT = t.CSizeT(i) * MAX_DEPS_STR_LEN
idx2: t.CSizeT = t.CSizeT(i) * StubMerger.MAX_DEPS_STR_LEN
return StubMerger._includes_deps_str + idx2
return None
def GetSha1StoreArrPtr() -> bytes | t.CPtr:
@@ -348,16 +348,16 @@ def GetSha1StoreModArrPtr() -> bytes | t.CPtr:
"""返回模块名数组指针(每个条目 64 字节)"""
return StubMerger._sha1_store_mod
def GetSha1StoreRelArrPtr() -> bytes | t.CPtr:
"""返回相对路径数组指针(每个条目 MAX_REL_PATH_LEN 字节)"""
"""返回相对路径数组指针(每个条目 StubMerger.MAX_REL_PATH_LEN 字节)"""
return StubMerger._sha1_store_rel
def GetSha1StoreIncdirArrPtr() -> bytes | t.CPtr:
"""返回所属 includes 根目录数组指针(每个条目 MAX_INC_DIR_LEN 字节,空串表示不属于任何 includes 目录)"""
"""返回所属 includes 根目录数组指针(每个条目 StubMerger.MAX_INC_DIR_LEN 字节,空串表示不属于任何 includes 目录)"""
return StubMerger._sha1_store_incdir
# ============================================================
# GetSha1StoreArr - 获取全局存储器数组指针(直接遍历用)
#
# 返回 sha1_arr、mod_arr、rel_arr 三个数组的指针和条目数。
# 调用者直接遍历数组:sha1_arr[i*17]、mod_arr[i*64]、rel_arr[i*MAX_REL_PATH_LEN]
# 调用者直接遍历数组:sha1_arr[i*17]、mod_arr[i*64]、rel_arr[i*StubMerger.MAX_REL_PATH_LEN]
# 内存归全局存储器所有,调用者不要 free
# ============================================================
def GetSha1StoreArr(out_sha1_arr: t.CPtr, out_mod_arr: t.CPtr, out_rel_arr: t.CPtr) -> int:
@@ -402,6 +402,6 @@ def LookupSha1RelPath(sha1: str) -> str:
for i in range(StubMerger._sha1_store_count):
sidx: t.CSizeT = t.CSizeT(i) * 17
if string.strcmp(StubMerger._sha1_store_arr + sidx, sha1) == 0:
ridx: t.CSizeT = t.CSizeT(i) * MAX_REL_PATH_LEN
ridx: t.CSizeT = t.CSizeT(i) * StubMerger.MAX_REL_PATH_LEN
return StubMerger._sha1_store_rel + ridx
return None
+31 -52
View File
@@ -2203,8 +2203,12 @@ class AsyncGenMixin(CallGenBase.CallGenBase):
if frame_ty is None:
return llvmlite.const_int32(pool, 0)
frame_ptr_ty: llvmlite.LLVMType | t.CPtr = llvmlite.Ptr(pool, frame_ty)
frame_ptr: llvmlite.Value | t.CPtr = self._coro_frame_ptr_from_arg(
builder, pool, mod, trans, cl.args.get(0), frame_ptr_ty)
frame_val: llvmlite.Value | t.CPtr = self.Gen.ExprGen.translate_value(
builder, pool, mod, cl.args.get(0), None, 0, trans)
if frame_val is None:
return llvmlite.const_int32(pool, 0)
frame_ptr: llvmlite.Value | t.CPtr = llvmlite.build_bitcast(
builder, frame_val, frame_ptr_ty)
if frame_ptr is None:
return llvmlite.const_int32(pool, 0)
# 回池:帧首 8 字节存旧池头;池头 = 本帧(i64)
@@ -2244,8 +2248,12 @@ class AsyncGenMixin(CallGenBase.CallGenBase):
if frame_ty is None:
return llvmlite.const_int32(pool, 0)
frame_ptr_ty: llvmlite.LLVMType | t.CPtr = llvmlite.Ptr(pool, frame_ty)
frame_ptr: llvmlite.Value | t.CPtr = self._coro_frame_ptr_from_arg(
builder, pool, mod, trans, cl.args.get(0), frame_ptr_ty)
frame_val: llvmlite.Value | t.CPtr = self.Gen.ExprGen.translate_value(
builder, pool, mod, cl.args.get(0), None, 0, trans)
if frame_val is None:
return llvmlite.const_int32(pool, 0)
frame_ptr: llvmlite.Value | t.CPtr = llvmlite.build_bitcast(
builder, frame_val, frame_ptr_ty)
if frame_ptr is None:
return llvmlite.const_int32(pool, 0)
exc_ptr: llvmlite.Value | t.CPtr = llvmlite.build_gep_struct(
@@ -2270,8 +2278,12 @@ class AsyncGenMixin(CallGenBase.CallGenBase):
if frame_ty is None:
return llvmlite.ConstNull(pool, i8_ptr_ty, "null")
frame_ptr_ty: llvmlite.LLVMType | t.CPtr = llvmlite.Ptr(pool, frame_ty)
frame_ptr: llvmlite.Value | t.CPtr = self._coro_frame_ptr_from_arg(
builder, pool, mod, trans, cl.args.get(0), frame_ptr_ty)
frame_val: llvmlite.Value | t.CPtr = self.Gen.ExprGen.translate_value(
builder, pool, mod, cl.args.get(0), None, 0, trans)
if frame_val is None:
return llvmlite.ConstNull(pool, i8_ptr_ty, "null")
frame_ptr: llvmlite.Value | t.CPtr = llvmlite.build_bitcast(
builder, frame_val, frame_ptr_ty)
if frame_ptr is None:
return llvmlite.ConstNull(pool, i8_ptr_ty, "null")
msg_ptr: llvmlite.Value | t.CPtr = llvmlite.build_gep_struct(
@@ -2299,8 +2311,12 @@ class AsyncGenMixin(CallGenBase.CallGenBase):
if frame_ty is None:
continue
frame_ptr_ty: llvmlite.LLVMType | t.CPtr = llvmlite.Ptr(pool, frame_ty)
frame_ptr: llvmlite.Value | t.CPtr = self._coro_frame_ptr_from_arg(
builder, pool, mod, trans, arg0, frame_ptr_ty)
frame_val: llvmlite.Value | t.CPtr = self.Gen.ExprGen.translate_value(
builder, pool, mod, arg0, None, 0, trans)
if frame_val is None:
continue
frame_ptr: llvmlite.Value | t.CPtr = llvmlite.build_bitcast(
builder, frame_val, frame_ptr_ty)
if frame_ptr is None:
continue
rn_buf: str = pool.alloc(64)
@@ -2328,47 +2344,6 @@ class AsyncGenMixin(CallGenBase.CallGenBase):
llvmlite.position_at_end(builder, after_bb)
return llvmlite.const_int32(pool, 0)
def _coro_frame_ptr_from_arg(self, builder: llvmlite.IRBuilder | t.CPtr,
pool: memhub.MemBuddy | t.CPtr,
mod: llvmlite.LLVMModule | t.CPtr,
trans: HT.Translator | t.CPtr,
arg0: ast.AST | t.CPtr,
frame_ptr_ty: llvmlite.LLVMType | t.CPtr
) -> llvmlite.Value | t.CPtr:
"""协程参数节点 → 帧指针 Ptr(帧):
- 普通指针(t.CPtr / 帧指针):直接 bitcast(既有路径)
- Coroutine 结构体变量(tt: Coroutine = c.Addr(task()) 就地解读):
translate_value 按"对象即指针"返回 alloca 地址(ExprGenName 对
pointee=Struct 不 load),故 pointee 是结构体时 GEP __ptr__(index 0)
load 帧指针——bitcast 聚合地址→帧指针会写越界,必须经字段提取。
"""
if arg0 is None or frame_ptr_ty is None:
return None
frame_val: llvmlite.Value | t.CPtr = self.Gen.ExprGen.translate_value(
builder, pool, mod, arg0, None, 0, trans)
if frame_val is None or frame_val.Ty is None:
return None
if self.Gen.ExprGenBase.is_ptr_type(frame_val.Ty) != 0:
pointee: llvmlite.LLVMType | t.CPtr = frame_val.Ty.Pointee
if pointee is not None:
match pointee:
case llvmlite.LLVMType.Struct(_, _, _):
i8_ptr_ty_t: llvmlite.LLVMType | t.CPtr = llvmlite.Ptr(
pool, llvmlite.Int8(pool))
ptr_field: llvmlite.Value | t.CPtr = llvmlite.build_gep_struct(
builder, pointee, i8_ptr_ty_t, frame_val, 0)
if ptr_field is None:
return None
raw_ptr: llvmlite.Value | t.CPtr = llvmlite.build_load(
builder, i8_ptr_ty_t, ptr_field)
if raw_ptr is None:
return None
return llvmlite.build_bitcast(
builder, raw_ptr, frame_ptr_ty)
case _:
pass
return llvmlite.build_bitcast(builder, frame_val, frame_ptr_ty)
def _var_to_async(self, trans: HT.Translator | t.CPtr,
arg0: ast.AST | t.CPtr) -> str:
"""变量节点 → async 函数名(_coro_var_async 反查),未命中返回 None"""
@@ -2548,9 +2523,13 @@ class AsyncGenMixin(CallGenBase.CallGenBase):
return llvmlite.const_int32(pool, 0)
frame_ptr_ty: llvmlite.LLVMType | t.CPtr = llvmlite.Ptr(pool, frame_ty)
# 帧变量值(i8* / Ptr(帧) / Coroutine 结构体)→ Ptr(帧)
frame_ptr: llvmlite.Value | t.CPtr = self._coro_frame_ptr_from_arg(
builder, pool, mod, trans, arg0, frame_ptr_ty)
# 帧变量值(i8* / Ptr(帧))→ bitcast 到 Ptr(帧)
frame_val: llvmlite.Value | t.CPtr = self.Gen.ExprGen.translate_value(
builder, pool, mod, arg0, None, 0, trans)
if frame_val is None:
return llvmlite.const_int32(pool, 0)
frame_ptr: llvmlite.Value | t.CPtr = llvmlite.build_bitcast(
builder, frame_val, frame_ptr_ty)
if frame_ptr is None:
return llvmlite.const_int32(pool, 0)
+1 -1
View File
@@ -14,7 +14,7 @@ import lib.core.VLogger as VLogger
import lib.core.Handles.HandlesBase as HandlesBase
import lib.core.Handles.HandlesTranslator as HT
import lib.core.Handles.HandlesExpr as HandlesExpr
import lib.core.StubMerger as StubMerger
import lib.Stub.StubMerger as StubMerger
import lib.core.Gen.Generator as Generator
# ============================================================
+27 -41
View File
@@ -21,14 +21,11 @@ import memhub
import argparse
import w32.win32console as w32cmd
import w32.fileio as fileio
import w32.win32file
import w32.win32base
import sys
import ast
import llvmlite
import subprocess
import viperlib
import hashlib
import t, c
import lib.Stub.StubMerger.StubMergerBuild as StubMergerBuild
import lib.Stub.StubMerger.StubMergerCollect as StubMergerCollect
@@ -44,13 +41,12 @@ CODE_PAGE: t.CDefine = 65001
# Source code buffer size (1MB)
SRC_BUF_SIZE: t.CDefine = 1048576
# Version (dev/beta/rc)
V_VIPER_VERSION: t.CDefine = "1.0.3-dev.29 2026-07-27 Non-LTS"
V_TPV_VERSION: t.CDefine = "0.0.2-dev.173"
V_RUNTIME_VERSION: t.CDefine = "0.2.2+3-Non-LTS"
V_TERMINEXUS_AGE: t.CDefine = "15.3"
V_TPC_COMMIT: t.CDefine = "a641c7c8da/2026‑08‑17T02:49:00Z"
V_TPV_COMMIT: t.CDefine = ""
V_RUNTIME_COMMIT: t.CDefine = "14ff9d109f/2026-08-17T03:02:20Z"
V_VIPER_VERSION: t.CDefine = "1.0.3-dev.30 2026-07-27 Non-LTS"
V_TPV_VERSION: t.CDefine = "0.0.3-dev.230"
V_RUNTIME_VERSION: t.CDefine = "0.2.2+4-Non-LTS"
V_TPC_COMMIT: t.CDefine = "1dc23ffdde"
V_TPV_COMMIT: t.CDefine = "f4fee79d4d"
V_RUNTIME_COMMIT: t.CDefine = "4ce6095359"
V_TARGET: t.CDefine = "x86_64-w64-windows-gnu"
V_LLVM: t.CDefine = "22.1.8"
@@ -160,14 +156,14 @@ Copyright (C) 2026 Viper Project
License MIT <https://opensource.org/licenses/MIT>
GVSDS(TM) Viper SE Runtime Environment and Library (VRTE) %s
Viper Frontend Compiler TransPyV %s
TermiNexus Age %sY
Author: terminexus@gvsds.com
Tpv commit: %s
Tpc commit: %s
VRTE commit: %s
Target: %s
""", V_VIPER_VERSION, V_RUNTIME_VERSION, V_TPV_VERSION, V_TERMINEXUS_AGE, V_TPV_COMMIT, V_TPC_COMMIT, V_RUNTIME_COMMIT, V_TARGET, V_LLVM)
""", V_VIPER_VERSION, V_RUNTIME_VERSION, V_TPV_VERSION, V_TPV_COMMIT, V_TPC_COMMIT, V_RUNTIME_COMMIT, V_TARGET, V_LLVM)
return 0
# 打印解析结果
@@ -176,51 +172,41 @@ Target: %s
# 字符串参数
project: str = args.get_str("project")
#if project is not None: stdio.printf(" --project: %s\n", project)
#else: stdio.printf(" --project: (未指定)\n")
src: str = args.get_str("src")
#if src is not None: stdio.printf(" --src: %s\n", src)
#else: stdio.printf(" --src: (未指定)\n")
temp: str = args.get_str("temp")
#if temp is not None: stdio.printf(" --temp: %s\n", temp)
#else: stdio.printf(" --temp: (未指定)\n")
output: str = args.get_str("output")
#if output is not None: stdio.printf(" --output: %s\n", output)
#else: stdio.printf(" --output: (未指定)\n")
phase: str = args.get_str("phase")
#if phase is not None: stdio.printf(" --phase: %s\n", phase)
#else: stdio.printf(" --phase: (未指定,默认 all)\n")
cc: str = args.get_str("cc")
#if cc is not None: stdio.printf(" --cc: %s\n", cc)
#else: stdio.printf(" --cc: (未指定)\n")
# 布尔参数
_gb_clean: INT = args.get_bool("clean")
#if _gb_clean: stdio.printf(" --clean: True\n")
#else: stdio.printf(" --clean: False\n")
#if project is not None: stdio.printf(" --project: %s\n", project)
#else: stdio.printf(" --project: (未指定)\n")
#if src is not None: stdio.printf(" --src: %s\n", src)
#else: stdio.printf(" --src: (未指定)\n")
#if temp is not None: stdio.printf(" --temp: %s\n", temp)
#else: stdio.printf(" --temp: (未指定)\n")
#if output is not None: stdio.printf(" --output: %s\n", output)
#else: stdio.printf(" --output: (未指定)\n")
#if phase is not None: stdio.printf(" --phase: %s\n", phase)
#else: stdio.printf(" --phase: (未指定,默认 all)\n")
#if cc is not None: stdio.printf(" --cc: %s\n", cc)
#else: stdio.printf(" --cc: (未指定)\n")
#if _gb_clean: stdio.printf(" --clean: True\n")
#else: stdio.printf(" --clean: False\n")
#if args.get_bool("run"): stdio.printf(" --run: True\n")
#else: stdio.printf(" --run: False\n")
#if args.get_bool("rebuild-includes"): stdio.printf(" --rebuild-includes: True\n")
#else: stdio.printf(" --rebuild-includes: False\n")
#if args.get_bool("clear-cache"): stdio.printf(" --clear-cache: True\n")
#else: stdio.printf(" --clear-cache: False\n")
#if args.get_bool("clear-cache"): stdio.printf(" --clear-cache: True\n")
#else: stdio.printf(" --clear-cache: False\n")
#stdio.printf("\n参数解析完成。\n")
# ASan 模式:设置 BuildPipeline 全局标志(compile_ll_to_obj 先 opt 插桩,链接 asan 库)
# ASan 模式
# includes 缓存用独立目录 .binary_asan 隔离 asan 插桩 obj,避免与非 asan obj 混链
# (asan obj 引用 __asan_init 等符号,非 asan 链接不提供 asan 库 → undefined reference)
if args.get_bool("asan"):
BuildPipeline._asan_mode = True
Config.set_inc_bin_suffix(".binary_asan")
Config._inc_bin_suffix = ".binary_asan"
if log is not None:
log.info("ASan 模式已启用(opt -passes=asan + libclang_rt)", "asan")
# ASan 模式清理 asan includes 缓存(强制重建 asan 插桩 obj)
@@ -234,7 +220,7 @@ Target: %s
log.info(fb_asan, "asan")
else:
BuildPipeline._asan_mode = False
Config.set_inc_bin_suffix(".binary")
Config._inc_bin_suffix = ".binary"
# --nowarn-register:抑制"外部函数返回类型未登记"类 WARN 输出
if args.get_bool("nowarn-register"):