diff --git a/App/lib/core/Gen/Call/CallGenBase.vp b/App/lib/core/Gen/Call/CallGenBase.vp index c7797b0..e8eb340 100644 --- a/App/lib/core/Gen/Call/CallGenBase.vp +++ b/App/lib/core/Gen/Call/CallGenBase.vp @@ -1021,6 +1021,207 @@ novirtual class CallGenBase: # 无法解析 return None + # ============================================================ + def _ParseMlirRetTyStr(self, pool: memhub.MemBuddy*, + buf: bytes, + start: sizet, + end: sizet) -> mlirlite.LLVMType*: + """把 mlirlite 的 MLIR 返回类型文本转成 mlirlite.LLVMType + + 覆盖 `llvm.func` 签名里会出现的形态(includes/mlirlite/README.md §2.1): + none → Void + iN → Int1/8/16/32/64 + f16/f32/f64/f128 → Half/Float/Double/FP128 + !llvm.ptr → Ptr(Int8)(MLIR 指针**不透明**,pointee 已丢) + !llvm.array → Array(T', N) + !llvm.struct<(T1, …)> → 字面结构体 + !llvm.struct<"名", (T1, …)> → 已登记具名结构体(未登记返回 None,不臆造) + + 无法解析返回 None(与 _ParseLLVMRetTyStr 同约定:宁缺毋错,不静默降级)。 + """ + if pool is None or buf is None or start >= end: + return None + s: sizet = start + while s < end and (buf[s] == ' ' or buf[s] == '\t'): + s += 1 + e: sizet = end + while e > s and (buf[e - 1] == ' ' or buf[e - 1] == '\t' or buf[e - 1] == '{'): + e -= 1 + if s >= e: + return None + n: sizet = e - s + # none → Void(MLIR 的 void 记法) + if n == 4 and string.strncmp(buf + s, "none", 4) == 0: + return mlirlite.Void(pool) + # 标量:iN / fN + if buf[s] == 'i' or buf[s] == 'f': + bits: int = 0 + di: sizet = s + 1 + ok: int = 1 + while di < e: + d: int = buf[di] + if d >= '0' and d <= '9': + bits = bits * 10 + (d - '0') + else: + ok = 0 + break + di += 1 + if ok != 0 and bits > 0: + if buf[s] == 'i': + if bits == 1: return mlirlite.Int1(pool) + if bits == 8: return mlirlite.Int8(pool) + if bits == 16: return mlirlite.Int16(pool) + if bits == 32: return mlirlite.Int32(pool) + if bits == 64: return mlirlite.Int64(pool) + else: + if bits == 16: return mlirlite.Half(pool) + if bits == 32: return mlirlite.Float(pool) + if bits == 64: return mlirlite.Double(pool) + if bits == 128: return mlirlite.FP128(pool) + return None + # 不透明指针 → 通用 i8* + if n >= 9 and string.strncmp(buf + s, "!llvm.ptr", 9) == 0: + return mlirlite.Ptr(pool, mlirlite.Int8(pool)) + # !llvm.array + if n >= 12 and string.strncmp(buf + s, "!llvm.array<", 12) == 0: + is_a: sizet = s + 12 + depth_a: int = 0 + iea: sizet = e + iia: sizet = is_a + while iia < e: + ca: int = buf[iia] + if ca == '<': + depth_a += 1 + elif ca == '>': + if depth_a == 0: + iea = iia + break + depth_a -= 1 + iia += 1 + if iea <= is_a: + return None + xs: sizet = is_a + while xs < iea and buf[xs] != 'x': + xs += 1 + if xs >= iea: + return None + cnt_a: int = 0 + ok_a: int = 0 + ci_a: sizet = is_a + while ci_a < xs: + da: int = buf[ci_a] + if da >= '0' and da <= '9': + cnt_a = cnt_a * 10 + (da - '0') + ok_a = 1 + ci_a += 1 + if ok_a == 0 or cnt_a <= 0: + return None + et_a: mlirlite.LLVMType* = self._ParseMlirRetTyStr(pool, buf, xs + 1, iea) + if et_a is None: + return None + return mlirlite.Array(pool, et_a, cnt_a) + # !llvm.struct<...>(匿名体 / 具名内联体) + if n >= 13 and string.strncmp(buf + s, "!llvm.struct<", 13) == 0: + is_s: sizet = s + 13 + depth_s: int = 0 + ies: sizet = e + iis: sizet = is_s + while iis < e: + cs: int = buf[iis] + if cs == '<': + depth_s += 1 + elif cs == '>': + if depth_s == 0: + ies = iis + break + depth_s -= 1 + iis += 1 + if ies <= is_s: + return None + a: sizet = is_s + while a < ies and (buf[a] == ' ' or buf[a] == '\t'): + a += 1 + b: sizet = ies + while b > a and (buf[b - 1] == ' ' or buf[b - 1] == '\t'): + b -= 1 + nm_buf: bytes = None + if a < b and buf[a] == '"': + ns: sizet = a + 1 + ne: sizet = ns + while ne < b and buf[ne] != '"': + ne += 1 + if ne <= ns: + return None + nm_buf = stdlib.malloc(ne - ns + 1) + if nm_buf is None: + return None + string.strncpy(nm_buf, buf + ns, ne - ns) + nm_buf[ne - ns] = '\0' + a = ne + 1 + while a < b and (buf[a] == ' ' or buf[a] == ','): + a += 1 + if a >= b or buf[a] != '(' or buf[b - 1] != ')': + if nm_buf is not None: + stdlib.free(nm_buf) + return None + # 字段表:按顶层逗号切分(括号/尖括号计入深度) + head: mlirlite.ParamNode* = None + tail: mlirlite.ParamNode* = None + cnt_f: int = 0 + seg_s: sizet = a + 1 + fe_f: sizet = b - 1 + cur_f: sizet = a + 1 + depth_f: int = 0 + done: int = 0 + while done == 0: + at_end: int = 0 + if cur_f >= fe_f: + at_end = 1 + elif buf[cur_f] == ',' and depth_f == 0: + at_end = 1 + if at_end != 0: + gs: sizet = seg_s + ge: sizet = cur_f + while gs < ge and (buf[gs] == ' ' or buf[gs] == '\t'): + gs += 1 + while ge > gs and (buf[ge - 1] == ' ' or buf[ge - 1] == '\t'): + ge -= 1 + if ge > gs: + ft: mlirlite.LLVMType* = self._ParseMlirRetTyStr(pool, buf, gs, ge) + if ft is None: + if nm_buf is not None: + stdlib.free(nm_buf) + return None + fn: mlirlite.ParamNode* = mlirlite.new_param_node(pool, ft) + if fn is None: + if nm_buf is not None: + stdlib.free(nm_buf) + return None + if head is None: + head = fn + else: + mlirlite.paramnode_set_next(tail, fn) + tail = fn + cnt_f += 1 + seg_s = cur_f + 1 + if cur_f >= fe_f: + done = 1 + else: + c3: int = buf[cur_f] + if c3 == '(' or c3 == '<': + depth_f += 1 + elif c3 == ')' or c3 == '>': + if depth_f > 0: + depth_f -= 1 + cur_f += 1 + # 具名:按登记表回查真实类型;未登记返回 None(不臆造类型对象) + if nm_buf is not None: + reg: mlirlite.LLVMType* = GenApi.get_struct_type(nm_buf) + stdlib.free(nm_buf) + return reg + return mlirlite.Struct(pool, head, cnt_f, None) + return None + # _LookupCachedRetTyText:查「依赖模块 text.ll 方法返回类型文本」持久缓存——键为 define 完整 mangled 名("{sha1}.{class}.{method}",bare 模式 "{sha1}.{method}"),命中返回文本,未命中/表未建返回 None def _LookupCachedRetTyText(self, class_sha1: str, class_name: str, method_name: str, use_bare: int) -> str: @@ -1087,58 +1288,126 @@ novirtual class CallGenBase: break le += 1 ll: sizet = le - ls - # define 行判定与 _LookupMethodRetTyFromTextLL 逐字一致 + # 函数定义行两种形态都要认: + # LLVM 文本:define @"名"(...) (不缩进) + # MLIR 文本: llvm.func @"名"(...) -> { (module{} 内带缩进;void 省略 ->) + # 本函数是 text.ll 的**回退**读取方(首选 _lookup_method_ret_ty_via_vpi); + # 单端 MLIR 后 text.ll 里已无 define 行,只认 LLVM 形态会让回退恒 None + # ⇒ 指针返回值退回默认 i32 被 inttoptr 截断。 + fs: sizet = ls + while fs < ls + ll and (text_buf[fs] == ' ' or text_buf[fs] == '\t'): + fs += 1 + is_mlir_line: int = 0 + mlir_none: int = 0 + matched: int = 0 + at_pos: sizet = 0 + ret_s: sizet = 0 + ret_e: sizet = 0 if ll >= 7 and text_buf[ls] == 'd' and string.strncmp(text_buf + ls, "define ", 7) == 0: - at_pos: sizet = ls + 7 + matched = 1 + at_pos = ls + 7 while at_pos < ls + ll: if text_buf[at_pos] == '@': break at_pos += 1 - if at_pos < ls + ll: - name_start: sizet = at_pos + 1 - quoted: int = 0 - if name_start < ls + ll and text_buf[name_start] == '"': - name_start += 1 - quoted = 1 - # 定界:带引号名到 '"',裸名到 '('(与查找侧边界判定等价) - name_end: sizet = name_start - if quoted != 0: - while name_end < ls + ll: - if text_buf[name_end] == '"': - break - name_end += 1 - else: - while name_end < ls + ll: - if text_buf[name_end] == '(': - break - name_end += 1 - name_len: sizet = name_end - name_start - # 只登记本模块 mangled 名 "{sha1}.{后缀}"(查询键恒为此前缀);表不可用时跳过登记 - if cache_on != 0 and name_len > sha1_len + 1: - if string.strncmp(text_buf + name_start, class_sha1, sha1_len) == 0 and text_buf[name_start + sha1_len] == '.': - key_buf: bytes = stdlib.malloc(name_len + 1) - if key_buf is not None: - string.strncpy(key_buf, text_buf + name_start, name_len) - key_buf[name_len] = '\0' - # 同名首次为准(不被后续同名覆盖,与首个命中一致) - if ht.__contains__(key_buf) == 0: - rt_len: sizet = at_pos - (ls + 7) - kcopy: str = perm.alloc(name_len + 1) - tcopy: str = perm.alloc(rt_len + 1) - if kcopy is not None and tcopy is not None: - string.strncpy(kcopy, text_buf + name_start, name_len) - kcopy[name_len] = '\0' + ret_s = ls + 7 + ret_e = at_pos + elif ll >= 11 and fs + 11 <= ls + ll and string.strncmp(text_buf + fs, "llvm.func @", 11) == 0: + matched = 1 + is_mlir_line = 1 + at_pos = fs + 10 # "llvm.func " 之后即 '@' + # 返回类型:` -> `(到行尾或 " {" 之前);无 `->` = void + ar_pos: sizet = at_pos + arrow: sizet = 0 + while ar_pos + 2 < ls + ll: + if text_buf[ar_pos] == ' ' and text_buf[ar_pos + 1] == '-' and text_buf[ar_pos + 2] == '>': + arrow = ar_pos + break + ar_pos += 1 + if arrow == 0: + mlir_none = 1 + ret_s = ls + ll + ret_e = ls + ll + else: + ret_s = arrow + 3 + while ret_s < ls + ll and text_buf[ret_s] == ' ': + ret_s += 1 + ret_e = ls + ll + kk: sizet = ret_s + while kk + 1 < ls + ll: + if text_buf[kk] == ' ' and text_buf[kk + 1] == '{': + ret_e = kk + break + kk += 1 + if matched != 0 and at_pos < ls + ll: + name_start: sizet = at_pos + 1 + quoted: int = 0 + if name_start < ls + ll and text_buf[name_start] == '"': + name_start += 1 + quoted = 1 + # 定界:带引号名到 '"',裸名到 '('(与查找侧边界判定等价) + name_end: sizet = name_start + if quoted != 0: + while name_end < ls + ll: + if text_buf[name_end] == '"': + break + name_end += 1 + else: + while name_end < ls + ll: + if text_buf[name_end] == '(': + break + name_end += 1 + name_len: sizet = name_end - name_start + # 只登记本模块 mangled 名 "{sha1}.{后缀}"(查询键恒为此前缀);表不可用时跳过登记 + if cache_on != 0 and name_len > sha1_len + 1: + if string.strncmp(text_buf + name_start, class_sha1, sha1_len) == 0 and text_buf[name_start + sha1_len] == '.': + key_buf: bytes = stdlib.malloc(name_len + 1) + if key_buf is not None: + string.strncpy(key_buf, text_buf + name_start, name_len) + key_buf[name_len] = '\0' + # 同名首次为准(不被后续同名覆盖,与首个命中一致) + if ht.__contains__(key_buf) == 0: + # 缓存值:LLVM 形态存返回类型原文;MLIR 形态存 + # '#' + MLIR 类型文本('#' 前缀标记形态,供 _ParseMlirRetTyStr + # 分派;LLVM 类型文本不可能以 '#' 开头,无歧义) + rt_len: sizet = 0 + if is_mlir_line != 0: + if mlir_none != 0: + rt_len = 5 # '#' + "none" + else: + rt_len = 1 + (ret_e - ret_s) + else: + rt_len = at_pos - (ls + 7) + kcopy: str = perm.alloc(name_len + 1) + tcopy: str = perm.alloc(rt_len + 1) + if kcopy is not None and tcopy is not None: + string.strncpy(kcopy, text_buf + name_start, name_len) + kcopy[name_len] = '\0' + if is_mlir_line != 0: + tcopy[0] = '#' + if mlir_none != 0: + string.strncpy(tcopy + 1, "none", 4) + else: + string.strncpy(tcopy + 1, text_buf + ret_s, ret_e - ret_s) + else: string.strncpy(tcopy, text_buf + ls + 7, rt_len) - tcopy[rt_len] = '\0' - ht.set_str(kcopy, tcopy) - stdlib.free(key_buf) - # 同趟查找:首个与 search_buf 匹配、且后随 '"' / '(' / 行尾的 define(判定与原二次扫描逐字一致),先命中者为准 - if result_ty is None and name_start + search_str_len <= ls + ll: - if string.strncmp(text_buf + name_start, search_buf, search_str_len) == 0: - end_ch: int = 0 - if name_start + search_str_len < ls + ll: - end_ch = text_buf[name_start + search_str_len] - if end_ch == 34 or end_ch == 40 or end_ch == 0: + tcopy[rt_len] = '\0' + ht.set_str(kcopy, tcopy) + stdlib.free(key_buf) + # 同趟查找:首个与 search_buf 匹配、且后随 '"' / '(' / 行尾的定义行 + # (判定与原二次扫描逐字一致),先命中者为准 + if result_ty is None and name_start + search_str_len <= ls + ll: + if string.strncmp(text_buf + name_start, search_buf, search_str_len) == 0: + end_ch: int = 0 + if name_start + search_str_len < ls + ll: + end_ch = text_buf[name_start + search_str_len] + if end_ch == 34 or end_ch == 40 or end_ch == 0: + if is_mlir_line != 0: + if mlir_none != 0: + result_ty = mlirlite.Void(pool) + else: + result_ty = self._ParseMlirRetTyStr(pool, text_buf, ret_s, ret_e) + else: result_ty = self._ParseLLVMRetTyStr(pool, text_buf, ls + 7, at_pos) pos = le + 1 return result_ty @@ -1168,6 +1437,9 @@ novirtual class CallGenBase: # 缓存命中:O(1) 取回返回类型文本并用调用方 pool 重建类型直接返回;未命中走下方原实现 cached_text: str = self._LookupCachedRetTyText(class_sha1, class_name, method_name, use_bare) if cached_text is not None: + # '#' 前缀 = MLIR 类型文本(_CacheModuleRetTyTexts 写入时打的形态标记) + if cached_text[0] == '#': + return self._ParseMlirRetTyStr(pool, cached_text, 1, string.strlen(cached_text)) return self._ParseLLVMRetTyStr(pool, cached_text, 0, string.strlen(cached_text)) # 构造 text.ll 路径 (level=1): {temp_dir}/{sha1[0:2]}/{sha1}.text.ll