700 lines
28 KiB
Python
700 lines
28 KiB
Python
import t, c
|
||
from stdint import *
|
||
import stdio
|
||
import string
|
||
import stdlib
|
||
import memhub
|
||
import viperlib
|
||
import w32.fileio as fileio
|
||
import w32.win32file
|
||
import w32.win32base
|
||
import ast
|
||
import llvmlite
|
||
import lib.core.VLogger as VLogger
|
||
import lib.core.Handles.HandlesTranslator as HandlesTranslator
|
||
import lib.core.Handles.HandlesStruct as HandlesStruct
|
||
import lib.core.Handles.HandlesType as HandlesType
|
||
import lib.core.Handles.HandlesExprCall as HandlesExprCall
|
||
import lib.core.Handles.HandlesImports as HandlesImports
|
||
import lib.core.IncludesScanner as IncludesScanner
|
||
import lib.core.StubMerger as StubMerger
|
||
import lib.Projectrans.Config as Config
|
||
|
||
# 全局 mbuddy 指针
|
||
_mbuddy: memhub.MemManager | t.CPtr
|
||
|
||
# 源代码缓冲区大小(1MB)
|
||
SRC_BUF_SIZE: t.CDefine = 1048576
|
||
|
||
# ============================================================
|
||
# RunPhase1 - Phase1: 扫描 includes 目录,按需翻译并生成 stub
|
||
#
|
||
# 对每个 .py 文件检查 stub 是否已存在,若不存在则翻译并分离 stub。
|
||
# "按需翻译":仅对 stub 不存在的文件执行翻译,避免重复工作。
|
||
#
|
||
# Args:
|
||
# mb: 内存池
|
||
# includes_dir: includes 目录路径
|
||
# temp_dir: 临时目录(保存 stub)
|
||
# log: 日志器
|
||
#
|
||
# Returns:
|
||
# 0 成功,非 0 失败
|
||
# ============================================================
|
||
def RunPhase1(mb: memhub.MemBuddy | t.CPtr, includes_dir: str, temp_dir: str,
|
||
log: VLogger.Logger | t.CPtr) -> int:
|
||
"""Phase1: 扫描 includes 目录,按需翻译并生成 stub"""
|
||
if includes_dir is None or temp_dir is None:
|
||
stdio.printf("[Phase1] includes_dir 或 temp_dir 为空,跳过\n")
|
||
return 1
|
||
|
||
if log is not None:
|
||
log.banner("Phase1: 扫描 includes(按需翻译)")
|
||
|
||
# 扫描 includes 目录
|
||
result: IncludesScanner.ScanResult | t.CPtr = IncludesScanner.scan_includes(mb, includes_dir)
|
||
if result is None:
|
||
stdio.printf("[Phase1] 扫描失败\n")
|
||
return 1
|
||
|
||
# 读取 _sha1_map.txt 获取需要的 includes SHA1 集合
|
||
# 优先使用 Projectrans.py 生成的 _sha1_map.txt(含依赖分析,只包含需要的 includes)
|
||
# 若不存在,则从扫描结果生成(包含所有 includes,可能导致结构体表溢出)
|
||
sha1_set: str = stdlib.malloc(StubMerger.MAX_INCLUDES_SHA1 * 17)
|
||
if sha1_set is None:
|
||
stdio.printf("[Phase1] sha1_set 分配失败\n")
|
||
return 1
|
||
string.memset(sha1_set, 0, StubMerger.MAX_INCLUDES_SHA1 * 17)
|
||
set_count: int = StubMerger._load_includes_sha1_set(mb, temp_dir, sha1_set)
|
||
if set_count <= 0:
|
||
stdio.printf("[Phase1] _sha1_map.txt 不存在或为空,从扫描结果生成\n")
|
||
StubMerger.WriteIncludesSha1Map(mb, temp_dir, result, None, 0)
|
||
set_count = StubMerger._load_includes_sha1_set(mb, temp_dir, sha1_set)
|
||
if set_count < 0:
|
||
stdio.printf("[Phase1] 无法加载 _sha1_map.txt,跳过 Phase1\n")
|
||
return 1
|
||
stdio.printf("[Phase1] includes SHA1 集合: %d 个\n", set_count)
|
||
stdio.fflush(0)
|
||
|
||
# 构建模块 SHA1 映射(供跨模块函数调用名混淆使用)
|
||
td_len_p1map: t.CSizeT = string.strlen(temp_dir)
|
||
p1_sha1_arr: bytes = stdlib.malloc(StubMerger.MAX_INCLUDES * 17)
|
||
p1_mod_arr: bytes = stdlib.malloc(StubMerger.MAX_INCLUDES * 64)
|
||
p1_inc_count: int = 0
|
||
if p1_sha1_arr is not None and p1_mod_arr is not None:
|
||
p1_inc_count = StubMerger._BuildIncludesSha1Map(temp_dir, td_len_p1map, p1_sha1_arr, p1_mod_arr)
|
||
HandlesExprCall.set_module_sha1_map(p1_sha1_arr, p1_mod_arr, p1_inc_count)
|
||
|
||
# 初始化 AST 表(只需一次)
|
||
ast._init_tables(mb)
|
||
|
||
# FileEntry 结构体大小(Phase 1a 和 1b 共用)
|
||
entry_size: t.CSizeT = IncludesScanner.FileEntry.__sizeof__()
|
||
|
||
# ============================================================
|
||
# Phase 1a-pre: 扫描所有 includes 文件的 import 依赖
|
||
#
|
||
# 只处理 Import/ImportFrom 语句,跳过 ClassDef/FunctionDef 等,
|
||
# 不调用 resolve_annotation_type,避免 list[...] 等不支持的语法触发 crash。
|
||
# 生成 .deps.txt 供依赖图按需翻译使用。
|
||
# ============================================================
|
||
stdio.printf("[Phase1a-pre] 扫描 import 依赖\n")
|
||
p1a_registered: int = 0
|
||
p1a_skipped: int = 0
|
||
p1a_failed: int = 0
|
||
|
||
for i in range(result.Count):
|
||
entry_addr_a: t.CUInt64T = t.CUInt64T(result.Entries) + i * entry_size
|
||
entry_a: IncludesScanner.FileEntry | t.CPtr = (IncludesScanner.FileEntry | t.CPtr)(t.CVoid(entry_addr_a, t.CPtr))
|
||
if entry_a is None:
|
||
p1a_failed += 1
|
||
continue
|
||
|
||
sha1_a: str = entry_a.Sha1
|
||
if sha1_a is None:
|
||
p1a_failed += 1
|
||
continue
|
||
|
||
if StubMerger._is_in_sha1_set(sha1_a, sha1_set, set_count) == 0:
|
||
p1a_skipped += 1
|
||
continue
|
||
|
||
# 读取文件内容
|
||
file_path_a: str = entry_a.Path
|
||
f_a: fileio.File | t.CPtr = fileio.File(file_path_a, fileio.MODE.R)
|
||
if f_a.closed:
|
||
p1a_failed += 1
|
||
continue
|
||
|
||
src_buf_a: bytes = stdlib.malloc(SRC_BUF_SIZE)
|
||
if src_buf_a is None:
|
||
f_a.close()
|
||
p1a_failed += 1
|
||
continue
|
||
|
||
bytes_read_a: LONG = f_a.read_all(src_buf_a, SRC_BUF_SIZE)
|
||
f_a.close()
|
||
if bytes_read_a <= 0:
|
||
stdlib.free(src_buf_a)
|
||
p1a_failed += 1
|
||
continue
|
||
if bytes_read_a < SRC_BUF_SIZE:
|
||
src_buf_a[bytes_read_a] = 0
|
||
else:
|
||
src_buf_a[SRC_BUF_SIZE - 1] = 0
|
||
|
||
# 解析 AST
|
||
lx_a: ast.Lexer | t.CPtr = ast.new_lexer(mb)
|
||
if lx_a is None:
|
||
stdlib.free(src_buf_a)
|
||
p1a_failed += 1
|
||
continue
|
||
ast._lexer_init(lx_a, src_buf_a, mb)
|
||
tokens_a: ast.Token | t.CPtr = ast.tokenize(lx_a)
|
||
tree_a: ast.AST | t.CPtr = ast.parse_tokens(mb, tokens_a)
|
||
if tree_a is None:
|
||
stdlib.free(src_buf_a)
|
||
p1a_failed += 1
|
||
continue
|
||
|
||
# 创建 Translator,设置 _declare_only=2(只扫描 import,跳过 ClassDef)
|
||
tr_a: HandlesTranslator.Translator | t.CPtr = HandlesTranslator.Translator()
|
||
if tr_a is None:
|
||
stdlib.free(src_buf_a)
|
||
p1a_failed += 1
|
||
continue
|
||
tr_a.ModuleSha1 = sha1_a
|
||
tr_a._declare_only = 2
|
||
tr_a.CurrentPackage = HandlesImports.compute_package_from_relpath(mb, entry_a.RelPath)
|
||
HandlesType.set_current_file(file_path_a)
|
||
HandlesType.clear_cdefine_constants()
|
||
HandlesStruct.reset_visible_structs(mb, 0)
|
||
ret_a: int = tr_a.translate(tree_a)
|
||
if ret_a != 0:
|
||
p1a_failed += 1
|
||
else:
|
||
p1a_registered += 1
|
||
|
||
# 生成 .deps.txt(记录依赖模块名,供依赖图按需翻译使用)
|
||
td_len_a: t.CSizeT = string.strlen(temp_dir)
|
||
deps_path_a: bytes = stdlib.malloc(td_len_a + 32)
|
||
if deps_path_a is not None:
|
||
viperlib.snprintf(deps_path_a, td_len_a + 32, "%s/%s.deps.txt", temp_dir, sha1_a)
|
||
df_a: fileio.File | t.CPtr = fileio.File(deps_path_a, fileio.MODE.W)
|
||
if not df_a.closed:
|
||
if tr_a._imported_modules is not None:
|
||
dl_a: t.CSizeT = string.strlen(tr_a._imported_modules)
|
||
df_a.write(tr_a._imported_modules, dl_a)
|
||
df_a.close()
|
||
stdlib.free(deps_path_a)
|
||
|
||
# 释放 Translator 的 C malloc 资源
|
||
if tr_a._global_names is not None:
|
||
stdlib.free(tr_a._global_names)
|
||
if tr_a._nonlocal_names is not None:
|
||
stdlib.free(tr_a._nonlocal_names)
|
||
|
||
stdlib.free(src_buf_a)
|
||
|
||
stdio.printf("[Phase1a-pre] 完成: 扫描=%d 跳过=%d 失败=%d\n", p1a_registered, p1a_skipped, p1a_failed)
|
||
|
||
# ============================================================
|
||
# 依赖图按需翻译:构建可达 SHA1 集合
|
||
#
|
||
# 从 Config.SourceDir 的源文件开始,解析 import 语句,递归收集
|
||
# 可达的 includes 文件 SHA1。Phase 1b 只翻译可达集合中的文件,
|
||
# 避免翻译不需要的 includes(如 Test 不依赖 llvmlite,则不翻译)。
|
||
# 如果 Config.SourceDir 不可用(仅运行 Phase1),回退到 sha1_set。
|
||
# ============================================================
|
||
reachable_set: str = None
|
||
reachable_count: int = 0
|
||
use_reachable: int = 0
|
||
if Config.SourceDir is not None:
|
||
reachable_set = stdlib.malloc(StubMerger.MAX_INCLUDES_SHA1 * 17)
|
||
if reachable_set is not None:
|
||
string.memset(reachable_set, 0, StubMerger.MAX_INCLUDES_SHA1 * 17)
|
||
reachable_count = StubMerger._BuildReachableSha1Set(mb, Config.SourceDir, temp_dir, reachable_set)
|
||
if reachable_count > 0:
|
||
use_reachable = 1
|
||
stdio.printf("[Phase1b] 使用可达 SHA1 集合过滤: %d 个\n", reachable_count)
|
||
# 用可达集合重新生成 _sha1_map.txt(按图求索的最终产物)
|
||
# Phase B+ 只遍历这些条目,避免编译不需要的 includes(如 asm.py)
|
||
StubMerger.WriteIncludesSha1Map(mb, temp_dir, result, reachable_set, reachable_count)
|
||
# 重新加载 sha1_set,使后续 Phase 1a-pre/1a/1b 的过滤也使用可达集合
|
||
string.memset(sha1_set, 0, StubMerger.MAX_INCLUDES_SHA1 * 17)
|
||
set_count = StubMerger._load_includes_sha1_set(mb, temp_dir, sha1_set)
|
||
stdio.printf("[Phase1b] _sha1_map.txt 已重写为可达集合: %d 个\n", set_count)
|
||
else:
|
||
stdio.printf("[Phase1b] 可达 SHA1 集合构建失败,回退到全量集合\n")
|
||
stdlib.free(reachable_set)
|
||
reachable_set = None
|
||
|
||
# ============================================================
|
||
# Phase 1a: 注册可达 includes 文件的 struct/enum/union
|
||
#
|
||
# 解决字母序依赖问题:按字母顺序翻译时,后面的 struct 未注册
|
||
# 前面就需要用。Phase 1a 先注册所有 struct/enum/union 到全局表,
|
||
# Phase 1b 全量翻译时 struct 已注册,走 existing 路径只翻译方法体。
|
||
# 只处理可达文件,避免翻译不需要的 includes(如 Test 不依赖 ast 模块)。
|
||
# ============================================================
|
||
stdio.printf("[Phase1a] 注册可达文件 struct/enum/union\n")
|
||
stdio.fflush(0)
|
||
p1a_reg: int = 0
|
||
p1a_skp: int = 0
|
||
p1a_fl: int = 0
|
||
|
||
for i in range(result.Count):
|
||
stdio.printf("[Phase1a] iter=%d/%d\n", i, result.Count)
|
||
stdio.fflush(0)
|
||
entry_addr_r: t.CUInt64T = t.CUInt64T(result.Entries) + i * entry_size
|
||
stdio.printf("[Phase1a] iter=%d entry_addr=%d\n", i, entry_addr_r)
|
||
stdio.fflush(0)
|
||
entry_r: IncludesScanner.FileEntry | t.CPtr = (IncludesScanner.FileEntry | t.CPtr)(t.CVoid(entry_addr_r, t.CPtr))
|
||
stdio.printf("[Phase1a] iter=%d entry_r=%d\n", i, entry_r)
|
||
stdio.fflush(0)
|
||
if entry_r is None:
|
||
p1a_fl += 1
|
||
continue
|
||
|
||
sha1_r: str = entry_r.Sha1
|
||
stdio.printf("[Phase1a] iter=%d sha1=%s\n", i, sha1_r)
|
||
stdio.fflush(0)
|
||
if sha1_r is None:
|
||
p1a_fl += 1
|
||
continue
|
||
|
||
# 按需翻译过滤:只处理可达文件
|
||
if use_reachable != 0:
|
||
if StubMerger._is_in_sha1_set(sha1_r, reachable_set, reachable_count) == 0:
|
||
p1a_skp += 1
|
||
continue
|
||
else:
|
||
if StubMerger._is_in_sha1_set(sha1_r, sha1_set, set_count) == 0:
|
||
p1a_skp += 1
|
||
continue
|
||
|
||
# 读取文件内容
|
||
file_path_r: str = entry_r.Path
|
||
stdio.printf("[Phase1a] 处理: sha1=%s path=%s\n", sha1_r, file_path_r)
|
||
stdio.fflush(0)
|
||
f_r: fileio.File | t.CPtr = fileio.File(file_path_r, fileio.MODE.R)
|
||
if f_r.closed:
|
||
p1a_fl += 1
|
||
continue
|
||
|
||
src_buf_r: bytes = stdlib.malloc(SRC_BUF_SIZE)
|
||
if src_buf_r is None:
|
||
f_r.close()
|
||
p1a_fl += 1
|
||
continue
|
||
|
||
bytes_read_r: LONG = f_r.read_all(src_buf_r, SRC_BUF_SIZE)
|
||
f_r.close()
|
||
if bytes_read_r <= 0:
|
||
stdlib.free(src_buf_r)
|
||
p1a_fl += 1
|
||
continue
|
||
if bytes_read_r < SRC_BUF_SIZE:
|
||
src_buf_r[bytes_read_r] = 0
|
||
else:
|
||
src_buf_r[SRC_BUF_SIZE - 1] = 0
|
||
|
||
# 解析 AST
|
||
lx_r: ast.Lexer | t.CPtr = ast.new_lexer(mb)
|
||
if lx_r is None:
|
||
stdlib.free(src_buf_r)
|
||
p1a_fl += 1
|
||
continue
|
||
ast._lexer_init(lx_r, src_buf_r, mb)
|
||
tokens_r: ast.Token | t.CPtr = ast.tokenize(lx_r)
|
||
tree_r: ast.AST | t.CPtr = ast.parse_tokens(mb, tokens_r)
|
||
if tree_r is None:
|
||
stdlib.free(src_buf_r)
|
||
p1a_fl += 1
|
||
continue
|
||
|
||
# 创建 Translator,设置 _declare_only=1(注册 struct/enum/union)
|
||
tr_r: HandlesTranslator.Translator | t.CPtr = HandlesTranslator.Translator()
|
||
if tr_r is None:
|
||
stdlib.free(src_buf_r)
|
||
p1a_fl += 1
|
||
continue
|
||
tr_r.ModuleSha1 = sha1_r
|
||
tr_r._declare_only = 1
|
||
tr_r.CurrentPackage = HandlesImports.compute_package_from_relpath(mb, entry_r.RelPath)
|
||
HandlesType.set_current_file(file_path_r)
|
||
HandlesType.clear_cdefine_constants()
|
||
HandlesStruct.reset_visible_structs(mb, 0)
|
||
stdio.printf("[Phase1a] 翻译开始: sha1=%s\n", sha1_r)
|
||
stdio.fflush(0)
|
||
ret_r: int = tr_r.translate(tree_r)
|
||
stdio.printf("[Phase1a] 翻译完成: sha1=%s ret=%d\n", sha1_r, ret_r)
|
||
stdio.fflush(0)
|
||
if ret_r != 0:
|
||
p1a_fl += 1
|
||
else:
|
||
p1a_reg += 1
|
||
|
||
# 释放 Translator 的 C malloc 资源
|
||
stdio.printf("[Phase1a] 释放开始: sha1=%s\n", sha1_r)
|
||
stdio.fflush(0)
|
||
if tr_r._global_names is not None:
|
||
stdio.printf("[Phase1a] free(_global_names) 前: sha1=%s\n", sha1_r)
|
||
stdio.fflush(0)
|
||
stdlib.free(tr_r._global_names)
|
||
stdio.printf("[Phase1a] free(_global_names) 后: sha1=%s\n", sha1_r)
|
||
stdio.fflush(0)
|
||
if tr_r._nonlocal_names is not None:
|
||
stdio.printf("[Phase1a] free(_nonlocal_names) 前: sha1=%s\n", sha1_r)
|
||
stdio.fflush(0)
|
||
stdlib.free(tr_r._nonlocal_names)
|
||
stdio.printf("[Phase1a] free(_nonlocal_names) 后: sha1=%s\n", sha1_r)
|
||
stdio.fflush(0)
|
||
stdio.printf("[Phase1a] free(src_buf_r) 前: sha1=%s\n", sha1_r)
|
||
stdio.fflush(0)
|
||
stdlib.free(src_buf_r)
|
||
stdio.printf("[Phase1a] free(src_buf_r) 后: sha1=%s\n", sha1_r)
|
||
stdio.fflush(0)
|
||
|
||
stdio.printf("[Phase1a] 循环已退出\n")
|
||
stdio.fflush(0)
|
||
test_val: int = 42
|
||
stdio.printf("[Phase1a] test_val=%d p1a_reg=%d p1a_skp=%d p1a_fl=%d\n", test_val, p1a_reg, p1a_skp, p1a_fl)
|
||
stdio.fflush(0)
|
||
stdio.printf("[Phase1a] done simple\n")
|
||
stdio.fflush(0)
|
||
stdio.printf("[Phase1a] done ascii reg=%d skp=%d fl=%d\n", p1a_reg, p1a_skp, p1a_fl)
|
||
stdio.fflush(0)
|
||
test_ptr: bytes = stdlib.malloc(64)
|
||
if test_ptr is not None:
|
||
stdio.printf("[Phase1a] malloc test ok ptr=%d\n", test_ptr)
|
||
stdio.fflush(0)
|
||
stdlib.free(test_ptr)
|
||
stdio.printf("[Phase1a] free test ok\n")
|
||
stdio.fflush(0)
|
||
stdio.printf("[Phase1a] 测试中文=%d\n", 42)
|
||
stdio.fflush(0)
|
||
stdio.printf("[Phase1a] 完成: 注册=%d 跳过=%d 失败=%d\n", 15, 78, 0)
|
||
stdio.fflush(0)
|
||
stdio.printf("[Phase1a] before_var_check ok\n")
|
||
stdio.fflush(0)
|
||
stdio.printf("[Phase1a] 完成: 注册=%d\n", p1a_reg)
|
||
stdio.fflush(0)
|
||
stdio.printf("[Phase1a] 完成: 注册=%d 跳过=%d\n", p1a_reg, p1a_skp)
|
||
stdio.fflush(0)
|
||
stdio.printf("[Phase1a] 完成: 注册=%d 跳过=%d 失败=%d\n", p1a_reg, p1a_skp, p1a_fl)
|
||
stdio.fflush(0)
|
||
stdio.printf("[Phase1a] ALL_DIAG_OK\n")
|
||
stdio.fflush(0)
|
||
|
||
# ============================================================
|
||
# Phase 1b: 全量翻译(struct 已注册,走 existing 路径翻译方法体)
|
||
# ============================================================
|
||
# 遍历每个文件
|
||
translated: int = 0
|
||
skipped: int = 0
|
||
failed: int = 0
|
||
|
||
stdio.printf("[Phase1b] 开始: Count=%d entry_size=%d\n", result.Count, entry_size)
|
||
stdio.fflush(0)
|
||
for i in range(result.Count):
|
||
stdio.printf("[Phase1b] iter=%d/%d\n", i, result.Count)
|
||
stdio.fflush(0)
|
||
# 获取 entry
|
||
entry_addr: t.CUInt64T = t.CUInt64T(result.Entries) + i * entry_size
|
||
stdio.printf("[Phase1b] iter=%d entry_addr=%d\n", i, entry_addr)
|
||
stdio.fflush(0)
|
||
entry: IncludesScanner.FileEntry | t.CPtr = (IncludesScanner.FileEntry | t.CPtr)(t.CVoid(entry_addr, t.CPtr))
|
||
stdio.printf("[Phase1b] iter=%d entry=%d\n", i, entry)
|
||
stdio.fflush(0)
|
||
if entry is None:
|
||
failed += 1
|
||
continue
|
||
|
||
sha1: str = entry.Sha1
|
||
stdio.printf("[Phase1b] iter=%d sha1=%s\n", i, sha1)
|
||
stdio.fflush(0)
|
||
if sha1 is None:
|
||
failed += 1
|
||
continue
|
||
|
||
# 检查 SHA1 是否在翻译集合中(按需翻译:只翻译可达的文件)
|
||
in_set: int = 0
|
||
if use_reachable != 0:
|
||
in_set = StubMerger._is_in_sha1_set(sha1, reachable_set, reachable_count)
|
||
else:
|
||
in_set = StubMerger._is_in_sha1_set(sha1, sha1_set, set_count)
|
||
stdio.printf("[Phase1b] iter=%d in_set=%d use_reachable=%d\n", i, in_set, use_reachable)
|
||
stdio.fflush(0)
|
||
if in_set == 0:
|
||
skipped += 1
|
||
continue
|
||
|
||
# 构造 stub 路径: {temp_dir}/{sha1}.stub.ll
|
||
stdio.printf("[Phase1b] iter=%d strlen 前\n", i)
|
||
stdio.fflush(0)
|
||
dir_len: t.CSizeT = string.strlen(temp_dir)
|
||
sha1_len: t.CSizeT = string.strlen(sha1)
|
||
stdio.printf("[Phase1b] iter=%d strlen 后 dir_len=%d sha1_len=%d\n", i, dir_len, sha1_len)
|
||
stdio.fflush(0)
|
||
stub_path: bytes = stdlib.malloc(dir_len + sha1_len + 16)
|
||
if stub_path is None:
|
||
failed += 1
|
||
continue
|
||
stdio.printf("[Phase1b] iter=%d snprintf 前 stub_path=%d\n", i, stub_path)
|
||
stdio.fflush(0)
|
||
viperlib.snprintf(stub_path, dir_len + sha1_len + 16, "%s/%s.stub.ll", temp_dir, sha1)
|
||
stdio.printf("[Phase1b] iter=%d snprintf 后\n", i)
|
||
stdio.fflush(0)
|
||
|
||
# 检查 stub 是否已存在(按需翻译:跳过已存在的)
|
||
stdio.printf("[Phase1b] iter=%d File() 前 stub_path=%d\n", i, stub_path)
|
||
stdio.fflush(0)
|
||
sf: fileio.File | t.CPtr = fileio.File(stub_path, fileio.MODE.R)
|
||
stdio.printf("[Phase1b] iter=%d File() 后 sf=%d\n", i, sf)
|
||
stdio.fflush(0)
|
||
if sf is None:
|
||
stdio.printf("[Phase1b] iter=%d sf is None, 翻译\n", i)
|
||
stdio.fflush(0)
|
||
else:
|
||
stdio.printf("[Phase1b] iter=%d sf.closed=%d\n", i, sf.closed)
|
||
stdio.fflush(0)
|
||
if not sf.closed:
|
||
sf.close()
|
||
# 检查 text.ll 是否也存在(虚表扫描需要 text.ll)
|
||
text_path: bytes = stdlib.malloc(dir_len + sha1_len + 16)
|
||
if text_path is not None:
|
||
viperlib.snprintf(text_path, dir_len + sha1_len + 16, "%s/%s.text.ll", temp_dir, sha1)
|
||
tf: fileio.File | t.CPtr = fileio.File(text_path, fileio.MODE.R)
|
||
if not tf.closed:
|
||
tf.close()
|
||
stdlib.free(text_path)
|
||
stdlib.free(stub_path)
|
||
continue
|
||
stdlib.free(text_path)
|
||
# text.ll 不存在,需要重新翻译
|
||
stdio.printf("[Phase1b] iter=%d RelPath 前\n", i)
|
||
stdio.fflush(0)
|
||
rp: str = entry.RelPath
|
||
stdio.printf("[Phase1b] iter=%d RelPath=%s\n", i, rp)
|
||
stdio.fflush(0)
|
||
stdio.printf("[Phase1] text.ll 不存在,重新翻译: %s (sha1=%s)\n", rp, sha1)
|
||
else:
|
||
# stub 不存在,需要翻译
|
||
stdio.printf("[Phase1b] iter=%d else 分支 RelPath 前\n", i)
|
||
stdio.fflush(0)
|
||
rp: str = entry.RelPath
|
||
stdio.printf("[Phase1b] iter=%d else RelPath=%s\n", i, rp)
|
||
stdio.fflush(0)
|
||
stdio.printf("[Phase1] 翻译: %s (sha1=%s)\n", rp, sha1)
|
||
stdio.fflush(0)
|
||
|
||
stdio.printf("[Phase1b] iter=%d free(stub_path) 前\n", i)
|
||
stdio.fflush(0)
|
||
stdlib.free(stub_path)
|
||
stdio.printf("[Phase1b] iter=%d free(stub_path) 后\n", i)
|
||
stdio.fflush(0)
|
||
|
||
# 读取文件内容
|
||
stdio.printf("[Phase1b] iter=%d entry.Path 前\n", i)
|
||
stdio.fflush(0)
|
||
file_path: str = entry.Path
|
||
stdio.printf("[Phase1b] iter=%d file_path=%s\n", i, file_path)
|
||
stdio.fflush(0)
|
||
stdio.printf("[Phase1b] iter=%d File(file_path) 前\n", i)
|
||
stdio.fflush(0)
|
||
f: fileio.File | t.CPtr = fileio.File(file_path, fileio.MODE.R)
|
||
stdio.printf("[Phase1b] iter=%d File(file_path) 后 f=%d\n", i, f)
|
||
stdio.fflush(0)
|
||
if f is None:
|
||
stdio.printf("[Phase1] 无法打开(None): %s\n", file_path)
|
||
stdio.fflush(0)
|
||
failed += 1
|
||
continue
|
||
stdio.printf("[Phase1b] iter=%d f.closed=%d\n", i, f.closed)
|
||
stdio.fflush(0)
|
||
if f.closed:
|
||
stdio.printf("[Phase1] 无法打开: %s\n", file_path)
|
||
stdio.fflush(0)
|
||
failed += 1
|
||
continue
|
||
|
||
stdio.printf("[Phase1b] iter=%d malloc(src_buf) 前\n", i)
|
||
stdio.fflush(0)
|
||
src_buf: bytes = stdlib.malloc(SRC_BUF_SIZE)
|
||
stdio.printf("[Phase1b] iter=%d malloc(src_buf) 后=%d\n", i, src_buf)
|
||
stdio.fflush(0)
|
||
if src_buf is None:
|
||
f.close()
|
||
failed += 1
|
||
continue
|
||
|
||
stdio.printf("[Phase1b] iter=%d read_all 前\n", i)
|
||
stdio.fflush(0)
|
||
bytes_read: LONG = f.read_all(src_buf, SRC_BUF_SIZE)
|
||
stdio.printf("[Phase1b] iter=%d read_all 后=%d\n", i, bytes_read)
|
||
stdio.fflush(0)
|
||
f.close()
|
||
if bytes_read <= 0:
|
||
stdio.printf("[Phase1] 读取失败: %s\n", file_path)
|
||
stdio.fflush(0)
|
||
stdlib.free(src_buf)
|
||
failed += 1
|
||
continue
|
||
if bytes_read < SRC_BUF_SIZE:
|
||
src_buf[bytes_read] = 0
|
||
else:
|
||
src_buf[SRC_BUF_SIZE - 1] = 0
|
||
|
||
stdio.printf("[Phase1b] iter=%d AST 前\n", i)
|
||
stdio.fflush(0)
|
||
|
||
# 解析 AST
|
||
stdio.printf("[Phase1b] iter=%d new_lexer 前\n", i)
|
||
stdio.fflush(0)
|
||
lx: ast.Lexer | t.CPtr = ast.new_lexer(mb)
|
||
stdio.printf("[Phase1b] iter=%d new_lexer 后=%d\n", i, lx)
|
||
stdio.fflush(0)
|
||
if lx is None:
|
||
stdlib.free(src_buf)
|
||
failed += 1
|
||
continue
|
||
stdio.printf("[Phase1b] iter=%d _lexer_init 前\n", i)
|
||
stdio.fflush(0)
|
||
ast._lexer_init(lx, src_buf, mb)
|
||
stdio.printf("[Phase1b] iter=%d _lexer_init 后\n", i)
|
||
stdio.fflush(0)
|
||
stdio.printf("[Phase1b] iter=%d tokenize 前\n", i)
|
||
stdio.fflush(0)
|
||
tokens: ast.Token | t.CPtr = ast.tokenize(lx)
|
||
stdio.printf("[Phase1b] iter=%d tokenize 后=%d\n", i, tokens)
|
||
stdio.fflush(0)
|
||
stdio.printf("[Phase1b] iter=%d parse_tokens 前\n", i)
|
||
stdio.fflush(0)
|
||
tree: ast.AST | t.CPtr = ast.parse_tokens(mb, tokens)
|
||
stdio.printf("[Phase1b] iter=%d parse_tokens 后=%d\n", i, tree)
|
||
stdio.fflush(0)
|
||
if tree is None:
|
||
stdio.printf("[Phase1] AST 解析失败: %s\n", file_path)
|
||
stdio.fflush(0)
|
||
stdlib.free(src_buf)
|
||
failed += 1
|
||
continue
|
||
|
||
# 翻译 AST → LLVM IR
|
||
stdio.printf("[Phase1b] iter=%d Translator() 前\n", i)
|
||
stdio.fflush(0)
|
||
tr: HandlesTranslator.Translator | t.CPtr = HandlesTranslator.Translator()
|
||
stdio.printf("[Phase1b] iter=%d Translator() 后=%d\n", i, tr)
|
||
stdio.fflush(0)
|
||
if tr is None:
|
||
stdlib.free(src_buf)
|
||
failed += 1
|
||
continue
|
||
stdio.printf("[Phase1b] iter=%d ModuleSha1 前\n", i)
|
||
stdio.fflush(0)
|
||
tr.ModuleSha1 = sha1
|
||
stdio.printf("[Phase1b] iter=%d CurrentPackage 前\n", i)
|
||
stdio.fflush(0)
|
||
tr.CurrentPackage = HandlesImports.compute_package_from_relpath(mb, entry.RelPath)
|
||
stdio.printf("[Phase1b] iter=%d set_current_file 前\n", i)
|
||
stdio.fflush(0)
|
||
HandlesType.set_current_file(file_path)
|
||
HandlesType.clear_cdefine_constants()
|
||
HandlesStruct.reset_visible_structs(mb, 0)
|
||
stdio.printf("[Phase1b] iter=%d translate 前\n", i)
|
||
stdio.fflush(0)
|
||
ret: int = tr.translate(tree)
|
||
stdio.printf("[Phase1b] iter=%d translate 后=%d\n", i, ret)
|
||
stdio.fflush(0)
|
||
if ret != 0:
|
||
stdio.printf("[Phase1] 翻译失败: %s\n", file_path)
|
||
stdlib.free(src_buf)
|
||
if tr._global_names is not None:
|
||
stdlib.free(tr._global_names)
|
||
if tr._nonlocal_names is not None:
|
||
stdlib.free(tr._nonlocal_names)
|
||
failed += 1
|
||
continue
|
||
|
||
# dump stub IR (declarations only)
|
||
PHASE1_IR_SIZE: t.CSizeT = 262144
|
||
stub_buf: bytes = stdlib.malloc(PHASE1_IR_SIZE)
|
||
if stub_buf is None:
|
||
stdlib.free(src_buf)
|
||
if tr._global_names is not None:
|
||
stdlib.free(tr._global_names)
|
||
if tr._nonlocal_names is not None:
|
||
stdlib.free(tr._nonlocal_names)
|
||
failed += 1
|
||
continue
|
||
tr.dump_ir(stub_buf, PHASE1_IR_SIZE, llvmlite.OUTPUT_STUB)
|
||
stub_len: t.CSizeT = string.strlen(stub_buf)
|
||
|
||
# save stub.ll
|
||
dir_len_p1: t.CSizeT = string.strlen(temp_dir)
|
||
stub_path_p1: bytes = stdlib.malloc(dir_len_p1 + 32)
|
||
if stub_path_p1 is not None:
|
||
viperlib.snprintf(stub_path_p1, dir_len_p1 + 32, "%s/%s.stub.ll", temp_dir, sha1)
|
||
sf_p1: fileio.File | t.CPtr = fileio.File(stub_path_p1, fileio.MODE.W)
|
||
if not sf_p1.closed:
|
||
sf_p1.write(stub_buf, stub_len)
|
||
sf_p1.close()
|
||
stdlib.free(stub_path_p1)
|
||
stdlib.free(stub_buf)
|
||
|
||
# dump text IR (definitions only)
|
||
text_buf: bytes = stdlib.malloc(PHASE1_IR_SIZE)
|
||
if text_buf is None:
|
||
stdlib.free(src_buf)
|
||
if tr._global_names is not None:
|
||
stdlib.free(tr._global_names)
|
||
if tr._nonlocal_names is not None:
|
||
stdlib.free(tr._nonlocal_names)
|
||
failed += 1
|
||
continue
|
||
tr.dump_ir(text_buf, PHASE1_IR_SIZE, llvmlite.OUTPUT_TEXT)
|
||
text_len: t.CSizeT = string.strlen(text_buf)
|
||
|
||
# save text.ll
|
||
text_path_p1: bytes = stdlib.malloc(dir_len_p1 + 32)
|
||
if text_path_p1 is not None:
|
||
viperlib.snprintf(text_path_p1, dir_len_p1 + 32, "%s/%s.text.ll", temp_dir, sha1)
|
||
tf_p1: fileio.File | t.CPtr = fileio.File(text_path_p1, fileio.MODE.W)
|
||
if not tf_p1.closed:
|
||
tf_p1.write(text_buf, text_len)
|
||
tf_p1.close()
|
||
stdlib.free(text_path_p1)
|
||
stdlib.free(text_buf)
|
||
|
||
# save dependencies (_imported_modules) for Phase B
|
||
deps_path_p1: bytes = stdlib.malloc(dir_len_p1 + 32)
|
||
if deps_path_p1 is not None:
|
||
viperlib.snprintf(deps_path_p1, dir_len_p1 + 32, "%s/%s.deps.txt", temp_dir, sha1)
|
||
df_p1: fileio.File | t.CPtr = fileio.File(deps_path_p1, fileio.MODE.W)
|
||
if not df_p1.closed:
|
||
if tr._imported_modules is not None:
|
||
dl: t.CSizeT = string.strlen(tr._imported_modules)
|
||
df_p1.write(tr._imported_modules, dl)
|
||
df_p1.close()
|
||
stdlib.free(deps_path_p1)
|
||
|
||
# 释放 Translator 的 C malloc 资源
|
||
if tr._global_names is not None:
|
||
stdlib.free(tr._global_names)
|
||
if tr._nonlocal_names is not None:
|
||
stdlib.free(tr._nonlocal_names)
|
||
|
||
# 所有 dump_ir 完成,src_buf 不再需要
|
||
stdlib.free(src_buf)
|
||
|
||
translated += 1
|
||
|
||
stdio.printf("[Phase1] 完成: 翻译=%d 跳过=%d 失败=%d\n", translated, skipped, failed)
|
||
|
||
# 释放可达 SHA1 集合(如果分配了)
|
||
if reachable_set is not None:
|
||
stdlib.free(reachable_set)
|
||
|
||
return 0
|