fix(phase1): 旧 5 参 def 前补全量 includes 预注册(1a-pre),修复'无法构建 SHA1 映射'

178ea40 重构把全量 includes 扫描/注册(PopulateSha1MapStore + 逐文件 import 依赖 PopulateIncludesDeps)从 Phase1Main 移除,依赖注册式 def 在 BFS 中自行登记。改用旧 5 参只读 def(调用点同步改回 5 参)后 store 无预注册 → _BuildIncludesSha1Map 返回 0 → '无法构建 SHA1 映射' 终止。

按 ab0f37e 1a-pre 模式补回:scan_includes 全量扫描 → PopulateSha1MapStore 登记 store → 逐文件 declare_only=2 解析 import 依赖(含 _inject_auto_container_visibility)→ PopulateIncludesDeps(文件级 mark/reset 防 OOM)。_BuildReachableResult 增加 reachable_set/count 过滤,result 只保留可达 includes 子集(1a/1b 只翻译可达文件)。
This commit is contained in:
TermiNexus committed 2026-09-05 12:56:10 +08:00
1 parent 50d53d3ce6
commit c35246f426
2 files changed
+117 -7

No files matched your search

+114 -4
View File
@@ -244,8 +244,14 @@ def _BreakContainerCyclesInDeps(temp_dir: str) -> int:
# ScanResult 指针(stdlib 分配,调用方负责释放);失败返回 None
# ============================================================
def _BuildReachableResult(mb: memhub.MemBuddy | t.CPtr,
includes_dir: str) -> IncludesScanner.ScanResult | t.CPtr:
"""从 Sha1Store(仅可达 includes + App)构建可达 FileEntry 列表"""
includes_dir: str,
reachable_set: str = None,
reachable_count: int = 0) -> IncludesScanner.ScanResult | t.CPtr:
"""从 Sha1Store(可达 includes + App)构建可达 FileEntry 列表
reachable_set/reachable_count 非空时按可达集合过滤:includes 预注册是
全量 store(PopulateSha1MapStore),1a/1b 只处理 reachable 子集。
"""
if mb is None:
return None
store_count: t.CSizeT = t.CSizeT(StubMerger._sha1_store_count)
@@ -264,6 +270,10 @@ def _BuildReachableResult(mb: memhub.MemBuddy | t.CPtr,
iidx: t.CSizeT = t.CSizeT(i) * StubMerger.MAX_INC_DIR_LEN
if StubMerger._sha1_store_incdir[iidx] == '\0':
continue
# 可达过滤(预注册为全量 store,result 只保留 reachable 子集)
if reachable_count > 0 and reachable_set is not None:
if StubMergerCollect._is_in_sha1_set(StubMerger._sha1_store_arr + sidx, reachable_set, reachable_count) == 0:
continue
eaddr: t.CUInt64T = t.CUInt64T(result.Entries) + t.CUInt64T(result.Count) * entry_size
entry: IncludesScanner.FileEntry | t.CPtr = (IncludesScanner.FileEntry | t.CPtr)(t.CVoid(eaddr, t.CPtr))
if entry is None:
@@ -361,6 +371,105 @@ def RunPhase1(mb: memhub.MemBuddy | t.CPtr, includes_dir: str, temp_dir: str,
# 悬空 → 后续 tokenize 的 _kw_lookup strcmp 访问 0x4 崩溃(1.log ASan)。
ast._init_tables(mb)
# ============================================================
# 旧 5 参 def 兼容预注册(补回 178ea40 重构时移除的 1a-pre)
#
# 旧 _BuildReachableSha1Set 只读全局存储器:BFS 前必须已有全量
# includes 的 sha1→module 映射(PopulateSha1MapStore)与每文件的
# import 依赖内存(PopulateIncludesDeps)。注册式新 def 是在 BFS 中
# 自行登记,旧 def 没有该逻辑,故在 reachable 之前全量扫描注册。
# ============================================================
pp_t0: t.CUInt64T = w32.win32base.GetTickCount64()
pp_res: IncludesScanner.ScanResult | t.CPtr = IncludesScanner.scan_includes(mb, includes_dir)
if pp_res is None:
VLogger.error("includes 预扫描失败(scan_includes 返回 None),终止编译", "Phase1")
return 1
pp_es: t.CSizeT = IncludesScanner.FileEntry.__sizeof__()
pp_store_count: int = StubMergerStore.PopulateSha1MapStore(pp_res)
if pp_store_count <= 0:
VLogger.error(f"includes 预注册失败(PopulateSha1MapStore={pp_store_count}),终止编译", "Phase1")
return 1
pp_fail: int = 0
pp_ok: int = 0
for pp_i in range(pp_res.Count):
pp_mark: t.CSizeT = mb.mark()
pp_ea: t.CUInt64T = t.CUInt64T(pp_res.Entries) + t.CUInt64T(pp_i) * pp_es
pp_ent: IncludesScanner.FileEntry | t.CPtr = (IncludesScanner.FileEntry | t.CPtr)(t.CVoid(pp_ea, t.CPtr))
if pp_ent is None or pp_ent.Sha1 is None or pp_ent.Path is None:
pp_fail += 1
mb.reset_to(pp_mark)
continue
pp_sha1: str = pp_ent.Sha1
pp_f: fileio.File | t.CPtr = fileio.File(pp_ent.Path, fileio.MODE.R)
if pp_f.closed:
pp_fail += 1
mb.reset_to(pp_mark)
continue
pp_buf: bytes = stdlib.malloc(Phase1.SRC_BUF_SIZE)
if pp_buf is None:
pp_f.close()
pp_fail += 1
mb.reset_to(pp_mark)
continue
pp_br: LONG = pp_f.read_all(pp_buf, Phase1.SRC_BUF_SIZE)
pp_f.close()
if pp_br <= 0:
stdlib.free(pp_buf)
pp_fail += 1
mb.reset_to(pp_mark)
continue
if pp_br < Phase1.SRC_BUF_SIZE:
pp_buf[pp_br] = 0
else:
pp_buf[Phase1.SRC_BUF_SIZE - 1] = 0
pp_lx: ast.Lexer | t.CPtr = ast.new_lexer(mb)
pp_tree: ast.AST | t.CPtr = None
if pp_lx is not None:
ast._lexer_init(pp_lx, pp_buf, mb)
pp_tok: ast.Token | t.CPtr = ast.tokenize(pp_lx)
pp_tree = ast.parse_tokens(mb, pp_tok)
if pp_tree is None:
stdlib.free(pp_buf)
pp_fail += 1
VLogger.error(f"includes 预注册解析失败: {pp_ent.Path}", "Phase1")
mb.reset_to(pp_mark)
continue
pp_tr: HandlesTranslator.Translator | t.CPtr = HandlesTranslator.Translator()
if pp_tr is None:
stdlib.free(pp_buf)
pp_fail += 1
mb.reset_to(pp_mark)
continue
pp_tr.ModuleSha1 = pp_sha1
pp_tr._declare_only = 2
pp_tr.CurrentPackage = GenApi.compute_package_from_relpath(mb, pp_ent.RelPath)
GenApi.set_current_file_type(pp_ent.Path)
GenApi.set_current_file_imports(pp_ent.Path)
GenApi.set_current_module_sha1(pp_sha1)
GenApi.clear_cdefine_constants()
GenApi.clear_ctypedefs()
GenApi.reset_visible_structs(mb, 0)
pp_rc: int = pp_tr.translate(pp_tree)
if pp_rc == 0:
pp_tr._inject_auto_container_visibility(mb, pp_tree)
if pp_tr._imported_modules is not None:
StubMergerStore.PopulateIncludesDeps(pp_sha1, pp_tr._imported_modules)
pp_ok += 1
else:
pp_fail += 1
VLogger.error(f"includes 预注册翻译失败: {pp_ent.Path}", "Phase1")
if pp_tr._global_names is not None:
stdlib.free(pp_tr._global_names)
if pp_tr._nonlocal_names is not None:
stdlib.free(pp_tr._nonlocal_names)
stdlib.free(pp_buf)
mb.reset_to(pp_mark)
pp_t1: t.CUInt64T = w32.win32base.GetTickCount64()
VLogger.info(f"includes 预注册: {pp_ok} 个(失败 {pp_fail},{pp_t1 - pp_t0} ms)", "Phase1")
if pp_fail > 0:
VLogger.error(f"includes 预注册有 {pp_fail} 个失败,终止编译", "Phase1")
return 1
# 依赖图按需扫描(App 优先模型):
# 1) 先扫 App 源文件(Config.SourceDir)的 import 依赖 → 初始队列
# 2) BFS 沿队列按文件系统解析 includes 文件,只对可达 includes
@@ -376,7 +485,7 @@ def RunPhase1(mb: memhub.MemBuddy | t.CPtr, includes_dir: str, temp_dir: str,
if reachable_set is not None:
string.memset(reachable_set, 0, StubMerger.MAX_INCLUDES_SHA1 * 17)
reachable_count = StubMergerBuild._BuildReachableSha1Set(
mb, Config.SourceDir, temp_dir, reachable_set, None, includes_dir)
mb, Config.SourceDir, temp_dir, reachable_set, None)
if reachable_count < 0:
VLogger.error("可达集合构建失败(依赖图扫描失败),终止编译", "Phase1")
return 1
@@ -398,7 +507,8 @@ def RunPhase1(mb: memhub.MemBuddy | t.CPtr, includes_dir: str, temp_dir: str,
# 从 Sha1Store(仅可达 includes + App)构造可达 FileEntry 列表:
# 后续 1a/1b-pre/1b 直接遍历 result(incdir 非空条目=includes),
# use_reachable 过滤幂等保留(result 即可达子集)
result: IncludesScanner.ScanResult | t.CPtr = _BuildReachableResult(mb, includes_dir)
result: IncludesScanner.ScanResult | t.CPtr = _BuildReachableResult(
mb, includes_dir, reachable_set, reachable_count)
if result is None:
VLogger.error("可达 FileEntry 列表构建失败,终止编译", "Phase1")
return 1
+3 -3
View File
@@ -763,7 +763,7 @@ def RunMultiFileProject(mb: memhub.MemBuddy | t.CPtr,
do_phase1: int, do_phase2: int,
log: VLogger.Logger | t.CPtr,
args: argparse.ParsedArgs | t.CPtr,
linker_static_libs: str = None,
linker_static_libs: str = None,
linker_dynamic_libs: str = None) -> int:
"""多文件项目编译
@@ -837,7 +837,7 @@ def RunMultiFileProject(mb: memhub.MemBuddy | t.CPtr,
else:
string.memset(rs_05, 0, StubMerger.MAX_INCLUDES_SHA1 * 17)
rc_05: int = StubMergerBuild._BuildReachableSha1Set(
mb, source_dir, temp_dir, rs_05, None, includes_dir)
mb, source_dir, temp_dir, rs_05, None)
if rc_05 < 0:
VLogger.error("依赖图扫描失败,无法填充 Sha1Store", "project")
elif rc_05 > 0:
@@ -1615,7 +1615,7 @@ def RunMultiFileProject(mb: memhub.MemBuddy | t.CPtr,
if reachable_set is not None:
string.memset(reachable_set, 0, REACHABLE_SET_SIZE)
reachable_count = StubMergerBuild._BuildReachableSha1Set(
mb, source_dir, temp_dir, reachable_set, app_deps_buf, includes_dir)
mb, source_dir, temp_dir, reachable_set, app_deps_buf)
VLogger.info(f"可达 includes SHA1: {reachable_count} 个", "PhaseB+")
# fast-fail: 可达集合构建失败(依赖未找到),永不回退,直接终止
if reachable_count < 0: