mlirlite 发射器改输出 MLIR 文本后,本测试 58 条断言仍在断言旧 LLVM IR 文本 (i32*、add i32、icmp sgt、asm sideeffect、label %then、@.str = 等)→ 全部 迁移到实际 MLIR 形态(!llvm.ptr、llvm.add、llvm.icmp "sgt"、 llvm.inline_asm has_side_effects、^then:、llvm.mlir.global 等)。属性用例按 README §3.3「记录但不渲染」改为签名正向 + 属性文本负向断言。 同时 POOL_SIZE 512KB → 80MB:本测试 27 用例共享同一池(不像 MLIRLiteTest 每用例切子池),mlirlite 单次 PrintModule 需约 1MiB 缩进缓冲,512KB 会池耗尽。 本文件另含既有未提交的注解现代化改动(X | t.CPtr → X*、t.CChar | t.CPtr → str 等),一并纳入本次提交。结果:PASS 80 / FAIL 0。
1164 lines
50 KiB
Plaintext
1164 lines
50 KiB
Plaintext
import stdio
|
||
import string
|
||
import stdlib
|
||
import memhub
|
||
import testcheck
|
||
import mlirlite
|
||
|
||
|
||
# 内存大小
|
||
# 单端 MLIR 后 mlirlite 渲染单次 PrintModule 需约 1 MiB 缩进缓冲 + 类型/初值
|
||
# 草稿,且本测试 27 个用例共享**同一个**池(不像 MLIRLiteTest 每用例切子池)
|
||
# ⇒ 512 KB 远不够(池耗尽)。与 MLIRLiteTest 主池同口径放大到 80 MiB。
|
||
define POOL_SIZE = 83886080 # 80MB
|
||
|
||
|
||
# ============================================================
|
||
# 测试 1: TypePrint 类型打印
|
||
# ============================================================
|
||
def test_type_print(pool: memhub.MemBuddy*):
|
||
testcheck.section("Test 1: TypePrint")
|
||
core: mlirlite.LLVMTypeCore* = mlirlite.LLVMTypeCore(pool)
|
||
buf: str = pool.alloc(64)
|
||
|
||
# i32
|
||
ty_i32: mlirlite.LLVMType* = core.Int32()
|
||
buf[0] = 0
|
||
core.PrintType(buf, 64, ty_i32)
|
||
testcheck.check(string.strcmp(buf, "i32") == 0,
|
||
"Int32 -> i32",
|
||
"Int32 fail")
|
||
|
||
# 不透明指针: Ptr(Int32) -> !llvm.ptr
|
||
ty_ptr: mlirlite.LLVMType* = core.Ptr(ty_i32)
|
||
buf[0] = 0
|
||
core.PrintType(buf, 64, ty_ptr)
|
||
testcheck.check(string.strcmp(buf, "!llvm.ptr") == 0,
|
||
"Ptr(Int32) -> !llvm.ptr",
|
||
"Ptr fail")
|
||
|
||
# Void -> none
|
||
ty_void: mlirlite.LLVMType* = core.Void()
|
||
buf[0] = 0
|
||
core.PrintType(buf, 64, ty_void)
|
||
testcheck.check(string.strcmp(buf, "none") == 0,
|
||
"Void -> none",
|
||
"Void fail")
|
||
|
||
# i64
|
||
ty_i64: mlirlite.LLVMType* = core.Int64()
|
||
buf[0] = 0
|
||
core.PrintType(buf, 64, ty_i64)
|
||
testcheck.check(string.strcmp(buf, "i64") == 0,
|
||
"Int64 -> i64",
|
||
"Int64 fail")
|
||
|
||
|
||
# ============================================================
|
||
# 测试 2: ValuePrint 值打印
|
||
# ============================================================
|
||
def test_value_print(pool: memhub.MemBuddy*):
|
||
testcheck.section("Test 2: ValuePrint")
|
||
core: mlirlite.LLVMTypeCore* = mlirlite.LLVMTypeCore(pool)
|
||
mcore: mlirlite.LLVMModuleCore* = mlirlite.LLVMModuleCore(pool)
|
||
buf: str = pool.alloc(64)
|
||
|
||
ty_i32: mlirlite.LLVMType* = core.Int32()
|
||
|
||
# 常量 42 -> "42 : i32"(MLIR attribute 文本形态)
|
||
val42: mlirlite.Value* = mcore.ConstInt32(42)
|
||
buf[0] = 0
|
||
mcore.PrintValue(buf, 64, val42)
|
||
testcheck.check(string.strcmp(buf, "42 : i32") == 0,
|
||
"ConstInt(42) -> '42 : i32'",
|
||
"ConstInt fail")
|
||
|
||
# SSA 值 %0 -> "%0"(MLIR 操作数不带类型)
|
||
name_ssa: str = pool.alloc(16)
|
||
string.strcpy(name_ssa, "%0")
|
||
val_ssa: mlirlite.Value* = mcore.SSAValue(ty_i32, name_ssa)
|
||
buf[0] = 0
|
||
mcore.PrintValue(buf, 64, val_ssa)
|
||
testcheck.check(string.strcmp(buf, "%0") == 0,
|
||
"SSAValue(%0) -> '%0'",
|
||
"SSAValue fail")
|
||
|
||
|
||
# ============================================================
|
||
# 测试 3: 构建 add 函数
|
||
# llvm.func @add(%a: i32, %b: i32) -> i32 {
|
||
# %0 = llvm.add %a, %b : i32
|
||
# llvm.return %0 : i32
|
||
# }
|
||
# ============================================================
|
||
def test_build_add(pool: memhub.MemBuddy*):
|
||
testcheck.section("Test 3: build_add function")
|
||
|
||
core: mlirlite.LLVMTypeCore* = mlirlite.LLVMTypeCore(pool)
|
||
mcore: mlirlite.LLVMModuleCore* = mlirlite.LLVMModuleCore(pool)
|
||
ty_i32: mlirlite.LLVMType* = core.Int32()
|
||
|
||
# 创建模块 + 函数
|
||
mod: mlirlite.Module* = mcore.NewModule("test_add")
|
||
func: mlirlite.Function* = mcore.CreateFunction(mod, "add", ty_i32)
|
||
|
||
# 添加参数
|
||
mcore.AddParam(func, ty_i32, "%a")
|
||
mcore.AddParam(func, ty_i32, "%b")
|
||
|
||
# 创建 entry 块
|
||
entry: mlirlite.BasicBlock* = mcore.CreateBlock(func, "entry")
|
||
|
||
# 创建 builder
|
||
builder: mlirlite.IRBuilder* = mcore.NewBuilder(func)
|
||
mlirlite.position_at_end(builder, entry)
|
||
|
||
# 为参数创建 Value 包装
|
||
v_a: mlirlite.Value* = mcore.SSAValue(ty_i32, "%a")
|
||
v_b: mlirlite.Value* = mcore.SSAValue(ty_i32, "%b")
|
||
|
||
# %0 = add i32 %a, %b
|
||
v_c: mlirlite.Value* = mlirlite.build_add(builder, v_a, v_b)
|
||
|
||
# ret i32 %0
|
||
mlirlite.build_ret(builder, v_c)
|
||
|
||
# 打印函数
|
||
buf: str = pool.alloc(4096)
|
||
buf[0] = 0
|
||
mcore.PrintFunction(buf, 4096, func)
|
||
testcheck.info(buf)
|
||
|
||
# 验证关键内容
|
||
testcheck.check(string.strstr(buf, "llvm.add %a, %b : i32") is not None,
|
||
"contains 'llvm.add %a, %b : i32'",
|
||
"missing 'llvm.add'")
|
||
testcheck.check(string.strstr(buf, "llvm.return") is not None,
|
||
"contains 'llvm.return'",
|
||
"missing 'llvm.return'")
|
||
testcheck.check(string.strstr(buf, "llvm.func @add(%a: i32, %b: i32) -> i32") is not None,
|
||
"contains 'llvm.func @add(%a: i32, %b: i32) -> i32'",
|
||
"missing function definition")
|
||
|
||
|
||
# ============================================================
|
||
# 测试 4: 构建 if-then-else 函数(max)
|
||
# llvm.func @max(%a: i32, %b: i32) -> i32 {
|
||
# %0 = llvm.icmp "sgt" %a, %b : i32
|
||
# llvm.cond_br %0, ^then, ^else
|
||
# ^then:
|
||
# llvm.return %a : i32
|
||
# ^else:
|
||
# llvm.return %b : i32
|
||
# }
|
||
# ============================================================
|
||
def test_build_if_else(pool: memhub.MemBuddy*):
|
||
testcheck.section("Test 4: build if-then-else (max)")
|
||
|
||
core: mlirlite.LLVMTypeCore* = mlirlite.LLVMTypeCore(pool)
|
||
mcore: mlirlite.LLVMModuleCore* = mlirlite.LLVMModuleCore(pool)
|
||
ty_i32: mlirlite.LLVMType* = core.Int32()
|
||
|
||
mod: mlirlite.Module* = mcore.NewModule("test_max")
|
||
func: mlirlite.Function* = mcore.CreateFunction(mod, "max", ty_i32)
|
||
mcore.AddParam(func, ty_i32, "%a")
|
||
mcore.AddParam(func, ty_i32, "%b")
|
||
|
||
entry: mlirlite.BasicBlock* = mcore.CreateBlock(func, "entry")
|
||
then_blk: mlirlite.BasicBlock* = mcore.CreateBlock(func, "then")
|
||
else_blk: mlirlite.BasicBlock* = mcore.CreateBlock(func, "else")
|
||
|
||
builder: mlirlite.IRBuilder* = mcore.NewBuilder(func)
|
||
|
||
# entry: %0 = icmp sgt i32 %a, %b; br i1 %0, label %then, label %else
|
||
mlirlite.position_at_end(builder, entry)
|
||
v_a: mlirlite.Value* = mcore.SSAValue(ty_i32, "%a")
|
||
v_b: mlirlite.Value* = mcore.SSAValue(ty_i32, "%b")
|
||
v_cond: mlirlite.Value* = mlirlite.build_icmp(builder, mlirlite.ICMP_SGT, v_a, v_b)
|
||
mlirlite.build_cond_br(builder, v_cond, then_blk, else_blk)
|
||
|
||
# then: ret i32 %a
|
||
mlirlite.position_at_end(builder, then_blk)
|
||
mlirlite.build_ret(builder, v_a)
|
||
|
||
# else: ret i32 %b
|
||
mlirlite.position_at_end(builder, else_blk)
|
||
mlirlite.build_ret(builder, v_b)
|
||
|
||
# 打印函数
|
||
buf: str = pool.alloc(4096)
|
||
buf[0] = 0
|
||
mcore.PrintFunction(buf, 4096, func)
|
||
testcheck.info(buf)
|
||
|
||
# 验证关键内容
|
||
testcheck.check(string.strstr(buf, "llvm.icmp \"sgt\"") is not None,
|
||
"contains 'llvm.icmp \"sgt\"'",
|
||
"missing 'llvm.icmp \"sgt\"'")
|
||
testcheck.check(string.strstr(buf, "llvm.cond_br") is not None,
|
||
"contains 'llvm.cond_br'",
|
||
"missing 'llvm.cond_br'")
|
||
testcheck.check(string.strstr(buf, "^then:") is not None,
|
||
"contains '^then:'",
|
||
"missing block label '^then:'")
|
||
testcheck.check(string.strstr(buf, "^else:") is not None,
|
||
"contains '^else:'",
|
||
"missing block label '^else:'")
|
||
|
||
|
||
# ============================================================
|
||
# 测试 5: 完整模块 ModulePrint
|
||
# ============================================================
|
||
def test_module_print(pool: memhub.MemBuddy*):
|
||
testcheck.section("Test 5: ModulePrint")
|
||
|
||
core: mlirlite.LLVMTypeCore* = mlirlite.LLVMTypeCore(pool)
|
||
mcore: mlirlite.LLVMModuleCore* = mlirlite.LLVMModuleCore(pool)
|
||
ty_i32: mlirlite.LLVMType* = core.Int32()
|
||
ty_void: mlirlite.LLVMType* = core.Void()
|
||
|
||
# 创建模块
|
||
mod: mlirlite.Module* = mcore.NewModule("test_module")
|
||
mlirlite.module_set_target(mod, "x86_64-pc-windows-gnu")
|
||
mlirlite.module_set_datalayout(mod, "e-m:w-p270:32:32")
|
||
|
||
# 函数 1: add
|
||
func_add: mlirlite.Function* = mcore.CreateFunction(mod, "add", ty_i32)
|
||
mcore.AddParam(func_add, ty_i32, "%a")
|
||
mcore.AddParam(func_add, ty_i32, "%b")
|
||
entry1: mlirlite.BasicBlock* = mcore.CreateBlock(func_add, "entry")
|
||
builder1: mlirlite.IRBuilder* = mcore.NewBuilder(func_add)
|
||
mlirlite.position_at_end(builder1, entry1)
|
||
v_a1: mlirlite.Value* = mcore.SSAValue(ty_i32, "%a")
|
||
v_b1: mlirlite.Value* = mcore.SSAValue(ty_i32, "%b")
|
||
v_sum: mlirlite.Value* = mlirlite.build_add(builder1, v_a1, v_b1)
|
||
mlirlite.build_ret(builder1, v_sum)
|
||
|
||
# 函数 2: void 函数
|
||
func_void: mlirlite.Function* = mcore.CreateFunction(mod, "noop", ty_void)
|
||
entry2: mlirlite.BasicBlock* = mcore.CreateBlock(func_void, "entry")
|
||
builder2: mlirlite.IRBuilder* = mcore.NewBuilder(func_void)
|
||
mlirlite.position_at_end(builder2, entry2)
|
||
mlirlite.build_ret_void(builder2)
|
||
|
||
# 打印模块
|
||
buf: str = pool.alloc(8192)
|
||
buf[0] = 0
|
||
mcore.PrintModule(buf, 8192, mod)
|
||
testcheck.info(buf)
|
||
|
||
# 验证关键内容
|
||
testcheck.check(string.strstr(buf, "module {") is not None,
|
||
"contains 'module {'",
|
||
"missing 'module {'")
|
||
testcheck.check(string.strstr(buf, "target triple") is not None,
|
||
"contains 'target triple'(MLIR 只在注释里标注)",
|
||
"missing 'target triple'")
|
||
testcheck.check(string.strstr(buf, "llvm.func @add") is not None,
|
||
"contains 'llvm.func @add'",
|
||
"missing add function")
|
||
testcheck.check(string.strstr(buf, "llvm.func @noop()") is not None,
|
||
"contains 'llvm.func @noop()'(void 返回省略 -> ty)",
|
||
"missing noop function")
|
||
testcheck.check(string.strstr(buf, "llvm.return") is not None,
|
||
"contains 'llvm.return'",
|
||
"missing 'llvm.return'")
|
||
|
||
|
||
# ============================================================
|
||
# 测试 6: 数组类型打印
|
||
# ============================================================
|
||
def test_array_type(pool: memhub.MemBuddy*):
|
||
testcheck.section("Test 6: ArrayType")
|
||
core: mlirlite.LLVMTypeCore* = mlirlite.LLVMTypeCore(pool)
|
||
buf: str = pool.alloc(128)
|
||
|
||
# [4 x i32] -> !llvm.array<4 x i32>
|
||
ty_i32: mlirlite.LLVMType* = core.Int32()
|
||
ty_arr: mlirlite.LLVMType* = core.Array(ty_i32, 4)
|
||
buf[0] = 0
|
||
core.PrintType(buf, 128, ty_arr)
|
||
testcheck.check(string.strcmp(buf, "!llvm.array<4 x i32>") == 0,
|
||
"Array(i32,4) -> !llvm.array<4 x i32>",
|
||
"Array fail")
|
||
|
||
# [2 x [3 x i8]] -> !llvm.array<2 x !llvm.array<3 x i8>>
|
||
ty_i8: mlirlite.LLVMType* = core.Int8()
|
||
ty_inner: mlirlite.LLVMType* = core.Array(ty_i8, 3)
|
||
ty_nested: mlirlite.LLVMType* = core.Array(ty_inner, 2)
|
||
buf[0] = 0
|
||
core.PrintType(buf, 128, ty_nested)
|
||
testcheck.check(string.strcmp(buf, "!llvm.array<2 x !llvm.array<3 x i8>>") == 0,
|
||
"nested array -> !llvm.array<2 x !llvm.array<3 x i8>>",
|
||
"nested array fail")
|
||
|
||
|
||
# ============================================================
|
||
# 测试 7: 结构体类型打印
|
||
# ============================================================
|
||
def test_struct_type(pool: memhub.MemBuddy*):
|
||
testcheck.section("Test 7: StructType")
|
||
core: mlirlite.LLVMTypeCore* = mlirlite.LLVMTypeCore(pool)
|
||
buf: str = pool.alloc(128)
|
||
|
||
ty_i32: mlirlite.LLVMType* = core.Int32()
|
||
ty_i8: mlirlite.LLVMType* = core.Int8()
|
||
ty_i8ptr: mlirlite.LLVMType* = core.Ptr(ty_i8)
|
||
|
||
# {i32, i8*} -> !llvm.struct<(i32, !llvm.ptr)>
|
||
n1: mlirlite.ParamNode* = core.NewParamNode(ty_i32)
|
||
n2: mlirlite.ParamNode* = core.NewParamNode(ty_i8ptr)
|
||
head: mlirlite.ParamNode* = core.ParamListAppend(None, None, n1)
|
||
core.ParamListAppend(head, n1, n2)
|
||
ty_struct: mlirlite.LLVMType* = core.Struct(head, 2)
|
||
buf[0] = 0
|
||
core.PrintType(buf, 128, ty_struct)
|
||
testcheck.check(string.strcmp(buf, "!llvm.struct<(i32, !llvm.ptr)>") == 0,
|
||
"struct {i32, i8*} -> !llvm.struct<(i32, !llvm.ptr)>",
|
||
"struct fail")
|
||
|
||
# 空结构体 -> !llvm.struct<()>
|
||
ty_empty: mlirlite.LLVMType* = core.Struct(None, 0)
|
||
buf[0] = 0
|
||
core.PrintType(buf, 128, ty_empty)
|
||
testcheck.check(string.strcmp(buf, "!llvm.struct<()>") == 0,
|
||
"empty struct -> !llvm.struct<()>",
|
||
"empty struct fail")
|
||
|
||
|
||
# ============================================================
|
||
# 测试 8: 函数类型打印
|
||
# ============================================================
|
||
def test_func_type(pool: memhub.MemBuddy*):
|
||
testcheck.section("Test 8: FuncType")
|
||
core: mlirlite.LLVMTypeCore* = mlirlite.LLVMTypeCore(pool)
|
||
buf: str = pool.alloc(128)
|
||
|
||
ty_i32: mlirlite.LLVMType* = core.Int32()
|
||
ty_i8: mlirlite.LLVMType* = core.Int8()
|
||
ty_i8ptr: mlirlite.LLVMType* = core.Ptr(ty_i8)
|
||
|
||
# i32 (i32, i8*) -> !llvm.func<i32 (i32, !llvm.ptr)>
|
||
n1: mlirlite.ParamNode* = core.NewParamNode(ty_i32)
|
||
n2: mlirlite.ParamNode* = core.NewParamNode(ty_i8ptr)
|
||
head: mlirlite.ParamNode* = core.ParamListAppend(None, None, n1)
|
||
core.ParamListAppend(head, n1, n2)
|
||
ty_func: mlirlite.LLVMType* = core.Func(ty_i32, head, 2)
|
||
buf[0] = 0
|
||
core.PrintType(buf, 128, ty_func)
|
||
testcheck.check(string.strcmp(buf, "!llvm.func<i32 (i32, !llvm.ptr)>") == 0,
|
||
"func type -> !llvm.func<i32 (i32, !llvm.ptr)>",
|
||
"func type fail")
|
||
|
||
# void () -> !llvm.func<none ()> — 无参数 void 函数类型
|
||
ty_void: mlirlite.LLVMType* = core.Void()
|
||
ty_func_void: mlirlite.LLVMType* = core.Func(ty_void, None, 0)
|
||
buf[0] = 0
|
||
core.PrintType(buf, 128, ty_func_void)
|
||
testcheck.check(string.strcmp(buf, "!llvm.func<none ()>") == 0,
|
||
"void func -> !llvm.func<none ()>",
|
||
"void func fail")
|
||
|
||
|
||
# ============================================================
|
||
# 测试 9: 声明系统(declare vs define)
|
||
# ============================================================
|
||
def test_declare(pool: memhub.MemBuddy*):
|
||
testcheck.section("Test 9: Declare vs Define")
|
||
core: mlirlite.LLVMTypeCore* = mlirlite.LLVMTypeCore(pool)
|
||
mcore: mlirlite.LLVMModuleCore* = mlirlite.LLVMModuleCore(pool)
|
||
ty_i32: mlirlite.LLVMType* = core.Int32()
|
||
|
||
mod: mlirlite.Module* = mcore.NewModule("test_declare")
|
||
|
||
# declare i32 @extern_func(i32)
|
||
func_decl: mlirlite.Function* = mcore.CreateDeclare(mod, "extern_func", ty_i32)
|
||
mcore.AddParam(func_decl, ty_i32, "%x")
|
||
|
||
# define i32 @defined_func(i32) { entry: ret i32 %x }
|
||
func_def: mlirlite.Function* = mcore.CreateFunction(mod, "defined_func", ty_i32)
|
||
mcore.AddParam(func_def, ty_i32, "%x")
|
||
entry: mlirlite.BasicBlock* = mcore.CreateBlock(func_def, "entry")
|
||
builder: mlirlite.IRBuilder* = mcore.NewBuilder(func_def)
|
||
mlirlite.position_at_end(builder, entry)
|
||
v_x: mlirlite.Value* = mcore.SSAValue(ty_i32, "%x")
|
||
mlirlite.build_ret(builder, v_x)
|
||
|
||
buf: str = pool.alloc(4096)
|
||
buf[0] = 0
|
||
mcore.PrintModule(buf, 4096, mod)
|
||
testcheck.info(buf)
|
||
|
||
testcheck.check(string.strstr(buf, "llvm.func @extern_func(%x: i32) -> i32") is not None,
|
||
"contains declare 'llvm.func @extern_func(%x: i32) -> i32'",
|
||
"missing declare")
|
||
testcheck.check(string.strstr(buf, "llvm.func @defined_func(%x: i32) -> i32") is not None,
|
||
"contains define 'llvm.func @defined_func(%x: i32) -> i32'",
|
||
"missing define")
|
||
testcheck.check(string.strstr(buf, "llvm.func @extern_func(%x: i32) -> i32 {") is None,
|
||
"declare 无函数体(不出现 '{')",
|
||
"declare missing param")
|
||
testcheck.check(string.strstr(buf, "llvm.return %x : i32") is not None,
|
||
"define has body 'llvm.return %x : i32'",
|
||
"define missing body")
|
||
|
||
|
||
# ============================================================
|
||
# 测试 10: 浮点类型与 ConstFloat
|
||
# ============================================================
|
||
def test_float_types(pool: memhub.MemBuddy*):
|
||
testcheck.section("Test 10: Float Types & ConstFloat")
|
||
core: mlirlite.LLVMTypeCore* = mlirlite.LLVMTypeCore(pool)
|
||
mcore: mlirlite.LLVMModuleCore* = mlirlite.LLVMModuleCore(pool)
|
||
buf: str = pool.alloc(128)
|
||
|
||
# half -> f16
|
||
ty_half: mlirlite.LLVMType* = core.Half()
|
||
buf[0] = 0
|
||
core.PrintType(buf, 128, ty_half)
|
||
testcheck.check(string.strcmp(buf, "f16") == 0,
|
||
"Half -> f16",
|
||
"Half fail")
|
||
|
||
# float -> f32
|
||
ty_float: mlirlite.LLVMType* = core.Float()
|
||
buf[0] = 0
|
||
core.PrintType(buf, 128, ty_float)
|
||
testcheck.check(string.strcmp(buf, "f32") == 0,
|
||
"Float -> f32",
|
||
"Float fail")
|
||
|
||
# double -> f64
|
||
ty_double: mlirlite.LLVMType* = core.Double()
|
||
buf[0] = 0
|
||
core.PrintType(buf, 128, ty_double)
|
||
testcheck.check(string.strcmp(buf, "f64") == 0,
|
||
"Double -> f64",
|
||
"Double fail")
|
||
|
||
# fp128 -> f128
|
||
ty_fp128: mlirlite.LLVMType* = core.FP128()
|
||
buf[0] = 0
|
||
core.PrintType(buf, 128, ty_fp128)
|
||
testcheck.check(string.strcmp(buf, "f128") == 0,
|
||
"FP128 -> f128",
|
||
"FP128 fail")
|
||
|
||
# ConstFloat(3.14) -> "0x40091EB851EB851F : f64"
|
||
# (位模式无精度损失;类型注解为 MLIR 形态 f64)
|
||
val_pi: mlirlite.Value* = mcore.ConstFloat(ty_double, 3.14)
|
||
buf[0] = 0
|
||
mcore.PrintValue(buf, 128, val_pi)
|
||
testcheck.check(string.strstr(buf, " : f64") is not None,
|
||
"ConstFloat has MLIR type ' : f64'",
|
||
"ConstFloat missing type")
|
||
testcheck.check(string.strstr(buf, "0x") is not None,
|
||
"ConstFloat has hex bit pattern",
|
||
"ConstFloat missing hex pattern")
|
||
|
||
|
||
# ============================================================
|
||
# 测试 11: 浮点二元运算
|
||
# ============================================================
|
||
def test_float_binops(pool: memhub.MemBuddy*):
|
||
testcheck.section("Test 11: Float Binary Ops")
|
||
core: mlirlite.LLVMTypeCore* = mlirlite.LLVMTypeCore(pool)
|
||
mcore: mlirlite.LLVMModuleCore* = mlirlite.LLVMModuleCore(pool)
|
||
ty_double: mlirlite.LLVMType* = core.Double()
|
||
|
||
mod: mlirlite.Module* = mcore.NewModule("test_fadd")
|
||
func: mlirlite.Function* = mcore.CreateFunction(mod, "fadd", ty_double)
|
||
mcore.AddParam(func, ty_double, "%a")
|
||
mcore.AddParam(func, ty_double, "%b")
|
||
entry: mlirlite.BasicBlock* = mcore.CreateBlock(func, "entry")
|
||
builder: mlirlite.IRBuilder* = mcore.NewBuilder(func)
|
||
mlirlite.position_at_end(builder, entry)
|
||
|
||
v_a: mlirlite.Value* = mcore.SSAValue(ty_double, "%a")
|
||
v_b: mlirlite.Value* = mcore.SSAValue(ty_double, "%b")
|
||
v_c: mlirlite.Value* = mlirlite.build_fadd(builder, v_a, v_b)
|
||
mlirlite.build_ret(builder, v_c)
|
||
|
||
buf: str = pool.alloc(4096)
|
||
buf[0] = 0
|
||
mcore.PrintFunction(buf, 4096, func)
|
||
testcheck.info(buf)
|
||
|
||
testcheck.check(string.strstr(buf, "llvm.fadd %a, %b : f64") is not None,
|
||
"contains 'llvm.fadd %a, %b : f64'",
|
||
"missing 'llvm.fadd'")
|
||
testcheck.check(string.strstr(buf, "llvm.return %0 : f64") is not None,
|
||
"contains 'llvm.return %0 : f64'",
|
||
"missing 'llvm.return'")
|
||
|
||
|
||
# ============================================================
|
||
# 测试 12: 位运算与移位
|
||
# ============================================================
|
||
def test_bitwise_ops(pool: memhub.MemBuddy*):
|
||
testcheck.section("Test 12: Bitwise & Shift Ops")
|
||
core: mlirlite.LLVMTypeCore* = mlirlite.LLVMTypeCore(pool)
|
||
mcore: mlirlite.LLVMModuleCore* = mlirlite.LLVMModuleCore(pool)
|
||
ty_i32: mlirlite.LLVMType* = core.Int32()
|
||
|
||
mod: mlirlite.Module* = mcore.NewModule("test_bitops")
|
||
func: mlirlite.Function* = mcore.CreateFunction(mod, "bitops", ty_i32)
|
||
mcore.AddParam(func, ty_i32, "%a")
|
||
mcore.AddParam(func, ty_i32, "%b")
|
||
entry: mlirlite.BasicBlock* = mcore.CreateBlock(func, "entry")
|
||
builder: mlirlite.IRBuilder* = mcore.NewBuilder(func)
|
||
mlirlite.position_at_end(builder, entry)
|
||
|
||
v_a: mlirlite.Value* = mcore.SSAValue(ty_i32, "%a")
|
||
v_b: mlirlite.Value* = mcore.SSAValue(ty_i32, "%b")
|
||
|
||
# and -> or -> xor -> shl -> ret
|
||
v_and: mlirlite.Value* = mlirlite.build_and(builder, v_a, v_b)
|
||
v_or: mlirlite.Value* = mlirlite.build_or(builder, v_and, v_b)
|
||
v_xor: mlirlite.Value* = mlirlite.build_xor(builder, v_or, v_a)
|
||
v_shl: mlirlite.Value* = mlirlite.build_shl(builder, v_xor, v_b)
|
||
mlirlite.build_ret(builder, v_shl)
|
||
|
||
buf: str = pool.alloc(4096)
|
||
buf[0] = 0
|
||
mcore.PrintFunction(buf, 4096, func)
|
||
testcheck.info(buf)
|
||
|
||
testcheck.check(string.strstr(buf, "llvm.and %a, %b : i32") is not None, "has 'llvm.and %a, %b : i32'", "missing 'llvm.and'")
|
||
testcheck.check(string.strstr(buf, "llvm.or %0, %b : i32") is not None, "has 'llvm.or %0, %b : i32'", "missing 'llvm.or'")
|
||
testcheck.check(string.strstr(buf, "llvm.xor %1, %a : i32") is not None, "has 'llvm.xor %1, %a : i32'", "missing 'llvm.xor'")
|
||
testcheck.check(string.strstr(buf, "llvm.shl %2, %b : i32") is not None, "has 'llvm.shl %2, %b : i32'", "missing 'llvm.shl'")
|
||
|
||
|
||
# ============================================================
|
||
# 测试 13: FCMP 比较
|
||
# ============================================================
|
||
def test_fcmp(pool: memhub.MemBuddy*):
|
||
testcheck.section("Test 13: FCMP")
|
||
core: mlirlite.LLVMTypeCore* = mlirlite.LLVMTypeCore(pool)
|
||
mcore: mlirlite.LLVMModuleCore* = mlirlite.LLVMModuleCore(pool)
|
||
ty_double: mlirlite.LLVMType* = core.Double()
|
||
ty_i1: mlirlite.LLVMType* = core.Int1()
|
||
|
||
mod: mlirlite.Module* = mcore.NewModule("test_fcmp")
|
||
func: mlirlite.Function* = mcore.CreateFunction(mod, "fcmp_test", ty_i1)
|
||
mcore.AddParam(func, ty_double, "%a")
|
||
mcore.AddParam(func, ty_double, "%b")
|
||
entry: mlirlite.BasicBlock* = mcore.CreateBlock(func, "entry")
|
||
builder: mlirlite.IRBuilder* = mcore.NewBuilder(func)
|
||
mlirlite.position_at_end(builder, entry)
|
||
|
||
v_a: mlirlite.Value* = mcore.SSAValue(ty_double, "%a")
|
||
v_b: mlirlite.Value* = mcore.SSAValue(ty_double, "%b")
|
||
v_cond: mlirlite.Value* = mlirlite.build_fcmp(builder, mlirlite.FCMP_OEQ, v_a, v_b)
|
||
mlirlite.build_ret(builder, v_cond)
|
||
|
||
buf: str = pool.alloc(4096)
|
||
buf[0] = 0
|
||
mcore.PrintFunction(buf, 4096, func)
|
||
testcheck.info(buf)
|
||
|
||
testcheck.check(string.strstr(buf, "llvm.fcmp \"oeq\" %a, %b : f64") is not None,
|
||
"contains 'llvm.fcmp \"oeq\" %a, %b : f64'",
|
||
"missing 'llvm.fcmp \"oeq\"'")
|
||
|
||
|
||
# ============================================================
|
||
# 测试 14: 类型转换 (zext, ptrtoint, inttoptr)
|
||
# ============================================================
|
||
def test_casts(pool: memhub.MemBuddy*):
|
||
testcheck.section("Test 14: Casts (zext/ptrtoint/inttoptr)")
|
||
core: mlirlite.LLVMTypeCore* = mlirlite.LLVMTypeCore(pool)
|
||
mcore: mlirlite.LLVMModuleCore* = mlirlite.LLVMModuleCore(pool)
|
||
ty_i32: mlirlite.LLVMType* = core.Int32()
|
||
ty_i64: mlirlite.LLVMType* = core.Int64()
|
||
ty_i8: mlirlite.LLVMType* = core.Int8()
|
||
ty_i8ptr: mlirlite.LLVMType* = core.Ptr(ty_i8)
|
||
|
||
mod: mlirlite.Module* = mcore.NewModule("test_casts")
|
||
func: mlirlite.Function* = mcore.CreateFunction(mod, "cast_test", ty_i64)
|
||
mcore.AddParam(func, ty_i32, "%x")
|
||
entry: mlirlite.BasicBlock* = mcore.CreateBlock(func, "entry")
|
||
builder: mlirlite.IRBuilder* = mcore.NewBuilder(func)
|
||
mlirlite.position_at_end(builder, entry)
|
||
|
||
v_x: mlirlite.Value* = mcore.SSAValue(ty_i32, "%x")
|
||
# zext i32 %x to i64
|
||
v_ext: mlirlite.Value* = mlirlite.build_zext(builder, v_x, ty_i64)
|
||
# ptrtoint i8* null to i64
|
||
v_null: mlirlite.Value* = mcore.ConstNull(ty_i8ptr, "null")
|
||
v_p2i: mlirlite.Value* = mlirlite.build_ptrtoint(builder, v_null, ty_i64)
|
||
# inttoptr i64 %p2i to i8*
|
||
v_i2p: mlirlite.Value* = mlirlite.build_inttoptr(builder, v_p2i, ty_i8ptr)
|
||
# ret i64 %ext
|
||
mlirlite.build_ret(builder, v_ext)
|
||
|
||
buf: str = pool.alloc(4096)
|
||
buf[0] = 0
|
||
mcore.PrintFunction(buf, 4096, func)
|
||
testcheck.info(buf)
|
||
|
||
testcheck.check(string.strstr(buf, "llvm.zext %x : i32 to i64") is not None, "has 'llvm.zext %x : i32 to i64'", "missing 'llvm.zext'")
|
||
testcheck.check(string.strstr(buf, "llvm.ptrtoint %c0 : !llvm.ptr to i64") is not None, "has 'llvm.ptrtoint %c0 : !llvm.ptr to i64'", "missing 'llvm.ptrtoint'")
|
||
testcheck.check(string.strstr(buf, "llvm.inttoptr %1 : i64 to !llvm.ptr") is not None, "has 'llvm.inttoptr %1 : i64 to !llvm.ptr'", "missing 'llvm.inttoptr'")
|
||
|
||
|
||
# ============================================================
|
||
# 测试 15: 浮点转换 (fp2si, si2fp)
|
||
# ============================================================
|
||
def test_fp_conversions(pool: memhub.MemBuddy*):
|
||
testcheck.section("Test 15: FP Conversions (fp2si/si2fp)")
|
||
core: mlirlite.LLVMTypeCore* = mlirlite.LLVMTypeCore(pool)
|
||
mcore: mlirlite.LLVMModuleCore* = mlirlite.LLVMModuleCore(pool)
|
||
ty_i32: mlirlite.LLVMType* = core.Int32()
|
||
ty_double: mlirlite.LLVMType* = core.Double()
|
||
|
||
mod: mlirlite.Module* = mcore.NewModule("test_fpconv")
|
||
func: mlirlite.Function* = mcore.CreateFunction(mod, "fpconv", ty_double)
|
||
mcore.AddParam(func, ty_i32, "%n")
|
||
entry: mlirlite.BasicBlock* = mcore.CreateBlock(func, "entry")
|
||
builder: mlirlite.IRBuilder* = mcore.NewBuilder(func)
|
||
mlirlite.position_at_end(builder, entry)
|
||
|
||
v_n: mlirlite.Value* = mcore.SSAValue(ty_i32, "%n")
|
||
# sitofp i32 %n to double
|
||
v_d: mlirlite.Value* = mlirlite.build_si2fp(builder, v_n, ty_double)
|
||
# fptosi double %d to i32
|
||
v_i: mlirlite.Value* = mlirlite.build_fp2si(builder, v_d, ty_i32)
|
||
# sitofp i32 %i to double (return)
|
||
v_r: mlirlite.Value* = mlirlite.build_si2fp(builder, v_i, ty_double)
|
||
mlirlite.build_ret(builder, v_r)
|
||
|
||
buf: str = pool.alloc(4096)
|
||
buf[0] = 0
|
||
mcore.PrintFunction(buf, 4096, func)
|
||
testcheck.info(buf)
|
||
|
||
testcheck.check(string.strstr(buf, "llvm.sitofp %n : i32 to f64") is not None, "has 'llvm.sitofp %n : i32 to f64'", "missing 'llvm.sitofp'")
|
||
testcheck.check(string.strstr(buf, "llvm.fptosi %0 : f64 to i32") is not None, "has 'llvm.fptosi %0 : f64 to i32'", "missing 'llvm.fptosi'")
|
||
|
||
|
||
# ============================================================
|
||
# 测试 16: Phi 节点
|
||
# ============================================================
|
||
def test_phi(pool: memhub.MemBuddy*):
|
||
testcheck.section("Test 16: Phi Node")
|
||
core: mlirlite.LLVMTypeCore* = mlirlite.LLVMTypeCore(pool)
|
||
mcore: mlirlite.LLVMModuleCore* = mlirlite.LLVMModuleCore(pool)
|
||
ty_i32: mlirlite.LLVMType* = core.Int32()
|
||
|
||
mod: mlirlite.Module* = mcore.NewModule("test_phi")
|
||
func: mlirlite.Function* = mcore.CreateFunction(mod, "phi_test", ty_i32)
|
||
entry: mlirlite.BasicBlock* = mcore.CreateBlock(func, "entry")
|
||
then_blk: mlirlite.BasicBlock* = mcore.CreateBlock(func, "then")
|
||
else_blk: mlirlite.BasicBlock* = mcore.CreateBlock(func, "else")
|
||
merge: mlirlite.BasicBlock* = mcore.CreateBlock(func, "merge")
|
||
builder: mlirlite.IRBuilder* = mcore.NewBuilder(func)
|
||
|
||
# entry: br label %then
|
||
mlirlite.position_at_end(builder, entry)
|
||
mlirlite.build_br(builder, then_blk)
|
||
|
||
# then: br label %merge
|
||
mlirlite.position_at_end(builder, then_blk)
|
||
v_1: mlirlite.Value* = mcore.ConstInt32(1)
|
||
mlirlite.build_br(builder, merge)
|
||
|
||
# else: br label %merge
|
||
mlirlite.position_at_end(builder, else_blk)
|
||
v_2: mlirlite.Value* = mcore.ConstInt32(2)
|
||
mlirlite.build_br(builder, merge)
|
||
|
||
# merge: %r = phi i32 [1, %then], [2, %else]; ret i32 %r
|
||
mlirlite.position_at_end(builder, merge)
|
||
inc1: mlirlite.PhiIncoming* = mlirlite.new_phi_incoming(pool, v_1, then_blk)
|
||
inc2: mlirlite.PhiIncoming* = mlirlite.new_phi_incoming(pool, v_2, else_blk)
|
||
inc1.Next = inc2
|
||
v_r: mlirlite.Value* = mlirlite.build_phi(builder, ty_i32, inc1, 2)
|
||
mlirlite.build_ret(builder, v_r)
|
||
|
||
buf: str = pool.alloc(4096)
|
||
buf[0] = 0
|
||
mcore.PrintFunction(buf, 4096, func)
|
||
testcheck.info(buf)
|
||
|
||
# phi 已转为块参数:不再输出 phi 行,改为 ^merge(%…) + llvm.br ^merge(%…)
|
||
testcheck.check(string.strstr(buf, "llvm.br ^merge(%c0 : i32)") is not None, "has 'llvm.br ^merge(%c0 : i32)'", "missing branch block operands")
|
||
testcheck.check(string.strstr(buf, "^merge(%0: i32):") is not None, "has '^merge(%0: i32):'", "missing block arguments")
|
||
testcheck.check(string.strstr(buf, "^then:") is not None, "has '^then:'", "missing '^then:'")
|
||
testcheck.check(string.strstr(buf, "^else:") is not None, "has '^else:'", "missing '^else:'")
|
||
testcheck.check(string.strstr(buf, " = phi ") is None, "phi 行不再输出", "phi line should not be emitted")
|
||
|
||
|
||
# ============================================================
|
||
# 测试 17: Switch
|
||
# ============================================================
|
||
def test_switch(pool: memhub.MemBuddy*):
|
||
testcheck.section("Test 17: Switch")
|
||
core: mlirlite.LLVMTypeCore* = mlirlite.LLVMTypeCore(pool)
|
||
mcore: mlirlite.LLVMModuleCore* = mlirlite.LLVMModuleCore(pool)
|
||
ty_i32: mlirlite.LLVMType* = core.Int32()
|
||
ty_void: mlirlite.LLVMType* = core.Void()
|
||
|
||
mod: mlirlite.Module* = mcore.NewModule("test_switch")
|
||
func: mlirlite.Function* = mcore.CreateFunction(mod, "switch_test", ty_void)
|
||
mcore.AddParam(func, ty_i32, "%x")
|
||
entry: mlirlite.BasicBlock* = mcore.CreateBlock(func, "entry")
|
||
case0: mlirlite.BasicBlock* = mcore.CreateBlock(func, "case0")
|
||
case1: mlirlite.BasicBlock* = mcore.CreateBlock(func, "case1")
|
||
default_blk: mlirlite.BasicBlock* = mcore.CreateBlock(func, "default")
|
||
builder: mlirlite.IRBuilder* = mcore.NewBuilder(func)
|
||
|
||
# entry: switch i32 %x, label %default [i32 0, label %case0; i32 1, label %case1]
|
||
mlirlite.position_at_end(builder, entry)
|
||
v_x: mlirlite.Value* = mcore.SSAValue(ty_i32, "%x")
|
||
v_0: mlirlite.Value* = mcore.ConstInt32(0)
|
||
v_1: mlirlite.Value* = mcore.ConstInt32(1)
|
||
c0: mlirlite.SwitchCase* = mlirlite.new_switch_case(pool, v_0, case0)
|
||
c1: mlirlite.SwitchCase* = mlirlite.new_switch_case(pool, v_1, case1)
|
||
c0.Next = c1
|
||
mlirlite.build_switch(builder, v_x, default_blk, c0, 2)
|
||
|
||
# case0/case1/default: ret void
|
||
mlirlite.position_at_end(builder, case0)
|
||
mlirlite.build_ret_void(builder)
|
||
mlirlite.position_at_end(builder, case1)
|
||
mlirlite.build_ret_void(builder)
|
||
mlirlite.position_at_end(builder, default_blk)
|
||
mlirlite.build_ret_void(builder)
|
||
|
||
buf: str = pool.alloc(4096)
|
||
buf[0] = 0
|
||
mcore.PrintFunction(buf, 4096, func)
|
||
testcheck.info(buf)
|
||
|
||
testcheck.check(string.strstr(buf, "llvm.switch %x : i32, ^default [0: ^case0, 1: ^case1]") is not None, "has 'llvm.switch %x : i32, ^default [0: ^case0, 1: ^case1]'", "missing 'llvm.switch'")
|
||
testcheck.check(string.strstr(buf, "^default:") is not None, "has '^default:'", "missing '^default:'")
|
||
testcheck.check(string.strstr(buf, "^case0:") is not None, "has '^case0:'", "missing '^case0:'")
|
||
|
||
|
||
# ============================================================
|
||
# 测试 18: Select
|
||
# ============================================================
|
||
def test_select(pool: memhub.MemBuddy*):
|
||
testcheck.section("Test 18: Select")
|
||
core: mlirlite.LLVMTypeCore* = mlirlite.LLVMTypeCore(pool)
|
||
mcore: mlirlite.LLVMModuleCore* = mlirlite.LLVMModuleCore(pool)
|
||
ty_i32: mlirlite.LLVMType* = core.Int32()
|
||
|
||
mod: mlirlite.Module* = mcore.NewModule("test_select")
|
||
func: mlirlite.Function* = mcore.CreateFunction(mod, "sel_test", ty_i32)
|
||
mcore.AddParam(func, ty_i32, "%a")
|
||
mcore.AddParam(func, ty_i32, "%b")
|
||
entry: mlirlite.BasicBlock* = mcore.CreateBlock(func, "entry")
|
||
builder: mlirlite.IRBuilder* = mcore.NewBuilder(func)
|
||
mlirlite.position_at_end(builder, entry)
|
||
|
||
v_a: mlirlite.Value* = mcore.SSAValue(ty_i32, "%a")
|
||
v_b: mlirlite.Value* = mcore.SSAValue(ty_i32, "%b")
|
||
v_cond: mlirlite.Value* = mlirlite.build_icmp(builder, mlirlite.ICMP_SLT, v_a, v_b)
|
||
v_sel: mlirlite.Value* = mlirlite.build_select(builder, v_cond, v_a, v_b)
|
||
mlirlite.build_ret(builder, v_sel)
|
||
|
||
buf: str = pool.alloc(4096)
|
||
buf[0] = 0
|
||
mcore.PrintFunction(buf, 4096, func)
|
||
testcheck.info(buf)
|
||
|
||
testcheck.check(string.strstr(buf, "llvm.select %0, %a, %b : i1, i32") is not None, "has 'llvm.select %0, %a, %b : i1, i32'", "missing 'llvm.select'")
|
||
|
||
|
||
# ============================================================
|
||
# 测试 19: 全局变量 (字符串常量 + 整数)
|
||
# ============================================================
|
||
def test_globals(pool: memhub.MemBuddy*):
|
||
testcheck.section("Test 19: Global Variables")
|
||
core: mlirlite.LLVMTypeCore* = mlirlite.LLVMTypeCore(pool)
|
||
mcore: mlirlite.LLVMModuleCore* = mlirlite.LLVMModuleCore(pool)
|
||
ty_i32: mlirlite.LLVMType* = core.Int32()
|
||
ty_void: mlirlite.LLVMType* = core.Void()
|
||
|
||
mod: mlirlite.Module* = mcore.NewModule("test_globals")
|
||
mlirlite.module_set_target(mod, "x86_64-pc-windows-gnu")
|
||
|
||
# 字符串常量: @.str = private unnamed_addr constant [6 x i8] c"hello\00"
|
||
mcore.CreateGlobalString(mod, ".str", "hello")
|
||
|
||
# 整数全局变量: @counter = global i32 0
|
||
mcore.CreateGlobalInt(mod, "counter", 32, 0)
|
||
|
||
# 添加一个简单函数使模块非空
|
||
func: mlirlite.Function* = mcore.CreateFunction(mod, "use_global", ty_void)
|
||
entry: mlirlite.BasicBlock* = mcore.CreateBlock(func, "entry")
|
||
builder: mlirlite.IRBuilder* = mcore.NewBuilder(func)
|
||
mlirlite.position_at_end(builder, entry)
|
||
mlirlite.build_ret_void(builder)
|
||
|
||
buf: str = pool.alloc(8192)
|
||
buf[0] = 0
|
||
mcore.PrintModule(buf, 8192, mod)
|
||
testcheck.info(buf)
|
||
|
||
testcheck.check(string.strstr(buf, "llvm.mlir.global") is not None, "has 'llvm.mlir.global'", "missing 'llvm.mlir.global'")
|
||
testcheck.check(string.strstr(buf, "private unnamed_addr constant") is not None,
|
||
"has 'private unnamed_addr constant'",
|
||
"missing 'private unnamed_addr constant'")
|
||
testcheck.check(string.strstr(buf, "@\".str\"(") is not None, "has '@\".str\"('", "missing quoted string global")
|
||
testcheck.check(string.strstr(buf, "hello\\00") is not None, "has 'hello\\00'", "missing string content")
|
||
testcheck.check(string.strstr(buf, "@counter(0 : i32) : i32") is not None, "has '@counter(0 : i32) : i32'", "missing '@counter'")
|
||
testcheck.check(string.strstr(buf, "llvm.mlir.global @counter") is not None, "has 'llvm.mlir.global @counter'", "missing integer global")
|
||
|
||
|
||
# ============================================================
|
||
# 测试 20: 函数与参数属性
|
||
# ============================================================
|
||
def test_attributes(pool: memhub.MemBuddy*):
|
||
testcheck.section("Test 20: Function & Param Attributes")
|
||
core: mlirlite.LLVMTypeCore* = mlirlite.LLVMTypeCore(pool)
|
||
mcore: mlirlite.LLVMModuleCore* = mlirlite.LLVMModuleCore(pool)
|
||
ty_i32: mlirlite.LLVMType* = core.Int32()
|
||
ty_i8ptr: mlirlite.LLVMType* = core.Ptr(core.Int8())
|
||
|
||
mod: mlirlite.Module* = mcore.NewModule("test_attrs")
|
||
func: mlirlite.Function* = mcore.CreateFunction(mod, "attr_test", ty_i32)
|
||
|
||
# 参数 0: i32 noundef %x
|
||
p0: mlirlite.Param* = mcore.AddParam(func, ty_i32, "%x")
|
||
mcore.ParamSetAttrs(p0, "noundef")
|
||
|
||
# 参数 1: i8* nocapture %p
|
||
p1: mlirlite.Param* = mcore.AddParam(func, ty_i8ptr, "%p")
|
||
mcore.ParamSetAttrs(p1, "nocapture")
|
||
|
||
# 函数属性: nounwind
|
||
mcore.FunctionSetAttrs(func, "nounwind")
|
||
|
||
entry: mlirlite.BasicBlock* = mcore.CreateBlock(func, "entry")
|
||
builder: mlirlite.IRBuilder* = mcore.NewBuilder(func)
|
||
mlirlite.position_at_end(builder, entry)
|
||
v_x: mlirlite.Value* = mcore.SSAValue(ty_i32, "%x")
|
||
mlirlite.build_ret(builder, v_x)
|
||
|
||
buf: str = pool.alloc(4096)
|
||
buf[0] = 0
|
||
mcore.PrintFunction(buf, 4096, func)
|
||
testcheck.info(buf)
|
||
|
||
# MLIR v1: 函数/参数属性(Attrs)记录但不渲染(见 includes/mlirlite/README.md §3.3)。
|
||
# 故断言签名本身正确、且属性文本不出现(模型字段仍保留)。
|
||
testcheck.check(string.strstr(buf, "llvm.func @attr_test(%x: i32, %p: !llvm.ptr) -> i32") is not None,
|
||
"has 'llvm.func @attr_test(%x: i32, %p: !llvm.ptr) -> i32'",
|
||
"missing attribute-test function signature")
|
||
testcheck.check(string.strstr(buf, "noundef") is None,
|
||
"参数属性 'noundef' 记录但不渲染",
|
||
"param attr 'noundef' should not be rendered")
|
||
testcheck.check(string.strstr(buf, "nocapture") is None,
|
||
"参数属性 'nocapture' 记录但不渲染",
|
||
"param attr 'nocapture' should not be rendered")
|
||
testcheck.check(string.strstr(buf, ") nounwind") is None,
|
||
"函数属性 'nounwind' 记录但不渲染",
|
||
"func attr 'nounwind' should not be rendered")
|
||
|
||
|
||
# ============================================================
|
||
# 测试 21: 原子操作 (atomicrmw / cmpxchg)
|
||
# ============================================================
|
||
def test_atomic(pool: memhub.MemBuddy*):
|
||
testcheck.section("Test 21: Atomic Ops")
|
||
core: mlirlite.LLVMTypeCore* = mlirlite.LLVMTypeCore(pool)
|
||
mcore: mlirlite.LLVMModuleCore* = mlirlite.LLVMModuleCore(pool)
|
||
ty_i32: mlirlite.LLVMType* = core.Int32()
|
||
ty_i32ptr: mlirlite.LLVMType* = core.Ptr(ty_i32)
|
||
|
||
mod: mlirlite.Module* = mcore.NewModule("test_atomic")
|
||
func: mlirlite.Function* = mcore.CreateFunction(mod, "atomic_test", ty_i32)
|
||
mcore.AddParam(func, ty_i32ptr, "%p")
|
||
entry: mlirlite.BasicBlock* = mcore.CreateBlock(func, "entry")
|
||
builder: mlirlite.IRBuilder* = mcore.NewBuilder(func)
|
||
mlirlite.position_at_end(builder, entry)
|
||
|
||
v_p: mlirlite.Value* = mcore.SSAValue(ty_i32ptr, "%p")
|
||
v_1: mlirlite.Value* = mcore.ConstInt32(1)
|
||
# atomicrmw add i32* %p, i32 1 monotonic
|
||
v_r: mlirlite.Value* = mlirlite.build_atomicrmw(builder, mlirlite.ATOMIC_ADD,
|
||
v_p, v_1, mlirlite.ATOMIC_ORDER_MONOTONIC)
|
||
mlirlite.build_ret(builder, v_r)
|
||
|
||
buf: str = pool.alloc(4096)
|
||
buf[0] = 0
|
||
mcore.PrintFunction(buf, 4096, func)
|
||
testcheck.info(buf)
|
||
|
||
testcheck.check(string.strstr(buf, "atomicrmw add") is not None, "has 'atomicrmw add'", "missing 'atomicrmw add'")
|
||
testcheck.check(string.strstr(buf, "monotonic") is not None, "has 'monotonic'", "missing 'monotonic'")
|
||
|
||
|
||
# ============================================================
|
||
# 测试 22: 内联汇编 + unreachable
|
||
# ============================================================
|
||
def test_inline_asm_unreachable(pool: memhub.MemBuddy*):
|
||
testcheck.section("Test 22: Inline ASM & Unreachable")
|
||
core: mlirlite.LLVMTypeCore* = mlirlite.LLVMTypeCore(pool)
|
||
mcore: mlirlite.LLVMModuleCore* = mlirlite.LLVMModuleCore(pool)
|
||
ty_void: mlirlite.LLVMType* = core.Void()
|
||
|
||
mod: mlirlite.Module* = mcore.NewModule("test_asm")
|
||
func: mlirlite.Function* = mcore.CreateFunction(mod, "asm_test", ty_void)
|
||
entry: mlirlite.BasicBlock* = mcore.CreateBlock(func, "entry")
|
||
trap_blk: mlirlite.BasicBlock* = mcore.CreateBlock(func, "trap")
|
||
builder: mlirlite.IRBuilder* = mcore.NewBuilder(func)
|
||
|
||
# entry: call void asm sideeffect "nop", ""(); br label %trap
|
||
mlirlite.position_at_end(builder, entry)
|
||
mlirlite.build_inline_asm(builder, ty_void, "nop", "", 1)
|
||
mlirlite.build_br(builder, trap_blk)
|
||
|
||
# trap: unreachable
|
||
mlirlite.position_at_end(builder, trap_blk)
|
||
mlirlite.build_unreachable(builder)
|
||
|
||
buf: str = pool.alloc(4096)
|
||
buf[0] = 0
|
||
mcore.PrintFunction(buf, 4096, func)
|
||
testcheck.info(buf)
|
||
|
||
testcheck.check(string.strstr(buf, "llvm.inline_asm has_side_effects \"nop\", \"\" : () -> ()") is not None, "has 'llvm.inline_asm has_side_effects \"nop\", \"\" : () -> ()'", "missing 'llvm.inline_asm'")
|
||
testcheck.check(string.strstr(buf, "unreachable") is not None, "has 'unreachable'", "missing 'unreachable'")
|
||
testcheck.check(string.strstr(buf, "llvm.unreachable") is not None, "has 'llvm.unreachable'", "missing 'llvm.unreachable'")
|
||
|
||
|
||
# ============================================================
|
||
# 测试 23: SSA 验证 - 合法函数通过
|
||
# ============================================================
|
||
def test_verify_valid(pool: memhub.MemBuddy*):
|
||
testcheck.section("Test 23: Verify Valid Function")
|
||
core: mlirlite.LLVMTypeCore* = mlirlite.LLVMTypeCore(pool)
|
||
mcore: mlirlite.LLVMModuleCore* = mlirlite.LLVMModuleCore(pool)
|
||
ty_i32: mlirlite.LLVMType* = core.Int32()
|
||
|
||
mod: mlirlite.Module* = mcore.NewModule("verify_valid")
|
||
func: mlirlite.Function* = mcore.CreateFunction(mod, "add", ty_i32)
|
||
mcore.AddParam(func, ty_i32, "%a")
|
||
mcore.AddParam(func, ty_i32, "%b")
|
||
entry: mlirlite.BasicBlock* = mcore.CreateBlock(func, "entry")
|
||
builder: mlirlite.IRBuilder* = mcore.NewBuilder(func)
|
||
mlirlite.position_at_end(builder, entry)
|
||
v_a: mlirlite.Value* = mcore.SSAValue(ty_i32, "%a")
|
||
v_b: mlirlite.Value* = mcore.SSAValue(ty_i32, "%b")
|
||
v_c: mlirlite.Value* = mlirlite.build_add(builder, v_a, v_b)
|
||
mlirlite.build_ret(builder, v_c)
|
||
|
||
result: mlirlite.VerifyResult* = mcore.NewVerifyResult(4096)
|
||
err_count: int = mcore.VerifyFunction(func, result)
|
||
testcheck.check(err_count == 0,
|
||
"valid add function: 0 errors",
|
||
"valid function should pass verification")
|
||
testcheck.check(result.ErrorCode == mlirlite.VERIFY_OK,
|
||
"error code = VERIFY_OK",
|
||
"wrong error code for valid function")
|
||
|
||
|
||
# ============================================================
|
||
# 测试 24: SSA 验证 - 缺少终止指令
|
||
# ============================================================
|
||
def test_verify_no_terminator(pool: memhub.MemBuddy*):
|
||
testcheck.section("Test 24: Verify Missing Terminator")
|
||
core: mlirlite.LLVMTypeCore* = mlirlite.LLVMTypeCore(pool)
|
||
mcore: mlirlite.LLVMModuleCore* = mlirlite.LLVMModuleCore(pool)
|
||
ty_i32: mlirlite.LLVMType* = core.Int32()
|
||
|
||
mod: mlirlite.Module* = mcore.NewModule("verify_noterm")
|
||
func: mlirlite.Function* = mcore.CreateFunction(mod, "noterm", ty_i32)
|
||
mcore.AddParam(func, ty_i32, "%a")
|
||
entry: mlirlite.BasicBlock* = mcore.CreateBlock(func, "entry")
|
||
builder: mlirlite.IRBuilder* = mcore.NewBuilder(func)
|
||
mlirlite.position_at_end(builder, entry)
|
||
v_a: mlirlite.Value* = mcore.SSAValue(ty_i32, "%a")
|
||
mlirlite.build_add(builder, v_a, v_a) # 无 ret
|
||
|
||
result: mlirlite.VerifyResult* = mcore.NewVerifyResult(4096)
|
||
err_count: int = mcore.VerifyFunction(func, result)
|
||
testcheck.check(err_count > 0,
|
||
"missing terminator detected",
|
||
"should detect missing terminator")
|
||
testcheck.check(result.ErrorCode == mlirlite.VERIFY_ERR_NO_TERMINATOR,
|
||
"error code = NO_TERMINATOR",
|
||
"wrong error code for missing terminator")
|
||
|
||
|
||
# ============================================================
|
||
# 测试 25: SSA 验证 - 重复定义
|
||
# ============================================================
|
||
def test_verify_duplicate_def(pool: memhub.MemBuddy*):
|
||
testcheck.section("Test 25: Verify Duplicate Definition")
|
||
core: mlirlite.LLVMTypeCore* = mlirlite.LLVMTypeCore(pool)
|
||
mcore: mlirlite.LLVMModuleCore* = mlirlite.LLVMModuleCore(pool)
|
||
ty_i32: mlirlite.LLVMType* = core.Int32()
|
||
|
||
mod: mlirlite.Module* = mcore.NewModule("verify_dup")
|
||
func: mlirlite.Function* = mcore.CreateFunction(mod, "dup_test", ty_i32)
|
||
mcore.AddParam(func, ty_i32, "%a")
|
||
entry: mlirlite.BasicBlock* = mcore.CreateBlock(func, "entry")
|
||
builder: mlirlite.IRBuilder* = mcore.NewBuilder(func)
|
||
mlirlite.position_at_end(builder, entry)
|
||
v_a: mlirlite.Value* = mcore.SSAValue(ty_i32, "%a")
|
||
v_c: mlirlite.Value* = mlirlite.build_add(builder, v_a, v_a)
|
||
|
||
# 手动追加重复定义行 "%0 = add i32 %a, %a"
|
||
dup_text: str = pool.alloc(64)
|
||
string.strcpy(dup_text, "%0 = add i32 %a, %a")
|
||
mlirlite.block_append_text(pool, entry, dup_text)
|
||
|
||
mlirlite.build_ret(builder, v_c)
|
||
|
||
result: mlirlite.VerifyResult* = mcore.NewVerifyResult(4096)
|
||
err_count: int = mcore.VerifyFunction(func, result)
|
||
testcheck.check(err_count > 0,
|
||
"duplicate definition detected",
|
||
"should detect duplicate definition")
|
||
testcheck.check(result.ErrorCode == mlirlite.VERIFY_ERR_DUPLICATE_DEF,
|
||
"error code = DUPLICATE_DEF",
|
||
"wrong error code for duplicate def")
|
||
|
||
|
||
# ============================================================
|
||
# 测试 26: SSA 验证 - 未定义引用
|
||
# ============================================================
|
||
def test_verify_undef_use(pool: memhub.MemBuddy*):
|
||
testcheck.section("Test 26: Verify Undefined Use")
|
||
core: mlirlite.LLVMTypeCore* = mlirlite.LLVMTypeCore(pool)
|
||
mcore: mlirlite.LLVMModuleCore* = mlirlite.LLVMModuleCore(pool)
|
||
ty_i32: mlirlite.LLVMType* = core.Int32()
|
||
|
||
mod: mlirlite.Module* = mcore.NewModule("verify_undef")
|
||
func: mlirlite.Function* = mcore.CreateFunction(mod, "undef_test", ty_i32)
|
||
mcore.AddParam(func, ty_i32, "%a")
|
||
entry: mlirlite.BasicBlock* = mcore.CreateBlock(func, "entry")
|
||
|
||
# 手动追加含未定义引用的行 "%0 = add i32 %ghost, %a"
|
||
line1: str = pool.alloc(64)
|
||
string.strcpy(line1, "%0 = add i32 %ghost, %a")
|
||
mlirlite.block_append_text(pool, entry, line1)
|
||
|
||
# 手动追加终止指令
|
||
line2: str = pool.alloc(64)
|
||
string.strcpy(line2, "ret i32 %0")
|
||
mlirlite.block_append_text(pool, entry, line2)
|
||
entry.IsTerminated = 1
|
||
|
||
result: mlirlite.VerifyResult* = mcore.NewVerifyResult(4096)
|
||
err_count: int = mcore.VerifyFunction(func, result)
|
||
testcheck.check(err_count > 0,
|
||
"undefined use detected",
|
||
"should detect undefined use")
|
||
testcheck.check(result.ErrorCode == mlirlite.VERIFY_ERR_UNDEFINED_USE,
|
||
"error code = UNDEFINED_USE",
|
||
"wrong error code for undefined use")
|
||
|
||
|
||
# ============================================================
|
||
# 测试 27: SSA 验证 - 模块级验证(含 phi/分支,验证块标签修复)
|
||
# ============================================================
|
||
def test_verify_module(pool: memhub.MemBuddy*):
|
||
testcheck.section("Test 27: Verify Module (phi/labels)")
|
||
core: mlirlite.LLVMTypeCore* = mlirlite.LLVMTypeCore(pool)
|
||
mcore: mlirlite.LLVMModuleCore* = mlirlite.LLVMModuleCore(pool)
|
||
ty_i32: mlirlite.LLVMType* = core.Int32()
|
||
|
||
mod: mlirlite.Module* = mcore.NewModule("verify_module")
|
||
|
||
# 函数 1: 简单 add(合法)
|
||
func1: mlirlite.Function* = mcore.CreateFunction(mod, "add", ty_i32)
|
||
mcore.AddParam(func1, ty_i32, "%a")
|
||
mcore.AddParam(func1, ty_i32, "%b")
|
||
entry1: mlirlite.BasicBlock* = mcore.CreateBlock(func1, "entry")
|
||
builder1: mlirlite.IRBuilder* = mcore.NewBuilder(func1)
|
||
mlirlite.position_at_end(builder1, entry1)
|
||
v_a: mlirlite.Value* = mcore.SSAValue(ty_i32, "%a")
|
||
v_b: mlirlite.Value* = mcore.SSAValue(ty_i32, "%b")
|
||
v_c: mlirlite.Value* = mlirlite.build_add(builder1, v_a, v_b)
|
||
mlirlite.build_ret(builder1, v_c)
|
||
|
||
# 函数 2: 含 phi 与分支(合法,验证块标签不被误报为未定义)
|
||
func2: mlirlite.Function* = mcore.CreateFunction(mod, "phi_test", ty_i32)
|
||
f2_entry: mlirlite.BasicBlock* = mcore.CreateBlock(func2, "entry")
|
||
then_blk: mlirlite.BasicBlock* = mcore.CreateBlock(func2, "then")
|
||
else_blk: mlirlite.BasicBlock* = mcore.CreateBlock(func2, "else")
|
||
merge: mlirlite.BasicBlock* = mcore.CreateBlock(func2, "merge")
|
||
builder2: mlirlite.IRBuilder* = mcore.NewBuilder(func2)
|
||
|
||
# entry: br label %then
|
||
mlirlite.position_at_end(builder2, f2_entry)
|
||
mlirlite.build_br(builder2, then_blk)
|
||
|
||
# then: br label %merge
|
||
mlirlite.position_at_end(builder2, then_blk)
|
||
v_1: mlirlite.Value* = mcore.ConstInt32(1)
|
||
mlirlite.build_br(builder2, merge)
|
||
|
||
# else: br label %merge
|
||
mlirlite.position_at_end(builder2, else_blk)
|
||
v_2: mlirlite.Value* = mcore.ConstInt32(2)
|
||
mlirlite.build_br(builder2, merge)
|
||
|
||
# merge: %r = phi i32 [1, %then], [2, %else]; ret i32 %r
|
||
mlirlite.position_at_end(builder2, merge)
|
||
inc1: mlirlite.PhiIncoming* = mlirlite.new_phi_incoming(pool, v_1, then_blk)
|
||
inc2: mlirlite.PhiIncoming* = mlirlite.new_phi_incoming(pool, v_2, else_blk)
|
||
inc1.Next = inc2
|
||
v_r: mlirlite.Value* = mlirlite.build_phi(builder2, ty_i32, inc1, 2)
|
||
mlirlite.build_ret(builder2, v_r)
|
||
|
||
result: mlirlite.VerifyResult* = mcore.NewVerifyResult(4096)
|
||
err_count: int = mcore.VerifyModule(mod, result)
|
||
testcheck.check(err_count == 0,
|
||
"module with phi/branches: 0 errors",
|
||
"valid module with phi should pass verification")
|
||
testcheck.check(result.ErrorCode == mlirlite.VERIFY_OK,
|
||
"error code = VERIFY_OK",
|
||
"wrong error code for valid module")
|
||
|
||
|
||
def main() -> int:
|
||
testcheck.begin("LLvmLiteTest: mlirlite 库(LLVM IR 生成)")
|
||
|
||
# 初始化 mpool
|
||
pool_mem: bytes = stdlib.malloc(POOL_SIZE)
|
||
if pool_mem is None:
|
||
stdio.printf("FAIL: malloc for pool failed\n")
|
||
return 1
|
||
pool: memhub.MemBuddy* = memhub.MemBuddy(pool_mem, POOL_SIZE)
|
||
if pool is None:
|
||
stdio.printf("FAIL: memhub.MemBuddy init failed\n")
|
||
return 1
|
||
|
||
test_type_print(pool)
|
||
test_value_print(pool)
|
||
test_build_add(pool)
|
||
test_build_if_else(pool)
|
||
test_module_print(pool)
|
||
test_array_type(pool)
|
||
test_struct_type(pool)
|
||
test_func_type(pool)
|
||
test_declare(pool)
|
||
test_float_types(pool)
|
||
test_float_binops(pool)
|
||
test_bitwise_ops(pool)
|
||
test_fcmp(pool)
|
||
test_casts(pool)
|
||
test_fp_conversions(pool)
|
||
test_phi(pool)
|
||
test_switch(pool)
|
||
test_select(pool)
|
||
test_globals(pool)
|
||
test_attributes(pool)
|
||
test_atomic(pool)
|
||
test_inline_asm_unreachable(pool)
|
||
test_verify_valid(pool)
|
||
test_verify_no_terminator(pool)
|
||
test_verify_duplicate_def(pool)
|
||
test_verify_undef_use(pool)
|
||
test_verify_module(pool)
|
||
|
||
return testcheck.end()
|