58 Commits
Author SHA1 Message Date
TermiNexus 7a329f7d1e 去除 import t, c 以及 FL 2026-10-17 21:58:05 +08:00
TermiNexus 1b21d58be3 fix(mlirlite): 消除 IR 文本缓冲与解析器的静默截断
构建器:_append_cstr 装不下时改调 MlirFail(原先静默截断会让 switch 少 case、asm 半截、call 少参数);新增 _line_cap_for 按实际片段长度分配行缓冲,覆盖 load/store、12 种转换指令、gep/gep_array/gep_struct、phi、switch、select、atomicrmw、cmpxchg、va_arg、inline asm;build_call 的 callee 不再按 128 截断,参数槽从 32 放宽到 64。解析器:_mlir_read_value/_mlir_read_type 超限即 MlirFail,不再悄悄少写;所有值/类型/符号 scratch 由 512 提到 4096,调用点容量同步;_replace_ssa_numbers 改为两遍精确分配(原 2x 估算会半行截断);全局初始化器的聚合 token 与 addressof 符号名同样改为 4096 + fail-loud;TypePrint 的 "..." 占位现在会置 _MlirTypeTrunc,由 TypePrint 统一报错。
2026-10-17 17:57:40 +08:00
TermiNexus 49889b39c7 docs(mlirlite): README 更新 2026-10-16 16:40:49 +08:00
TermiNexus c816f53af4 chore(mlirlite): too-many-elements 处打印 n/g/src 前缀 - 定位哪个全局数组被放大 2026-10-16 12:53:31 +08:00
TermiNexus e9e1933a62 fix(mlirlite): 全局数组 dense 渲染缓冲提到循环外复用(消每元素~5KB泄漏) + 聚合值读取必前进(修 too many global array elements) 2026-10-16 12:04:24 +08:00
TermiNexus 1eb46faa41 fix(mlirlite): T2「store→load 转发」改为类型感知(跨类型 load 不再被按名替换)
现场(位拷贝早期实现写成 `load i64, ptr %xv`):
  697:16: error: use of value '%x' expects different type than prior uses: 'i64' vs 'f64'
    llvm.store %x, %0 : i64, !llvm.ptr
—— T2 转发是纯**按名字**替换的:把 `store double %x, ptr %xv` 的 %x 顶进了那条 i64 行。

- 扫描时同时记录 store 存值的**类型文本**(括号配平读)与每个 load 的**声明类型文本**
  (同样括号配平,读到第一个顶层 ',' 或空格);
- 仅当**所有 load 的声明类型都与存值类型一致**时才转发,否则整槽放弃(保守,IR 始终合法);
- 同类型槽(标量/指针/聚合的常见情形)转发不受影响:聚合两侧读法同口径,不会因文本截断白丢。
2026-10-15 20:18:59 +08:00
TermiNexus 1aafde09fc fix(mlirlite): 修掉上一提交里 MlirTypeText 的误用(其第 3 参是类型文本,不是 LLVMType*)
现场:cannot convert to MLIR type text (v1 does not cover this form): ''

- 传类型对象当文本 → 取到空串 → fail-fast;改为不调它。
- 位宽改回类型对象自带的 LLVMType.Bits(f16/f32/f64/f128 ↔ 4/8/16/32),并恢复对未知类型的
  容忍(非 4/8/16/32 一律按 f64 位模式,即旧行为)。
- 逐 nibble 自写(_HexDigits)保留:真凶是 printf 对高位置位的 32 位值按符号扩展后的 64 位
  打印(f32 位型 → 16 位文本,配 f32 类型被判位宽不匹配);现在位数严格等于类型位数。
2026-10-15 19:47:55 +08:00
TermiNexus 8dbad705e9 fix(mlirlite): 浮点常量位型改为逐 nibble 自写,位宽只由 MlirTypeText 决定
现场(f32 类型配 16 位文本):
  [MLIR-FAIL] ... (type 'f32' needs 8 hex digits, value '0xffffffffc0490fdb' has 16)
即 -π 的 f32 位型被 printf 按**符号扩展后的 64 位**打印(高位置位 → 16 位),
而 _MlirFloatLiteral 按类型只收 8 位 → 整个模块编不过。

- 名字不再用 snprintf 的 %08x / %016llx / %04x,改 _HexDigits 逐 nibble 写固定位数;
  位数只由 MlirTypeText(ty) 定(与 MLIR 渲染器取类型文本是同一函数)⇒ 两侧位宽构造上一致。
- 位型计算保持不变(f16 先转 half、f32 先转 float、f128 hi/lo、f64 直接取位)。
2026-10-15 19:38:52 +08:00
TermiNexus 32b631ef6f feat(mlirlite): float 位模式位宽不匹配的报文带上类型/常量文本/实际位数
- 只报'宽度不匹配'无法定位是哪条常量(本次现场只能靠二分源码才找到);补上
  (type, want, value, nd) 后一眼可见,与 _MlirConstFail 同风格。
- 同一文件里还带着你之前未提交的改动(函数属性渲染:_MlirFuncAttrs / _SC_Attr /
  AttrGroup 语义注释等),一并入库;如需拆分请示意。
2026-10-15 19:26:16 +08:00
TermiNexus 7f82bec5d1 chore: 全仓同步 TPV→VPC 注释改名与 range(int(...)) 显式收窄适配 2026-10-12 20:59:35 +08:00
TermiNexus 44c1bc4168 fix(mlir): 窥孔取 store 值改按括号配平,修聚合类型被截在第一个逗号 2026-10-12 18:24:55 +08:00
TermiNexus fb365a1707 chore: 改名同步 TransPyV -> ViperC(源码/配置内的纯替换) 2026-10-12 15:06:47 +08:00
TermiNexus bca23ffa06 fix(mlirlite): MLIR 间接调用点也过 alias 解析,callee 不再悬空
no-op bitcast(含函数指针 bitcast)被 alias 机制省略后,参数用法会改写成别名目标,
但 llvm.call 的 callee 位置原样写出 → 悬空 %N,mlir-opt 报 use of undeclared SSA value /
definition of SSA value has type 'i8' but previously used here with type '!llvm.ptr'。

- _MlirCall:callee 走 _MlirResolve,并用解析后的名字判断直接/间接调用
  (别名解析可能把 callee 指到 @符号,那就成了直接调用,不能再写 !llvm.ptr)
2026-10-12 13:18:51 +08:00
TermiNexus 4914311014 fix(mlirlite): 常量表与自动常量名空间(%c<seq>)按需扩容
原实现三处都钉死在 MLIR_CONST_CAP(512):常量表满 → MlirFail("constant table overflow")、%c0..%c511 用尽 → MlirFail、_MlirMarkUsedCName 里"更大的后缀不可能冲突"的假设。这些只是资源限制,不该中断编译。

- 新增 _MLIR_ConstCap 活容量与 _MlirConstGrow(池内翻倍扩容常量表 + 已用名表并拷贝旧内容)
- 常量表满、名字空间用尽改为扩容后重试;_MlirMarkUsedCName 记录任意 c<digits> 并先扩容再置位
- _MlirTablesInit 按活容量分配/清零,复用分支保留已扩容容量
2026-10-12 12:40:20 +08:00
TermiNexus cc7cfdb4af fix(mlirlite): alias 表按需扩容;工厂改 new memgr;define 位宽/截断配套
- mlirlite/__function.vp:_MlirAliasAdd 的 512 条硬上限改为 _MlirAliasGrow 池内翻倍扩容,不再把资源限制当编译错误
- mlirlite 类型工厂改 new memgr(pool) 返回值(消除栈逃逸);__module.vp 补 triple/datalayout
- viperlib.get_digit_count 用 uint(base) 显式声明无符号除法语义(新 AugAssign 符号规则)
- string.vp:strcpy/strcat/strncpy/strncat/memset/memset32/memcpy/memmove 加 @life(noescape(...))
2026-10-12 12:38:15 +08:00
TermiNexus 244179eac7 fix(mlirlite): MLIR 模块头补齐 llvm.target_triple/llvm.data_layout 属性
MLIR 路径原先只在模块头写注释、不落 target triple/datalayout;而 mlir-translate
只从 MLIR 模块属性取值,project.vpj 的 llc 也没有 -mtriple 兜底,因此降级出的
LLVM IR 完全没有 target triple。后果是 opt -passes=asan 按非 Windows 目标选择
固定 shadow 偏移 1<<44,与链接的动态 ASan 运行库实际映射的 shadow 基址不一致,
第一个被插桩的访问即踩到未映射的 shadow 页而崩(现场:启动期
__traceback_install_ctor -> Install -> strcpy 读字面量)。

改为输出 module attributes {llvm.target_triple, llvm.data_layout},使 IR 头随
mlir-translate 降级带出(同时让 llc 拿到正确 target,不再依赖宿主默认)。
2026-10-11 21:21:02 +08:00
TermiNexus 6bd5a6e7a4 refactor(mlirlite): 语法迁移(rawptr/novirtual/解引用写入) 并修正 DerefAs 迁移为整对象拷贝
REnum 变体构造(*LLVMType.X(...))返回的是栈 alloca 地址,不能跨帧存活;原 c.DerefAs(ptr, LLVMType.X(...)) 是'同帧 load+store 拷贝'。机械迁移成 *ptr = LLVMType.X(...) 会把栈地址写进 pool 缓冲并返回(栈逃逸),导致 SpecTypeBits 读到非变体返回 0(现场: enum 宽度推断失败)。改为 *ptr = *LLVMType.X(...) 恢复同帧整对象拷贝;*result_ty_ptr = *result_ty 同理
2026-10-11 12:47:06 +08:00
TermiNexus 466c777f34 feat(mlirlite): 常量渲染失败时报出 (类型, 值),便于定位 unsupported constant operand form
MlirFail 无栈回溯,原报文只有 'unsupported constant operand form',无法判断是哪种非常量形态(指针/聚合类型字面量或常量表达式)。新增 _MlirConstFail:把 MLIR 类型文本与常量文本一并打印。
2026-10-10 20:07:03 +08:00
TermiNexus 76deaa27bf feat(mlirlite): 新增 IRBuilder.build_store_at_entry,支持在入口块写入以建立支配关系
M3 owned slife 的所有权影子标志必须在函数入口块置 0:赋值语句可能落在 if/while 里而运行期不执行,那种路径上出口 free 的是未初始化栈垃圾。实现照搬 build_alloca_at_entry:文本插到入口终止符之前,保证支配所有路径。
2026-10-08 20:03:33 +08:00
TermiNexus 92c2c324cb fix(mlir): 数组包裹的具名结构体回查登记表以补回 packed
build 期的 TypePrint 在具名结构体登记表发布前渲染类型文本,内嵌的具名结构体体
没有 packed;打印期 MlirTypeText 只对扁平 !llvm.struct<" 前缀回查登记表,
!llvm.array< 整段直通,于是同一个 identified type 在模块内出现 packed 与非 packed
两种体,mlir-opt 报 identified type already used with a different body
(现场 Elf64_Phdr:数组元素体无 packed、llvm.load 结果体有 packed,两处字段表
逐字符比对完全相同,只差 packed 关键字)。

新增 _MlirArrayMlirText,只重新转换数组元素类型,使其与其余位置一样回查登记表;
抽出共用的 _MlirArrayXPos / _MlirArrayBody,_MlirArrayText 改为委托(行为不变)。
2026-10-07 15:41:52 +08:00
TermiNexus a8403ee550 chore(detsite): MLIR 类型文本与区域渲染路径补插桩
--detection 的 [FREEFRAME] 取证原先报 site=?:已注册的 17 个 DETSITE 标签全在
结构体/表类分配上,类型文本路径一个都没插。本次新增 34 个标签(18..51):
- mlirlite:_type_str 类型文本、build_call 参数/函数类型文本、常量值类型文本、
  区域渲染 scratch(tb/la/pr/r1/r2/nm/vl/tyb/nb/ps)
- 与之配套的 pool.alloc 全部改用 alloc_tagged,detection==0 时无额外开销。

据此定位到 [FREEFRAME] 写者:TranslatorGenMixin._stg_field_zero_text 的 160B 缓冲。
2026-10-07 15:16:40 +08:00
TermiNexus 825cd2b027 fix(mlir): 全局初始化器区域缓冲溢出不再误报为模块缓冲溢出
- GV_REGION_BUF_SIZE 由 32KB 提升到 4MB,并改用 malloc 分配(原走模块子池,容量受限)
- 新增 _MlirGvOutTrunc 与 _append_gv:区域缓冲溢出独立上报,不再置位模块截断标志
- MlirGvResetScratch 负责释放这两块 malloc 缓冲

复现:font 这类嵌套聚合全局初始化器超过 23 行(368 元素)即误报
module text exceeds output buffer,实际模块缓冲 8MB 远未写满。
2026-10-07 14:24:06 +08:00
TermiNexus 825919b202 fix(compiler): 修复 ViperApps 暴露的 3 处缺陷(vqt6 返回注解 / MLIR 常量命名 / scratch 复用)
1) vqt6/__init__.vp:6 处类实例返回注解由引号前向引用(QAction/QMenu/QTreeWidgetItem)改为 T*——引号前向引用解析为结构体值类型,而实例是指针,致 QAction Foo*→Foo CastError(4 个 Qt 系工程失败)。

2) mlirlite/__function.vp:常量自动 SSA 名 %cN 避让用户同名标识符(形参 c1/c2 与常量 %c1 冲突 => mlir-opt redefinition of SSA value,致 ViperMNIST 失败)。

3) mlirlite/__function.vp + __module.vp:新增 MlirTablesReset,使打印窗口内的表/scratch 跨函数复用(原每函数分配约 153KiB 且窗口内不回收 => 1GiB 主池被榨干,致 ViperFLProject parse scratch allocation failed)。
2026-10-07 08:48:03 +08:00
TermiNexus 587d989dec chore(messages): includes 运行时中文字符串英文化
把 includes 下 11 个文件(memhub 94、mlirlite/__function 71、ast/parser 54、mlirlite/__module 41、mlirlite/__types 28、ast/lexer 8、ast/tokens 4、sys 2、traceback 1、mlirlite/__builder 1、requests/https 1)的运行时诊断/报错字符串(OOM/MEM/FREEFRAME/MLIR 报错/AST 报错/栈转储横幅等)由中文改为英文。

口径:只改字符串字面量内部文字,行数零变化(+307/-307);printf 格式符与转义序列的多重集合逐一校验不变(_strcheck 异常 0)。验证:三重重编 SUCCESS(184.28s)+ 全量 77/77 顺序回归通过 + VET 编译 SUCCESS / --search-paths 7 条 exit 0。
2026-10-06 12:23:45 +08:00
TermiNexus c0d56b127d chore(comments): includes 头注释英文化(R11 收尾)
把 includes 下 64 个 .vp 的文件头注释(含 traceback.vp 第 13-427 行的整块文件级说明)以及 2 处漏网的正文中文注释(ast/lexer.vp、json/__writer.vp)与 1 处中文 docstring(memhub.vp)逐行译为英文;同步把 fltk/gen_ffi.py 的生成模板与其自身注释英文化,使重新生成仍为英文。

只改注释/文档串文字:行数与代码逐字节不变(骨架比对 140 文件漂移 0),运行时中文字符串字面量 305 处保持原样。验证:三重重编 SUCCESS(170.21s)+ 全量 77/77 顺序回归通过 + VET 编译 SUCCESS / --search-paths 7 条 exit 0。
2026-10-06 09:42:25 +08:00
TermiNexus 03450a71ff fix(mlirlite): 局部窥孔优化每个函数体只执行一次
PrintModule 会按 STUB/TEXT/FULL 三次 dump 同一模块,而 FunctionPrint 每次都跑 _peephole_opt;T2(entry-slot store→load 转发)不是幂等变换,第二遍会误删仍有 load 指向的 entry alloca,留下悬空 SSA 名(mlir-opt: op using value defined outside the region)。给 Function 加 PeepDone 守卫,优化只作用于 builder 产出的原始文本。
2026-10-05 19:58:39 +08:00
TermiNexus 0055ab7ea7 refactor: rawptr[T] -> T* 与 t.CConst 前缀迁移(R14/R16)
R14:rawptr[X] -> X*(41 文件 / 2037 行改动),X 含模块限定名与嵌套下标(rawptr[GSList[NameEntry]] -> GSList[NameEntry]*)。保留 6 处 rawptr[t.CPtr](规范例外:存纯裸指针);# 注释与字符串里的 rawptr[...] 属元语法描述,未动。 R16(保守子集):t.CConst | str/bytes -> const str/bytes,t.CConst | char | t.CPtr -> const str;typedef 右值位置豁免(const str 在该处无法注册,与 R1 同源)。 验证:TPC 自举三重重编 SUCCESS;TransPyV.exe 全量 77/77 顺序回归通过。
2026-10-05 17:38:21 +08:00
TermiNexus e71daeea0e docs(includes): R11 注释英文化——75 个文件的中文注释改写为英文短注释
按规范「注释只讲解作用,不掺杂历史原因,尽量英文」:把 includes 下 75 个 .vp 的中文 # 注释与三引号 docstring 改写为英文,每个注释块压到 2 行以内。

保留要点:作用、约束、危险警告(不得/必须/注意)、ABI 与类型约定(如 BYTEPTR | t.CPtr = i8** 的跨模块坍缩坑)、位宽/长度约定、fail-fast 要求、内存与句柄所有权。

未动:文件头注释(规范豁免,仍是中文)、运行时中文字符串常量(printf / fatal_error / MlirFail 等用户可见消息,属代码字面量)。

验证:独立脚本比对 HEAD 与工作区的代码骨架(剥离 # 注释与三引号 docstring 后的非空行)——75 个文件逐字节一致;行尾 CRLF/LF 未被改动;全文剩余中文仅 547 行头注释、0 条行尾注释。bootstrap 三重重编 SUCCESS;全量 77/77 顺序回归通过。
2026-10-05 16:18:44 +08:00
TermiNexus 27121f56a7 refactor(includes): R12 下标 while 循环改 for range,R13 c.Set 迁移为赋值
R12(wiki/新规范 L27-39):把「i: int = 0 与 while i < N: … i += 1」形式的下标循环改写为「for i in range(N):」。保守判定:仅当条件为裸 NAME < EXPR、循环体无 continue、NAME 在体内无其它赋值、无嵌套重绑定、循环后同层不再引用 NAME 时才改写。共 269 处 / 48 文件。

R13:c.Set 是正在退化的路径——c.Set(*p, v) 期望写作 *p = v,c.Set(a, b) 等于 a = b。本次把 includes 内 45 处 c.Set 全部迁移为赋值,includes 已无 c.Set 调用。

验证:bootstrap 三重重编 SUCCESS(无 vast_c 解析回退);全量 77/77 顺序回归通过;ZlibTest 内部断言 79 passed / 0 failed。
2026-10-05 15:33:52 +08:00
TermiNexus e80284a6d5 refactor: 全量迁移 includes 到新规范语法
按根目录 新规范 迁移 R1/R2/R3/R4/R6/R7/R8/R9:指针 T* 后缀、内建类型短别名、c.Addr/c.Deref 单目化、c.Asm 改 __asm__、t.CDefine 改 define 软关键字、t.CEnum 改 enum。R4 对内建 cast 多参实参保留 c.Deref 原写法(单目化会致 TPC 类型退化)。验证:includes 52/52 编译通过,TransPyV 自举产物顺序回归 77/77 全通过。
2026-10-05 09:04:46 +08:00
TermiNexus aecdf27132 feat(mlirlite): 新增调用点记录 API 供 --traceback 旁文件(关闭时零开销)
新增 DebugSetEnabled / DebugNoteFunc / DebugClearFunc / DebugNoteLine /
DebugResetFunc / DebugTakeText 与内部 _DebugNoteCall;build_call 在启用时把
(调用方, 被调方, 当前源行) 追加到可增长文本缓冲,供每模块 DebugTakeText 取出
写 .vpcall。默认(未开 --traceback)不启用,输出不变。
2026-10-04 22:38:07 +08:00
TermiNexus 5dad869a40 fix(mlir): 全局初值 region 草稿缓冲改为单次 PrintModule 复用,修子池耗尽
每个全局初值 region 逐全局 alloc leaf/ins 各 32 KiB、每个初值节点 alloc
4 KiB 类型/符号草稿且从不释放:结构体/vtable 全局多的模块(MLIRLiteTest
#12)在约 2 MiB 模块子池上耗尽,报"零初值类型缓冲分配失败"。

改为按 PrintModule 惰性分配一组复用草稿(leaf/ins/类型/符号/路径栈),
跨全局、跨节点共享;PrintModule 入口 MlirGvResetScratch 使上次草稿失效,
下次按当前池重建(绝不复用已释放/被复用地址的池,避免悬空写穿 canary)。
下标路径改按递归深度分槽的复用栈,不再逐节点分配。
2026-10-04 21:09:36 +08:00
TermiNexus 68fe839da9 fix(mlir): 类型文本缓冲成对扩容(scratch 尺寸 + 各处 cap)
重编 TransPyV 自身时触发类型文本截断护栏:
  [MLIR-FAIL] MLIR 渲染: 类型文本超出输出缓冲被截断(该处缓冲过小,需按类型长度增大)
  (PhaseA ./TransPyV/App/lib/core/CompilerFactory.vp)

根因:内联具名结构体在使用处展开完整字段体,类型文本可达数百字节,而
_append_cstr / MlirTypeText / TypePrint / _MlirTypePrintDepth 的定长
cap(256/512/1024/2048)与对应 scratch 缓冲偏小。

修复(cap 与底层缓冲**成对**放大,保证 cap ≤ 缓冲,绝不越界):
- _MlirTablesInit:_SC_Ty/_SC_Ty2/_SC_Mt/_SC_Buf/_SC_B1/_SC_B2 512→4096、
  _SC_Tmp2/_SC_IdxT 1024→4096、_SC_ArgTs 2048→8192、_SC_Tmp 4096→8192;
- 以"别名 → 缓冲尺寸"追踪脚本放大各调用点 cap(77 处,含被当作 cap 缓冲使用的
  pool.alloc 同步 512/1024→4096),如 _MlirGep 的 idxt/bmt、_MlirCall 的
  argts/rmt/vftys、_MlirNamedStructAppend/TypePrint 的 tmp/rfb/tmp3 等;
- __builder.vp 的 _TY_TEXT_CAP 512→2048(类型文本内嵌缓冲 + cap;arg_cap 由它
  推导,不宜过高以免多参调用单次分配逼近模块池单块上限)。
2026-10-04 19:56:42 +08:00
TermiNexus bca0107240 fix(mlir): 模块缩进辅助缓冲改为池可服务的最大单块 1048560(1 MiB − 16)
256 KiB 对个别大函数偏小,触发自己加的截断护栏:
  [MLIR-FAIL] MLIR 渲染: 输出文本超出缓冲被截断(需增大 dump_ir/FunctionPrint 的缓冲)

模块池(~2 MiB 子池)max_order=15 ⇒ 单个 buddy 块最大 1 MiB,减去 16 字节块头
⇒ 单次 alloc 请求上限 = 1048560。取该值:既不再因 order 16 结构性失败
(1048576 会失败),又给足单函数文本(内联具名结构体使文本显著变长)。
若仍超出,截断由 FunctionPrint/LLVMModulePrint 的截断检查响亮报错。
2026-10-04 18:25:57 +08:00
TermiNexus 1cf7186824 fix(mlir): 模块缩进辅助缓冲 1 MiB → 256 KiB(1 MiB 超出模块池 buddy 上限)
Test 6(ModulePrint)运行期分配失败:
  [MEM] alloc 失败 size=1048576 needed=1048592 order=16 max_order=15
        池容量=2096864

模块池是 ~2 MiB 子池(SUB_POOL_SIZE 2097136),max_order=15 ⇒ 单个 buddy 块
≤ 1 MiB;再加上 16 字节块头,单次 alloc 请求必须 ≤ 1 MiB − 16。请求 1048576
被判需 order 16 ⇒ **结构性失败**(与池内剩余空间多少无关)。

改为 256 KiB:实测最大单成员文本仅 ~54 KB(670 KB 模块 / 12296 行 / 最大函数
991 行,平均 ~54 B/行),余量 ~4.7×;且只需 order 14(512 KiB 块)。
截断仍由 FunctionPrint/LLVMModulePrint 的截断检查响亮报错。
2026-10-03 22:28:34 +08:00
TermiNexus 1860259659 fix(mlir): 具名结构体统一按模块登记定义渲染(同名同体)
mlir-opt 报:
  error: identified type already used with a different body
      %110 = llvm.getelementptr %109[0, 1] : (!llvm.ptr) -> !llvm.ptr,
             !llvm.struct<"0ba5c56e78e3ff23.ParamNode", ()>

同一具名结构体在模块内出现两种体:多数处是 `(!llvm.ptr, !llvm.ptr)`(2 字段),
两处是 `()`(0 字段)。MLIR 的 identified type 要求**同名同体**。

根因:跨模块 stub 构造的**0 字段占位类型对象**被 TypePrint 内联成 `()` 体;
而 `_MlirTypeAppend` 对 `!` 前缀文本(`!llvm.struct<"name", …>`)原样直通,
也不回查登记表。

修复:新增 `_MlirNamedBodyFromTable`(按名字回查登记表,用**模块登记定义**渲染),
两条路径都先回查:
- `_MlirTypeAppend`:`!llvm.struct<"name", …>` 文本命中登记表则改用登记定义重渲;
- `TypePrint` 的 Struct 分支:命中登记表则用登记字段(含 packed 标记)替代自身字段。
未登记(独立 TypePrint / 外在类型)保持原行为(按自身字段内联)。

README §2.10 补"同名同体"硬性约束说明。
2026-10-03 22:18:29 +08:00
TermiNexus f95eb8016b fix(mlir): i1 常量物化用裸布尔关键字(true/false 不带 : i1)
mlir-opt 报:
  error: expected ')'
      %c7 = llvm.mlir.constant(false : i1) : i1

`true`/`false` 是 MLIR 的裸布尔关键字,不能再带类型后缀(其余标量必须写
`值 : 类型`)。

修复两处常量物化:
- `_MlirEmitOneConst`(函数内常量);
- `_MlirGvEmitConst`(全局初值 region 叶子 op)。

README §2.3 常量表补 i1 行。
2026-10-03 22:11:45 +08:00
TermiNexus a7aaed01f4 fix(mlir): LLVM intrinsic 调用改走 llvm.call_intrinsic,声明不输出
mlir-translate 是**程序化构造** LLVM IR,不像 LLVM 的 IR 解析器那样把旧式
intrinsic 名 upgrade 成带类型后缀的形式。原先 `@llvm.va_start` 走普通
llvm.call,且 declare 被原样输出为 `llvm.func @llvm.va_start`,降级得到未
mangle 的 `@llvm.va_start`,LLVM 校验报:

  Intrinsic name not mangled correctly for type arguments!
  Should be: llvm.va_start.p0
  ptr @llvm.va_start

修复:
- `_MlirCall`:裸符号名以 `llvm.` 开头(且非 `llvm.mlir.*`)的调用改渲染为
  `llvm.call_intrinsic "llvm.xxx"(...) : (...) -> ...`,由 mlir-translate
  按操作数类型自动 mangle 名字(llvm.va_start -> llvm.va_start.p0);
- `FunctionPrint`:intrinsic 的 declare **不输出**(否则残留的
  `llvm.func @llvm.va_start` 仍会触发同一校验错误)。

README §2.1 映射表补 intrinsic 行,§2.9 新增 ③′ 说明。
2026-10-03 22:05:30 +08:00
TermiNexus 31fe1bae58 fix(mlir): 补 _MlirModOutTrunc 声明(截断标志此前未落盘)
LLVMModulePrint 已在 bff0f20 使用 global _MlirModOutTrunc,但模块级声明
未随之提交,补上 `_MlirModOutTrunc: int`(否则模块输出截断检查无法编译)。

本文件同时包含一次行尾规范化(mixed -> CRLF),使 diff 显示为全文改动;
忽略空白后实际仅此 1 行内容变化。
2026-10-03 21:33:56 +08:00
TermiNexus aa94d67183 fix(mlir): GEP 常量索引写字面量并修正类型列表
mlir-opt 的 llvm.getelementptr 要求“索引到结构体”的索引必须是常量字面量,
而 _MlirGep 原先把常量索引经 _MlirOperand 物化成 SSA 操作数(%cN),
触发 verifier:
  error: 'llvm.getelementptr' op expected index 1 indexing a struct to be constant

按 MLIR LLVMDialect 的定义修正为官方形态:
- 常量索引 -> 整数字面量([0, 1]),不物化、不占类型位;
- 仅 SSA 索引物化为操作数,其类型进入 (...) 类型列表。

同步修正 README §2.1 映射表(原 [%c0, %c1] : (!llvm.ptr, i32, i32) 形态错误),
并在 §2.3 补充“常量必须物化”的 GEP 索引例外说明。
2026-10-03 21:33:25 +08:00
TermiNexus bff0f20f51 fix(mlir): 模块/函数输出缓冲截断响亮报错 + 缩进辅助缓冲 64 KiB → 1 MiB
dump_ir 的输出缓冲(8/16 MB)此前用 _append_cstr **静默**丢内容 —— MLIR 文本因
内联具名结构体完整字段体而明显长于 LLVM IR,一旦超出就得到被截断的半截模块,
mlir-opt 只会报难以定位的语法错。

- __module.vp:_append_cstr 写入被截断时置 _MlirModOutTrunc;LLVMModulePrint
  结束前检查并 MlirFail;模块缩进辅助缓冲 64 KiB → 1 MiB(tmp_cap),并把该
  缓冲分配失败也改为响亮报错(否则会静默漏印全部模块成员)
- __function.vp:_append_cstr 写入被截断时置 _MlirOutTrunc;FunctionPrint
  三个出口(declare / 无基本块 / 正常结束)均检查并 MlirFail
2026-10-03 21:15:34 +08:00
TermiNexus a502c7242f fix(mlir): 类型文本缓冲按长度给足 + 截断响亮报错(系统性)
根因:MLIR 把具名结构体内联为完整字段体(`!llvm.struct<"名", (i32, !llvm.ptr, …)>`),
单个类型文本可达数百字节,远长于 LLVM 形态的 `%"名"` 引用(十几字节);而 builders
仍按旧的短类型尺寸分配(128/256),指令行里的类型被截断 → 畸形 MLIR。
实测:alloca 行类型被 128 字节缓冲截断,mlir-opt 报
"unbalanced '(' character in pretty dialect name"。

- __types.vp:新增截断溢出标志 _MlirTypeTrunc(_strappend/_MlirAppendN 写入
  被截断时置位),TypePrint / MlirTypeText 渲染后检查并 MlirFail —— 任何截断
  都不再静默产出畸形 MLIR
- __builder.vp:新增 _TY_TEXT_CAP(512)/_LINE_CAP(2560),全部指令行缓冲(alloca
  /ret/load/store/各类 cast/gep/icmp/fcmp/select/atomicrmw/cmpxchg/va_arg/switch
  /case/inline_asm…)改为 _LINE_CAP;build_call / build_call_indirect 的实参表
  与行缓冲按实参个数与实际长度动态分配(原固定 1024/2048 会在两个以上结构体
  实参时静默截断)
- __values.vp:ValuePrint 的类型缓冲 256 → 512
2026-10-03 21:07:55 +08:00
TermiNexus 33d5737f0c feat(mlir): 补齐 f16/f128 浮点位模式物化
ConstFloat 现按类型宽度产出位模式:f16 → 0x%04x(t.CFloat16T 按 half 舍入后取
2 字节)、f32 → 0x%08x、f64 → 0x%016llx、f128 → 高低两个 64 位字拼成 32 位
十六进制(t.CFloat128T 为 double 的无损扩展;c.Load 的宽度取源指针 pointee,
故源显式转成 u64*,避免按 16 字节写入 8 字节目标而越界)。name_buf 由 32 增至
64(f128 文本需 35 字节)。

- _MlirFloatLiteral 接受 f16/f128 原样直通,并新增“位模式位数与类型是否相符”
  强校验(f16/f32/f64/f128 ↔ 4/8/16/32 位十六进制;MLIR 按类型宽度解释该十六进制值)
- README §2.3 常量表 / §5 打印阶段转换说明同步
2026-10-03 20:52:02 +08:00
TermiNexus 597e0e5c4a fix(mlir): ConstFloat 的 f32 位模式改取 float 编码(原取 double 低 32 位)
ConstFloat 以 CDouble 形参接收值,原先 f_bits==32 时直接取 double 位模式的低
32 位当作 f32 位模式 —— 这是错的:3.14 的 double 是 0x40091EB851EB851F,
低 32 位为 0x51EB851F,而 f32 编码应为 0x4048F5C3。
影响以 Float(32) 为类型调用 ConstFloat 的路径(如模块级 t.CFloat 全局初始化
器,TranslatorGenMixin.vp:1014 传 var_ty);指令里的浮点字面量恒以 Double(pool)
创建,不受影响。

- f_bits==32:先 t.CFloat(val) 按 f32 舍入,再 Load 其 4 字节编码
- 更新函数注释:Name 为位模式文本,MLIR FloatAttr 按底层二进制位解释

已知残留(未改,下游会响亮报错):f16/f128 仍按 64 位格式化,宽度与类型不符。
2026-10-03 20:38:27 +08:00
TermiNexus f813c0543b fix(mlir): 浮点常量位模式原样直通,消除 %e 截断精度
MLIR FloatAttr 语法支持十六进制位模式(Builtin Dialect:
`hexadecimal-literal ':' float-type`,按底层二进制位解释),故 ConstFloat 产出的
`0x…` 无需转十进制。此前 _MlirFloatLiteral 把它转成 `%e`(默认 7 位有效数字):
3.141592653589793 → 3.141593e+00,静默截断,与 __values.vp 选位模式的初衷相悖。

- _MlirFloatLiteral:hex 且 mt 为 f32/f64 → 原样返回(无损);
  f16/f128 仍响亮报错(ConstFloat 只产出 64 位位模式,宽度与该两类型不符)
- 删除因此失效的 _MlirParseHexU64
- README §2.3 常量表 / §5 打印阶段转换说明同步
2026-10-03 20:35:37 +08:00
TermiNexus 751e7e7ef7 fix(mlir): 全局嵌套数组/聚合类型前缀走 region;补 MLIR 形态内层前缀剥离
生产者 TranslatorGenMixin._build_array_initializer_text 的嵌套数组初始化器写作
`[!llvm.array<16 x i8>[i8 0, …], …]`(内层类型前缀来自 mlirlite.TypePrint)。
两处缺口叠加导致渲染失败:
1) _MlirGlobalInitNeedsRegion 只按 '@'/'{' 判定是否走 region,嵌套数组被送进
   属性路径 _MlirArrayDenseAt —— 该路径只能表达"值 : 标量类型"的稠密数组,
   内层类型前缀与子 zeroinitializer 都无法表达;
2) _MlirGvWalk 只剥离 LLVM 形态前缀([N x T] / {…}),不认 MLIR 形态
   `!llvm.…` 前缀,元素被当叶子 → 报"全局初值叶子形态 v1 不支持"。

- _MlirGvHasSymOrStruct → _MlirGvArrayNeedsRegion:增认 '!' 前缀,路由到 region
- _MlirGvWalk:新增 MLIR 形态聚合类型前缀剥离(类型记号后紧跟 '[' / '{')
- README §2.5 同步初值两条路径与新增表项
2026-10-03 20:32:56 +08:00
TermiNexus b519269398 fix(mlir): 全局初值支持结构体类型前缀 {…} {…}
_MlirGvWalk 已处理数组类型前缀 `[N x TY][…]`,但 llvm.global_ctors 这类元素写成
`{ i32, void ()*, i8* } { i32 65535, void ()* @ctor, i8* null }` 时,首个花括号组
(类型)被误当字面量解析,报
[MLIR-FAIL] 全局初值叶子形态 v1 不支持:', void ()*, i8* } { i32 65535, … }]'。

- 新增 _MlirGvIsStructType:按深度配平读完首个花括号组(跳过引号内文本),
  其后非空白记号仍是 '{' ⇒ 前一花括号组是类型前缀(同一元素的花括号组之后
  只会是 ',' / ']' / '}' / 结束,故判据无歧义)
- _MlirGvWalk 增加对应的前缀剥离(与数组类型前缀同款处理)
2026-10-03 20:21:19 +08:00
TermiNexus d37d8520c2 fix(mlir): 类型文本转换直通 MLIR 浮点标量 f16/f32/f64/f128
builders 经 TypePrint 输出的内嵌类型已是 MLIR 形态(见本文件 TypePrint 段说明),
但 _MlirTypeAppend 只对 '!' 前缀原样直通,浮点标量落到兜底 fail:实测
`%0 = alloca f64` 报 [MLIR-FAIL] 无法转换为 MLIR 类型文本(v1 未覆盖该形态):'f64'。

- 补 'f' + 全数字直通(与 LLVM 形态 half/float/double/fp128 分支不冲突)
- 订正函数头注释与 MlirTypeText docstring:中间文本两种形态都接受
  (MLIR 常态直通 / LLVM 形态转写)
2026-10-03 20:12:48 +08:00
TermiNexus a99e44863d fix(gep): GEP 下标 zext 下沉到 build_gep/build_gep_array(唯一真源),修复窄整数下标被符号扩展导致越界 2026-10-03 13:35:31 +08:00
TermiNexus 99c1ad44c4 fix(mlirlite): 结构体字段链改用 ParamNode 访问器,消除 ParamNode*→Param* CastError
__module.vp 的 _MlirGvWalkStruct 遍历 LLVMType.Struct 字段链(cur 是 ParamNode*),却调用了 __function 的 param_get_ty/param_get_next(形参是 Param*)→ 触发编译器的「非基本类型指针间禁隐式转换」CastError(MLIRLiteTest 根因)。ParamNode(类型树字段节点)与 Param(函数参数,带名/属性)是两个刻意区分的类,不可合并。改为导入并使用 __types 的 paramnode_get_ty/paramnode_get_next;移除 __module.vp 中已无引用的 Param/param_get_ty/param_get_next 导入。未做指针强转(避免掩盖真实类型错误)。
2026-10-03 12:21:33 +08:00