修正了种子编译器的错误

This commit is contained in:
2026-07-22 21:55:36 +08:00
parent 135aa05485
commit ca7c2120b8
1185 changed files with 12056 additions and 2673 deletions

View File

@@ -14,6 +14,7 @@ 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.HandlesImports as HandlesImports
import lib.Projectrans.Config as Config
# ============================================================
# BuildPipeline - 编译管线
@@ -48,10 +49,12 @@ SRC_BUF_SIZE: t.CDefine = 1048576
# ============================================================
def TranslateFileGetTrans(mb: memhub.MemBuddy | t.CPtr, file_path: str,
sha1_val: str,
current_package: str = None) -> HandlesTranslator.Translator | t.CPtr:
current_package: str = None,
declare_only: int = 0) -> HandlesTranslator.Translator | t.CPtr:
"""翻译文件,返回 Translator 对象(调用者负责 dump_irNone 失败
current_package: 当前文件所属包名用于解析相对导入None 表示顶级模块
declare_only: 0=全量翻译默认1=仅注册 struct/enum/union不翻译方法体
"""
if file_path is None:
return None
@@ -81,6 +84,7 @@ def TranslateFileGetTrans(mb: memhub.MemBuddy | t.CPtr, file_path: str,
tr.__init__()
tr.ModuleSha1 = sha1_val
tr.CurrentPackage = current_package
tr._declare_only = declare_only
# 设置当前文件名(供报错使用)
HandlesType.set_current_file(file_path)
# 模块切换:清空 CDefine 常量表,确保每个模块的 CDefine 常量正确隔离
@@ -134,19 +138,74 @@ def ensure_dir(path: str) -> int:
# 遇到分隔符时临时截断,创建每一层目录
# CreateDirectoryA 在目录已存在时返回 0失败忽略即可
for i in range(path_len):
ch: int = c.Deref(buf + i)
if ch == ord('/') or ch == ord('\\'):
i: int = 0
plen: int = path_len
while i < plen:
ch: int = buf[i]
if ch == 47 or ch == 92: # '/' = 47, '\\' = 92
saved: int = ch
buf[i] = '\0'
w32.win32file.CreateDirectoryA(buf, None)
buf[i] = saved
i += 1
# 创建最终目录
w32.win32file.CreateDirectoryA(buf, None)
return 0
# ============================================================
# build_sliced_path - 构建切片路径并确保目录存在
#
# 根据 Config.Sha1SliceLevel 将文件分散到 SHA1 前缀子目录:
# level=0 → {base_dir}/{sha1}.{ext}
# level=1 → {base_dir}/b7/{sha1}.{ext}
# level=2 → {base_dir}/b7/90/{sha1}.{ext}
#
# 自动调用 ensure_dir 创建子目录。
#
# Args:
# base_dir: 基础目录(如 temp_dir
# sha1: SHA1 字符串
# ext: 文件扩展名(如 "stub.ll"
#
# Returns:
# 完整文件路径mbuddy 分配None 失败
# ============================================================
def build_sliced_path(base_dir: str, sha1: str, ext: str) -> str:
"""构建切片路径并确保目录存在"""
if base_dir is None or sha1 is None or ext is None:
return None
subdir: str = Config.slice_subdir(sha1, Config.Sha1SliceLevel)
base_len: t.CSizeT = string.strlen(base_dir)
sha1_len: t.CSizeT = string.strlen(sha1)
ext_len: t.CSizeT = string.strlen(ext)
if subdir is not None:
sub_len: t.CSizeT = string.strlen(subdir)
# ensure_dir({base_dir}/{subdir})
dir_path: str = _mbuddy.alloc(base_len + sub_len + 2)
if dir_path is not None:
viperlib.snprintf(dir_path, base_len + sub_len + 2, "%s/%s", base_dir, subdir)
ensure_dir(dir_path)
# 文件路径: {base_dir}/{subdir}/{sha1}.{ext}
path_len: t.CSizeT = base_len + sub_len + sha1_len + ext_len + 4
path: str = _mbuddy.alloc(path_len)
if path is None:
return None
viperlib.snprintf(path, path_len, "%s/%s/%s.%s", base_dir, subdir, sha1, ext)
return path
else:
# 无切片: {base_dir}/{sha1}.{ext}
path_len = base_len + sha1_len + ext_len + 3
path = _mbuddy.alloc(path_len)
if path is None:
return None
viperlib.snprintf(path, path_len, "%s/%s.%s", base_dir, sha1, ext)
return path
def write_ir_to_file(ir_buf: bytes, ir_len: t.CSizeT, output_dir: str, module_name: str) -> int:
"""将 IR 缓冲区写入 .ll 文件
@@ -154,22 +213,18 @@ def write_ir_to_file(ir_buf: bytes, ir_len: t.CSizeT, output_dir: str, module_na
ir_buf: IR 文本缓冲区
ir_len: IR 文本长度
output_dir: 输出目录temp 或 output
module_name: 模块名("main"
module_name: 模块名(SHA1
Returns:
0 成功,非 0 失败
"""
if ir_buf is None or output_dir is None:
if ir_buf is None or output_dir is None or module_name is None:
return 1
# 构造文件路径: output_dir/module_name.ll
dir_len: t.CSizeT = string.strlen(output_dir)
name_len: t.CSizeT = string.strlen(module_name)
path_len: t.CSizeT = dir_len + 1 + name_len + 4 # dir/module.ll\0
path: bytes = _mbuddy.alloc(path_len)
# 构造切片路径: output_dir/{sha1前缀}/{module_name}.ll
path: str = build_sliced_path(output_dir, module_name, "ll")
if path is None:
return 1
viperlib.snprintf(path, path_len, "%s/%s.ll", output_dir, module_name)
# 打开文件写入
f: fileio.File | t.CPtr = fileio.File(path, fileio.MODE.W)
@@ -189,22 +244,27 @@ def compile_ll_to_obj(ir_path: str, output_dir: str, module_name: str, cc_cmd: s
Args:
ir_path: .ll 文件路径
output_dir: 输出目录
module_name: 模块名(用于生成 .obj 文件名)
module_name: 模块名(SHA1用于生成 .obj 文件名)
cc_cmd: 编译器命令(如 "llc"
cc_flags: 编译器参数(如 "-filetype=obj -relocation-model=pic"
Returns:
0 成功,非 0 失败
"""
if ir_path is None or cc_cmd is None:
if ir_path is None or cc_cmd is None or output_dir is None or module_name is None:
return 1
# 构造命令: llc -filetype=obj -o output_dir/module_name.obj ir_path
cmd_len: t.CSizeT = string.strlen(cc_cmd) + string.strlen(cc_flags) + string.strlen(output_dir) + string.strlen(module_name) + string.strlen(ir_path) + 64
# 构造切片 .obj 路径: output_dir/{sha1前缀}/{module_name}.obj
obj_path: str = build_sliced_path(output_dir, module_name, "obj")
if obj_path is None:
return 1
# 构造命令: llc -filetype=obj -o {obj_path} ir_path
cmd_len: t.CSizeT = string.strlen(cc_cmd) + string.strlen(cc_flags) + string.strlen(obj_path) + string.strlen(ir_path) + 64
cmd: bytes = _mbuddy.alloc(cmd_len)
if cmd is None:
return 1
viperlib.snprintf(cmd, cmd_len, "%s %s -o %s/%s.obj %s", cc_cmd, cc_flags, output_dir, module_name, ir_path)
viperlib.snprintf(cmd, cmd_len, "%s %s -o %s %s", cc_cmd, cc_flags, obj_path, ir_path)
result: subprocess.CompletedProcess | t.CPtr = subprocess.run(cmd, True, True)
if result is None:
@@ -284,7 +344,7 @@ def link_obj_to_exe(output_dir: str, module_name: str, linker_cmd: str, linker_f
Args:
output_dir: 输出目录(包含 .obj 文件)
module_name: 模块名
module_name: 模块名SHA1
linker_cmd: 链接器命令(如 "clang++"
linker_flags: 链接器参数
linker_output: 输出文件名(如 "test.exe"
@@ -293,7 +353,12 @@ def link_obj_to_exe(output_dir: str, module_name: str, linker_cmd: str, linker_f
Returns:
0 成功,非 0 失败
"""
if output_dir is None or linker_cmd is None:
if output_dir is None or linker_cmd is None or module_name is None:
return 1
# 构造切片 .obj 路径: output_dir/{sha1前缀}/{module_name}.obj
obj_path: str = build_sliced_path(output_dir, module_name, "obj")
if obj_path is None:
return 1
# 收集 includes.binary 的 .obj 文件路径
@@ -309,19 +374,19 @@ def link_obj_to_exe(output_dir: str, module_name: str, linker_cmd: str, linker_f
else:
stdio.printf("[link] 警告: includes.binary 无 .obj 文件: %s\n", includes_binary_dir)
# 构造命令: clang++ main.obj extra_objs -o output linker_flags
# 构造命令: clang++ {obj_path} extra_objs -o {output_dir}/{linker_output} linker_flags
# 注意: .obj 文件必须在 -l 库标志之前,否则链接器无法解析符号依赖
cmd_len: t.CSizeT = string.strlen(linker_cmd) + string.strlen(output_dir) + string.strlen(module_name) + string.strlen(linker_flags) + string.strlen(linker_output) + extra_len + 128
cmd_len: t.CSizeT = string.strlen(linker_cmd) + string.strlen(obj_path) + string.strlen(linker_flags) + string.strlen(output_dir) + string.strlen(linker_output) + extra_len + 128
cmd: bytes = _mbuddy.alloc(cmd_len)
if cmd is None:
return 1
if extra_len > 0:
viperlib.snprintf(cmd, cmd_len, "%s %s/%s.obj %s -o %s/%s %s",
linker_cmd, output_dir, module_name, extra_objs,
viperlib.snprintf(cmd, cmd_len, "%s %s %s -o %s/%s %s",
linker_cmd, obj_path, extra_objs,
output_dir, linker_output, linker_flags)
else:
viperlib.snprintf(cmd, cmd_len, "%s %s/%s.obj -o %s/%s %s",
linker_cmd, output_dir, module_name, output_dir, linker_output,
viperlib.snprintf(cmd, cmd_len, "%s %s -o %s/%s %s",
linker_cmd, obj_path, output_dir, linker_output,
linker_flags)
result: subprocess.CompletedProcess | t.CPtr = subprocess.run(cmd, True, True)
@@ -357,7 +422,7 @@ def compile_module_to_obj(ir_buf: bytes, ir_len: t.CSizeT,
Returns:
0 成功,非 0 失败
"""
if ir_buf is None or temp_dir is None or output_dir is None:
if ir_buf is None or temp_dir is None or output_dir is None or module_name is None:
return 1
# Step 1: 写 .ll 文件
@@ -366,13 +431,10 @@ def compile_module_to_obj(ir_buf: bytes, ir_len: t.CSizeT,
stdio.printf("[compile] 写 .ll 失败: %s\n", module_name)
return 1
# Step 2: 构造 .ll 路径并编译 → .obj
name_len: t.CSizeT = string.strlen(module_name)
dir_len: t.CSizeT = string.strlen(temp_dir)
ir_path: bytes = _mbuddy.alloc(dir_len + name_len + 5)
# Step 2: 构造切片 .ll 路径并编译 → .obj
ir_path: str = build_sliced_path(temp_dir, module_name, "ll")
if ir_path is None:
return 1
viperlib.snprintf(ir_path, dir_len + name_len + 5, "%s/%s.ll", temp_dir, module_name)
ret = compile_ll_to_obj(ir_path, output_dir, module_name, cc_cmd, cc_flags)
if ret != 0:
@@ -474,15 +536,12 @@ def run_pipeline(ir_buf: bytes, ir_len: t.CSizeT,
return result
# Step 2: llc 编译 .ll → .obj
# 构造 .ll 文件路径
name_len: t.CSizeT = string.strlen(module_name)
dir_len: t.CSizeT = string.strlen(temp_dir)
ir_path: bytes = _mbuddy.alloc(dir_len + name_len + 5)
# 构造切片 .ll 文件路径
ir_path: str = build_sliced_path(temp_dir, module_name, "ll")
if ir_path is None:
result.Success = 0
result.ErrorMsg = "内存分配失败"
return result
viperlib.snprintf(ir_path, dir_len + name_len + 5, "%s/%s.ll", temp_dir, module_name)
ret = compile_ll_to_obj(ir_path, output_dir, module_name, cc_cmd, cc_flags)
if ret != 0: