diff --git a/App/lib/Stub/StubMerger/StubMergerIR.vp b/App/lib/Stub/StubMerger/StubMergerIR.vp index c9b9a2c..d8c0749 100644 --- a/App/lib/Stub/StubMerger/StubMergerIR.vp +++ b/App/lib/Stub/StubMerger/StubMergerIR.vp @@ -27,7 +27,7 @@ import lib.Stub.StubMerger as StubMerger # ============================================================ -# StubMergerIR - IR 文本去重/注释与模块名-SHA1 映射工具 +# StubMergerIR - 模块结构化 sidecar({sha1}.meta)写出/读取、子模块判定与模块名-SHA1 映射工具 # ============================================================ # ============================================================ @@ -205,154 +205,6 @@ def IsDeclOnlyModule(temp_dir: str, td_len: sizet, sha1: str) -> int: return 0 return 1 # ============================================================ -# _IsFuncDeclaredOrDefined - 检查 out_buf 中是否已有函数的 declare/define -# -# 逐字节 strncmp 搜索 func_sig(如 @"sha1.func"(/ @printf(),命中后检查行首是否为 "declare "/"define ",跳过 call 语句 -# (避免 strstr 子串匹配误命中 call ... @"func"(...)。 -# -# Args: out_buf 已有 IR 文本缓冲区;func_sig 函数签名片段,如 @"sha1.func"(/ @printf( -# Returns: 1=已存在 declare/define, 0=不存在 -# ============================================================ -def _IsFuncDeclaredOrDefined(out_buf: bytes, func_sig: str) -> int: - """检查 out_buf 中是否已有函数的 declare 或 define 行""" - if out_buf is None or func_sig is None: - return 0 - sig_len: sizet = string.strlen(func_sig) - out_len: sizet = string.strlen(out_buf) - if sig_len == 0 or out_len == 0 or sig_len > out_len: - return 0 - pos: sizet = 0 - for pos in range(0, out_len - sig_len + 1): - if string.strncmp(out_buf + pos, func_sig, sig_len) == 0: - ls: sizet = pos - while ls > 0 and out_buf[ls - 1] != '\n': - ls -= 1 - if string.strncmp(out_buf + ls, "declare ", 8) == 0: - return 1 - if string.strncmp(out_buf + ls, "define ", 7) == 0: - return 1 - return 0 -# ============================================================ -# _CommentOutDeclareInBuf - 将 out_buf 中匹配 func_sig 的 declare 行注释掉 -# -# 用于解决 declare/define 冲突:当本地 text.ll 包含 define 而依赖 -# text.ll 已生成了同函数的 declare 时,将 declare 行首字符改为 ';' -# 使其成为注释,然后追加 define 行。 -# ============================================================ -def _CommentOutDeclareInBuf(out_buf: bytes, func_sig: str) -> int: - """在 out_buf 中搜索 declare 行(包含 func_sig),将其注释掉""" - if out_buf is None or func_sig is None: - return 0 - sig_len: sizet = string.strlen(func_sig) - out_len: sizet = string.strlen(out_buf) - if sig_len == 0 or out_len == 0 or sig_len > out_len: - return 0 - pos: sizet = 0 - while pos + sig_len <= out_len: - if string.strncmp(out_buf + pos, func_sig, sig_len) == 0: - ls: sizet = pos - while ls > 0 and out_buf[ls - 1] != '\n': - ls -= 1 - if string.strncmp(out_buf + ls, "declare ", 8) == 0: - out_buf[ls] = ';' - return 1 - pos += 1 - return 0 -# ============================================================ -# _CommentOutGlobalInBuf - 将 out_buf 中匹配全局变量名的行注释掉 -# -# 解决 stub/text 全局变量重复定义问题:stub 中可能是 external 声明 -# 或完整定义,以 text 中的定义为准,将 stub 中的同名行注释掉。 -# ============================================================ -def _CommentOutGlobalInBuf(out_buf: bytes, global_name: str) -> int: - """在 out_buf 中搜索全局变量定义行(以 global_name 开头),将行首改为 ';' - - 注释掉**所有**匹配行(而非仅第一个):跨模块同名裸全局(如 main.vp 与 - argparse.vp 都声明 StubMerger._mbuddy)时,本地 stub external + 依赖 stub external + - 依赖 text 定义会同时存在。只注释第一个会导致依赖 text 的定义残留 → - 合成 IR 重复定义 → llc "redefinition of global '@StubMerger._mbuddy'"(ArgparseTest - 回归根因)。"以 text 中定义为准"的语义:后追加者注释掉全部旧行,最终 - 只保留最后一个定义。 - """ - if out_buf is None or global_name is None: - return 0 - name_len: sizet = string.strlen(global_name) - out_len: sizet = string.strlen(out_buf) - if name_len == 0 or out_len == 0 or name_len > out_len: - return 0 - pos: sizet = 0 - commented: int = 0 - while pos + name_len <= out_len: - if string.strncmp(out_buf + pos, global_name, name_len) == 0: - # 确认是行首(前一个是换行或 pos==0) - if pos == 0 or out_buf[pos - 1] == '\n': - out_buf[pos] = ';' - commented = 1 - pos += 1 - return commented -def _HasGlobalInBuf(out_buf: bytes, global_name: str) -> int: - """检测 out_buf 中是否已有同名全局变量行(行首匹配,未注释) - - 用于跳过重复追加依赖全局强定义:stub 注入已提供 external 声明, - 依赖 text.ll 的强定义只需在定义模块存在一份,复制进每个依赖方 - 会导致 ld.lld duplicate symbol(如 _op_head、MemBuddy.vtable)。 - """ - if out_buf is None or global_name is None: - return 0 - name_len: sizet = string.strlen(global_name) - out_len: sizet = string.strlen(out_buf) - if name_len == 0 or out_len == 0 or name_len > out_len: - return 0 - pos: sizet = 0 - while pos + name_len <= out_len: - if string.strncmp(out_buf + pos, global_name, name_len) == 0: - # 确认是行首(前一个是换行或 pos==0) - if pos == 0 or out_buf[pos - 1] == '\n': - return 1 - pos += 1 - return 0 -# ============================================================ -# _CommentOutOpaqueTypeInBuf - 将 out_buf 中匹配类型名的 opaque 声明行注释掉 -# -# 解决跨模块类型定义冲突:本地 stub 可能包含自动生成的 opaque 声明 -#(如 %"sha1.Widget" = type opaque),而依赖 stub 包含完整定义 -#(如 %"sha1.Widget" = type { i8*, i32 })。去重时需要将 opaque 声明 -# 注释掉,让完整定义被追加,否则 LLC 报错 "Cannot allocate unsized type"。 -# ============================================================ -def _CommentOutOpaqueTypeInBuf(out_buf: bytes, type_name_prefix: str) -> int: - """在 out_buf 中搜索 type_name_prefix 对应的 opaque 声明行,将行首改为 ';' - - type_name_prefix 格式: '%"sha1.ClassName"'(不含 '=' 和后续内容) - 返回 1=已注释, 0=未找到 - """ - if out_buf is None or type_name_prefix is None: - return 0 - prefix_len: sizet = string.strlen(type_name_prefix) - out_len: sizet = string.strlen(out_buf) - if prefix_len == 0 or out_len == 0 or prefix_len > out_len: - return 0 - pos: sizet = 0 - while pos + prefix_len <= out_len: - if string.strncmp(out_buf + pos, type_name_prefix, prefix_len) == 0: - # 确认是行首(前一个是换行或 pos==0) - if pos == 0 or out_buf[pos - 1] == '\n': - # 检查后面是否是 " = type opaque" - p: sizet = pos + prefix_len - # 跳过空格 - while p < out_len and out_buf[p] == ' ': - p += 1 - if p < out_len and out_buf[p] == '=': - p += 1 - while p < out_len and out_buf[p] == ' ': - p += 1 - if p + 11 <= out_len: - if string.strncmp(out_buf + p, "type opaque", 11) == 0: - # 找到 opaque 声明,将行首改为 ';' - out_buf[pos] = ';' - return 1 - pos += 1 - return 0 -# ============================================================ # _is_submodule_of_imported - 检查模块名是否是已导入包的子模块 # # deps_buf 只记录直接导入的模块名(如 "ast"),但包的 __init__.vp 内部 from .lexer import Lexer 会让 IR 引用 ast.lexer @@ -377,47 +229,6 @@ def _is_submodule_of_imported(deps_buf: str, mod_name: str) -> int: mod_name[pkg_len] = saved_ch return result # ============================================================ -# _HasFullTypeDefinition - 检查 out_buf 中是否已有完整类型定义(非 opaque) -# -# type_name_prefix 格式: '%"sha1.ClassName"'(不含 '=') -# 完整定义: %"name" = type { ... } 或 %"name" = type < { ... } > -# 返回 1=已有完整定义, 0=无完整定义 -# ============================================================ -def _HasFullTypeDefinition(out_buf: bytes, type_name_prefix: str) -> int: - """检查 out_buf 中是否已有 type_name_prefix 的完整定义""" - if out_buf is None or type_name_prefix is None: - return 0 - prefix_len: sizet = string.strlen(type_name_prefix) - out_len: sizet = string.strlen(out_buf) - if prefix_len == 0 or out_len == 0 or prefix_len > out_len: - return 0 - pos: sizet = 0 - while pos + prefix_len <= out_len: - if string.strncmp(out_buf + pos, type_name_prefix, prefix_len) == 0: - # 确认是行首(前一个是换行或 pos==0),且未被注释(行首不是 ';') - is_line_start: int = 0 - if pos == 0: - is_line_start = 1 - elif out_buf[pos - 1] == '\n': - is_line_start = 1 - if is_line_start == 1: - # 检查后面是否是 " = type {" 或 " = type <" - p: sizet = pos + prefix_len - while p < out_len and out_buf[p] == ' ': - p += 1 - if p < out_len and out_buf[p] == '=': - p += 1 - while p < out_len and out_buf[p] == ' ': - p += 1 - if p + 5 < out_len: - if string.strncmp(out_buf + p, "type ", 5) == 0: - p += 5 - if p < out_len: - if out_buf[p] == '{' or out_buf[p] == '<': - return 1 - pos += 1 - return 0 -# ============================================================ # _BuildIncludesSha1Map - 从全局内存存储器构建 sha1 → module_name 映射 # # 数据来源是 PopulateSha1MapStore 填充的全局存储器(不读取 _sha1_map.txt)。