fix(callgen): text.ll 返回类型回退支持 MLIR 形态 llvm.func
- _CacheModuleRetTyTexts 同时认 define 行与 mlirlite 的 llvm.func 行(含缩进/void 省略 ->/变参) - 缓存值以 '#' 前缀标记 MLIR 形态,命中时用新增 _ParseMlirRetTyStr 解析 - _ParseMlirRetTyStr 覆盖 none/iN/f16..f128/!llvm.ptr/!llvm.array/!llvm.struct(具名按登记表回查,未登记返回 None 不臆造) - 背景:单端 MLIR 后 text.ll 无 define 行,回退恒空 ⇒ 指针返回值退回默认 i32 被 inttoptr 截断
This commit is contained in:
1 parent
7b3e814524
commit
cbf76cd468
1 file changed
+318
-46
@@ -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<N x T> → 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<N x T>
|
||||
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 <ret> @"名"(...) (不缩进)
|
||||
# MLIR 文本: llvm.func @"名"(...) -> <ret> { (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 " 之后即 '@'
|
||||
# 返回类型:` -> <ret>`(到行尾或 " {" 之前);无 `->` = 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
|
||||
|
||||
Reference in new issue
Block a user