修正了种子编译器的错误
This commit is contained in:
@@ -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_ir),None 失败
|
||||
|
||||
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:
|
||||
|
||||
Reference in New Issue
Block a user