From 4203b4754f39edf1ff7f3d0b11e41412766df573 Mon Sep 17 00:00:00 2001 From: TermiNexus Date: Sat, 3 Oct 2026 16:31:46 +0800 Subject: [PATCH] =?UTF-8?q?fix(mlirlitetest):=20=E5=AD=90=E6=B1=A0?= =?UTF-8?q?=E6=94=B9=E5=9C=A8=20main=20=E5=B8=A7=E5=86=85=E6=9E=84?= =?UTF-8?q?=E9=80=A0=EF=BC=8C=E4=BF=AE=E5=A4=8D=E8=BF=94=E5=9B=9E=E6=9C=AC?= =?UTF-8?q?=E5=B8=A7=E6=A0=88=E5=AF=B9=E8=B1=A1=E6=8C=87=E9=92=88=E5=AF=BC?= =?UTF-8?q?=E8=87=B4=E7=9A=84=E6=82=AC=E7=A9=BA=E5=86=99=E7=A9=BF?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 现象:Test 1 第一次 alloc 就报 memhub "_split_to_order max_order 非法(字段被写穿): max_order=450754216 usable_size=2096864"(子池对象只有 max_order 是垃圾、相邻字段正常)。 静态查 IR 定根因(temp/a2/a2d629ccc917eaa6.ll):_sub_pool 内 %13 = alloca %MemBuddy,__before_init__/__init__ 都作用在这个栈对象上,最后 ret %MemBuddy* —— Viper 中无 __new__ 的类实例是值语义(降级为栈 alloca),返回"指向本帧局部对象"的指针即悬空;调用方第一次 alloc 读 max_order 落到复用后的栈垃圾。 修复:删掉返回 MemBuddy* 的 _sub_pool 助手,改为在 main 帧内逐测试构造子池(与原代码在 main 建池同款;main 内同样的 alloca %MemBuddy 一直有效,故原版能跑到 Test 14)。 --- MLIRLiteTest/App/main.vp | 89 ++++++++++++++++++++++++---------------- 1 file changed, 54 insertions(+), 35 deletions(-) diff --git a/MLIRLiteTest/App/main.vp b/MLIRLiteTest/App/main.vp index fdeaebb..7d184a8 100644 --- a/MLIRLiteTest/App/main.vp +++ b/MLIRLiteTest/App/main.vp @@ -1451,28 +1451,10 @@ def test_extractvalue_multi_asm(pool: memhub.MemBuddy | t.CPtr): "extractvalue result not referenced") -def _sub_pool(main_pool: memhub.MemBuddy | t.CPtr) -> memhub.MemBuddy | t.CPtr: - """从主池切一块子池给单个测试用(伙伴分配器返回 2 的幂块,可直接作 arena) - - 每个测试在自己的子池里分配:测试内的 IR 对象与渲染器每函数重分配的 - scratch/常量表都落在子池,互不叠加(理由见 SUB_POOL_SIZE 注释)。子池不 - 单独回收——主池按"每个测试一块"给足,测试进程短命。 - """ - mem: rawptr = main_pool.alloc(SUB_POOL_SIZE) - if mem is None: - stdio.printf("FAIL: sub pool alloc failed (raise POOL_SIZE)\n") - stdlib.exit(1) - sub: memhub.MemBuddy | t.CPtr = memhub.MemBuddy(mem, SUB_POOL_SIZE) - if sub is None: - stdio.printf("FAIL: sub pool MemBuddy init failed\n") - stdlib.exit(1) - return sub - - def main() -> int: testcheck.begin("MLIRLiteTest: mlirlite 库(MLIR llvm 方言文本生成)") - # 初始化主池:仅用于切子池(测试内分配一律走各自的子池) + # 初始化主池:仅用于给每个测试切子池(测试内分配一律走各自的子池) pool_mem: bytes = stdlib.malloc(POOL_SIZE) if pool_mem is None: stdio.printf("FAIL: malloc for pool failed\n") @@ -1482,21 +1464,58 @@ def main() -> int: stdio.printf("FAIL: memhub.MemBuddy init failed\n") return 1 - test_type_print(_sub_pool(pool)) - test_value_print(_sub_pool(pool)) - test_build_add(_sub_pool(pool)) - test_build_if_else(_sub_pool(pool)) - test_build_void(_sub_pool(pool)) - test_module_print(_sub_pool(pool)) - test_const_materialize(_sub_pool(pool)) - test_phi_block_args(_sub_pool(pool)) - test_mem_call_cast(_sub_pool(pool)) - test_globals(_sub_pool(pool)) - test_verify_valid(_sub_pool(pool)) - test_struct_global(_sub_pool(pool)) - test_alloca_align_switch_asm(_sub_pool(pool)) - test_vararg_vaarg_cmpxchg(_sub_pool(pool)) - test_named_struct(_sub_pool(pool)) - test_extractvalue_multi_asm(_sub_pool(pool)) + # 子池必须在 **main 的帧内** 构造:Viper 中无 __new__ 的类实例是值语义, + # `MemBuddy(...)` 被降级为栈 alloca;若把它放进"返回 MemBuddy*"的助手函数, + # 返回的就是**指向已销毁栈帧的指针**(IR 物证:_sub_pool 内 + # `%13 = alloca %MemBuddy` … `ret %MemBuddy* %28`),随后第一次 alloc 读 + # `max_order` 即落到复用的栈垃圾 → memhub 报 + # "_split_to_order max_order 非法(字段被写穿)"。故此处在 main 内逐测试构造。 + sub: memhub.MemBuddy | t.CPtr = memhub.MemBuddy(pool.alloc(SUB_POOL_SIZE), SUB_POOL_SIZE) + test_type_print(sub) + + sub = memhub.MemBuddy(pool.alloc(SUB_POOL_SIZE), SUB_POOL_SIZE) + test_value_print(sub) + + sub = memhub.MemBuddy(pool.alloc(SUB_POOL_SIZE), SUB_POOL_SIZE) + test_build_add(sub) + + sub = memhub.MemBuddy(pool.alloc(SUB_POOL_SIZE), SUB_POOL_SIZE) + test_build_if_else(sub) + + sub = memhub.MemBuddy(pool.alloc(SUB_POOL_SIZE), SUB_POOL_SIZE) + test_build_void(sub) + + sub = memhub.MemBuddy(pool.alloc(SUB_POOL_SIZE), SUB_POOL_SIZE) + test_module_print(sub) + + sub = memhub.MemBuddy(pool.alloc(SUB_POOL_SIZE), SUB_POOL_SIZE) + test_const_materialize(sub) + + sub = memhub.MemBuddy(pool.alloc(SUB_POOL_SIZE), SUB_POOL_SIZE) + test_phi_block_args(sub) + + sub = memhub.MemBuddy(pool.alloc(SUB_POOL_SIZE), SUB_POOL_SIZE) + test_mem_call_cast(sub) + + sub = memhub.MemBuddy(pool.alloc(SUB_POOL_SIZE), SUB_POOL_SIZE) + test_globals(sub) + + sub = memhub.MemBuddy(pool.alloc(SUB_POOL_SIZE), SUB_POOL_SIZE) + test_verify_valid(sub) + + sub = memhub.MemBuddy(pool.alloc(SUB_POOL_SIZE), SUB_POOL_SIZE) + test_struct_global(sub) + + sub = memhub.MemBuddy(pool.alloc(SUB_POOL_SIZE), SUB_POOL_SIZE) + test_alloca_align_switch_asm(sub) + + sub = memhub.MemBuddy(pool.alloc(SUB_POOL_SIZE), SUB_POOL_SIZE) + test_vararg_vaarg_cmpxchg(sub) + + sub = memhub.MemBuddy(pool.alloc(SUB_POOL_SIZE), SUB_POOL_SIZE) + test_named_struct(sub) + + sub = memhub.MemBuddy(pool.alloc(SUB_POOL_SIZE), SUB_POOL_SIZE) + test_extractvalue_multi_asm(sub) return testcheck.end()