fix(tpv): 泛型类型参数 SHA1 规范化 + 自举链接修复
- 类型参数统一 "{定义模块SHA1}.{Class}"(ast.AST/AST → f467978339422f32.AST),
消除跨模块特化名分裂导致的 undefined symbol(list[AST|t.CPtr].set 根因)
- TypeGenResolve 新增 _norm_type_arg_name/_is_sha1_prefixed/_concat_sha1_class;
resolve_annotation_type 兼容 "{16hex}.Class" Attribute 形态(跳过
imported_modules 检查,优先完整名命中定义侧 struct)
- CallGenCtor._extract_type_args_from_slice / extract_class_name_from_annotation
新增 from_imports 参数,8 处调用方传 trans._from_imports 保持注册/查找一致
- 修复模块级函数链式调用推断(get_perm_pool() 联合返回 → .alloc() 裸名 alloc)
- 跨模块方法 declare self 改为类指针 %"sha1.Class"*,调用侧按形参 coerce bitcast
- 撤销泛型特化双 SHA1 前缀,恢复单前缀(模板 SHA1)
- 新增 --phase2command xxx.bat:不执行 llc/链接,命令写入 bat
This commit is contained in:
1 parent
a6e28c71f5
commit
a12dcafed2
21 files changed
+533
-108
No files matched your search
@@ -35,8 +35,8 @@ LinkerFlags: str = None # 链接器参数(空格分隔,从 linker.
|
||||
LinkerOutput: str = None
|
||||
TargetTriple: str = None
|
||||
TargetDataLayout: str = None
|
||||
Sha1SliceLevel: t.CInt = 0 # SHA1 切片层数(目录分散等级)
|
||||
StrictMode: t.CInt = 0
|
||||
Sha1SliceLevel: int = 0 # SHA1 切片层数(目录分散等级)
|
||||
StrictMode: int = 0
|
||||
IncludesDir: str = None # includes 目录路径(从 includes 数组首元素,兼容单目录场景)
|
||||
IncludesDirs: str = None # 全部 includes 目录(空格分隔,多 includes 目录支持)
|
||||
|
||||
@@ -60,17 +60,13 @@ def Load_project_config(path: str) -> int:
|
||||
global TargetTriple, TargetDataLayout, Sha1SliceLevel, StrictMode
|
||||
global IncludesDir, IncludesDirs
|
||||
|
||||
if path is None:
|
||||
return 1
|
||||
if _mbuddy is None:
|
||||
return 1
|
||||
if path is None: return 1
|
||||
if _mbuddy is None: return 1
|
||||
|
||||
# 打开文件
|
||||
f: fileio.File | t.CPtr = fileio.File(path, fileio.MODE.R)
|
||||
if f is None:
|
||||
return 1
|
||||
if f.closed:
|
||||
return 1
|
||||
if f is None: return 1
|
||||
if f.closed: return 1
|
||||
|
||||
# 分配读取缓冲区
|
||||
CFG_BUF_SIZE: t.CSizeT = 8192
|
||||
@@ -82,56 +78,53 @@ def Load_project_config(path: str) -> int:
|
||||
bytes_read: t.CInt64T = f.read_all(buf, CFG_BUF_SIZE)
|
||||
f.close()
|
||||
|
||||
if bytes_read <= 0:
|
||||
return 1
|
||||
if bytes_read <= 0: return 1
|
||||
|
||||
# 解析 JSON
|
||||
root: JsonValue | t.CPtr = json_parse(_mbuddy, buf)
|
||||
if root is None:
|
||||
return 1
|
||||
if not root.is_object():
|
||||
return 1
|
||||
if root is None: return 1
|
||||
if not root.is_object(): return 1
|
||||
|
||||
# 读取顶层字段(使用显式 __getitem__ 调用,兼容旧编译器二进制)
|
||||
sd_val: JsonValue | t.CPtr = root.__getitem__("source_dir")
|
||||
sd_val: JsonValue | t.CPtr = root["source_dir"]
|
||||
SourceDir = sd_val.as_string() if sd_val is not None else None
|
||||
# build_dir: 统一构建目录(默认 ./.tpv_build),temp 和 output 作为其子目录
|
||||
bd_val: JsonValue | t.CPtr = root.__getitem__("build_dir")
|
||||
bd_val: JsonValue | t.CPtr = root["build_dir"]
|
||||
if bd_val is not None and bd_val.is_string():
|
||||
BuildDir = bd_val.as_string()
|
||||
else:
|
||||
BuildDir = "./.tpv_build"
|
||||
name_val: JsonValue | t.CPtr = root.__getitem__("name")
|
||||
name_val: JsonValue | t.CPtr = root["name"]
|
||||
ProjectName = name_val.as_string() if name_val is not None else None
|
||||
ver_val: JsonValue | t.CPtr = root.__getitem__("version")
|
||||
ver_val: JsonValue | t.CPtr = root["version"]
|
||||
ProjectVersion = ver_val.as_string() if ver_val is not None else None
|
||||
|
||||
# 读取 compiler 子对象
|
||||
compiler: JsonValue | t.CPtr = root.__getitem__("compiler")
|
||||
compiler: JsonValue | t.CPtr = root["compiler"]
|
||||
if compiler is not None and compiler.is_object():
|
||||
cc_cmd_val: JsonValue | t.CPtr = compiler.__getitem__("cmd")
|
||||
cc_cmd_val: JsonValue | t.CPtr = compiler["cmd"]
|
||||
CompilerCmd = cc_cmd_val.as_string() if cc_cmd_val is not None else None
|
||||
# 读取 compiler.flags 数组,拼接成空格分隔的字符串
|
||||
cc_flags_val: JsonValue | t.CPtr = compiler.__getitem__("flags")
|
||||
cc_flags_val: JsonValue | t.CPtr = compiler["flags"]
|
||||
CompilerFlags = _join_flags_array(cc_flags_val)
|
||||
|
||||
# 读取 linker 子对象
|
||||
linker: JsonValue | t.CPtr = root.__getitem__("linker")
|
||||
linker: JsonValue | t.CPtr = root["linker"]
|
||||
if linker is not None and linker.is_object():
|
||||
ld_cmd_val: JsonValue | t.CPtr = linker.__getitem__("cmd")
|
||||
ld_cmd_val: JsonValue | t.CPtr = linker["cmd"]
|
||||
LinkerCmd = ld_cmd_val.as_string() if ld_cmd_val is not None else None
|
||||
ld_out_val: JsonValue | t.CPtr = linker.__getitem__("output")
|
||||
ld_out_val: JsonValue | t.CPtr = linker["output"]
|
||||
LinkerOutput = ld_out_val.as_string() if ld_out_val is not None else None
|
||||
# 读取 linker.flags 数组,拼接成空格分隔的字符串
|
||||
ld_flags_val: JsonValue | t.CPtr = linker.__getitem__("flags")
|
||||
ld_flags_val: JsonValue | t.CPtr = linker["flags"]
|
||||
LinkerFlags = _join_flags_array(ld_flags_val)
|
||||
|
||||
# 读取 target 子对象
|
||||
target: JsonValue | t.CPtr = root.__getitem__("target")
|
||||
target: JsonValue | t.CPtr = root["target"]
|
||||
if target is not None and target.is_object():
|
||||
tgt_triple_val: JsonValue | t.CPtr = target.__getitem__("triple")
|
||||
tgt_triple_val: JsonValue | t.CPtr = target["triple"]
|
||||
TargetTriple = tgt_triple_val.as_string() if tgt_triple_val is not None else None
|
||||
tgt_dl_val: JsonValue | t.CPtr = target.__getitem__("datalayout")
|
||||
tgt_dl_val: JsonValue | t.CPtr = target["datalayout"]
|
||||
TargetDataLayout = tgt_dl_val.as_string() if tgt_dl_val is not None else None
|
||||
|
||||
# 读取 options 子对象
|
||||
@@ -139,19 +132,19 @@ def Load_project_config(path: str) -> int:
|
||||
# level=0 → 不切片,文件直接放 base_dir
|
||||
# level=1 → b7/{sha1}.ext
|
||||
# level=2 → b7/90/{sha1}.ext
|
||||
options: JsonValue | t.CPtr = root.__getitem__("options")
|
||||
options: JsonValue | t.CPtr = root["options"]
|
||||
Sha1SliceLevel = 1
|
||||
StrictMode = 1
|
||||
if options is not None and options.is_object():
|
||||
sl: JsonValue | t.CPtr = options.__getitem__("sha1_slice_level")
|
||||
sl: JsonValue | t.CPtr = options["sha1_slice_level"]
|
||||
if sl is not None and sl.is_int():
|
||||
Sha1SliceLevel = sl.as_int()
|
||||
sm: JsonValue | t.CPtr = options.__getitem__("strict_mode")
|
||||
sm: JsonValue | t.CPtr = options["strict_mode"]
|
||||
if sm is not None and sm.is_bool():
|
||||
StrictMode = 1 if sm.as_bool() else 0
|
||||
|
||||
# 读取 includes 数组(支持多目录:首元素存 IncludesDir,全部拼接存 IncludesDirs)
|
||||
includes_val: JsonValue | t.CPtr = root.__getitem__("includes")
|
||||
includes_val: JsonValue | t.CPtr = root["includes"]
|
||||
if includes_val is not None and includes_val.is_array():
|
||||
arr_len: t.CSizeT = includes_val.__len__()
|
||||
inc_buf: bytes = stdlib.malloc(2048)
|
||||
@@ -204,14 +197,12 @@ def _join_flags_array(flags_val: JsonValue | t.CPtr) -> str:
|
||||
|
||||
# 第一遍:计算总长度(所有 flag 长度 + 空格分隔符)
|
||||
total_len: t.CSizeT = 0
|
||||
i: t.CSizeT = 0
|
||||
while i < arr_len:
|
||||
for i in range(arr_len):
|
||||
item: JsonValue | t.CPtr = flags_val.get_item(i)
|
||||
if item is not None and item.is_string():
|
||||
s: str = item.as_string()
|
||||
if s is not None:
|
||||
total_len += string.strlen(s) + 1 # +1 for space
|
||||
i += 1
|
||||
|
||||
if total_len == 0:
|
||||
return None
|
||||
@@ -223,8 +214,7 @@ def _join_flags_array(flags_val: JsonValue | t.CPtr) -> str:
|
||||
|
||||
# 第二遍:拼接(flag 之间用空格分隔)
|
||||
pos: t.CSizeT = 0
|
||||
i = 0
|
||||
while i < arr_len:
|
||||
for i in range(arr_len):
|
||||
item = flags_val.get_item(i)
|
||||
if item is not None and item.is_string():
|
||||
s = item.as_string()
|
||||
@@ -235,7 +225,6 @@ def _join_flags_array(flags_val: JsonValue | t.CPtr) -> str:
|
||||
pos += 1
|
||||
string.strcpy(buf + pos, s)
|
||||
pos += slen
|
||||
i += 1
|
||||
buf[pos] = '\0'
|
||||
return buf
|
||||
|
||||
|
||||
@@ -25,11 +25,9 @@ _mbuddy: memhub.MemBuddy | t.CPtr
|
||||
# ============================================================
|
||||
def nibble_to_hex_char(n: int, uppercase: int) -> t.CChar:
|
||||
"""0-15 → '0'-'9'/'a'-'f'(uppercase=1 时用 'A'-'F')"""
|
||||
if n < 10:
|
||||
return '0' + n
|
||||
if uppercase != 0:
|
||||
return 'A' + (n - 10)
|
||||
return 'a' + (n - 10)
|
||||
if n < 10: return '0' + n
|
||||
if uppercase != 0: return 'A' + (n - 10)
|
||||
return 'a' + (n - 10)
|
||||
|
||||
|
||||
# ============================================================
|
||||
@@ -78,14 +76,12 @@ def compute_sha1(pool: memhub.MemBuddy | t.CPtr, content: str) -> str:
|
||||
# 构造 sha1 对象(__init__ 会初始化 state/count/buf)
|
||||
# ctx 在栈上分配(alloca),函数内使用完即丢弃,无需堆分配
|
||||
ctx: hashlib.sha1 | t.CPtr = hashlib.sha1()
|
||||
if ctx is None:
|
||||
return None
|
||||
if ctx is None: return None
|
||||
|
||||
# 计算摘要
|
||||
ctx.update(content)
|
||||
digest: bytes = pool.alloc(hashlib.SHA1_DIGEST_LEN)
|
||||
if digest is None:
|
||||
return None
|
||||
if digest is None: return None
|
||||
ctx.final(digest)
|
||||
|
||||
# 转为十六进制字符串(取前 8 字节 = 16 个十六进制字符)
|
||||
@@ -101,10 +97,8 @@ def is_vp_or_py_at(p: str, start: t.CSizeT, plen: t.CSizeT) -> int:
|
||||
return 0
|
||||
base: t.CSizeT = start + plen - 3
|
||||
if p[base] == '.':
|
||||
if p[base + 1] == 'v' and p[base + 2] == 'p':
|
||||
return 1
|
||||
if p[base + 1] == 'p' and p[base + 2] == 'y':
|
||||
return 1
|
||||
if p[base + 1] == 'v' and p[base + 2] == 'p': return 1
|
||||
if p[base + 1] == 'p' and p[base + 2] == 'y': return 1
|
||||
return 0
|
||||
|
||||
|
||||
@@ -119,8 +113,7 @@ def JoinPath(a: str, b: str) -> str:
|
||||
b_len: t.CSizeT = string.strlen(b)
|
||||
total_len: t.CSizeT = a_len + b_len + 2
|
||||
buf: str = stdlib.malloc(total_len)
|
||||
if buf is None:
|
||||
return None
|
||||
if buf is None: return None
|
||||
viperlib.snprintf(buf, total_len, "%s/%s", a, b)
|
||||
return buf
|
||||
|
||||
@@ -134,11 +127,9 @@ def read_file_to_buf(path: str, buf_size: t.CSizeT) -> bytes:
|
||||
返回缓冲区(调用方负责 free);打开失败/空文件/分配失败返回 None。
|
||||
合并自 Phase2/StubMerger/IncludesScanner 的重复"打开+读取+终止"序列。
|
||||
"""
|
||||
if path is None or buf_size <= 0:
|
||||
return None
|
||||
if path is None or buf_size <= 0: return None
|
||||
sf: fileio.File | t.CPtr = fileio.File(path, fileio.MODE.R)
|
||||
if sf.closed:
|
||||
return None
|
||||
if sf.closed: return None
|
||||
buf: bytes = stdlib.malloc(buf_size)
|
||||
if buf is None:
|
||||
sf.close()
|
||||
@@ -238,7 +229,7 @@ def CleanDir(dir_path: str) -> int:
|
||||
return 0
|
||||
|
||||
deleted: int = 0
|
||||
while 1:
|
||||
while True:
|
||||
fname: str = find_data.cFileName
|
||||
if fname is not None:
|
||||
# 跳过 . 和 ..
|
||||
|
||||
Reference in new issue
Block a user