import t, c
from stdint import *
import stdio
import string
import stdlib
import memhub
import testcheck
import llvmlite


# 内存大小
POOL_SIZE: t.CDefine = 524288  # 512KB


# ============================================================
# 测试 1: TypePrint 类型打印
# ============================================================
def test_type_print(pool: memhub.MemPool | t.CPtr):
    testcheck.section("Test 1: TypePrint")
    core: llvmlite.LLVMTypeCore | t.CPtr = llvmlite.LLVMTypeCore(pool)
    buf: t.CChar | t.CPtr = pool.alloc(64)

    # i32
    ty_i32: llvmlite.LLVMType | t.CPtr = core.Int32()
    buf[0] = 0
    core.PrintType(buf, 64, ty_i32)
    testcheck.check(buf == "i32",
                    "Int32 -> i32",
                    "Int32 fail")

    # i32*
    ty_ptr: llvmlite.LLVMType | t.CPtr = core.Ptr(ty_i32)
    buf[0] = 0
    core.PrintType(buf, 64, ty_ptr)
    testcheck.check(buf == "i32*",
                    "Ptr(Int32) -> i32*",
                    "Ptr fail")

    # void
    ty_void: llvmlite.LLVMType | t.CPtr = core.Void()
    buf[0] = 0
    core.PrintType(buf, 64, ty_void)
    testcheck.check(buf == "void",
                    "Void -> void",
                    "Void fail")

    # i64
    ty_i64: llvmlite.LLVMType | t.CPtr = core.Int64()
    buf[0] = 0
    core.PrintType(buf, 64, ty_i64)
    testcheck.check(buf == "i64",
                    "Int64 -> i64",
                    "Int64 fail")


# ============================================================
# 测试 2: ValuePrint 值打印
# ============================================================
def test_value_print(pool: memhub.MemPool | t.CPtr):
    testcheck.section("Test 2: ValuePrint")
    core: llvmlite.LLVMTypeCore | t.CPtr = llvmlite.LLVMTypeCore(pool)
    mcore: llvmlite.LLVMModuleCore | t.CPtr = llvmlite.LLVMModuleCore(pool)
    buf: t.CChar | t.CPtr = pool.alloc(64)

    ty_i32: llvmlite.LLVMType | t.CPtr = core.Int32()

    # 常量 42
    val42: llvmlite.Value | t.CPtr = mcore.ConstInt32(42)
    buf[0] = 0
    mcore.PrintValue(buf, 64, val42)
    testcheck.check(buf == "i32 42",
                    "ConstInt(42) -> i32 42",
                    "ConstInt fail")

    # SSA 值 %0
    name_ssa: t.CChar | t.CPtr = pool.alloc(16)
    string.strcpy(name_ssa, "%0")
    val_ssa: llvmlite.Value | t.CPtr = mcore.SSAValue(ty_i32, name_ssa)
    buf[0] = 0
    mcore.PrintValue(buf, 64, val_ssa)
    testcheck.check(buf == "i32 %0",
                    "SSAValue(%0) -> i32 %0",
                    "SSAValue fail")


# ============================================================
# 测试 3: 构建 add 函数
# define i32 @add(i32 %a, i32 %b) {
# entry:
#   %0 = add i32 %a, %b
#   ret i32 %0
# }
# ============================================================
def test_build_add(pool: memhub.MemPool | t.CPtr):
    testcheck.section("Test 3: build_add function")

    core: llvmlite.LLVMTypeCore | t.CPtr = llvmlite.LLVMTypeCore(pool)
    mcore: llvmlite.LLVMModuleCore | t.CPtr = llvmlite.LLVMModuleCore(pool)
    ty_i32: llvmlite.LLVMType | t.CPtr = core.Int32()
    testcheck.info("DBG: step1 core/ty_i32 ok")

    # 创建模块 + 函数
    mod: llvmlite.Module | t.CPtr = mcore.NewModule("test_add")
    testcheck.info("DBG: step2 NewModule ok")
    func: llvmlite.Function | t.CPtr = mcore.CreateFunction(mod, "add", ty_i32)
    testcheck.info("DBG: step3 CreateFunction ok")

    # 添加参数
    mcore.AddParam(func, ty_i32, "%a")
    testcheck.info("DBG: step4 AddParam a ok")
    mcore.AddParam(func, ty_i32, "%b")
    testcheck.info("DBG: step5 AddParam b ok")

    # 创建 entry 块
    entry: llvmlite.BasicBlock | t.CPtr = mcore.CreateBlock(func, "entry")
    testcheck.info("DBG: step6 CreateBlock ok")

    # 创建 builder
    builder: llvmlite.IRBuilder | t.CPtr = mcore.NewBuilder(func)
    testcheck.info("DBG: step7 NewBuilder ok")
    llvmlite.position_at_end(builder, entry)
    testcheck.info("DBG: step8 position_at_end ok")

    # 为参数创建 Value 包装
    v_a: llvmlite.Value | t.CPtr = mcore.SSAValue(ty_i32, "%a")
    testcheck.info("DBG: step9 SSAValue a ok")
    v_b: llvmlite.Value | t.CPtr = mcore.SSAValue(ty_i32, "%b")
    testcheck.info("DBG: step10 SSAValue b ok")

    # %0 = add i32 %a, %b
    v_c: llvmlite.Value | t.CPtr = llvmlite.build_add(builder, v_a, v_b)
    testcheck.info("DBG: step11 build_add ok")

    # ret i32 %0
    llvmlite.build_ret(builder, v_c)
    testcheck.info("DBG: step12 build_ret ok")

    # 打印函数
    buf: t.CChar | t.CPtr = pool.alloc(4096)
    testcheck.info("DBG: step13 pool.alloc buf ok")
    buf[0] = 0
    mcore.PrintFunction(buf, 4096, func)
    testcheck.info("DBG: step14 PrintFunction ok")
    testcheck.info(buf)

    # 验证关键内容
    testcheck.check(string.strstr(buf, "add i32") is not None,
                    "contains 'add i32'",
                    "missing 'add i32'")
    testcheck.check(string.strstr(buf, "ret i32") is not None,
                    "contains 'ret i32'",
                    "missing 'ret i32'")
    testcheck.check(string.strstr(buf, "define i32 @add") is not None,
                    "contains 'define i32 @add'",
                    "missing function definition")


# ============================================================
# 测试 4: 构建 if-then-else 函数（max）
# define i32 @max(i32 %a, i32 %b) {
# entry:
#   %0 = icmp sgt i32 %a, %b
#   br i1 %0, label %then, label %else
# then:
#   ret i32 %a
# else:
#   ret i32 %b
# }
# ============================================================
def test_build_if_else(pool: memhub.MemPool | t.CPtr):
    testcheck.section("Test 4: build if-then-else (max)")

    core: llvmlite.LLVMTypeCore | t.CPtr = llvmlite.LLVMTypeCore(pool)
    mcore: llvmlite.LLVMModuleCore | t.CPtr = llvmlite.LLVMModuleCore(pool)
    ty_i32: llvmlite.LLVMType | t.CPtr = core.Int32()

    mod: llvmlite.Module | t.CPtr = mcore.NewModule("test_max")
    func: llvmlite.Function | t.CPtr = mcore.CreateFunction(mod, "max", ty_i32)
    mcore.AddParam(func, ty_i32, "%a")
    mcore.AddParam(func, ty_i32, "%b")

    entry:    llvmlite.BasicBlock | t.CPtr = mcore.CreateBlock(func, "entry")
    then_blk: llvmlite.BasicBlock | t.CPtr = mcore.CreateBlock(func, "then")
    else_blk: llvmlite.BasicBlock | t.CPtr = mcore.CreateBlock(func, "else")

    builder: llvmlite.IRBuilder | t.CPtr = mcore.NewBuilder(func)

    # entry: %0 = icmp sgt i32 %a, %b; br i1 %0, label %then, label %else
    llvmlite.position_at_end(builder, entry)
    v_a: llvmlite.Value | t.CPtr = mcore.SSAValue(ty_i32, "%a")
    v_b: llvmlite.Value | t.CPtr = mcore.SSAValue(ty_i32, "%b")
    v_cond: llvmlite.Value | t.CPtr = llvmlite.build_icmp(builder, llvmlite.ICMP_SGT, v_a, v_b)
    llvmlite.build_cond_br(builder, v_cond, then_blk, else_blk)

    # then: ret i32 %a
    llvmlite.position_at_end(builder, then_blk)
    llvmlite.build_ret(builder, v_a)

    # else: ret i32 %b
    llvmlite.position_at_end(builder, else_blk)
    llvmlite.build_ret(builder, v_b)

    # 打印函数
    buf: t.CChar | t.CPtr = pool.alloc(4096)
    buf[0] = 0
    mcore.PrintFunction(buf, 4096, func)
    testcheck.info(buf)

    # 验证关键内容
    testcheck.check(string.strstr(buf, "icmp sgt") is not None,
                    "contains 'icmp sgt'",
                    "missing 'icmp sgt'")
    testcheck.check(string.strstr(buf, "br i1") is not None,
                    "contains 'br i1'",
                    "missing 'br i1'")
    testcheck.check(string.strstr(buf, "label %then") is not None,
                    "contains 'label %then'",
                    "missing 'label %then'")
    testcheck.check(string.strstr(buf, "label %else") is not None,
                    "contains 'label %else'",
                    "missing 'label %else'")


# ============================================================
# 测试 5: 完整模块 ModulePrint
# ============================================================
def test_module_print(pool: memhub.MemPool | t.CPtr):
    testcheck.section("Test 5: ModulePrint")

    core: llvmlite.LLVMTypeCore | t.CPtr = llvmlite.LLVMTypeCore(pool)
    mcore: llvmlite.LLVMModuleCore | t.CPtr = llvmlite.LLVMModuleCore(pool)
    ty_i32: llvmlite.LLVMType | t.CPtr = core.Int32()
    ty_void: llvmlite.LLVMType | t.CPtr = core.Void()

    # 创建模块
    mod: llvmlite.Module | t.CPtr = mcore.NewModule("test_module")
    llvmlite.module_set_target(mod, "x86_64-pc-windows-gnu")
    llvmlite.module_set_datalayout(mod, "e-m:w-p270:32:32")

    # 函数 1: add
    func_add: llvmlite.Function | t.CPtr = mcore.CreateFunction(mod, "add", ty_i32)
    mcore.AddParam(func_add, ty_i32, "%a")
    mcore.AddParam(func_add, ty_i32, "%b")
    entry1: llvmlite.BasicBlock | t.CPtr = mcore.CreateBlock(func_add, "entry")
    builder1: llvmlite.IRBuilder | t.CPtr = mcore.NewBuilder(func_add)
    llvmlite.position_at_end(builder1, entry1)
    v_a1: llvmlite.Value | t.CPtr = mcore.SSAValue(ty_i32, "%a")
    v_b1: llvmlite.Value | t.CPtr = mcore.SSAValue(ty_i32, "%b")
    v_sum: llvmlite.Value | t.CPtr = llvmlite.build_add(builder1, v_a1, v_b1)
    llvmlite.build_ret(builder1, v_sum)

    # 函数 2: void 函数
    func_void: llvmlite.Function | t.CPtr = mcore.CreateFunction(mod, "noop", ty_void)
    entry2: llvmlite.BasicBlock | t.CPtr = mcore.CreateBlock(func_void, "entry")
    builder2: llvmlite.IRBuilder | t.CPtr = mcore.NewBuilder(func_void)
    llvmlite.position_at_end(builder2, entry2)
    llvmlite.build_ret_void(builder2)

    # 打印模块
    buf: t.CChar | t.CPtr = pool.alloc(8192)
    buf[0] = 0
    mcore.PrintModule(buf, 8192, mod)
    testcheck.info(buf)

    # 验证关键内容
    testcheck.check(string.strstr(buf, "ModuleID") is not None,
                    "contains 'ModuleID'",
                    "missing 'ModuleID'")
    testcheck.check(string.strstr(buf, "target triple") is not None,
                    "contains 'target triple'",
                    "missing 'target triple'")
    testcheck.check(string.strstr(buf, "define i32 @add") is not None,
                    "contains 'define i32 @add'",
                    "missing add function")
    testcheck.check(string.strstr(buf, "define void @noop") is not None,
                    "contains 'define void @noop'",
                    "missing noop function")
    testcheck.check(string.strstr(buf, "ret void") is not None,
                    "contains 'ret void'",
                    "missing 'ret void'")


# ============================================================
# 测试 6: 数组类型打印
# ============================================================
def test_array_type(pool: memhub.MemPool | t.CPtr):
    testcheck.section("Test 6: ArrayType")
    core: llvmlite.LLVMTypeCore | t.CPtr = llvmlite.LLVMTypeCore(pool)
    buf: t.CChar | t.CPtr = pool.alloc(128)

    # [4 x i32]
    ty_i32: llvmlite.LLVMType | t.CPtr = core.Int32()
    ty_arr: llvmlite.LLVMType | t.CPtr = core.Array(ty_i32, 4)
    buf[0] = 0
    core.PrintType(buf, 128, ty_arr)
    testcheck.check(buf == "[4 x i32]",
                    "Array(i32,4) -> [4 x i32]",
                    "Array fail")

    # [2 x [3 x i8]] (嵌套数组)
    ty_i8: llvmlite.LLVMType | t.CPtr = core.Int8()
    ty_inner: llvmlite.LLVMType | t.CPtr = core.Array(ty_i8, 3)
    ty_nested: llvmlite.LLVMType | t.CPtr = core.Array(ty_inner, 2)
    buf[0] = 0
    core.PrintType(buf, 128, ty_nested)
    testcheck.check(buf == "[2 x [3 x i8]]",
                    "nested array -> [2 x [3 x i8]]",
                    "nested array fail")


# ============================================================
# 测试 7: 结构体类型打印
# ============================================================
def test_struct_type(pool: memhub.MemPool | t.CPtr):
    testcheck.section("Test 7: StructType")
    core: llvmlite.LLVMTypeCore | t.CPtr = llvmlite.LLVMTypeCore(pool)
    buf: t.CChar | t.CPtr = pool.alloc(128)

    ty_i32: llvmlite.LLVMType | t.CPtr = core.Int32()
    ty_i8: llvmlite.LLVMType | t.CPtr = core.Int8()
    ty_i8ptr: llvmlite.LLVMType | t.CPtr = core.Ptr(ty_i8)

    # {i32, i8*}
    n1: llvmlite.ParamNode | t.CPtr = core.NewParamNode(ty_i32)
    n2: llvmlite.ParamNode | t.CPtr = core.NewParamNode(ty_i8ptr)
    head: llvmlite.ParamNode | t.CPtr = core.ParamListAppend(None, None, n1)
    core.ParamListAppend(head, n1, n2)
    ty_struct: llvmlite.LLVMType | t.CPtr = core.Struct(head, 2)
    buf[0] = 0
    core.PrintType(buf, 128, ty_struct)
    testcheck.check(buf == "{i32, i8*}",
                    "struct {i32, i8*}",
                    "struct fail")

    # 空结构体 {}
    ty_empty: llvmlite.LLVMType | t.CPtr = core.Struct(None, 0)
    buf[0] = 0
    core.PrintType(buf, 128, ty_empty)
    testcheck.check(buf == "{}",
                    "empty struct -> {}",
                    "empty struct fail")


# ============================================================
# 测试 8: 函数类型打印
# ============================================================
def test_func_type(pool: memhub.MemPool | t.CPtr):
    testcheck.section("Test 8: FuncType")
    core: llvmlite.LLVMTypeCore | t.CPtr = llvmlite.LLVMTypeCore(pool)
    buf: t.CChar | t.CPtr = pool.alloc(128)

    ty_i32: llvmlite.LLVMType | t.CPtr = core.Int32()
    ty_i8: llvmlite.LLVMType | t.CPtr = core.Int8()
    ty_i8ptr: llvmlite.LLVMType | t.CPtr = core.Ptr(ty_i8)

    # i32 (i32, i8*)
    n1: llvmlite.ParamNode | t.CPtr = core.NewParamNode(ty_i32)
    n2: llvmlite.ParamNode | t.CPtr = core.NewParamNode(ty_i8ptr)
    head: llvmlite.ParamNode | t.CPtr = core.ParamListAppend(None, None, n1)
    core.ParamListAppend(head, n1, n2)
    ty_func: llvmlite.LLVMType | t.CPtr = core.Func(ty_i32, head, 2)
    buf[0] = 0
    core.PrintType(buf, 128, ty_func)
    testcheck.check(buf == "i32 (i32, i8*)",
                    "func type -> i32 (i32, i8*)",
                    "func type fail")

    # void () — 无参数函数类型
    ty_void: llvmlite.LLVMType | t.CPtr = core.Void()
    ty_func_void: llvmlite.LLVMType | t.CPtr = core.Func(ty_void, None, 0)
    buf[0] = 0
    core.PrintType(buf, 128, ty_func_void)
    testcheck.check(buf == "void ()",
                    "void func -> void ()",
                    "void func fail")


# ============================================================
# 测试 9: 声明系统（declare vs define）
# ============================================================
def test_declare(pool: memhub.MemPool | t.CPtr):
    testcheck.section("Test 9: Declare vs Define")
    core: llvmlite.LLVMTypeCore | t.CPtr = llvmlite.LLVMTypeCore(pool)
    mcore: llvmlite.LLVMModuleCore | t.CPtr = llvmlite.LLVMModuleCore(pool)
    ty_i32: llvmlite.LLVMType | t.CPtr = core.Int32()

    mod: llvmlite.Module | t.CPtr = mcore.NewModule("test_declare")

    # declare i32 @extern_func(i32)
    func_decl: llvmlite.Function | t.CPtr = 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: llvmlite.Function | t.CPtr = mcore.CreateFunction(mod, "defined_func", ty_i32)
    mcore.AddParam(func_def, ty_i32, "%x")
    entry: llvmlite.BasicBlock | t.CPtr = mcore.CreateBlock(func_def, "entry")
    builder: llvmlite.IRBuilder | t.CPtr = mcore.NewBuilder(func_def)
    llvmlite.position_at_end(builder, entry)
    v_x: llvmlite.Value | t.CPtr = mcore.SSAValue(ty_i32, "%x")
    llvmlite.build_ret(builder, v_x)

    buf: t.CChar | t.CPtr = pool.alloc(4096)
    buf[0] = 0
    mcore.PrintModule(buf, 4096, mod)
    testcheck.info(buf)

    testcheck.check(string.strstr(buf, "declare i32 @extern_func") is not None,
                    "contains 'declare i32 @extern_func'",
                    "missing declare")
    testcheck.check(string.strstr(buf, "define i32 @defined_func") is not None,
                    "contains 'define i32 @defined_func'",
                    "missing define")
    testcheck.check(string.strstr(buf, "declare i32 @extern_func(i32 %x)") is not None,
                    "declare has param",
                    "declare missing param")
    testcheck.check(string.strstr(buf, "ret i32 %x") is not None,
                    "define has body",
                    "define missing body")


# ============================================================
# 测试 10: 浮点类型与 ConstFloat
# ============================================================
def test_float_types(pool: memhub.MemPool | t.CPtr):
    testcheck.section("Test 10: Float Types & ConstFloat")
    core: llvmlite.LLVMTypeCore | t.CPtr = llvmlite.LLVMTypeCore(pool)
    mcore: llvmlite.LLVMModuleCore | t.CPtr = llvmlite.LLVMModuleCore(pool)
    buf: t.CChar | t.CPtr = pool.alloc(128)

    # half
    ty_half: llvmlite.LLVMType | t.CPtr = core.Half()
    buf[0] = 0
    core.PrintType(buf, 128, ty_half)
    testcheck.check(buf == "half",
                    "Half -> half",
                    "Half fail")

    # float
    ty_float: llvmlite.LLVMType | t.CPtr = core.Float()
    buf[0] = 0
    core.PrintType(buf, 128, ty_float)
    testcheck.check(buf == "float",
                    "Float -> float",
                    "Float fail")

    # double
    ty_double: llvmlite.LLVMType | t.CPtr = core.Double()
    buf[0] = 0
    core.PrintType(buf, 128, ty_double)
    testcheck.check(buf == "double",
                    "Double -> double",
                    "Double fail")

    # fp128
    ty_fp128: llvmlite.LLVMType | t.CPtr = core.FP128()
    buf[0] = 0
    core.PrintType(buf, 128, ty_fp128)
    testcheck.check(buf == "fp128",
                    "FP128 -> fp128",
                    "FP128 fail")

    # ConstFloat(3.14) -> "double 3.140000e+00"
    val_pi: llvmlite.Value | t.CPtr = mcore.ConstFloat(ty_double, 3.14)
    buf[0] = 0
    mcore.PrintValue(buf, 128, val_pi)
    testcheck.check(string.strstr(buf, "double") is not None,
                    "ConstFloat has 'double'",
                    "ConstFloat missing type")
    testcheck.check(string.strstr(buf, "e+") is not None or string.strstr(buf, "e-") is not None,
                    "ConstFloat has scientific notation",
                    "ConstFloat missing sci notation")


# ============================================================
# 测试 11: 浮点二元运算
# ============================================================
def test_float_binops(pool: memhub.MemPool | t.CPtr):
    testcheck.section("Test 11: Float Binary Ops")
    core: llvmlite.LLVMTypeCore | t.CPtr = llvmlite.LLVMTypeCore(pool)
    mcore: llvmlite.LLVMModuleCore | t.CPtr = llvmlite.LLVMModuleCore(pool)
    ty_double: llvmlite.LLVMType | t.CPtr = core.Double()

    mod: llvmlite.Module | t.CPtr = mcore.NewModule("test_fadd")
    func: llvmlite.Function | t.CPtr = mcore.CreateFunction(mod, "fadd", ty_double)
    mcore.AddParam(func, ty_double, "%a")
    mcore.AddParam(func, ty_double, "%b")
    entry: llvmlite.BasicBlock | t.CPtr = mcore.CreateBlock(func, "entry")
    builder: llvmlite.IRBuilder | t.CPtr = mcore.NewBuilder(func)
    llvmlite.position_at_end(builder, entry)

    v_a: llvmlite.Value | t.CPtr = mcore.SSAValue(ty_double, "%a")
    v_b: llvmlite.Value | t.CPtr = mcore.SSAValue(ty_double, "%b")
    v_c: llvmlite.Value | t.CPtr = llvmlite.build_fadd(builder, v_a, v_b)
    llvmlite.build_ret(builder, v_c)

    buf: t.CChar | t.CPtr = pool.alloc(4096)
    buf[0] = 0
    mcore.PrintFunction(buf, 4096, func)
    testcheck.info(buf)

    testcheck.check(string.strstr(buf, "fadd double") is not None,
                    "contains 'fadd double'",
                    "missing 'fadd double'")
    testcheck.check(string.strstr(buf, "ret double") is not None,
                    "contains 'ret double'",
                    "missing 'ret double'")


# ============================================================
# 测试 12: 位运算与移位
# ============================================================
def test_bitwise_ops(pool: memhub.MemPool | t.CPtr):
    testcheck.section("Test 12: Bitwise & Shift Ops")
    core: llvmlite.LLVMTypeCore | t.CPtr = llvmlite.LLVMTypeCore(pool)
    mcore: llvmlite.LLVMModuleCore | t.CPtr = llvmlite.LLVMModuleCore(pool)
    ty_i32: llvmlite.LLVMType | t.CPtr = core.Int32()

    mod: llvmlite.Module | t.CPtr = mcore.NewModule("test_bitops")
    func: llvmlite.Function | t.CPtr = mcore.CreateFunction(mod, "bitops", ty_i32)
    mcore.AddParam(func, ty_i32, "%a")
    mcore.AddParam(func, ty_i32, "%b")
    entry: llvmlite.BasicBlock | t.CPtr = mcore.CreateBlock(func, "entry")
    builder: llvmlite.IRBuilder | t.CPtr = mcore.NewBuilder(func)
    llvmlite.position_at_end(builder, entry)

    v_a: llvmlite.Value | t.CPtr = mcore.SSAValue(ty_i32, "%a")
    v_b: llvmlite.Value | t.CPtr = mcore.SSAValue(ty_i32, "%b")

    # and -> or -> xor -> shl -> ret
    v_and: llvmlite.Value | t.CPtr = llvmlite.build_and(builder, v_a, v_b)
    v_or: llvmlite.Value | t.CPtr = llvmlite.build_or(builder, v_and, v_b)
    v_xor: llvmlite.Value | t.CPtr = llvmlite.build_xor(builder, v_or, v_a)
    v_shl: llvmlite.Value | t.CPtr = llvmlite.build_shl(builder, v_xor, v_b)
    llvmlite.build_ret(builder, v_shl)

    buf: t.CChar | t.CPtr = pool.alloc(4096)
    buf[0] = 0
    mcore.PrintFunction(buf, 4096, func)
    testcheck.info(buf)

    testcheck.check(string.strstr(buf, "and i32") is not None, "has 'and i32'", "missing 'and i32'")
    testcheck.check(string.strstr(buf, "or i32") is not None, "has 'or i32'", "missing 'or i32'")
    testcheck.check(string.strstr(buf, "xor i32") is not None, "has 'xor i32'", "missing 'xor i32'")
    testcheck.check(string.strstr(buf, "shl i32") is not None, "has 'shl i32'", "missing 'shl i32'")


# ============================================================
# 测试 13: FCMP 比较
# ============================================================
def test_fcmp(pool: memhub.MemPool | t.CPtr):
    testcheck.section("Test 13: FCMP")
    core: llvmlite.LLVMTypeCore | t.CPtr = llvmlite.LLVMTypeCore(pool)
    mcore: llvmlite.LLVMModuleCore | t.CPtr = llvmlite.LLVMModuleCore(pool)
    ty_double: llvmlite.LLVMType | t.CPtr = core.Double()
    ty_i1: llvmlite.LLVMType | t.CPtr = core.Int1()

    mod: llvmlite.Module | t.CPtr = mcore.NewModule("test_fcmp")
    func: llvmlite.Function | t.CPtr = mcore.CreateFunction(mod, "fcmp_test", ty_i1)
    mcore.AddParam(func, ty_double, "%a")
    mcore.AddParam(func, ty_double, "%b")
    entry: llvmlite.BasicBlock | t.CPtr = mcore.CreateBlock(func, "entry")
    builder: llvmlite.IRBuilder | t.CPtr = mcore.NewBuilder(func)
    llvmlite.position_at_end(builder, entry)

    v_a: llvmlite.Value | t.CPtr = mcore.SSAValue(ty_double, "%a")
    v_b: llvmlite.Value | t.CPtr = mcore.SSAValue(ty_double, "%b")
    v_cond: llvmlite.Value | t.CPtr = llvmlite.build_fcmp(builder, llvmlite.FCMP_OEQ, v_a, v_b)
    llvmlite.build_ret(builder, v_cond)

    buf: t.CChar | t.CPtr = pool.alloc(4096)
    buf[0] = 0
    mcore.PrintFunction(buf, 4096, func)
    testcheck.info(buf)

    testcheck.check(string.strstr(buf, "fcmp oeq double") is not None,
                    "contains 'fcmp oeq double'",
                    "missing 'fcmp oeq double'")


# ============================================================
# 测试 14: 类型转换 (zext, ptrtoint, inttoptr)
# ============================================================
def test_casts(pool: memhub.MemPool | t.CPtr):
    testcheck.section("Test 14: Casts (zext/ptrtoint/inttoptr)")
    core: llvmlite.LLVMTypeCore | t.CPtr = llvmlite.LLVMTypeCore(pool)
    mcore: llvmlite.LLVMModuleCore | t.CPtr = llvmlite.LLVMModuleCore(pool)
    ty_i32: llvmlite.LLVMType | t.CPtr = core.Int32()
    ty_i64: llvmlite.LLVMType | t.CPtr = core.Int64()
    ty_i8: llvmlite.LLVMType | t.CPtr = core.Int8()
    ty_i8ptr: llvmlite.LLVMType | t.CPtr = core.Ptr(ty_i8)

    mod: llvmlite.Module | t.CPtr = mcore.NewModule("test_casts")
    func: llvmlite.Function | t.CPtr = mcore.CreateFunction(mod, "cast_test", ty_i64)
    mcore.AddParam(func, ty_i32, "%x")
    entry: llvmlite.BasicBlock | t.CPtr = mcore.CreateBlock(func, "entry")
    builder: llvmlite.IRBuilder | t.CPtr = mcore.NewBuilder(func)
    llvmlite.position_at_end(builder, entry)

    v_x: llvmlite.Value | t.CPtr = mcore.SSAValue(ty_i32, "%x")
    # zext i32 %x to i64
    v_ext: llvmlite.Value | t.CPtr = llvmlite.build_zext(builder, v_x, ty_i64)
    # ptrtoint i8* null to i64
    v_null: llvmlite.Value | t.CPtr = mcore.ConstNull(ty_i8ptr, "null")
    v_p2i: llvmlite.Value | t.CPtr = llvmlite.build_ptrtoint(builder, v_null, ty_i64)
    # inttoptr i64 %p2i to i8*
    v_i2p: llvmlite.Value | t.CPtr = llvmlite.build_inttoptr(builder, v_p2i, ty_i8ptr)
    # ret i64 %ext
    llvmlite.build_ret(builder, v_ext)

    buf: t.CChar | t.CPtr = pool.alloc(4096)
    buf[0] = 0
    mcore.PrintFunction(buf, 4096, func)
    testcheck.info(buf)

    testcheck.check(string.strstr(buf, "zext i32") is not None, "has 'zext i32'", "missing 'zext i32'")
    testcheck.check(string.strstr(buf, "ptrtoint i8*") is not None, "has 'ptrtoint i8*'", "missing 'ptrtoint i8*'")
    testcheck.check(string.strstr(buf, "inttoptr i64") is not None, "has 'inttoptr i64'", "missing 'inttoptr i64'")


# ============================================================
# 测试 15: 浮点转换 (fp2si, si2fp)
# ============================================================
def test_fp_conversions(pool: memhub.MemPool | t.CPtr):
    testcheck.section("Test 15: FP Conversions (fp2si/si2fp)")
    core: llvmlite.LLVMTypeCore | t.CPtr = llvmlite.LLVMTypeCore(pool)
    mcore: llvmlite.LLVMModuleCore | t.CPtr = llvmlite.LLVMModuleCore(pool)
    ty_i32: llvmlite.LLVMType | t.CPtr = core.Int32()
    ty_double: llvmlite.LLVMType | t.CPtr = core.Double()

    mod: llvmlite.Module | t.CPtr = mcore.NewModule("test_fpconv")
    func: llvmlite.Function | t.CPtr = mcore.CreateFunction(mod, "fpconv", ty_double)
    mcore.AddParam(func, ty_i32, "%n")
    entry: llvmlite.BasicBlock | t.CPtr = mcore.CreateBlock(func, "entry")
    builder: llvmlite.IRBuilder | t.CPtr = mcore.NewBuilder(func)
    llvmlite.position_at_end(builder, entry)

    v_n: llvmlite.Value | t.CPtr = mcore.SSAValue(ty_i32, "%n")
    # sitofp i32 %n to double
    v_d: llvmlite.Value | t.CPtr = llvmlite.build_si2fp(builder, v_n, ty_double)
    # fptosi double %d to i32
    v_i: llvmlite.Value | t.CPtr = llvmlite.build_fp2si(builder, v_d, ty_i32)
    # sitofp i32 %i to double (return)
    v_r: llvmlite.Value | t.CPtr = llvmlite.build_si2fp(builder, v_i, ty_double)
    llvmlite.build_ret(builder, v_r)

    buf: t.CChar | t.CPtr = pool.alloc(4096)
    buf[0] = 0
    mcore.PrintFunction(buf, 4096, func)
    testcheck.info(buf)

    testcheck.check(string.strstr(buf, "sitofp i32") is not None, "has 'sitofp i32'", "missing 'sitofp i32'")
    testcheck.check(string.strstr(buf, "fptosi double") is not None, "has 'fptosi double'", "missing 'fptosi double'")


# ============================================================
# 测试 16: Phi 节点
# ============================================================
def test_phi(pool: memhub.MemPool | t.CPtr):
    testcheck.section("Test 16: Phi Node")
    core: llvmlite.LLVMTypeCore | t.CPtr = llvmlite.LLVMTypeCore(pool)
    mcore: llvmlite.LLVMModuleCore | t.CPtr = llvmlite.LLVMModuleCore(pool)
    ty_i32: llvmlite.LLVMType | t.CPtr = core.Int32()

    mod: llvmlite.Module | t.CPtr = mcore.NewModule("test_phi")
    func: llvmlite.Function | t.CPtr = mcore.CreateFunction(mod, "phi_test", ty_i32)
    entry: llvmlite.BasicBlock | t.CPtr = mcore.CreateBlock(func, "entry")
    then_blk: llvmlite.BasicBlock | t.CPtr = mcore.CreateBlock(func, "then")
    else_blk: llvmlite.BasicBlock | t.CPtr = mcore.CreateBlock(func, "else")
    merge: llvmlite.BasicBlock | t.CPtr = mcore.CreateBlock(func, "merge")
    builder: llvmlite.IRBuilder | t.CPtr = mcore.NewBuilder(func)

    # entry: br label %then
    llvmlite.position_at_end(builder, entry)
    llvmlite.build_br(builder, then_blk)

    # then: br label %merge
    llvmlite.position_at_end(builder, then_blk)
    v_1: llvmlite.Value | t.CPtr = mcore.ConstInt32(1)
    llvmlite.build_br(builder, merge)

    # else: br label %merge
    llvmlite.position_at_end(builder, else_blk)
    v_2: llvmlite.Value | t.CPtr = mcore.ConstInt32(2)
    llvmlite.build_br(builder, merge)

    # merge: %r = phi i32 [1, %then], [2, %else]; ret i32 %r
    llvmlite.position_at_end(builder, merge)
    inc1: llvmlite.PhiIncoming | t.CPtr = llvmlite.new_phi_incoming(pool, v_1, then_blk)
    inc2: llvmlite.PhiIncoming | t.CPtr = llvmlite.new_phi_incoming(pool, v_2, else_blk)
    inc1.Next = inc2
    v_r: llvmlite.Value | t.CPtr = llvmlite.build_phi(builder, ty_i32, inc1, 2)
    llvmlite.build_ret(builder, v_r)

    buf: t.CChar | t.CPtr = pool.alloc(4096)
    buf[0] = 0
    mcore.PrintFunction(buf, 4096, func)
    testcheck.info(buf)

    testcheck.check(string.strstr(buf, "phi i32") is not None, "has 'phi i32'", "missing 'phi i32'")
    testcheck.check(string.strstr(buf, "[") is not None, "has '['", "missing '['")
    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'")


# ============================================================
# 测试 17: Switch
# ============================================================
def test_switch(pool: memhub.MemPool | t.CPtr):
    testcheck.section("Test 17: Switch")
    core: llvmlite.LLVMTypeCore | t.CPtr = llvmlite.LLVMTypeCore(pool)
    mcore: llvmlite.LLVMModuleCore | t.CPtr = llvmlite.LLVMModuleCore(pool)
    ty_i32: llvmlite.LLVMType | t.CPtr = core.Int32()
    ty_void: llvmlite.LLVMType | t.CPtr = core.Void()

    mod: llvmlite.Module | t.CPtr = mcore.NewModule("test_switch")
    func: llvmlite.Function | t.CPtr = mcore.CreateFunction(mod, "switch_test", ty_void)
    mcore.AddParam(func, ty_i32, "%x")
    entry: llvmlite.BasicBlock | t.CPtr = mcore.CreateBlock(func, "entry")
    case0: llvmlite.BasicBlock | t.CPtr = mcore.CreateBlock(func, "case0")
    case1: llvmlite.BasicBlock | t.CPtr = mcore.CreateBlock(func, "case1")
    default_blk: llvmlite.BasicBlock | t.CPtr = mcore.CreateBlock(func, "default")
    builder: llvmlite.IRBuilder | t.CPtr = mcore.NewBuilder(func)

    # entry: switch i32 %x, label %default [i32 0, label %case0; i32 1, label %case1]
    llvmlite.position_at_end(builder, entry)
    v_x: llvmlite.Value | t.CPtr = mcore.SSAValue(ty_i32, "%x")
    v_0: llvmlite.Value | t.CPtr = mcore.ConstInt32(0)
    v_1: llvmlite.Value | t.CPtr = mcore.ConstInt32(1)
    c0: llvmlite.SwitchCase | t.CPtr = llvmlite.new_switch_case(pool, v_0, case0)
    c1: llvmlite.SwitchCase | t.CPtr = llvmlite.new_switch_case(pool, v_1, case1)
    c0.Next = c1
    llvmlite.build_switch(builder, v_x, default_blk, c0, 2)

    # case0/case1/default: ret void
    llvmlite.position_at_end(builder, case0)
    llvmlite.build_ret_void(builder)
    llvmlite.position_at_end(builder, case1)
    llvmlite.build_ret_void(builder)
    llvmlite.position_at_end(builder, default_blk)
    llvmlite.build_ret_void(builder)

    buf: t.CChar | t.CPtr = pool.alloc(4096)
    buf[0] = 0
    mcore.PrintFunction(buf, 4096, func)
    testcheck.info(buf)

    testcheck.check(string.strstr(buf, "switch i32") is not None, "has 'switch i32'", "missing 'switch i32'")
    testcheck.check(string.strstr(buf, "label %default") is not None, "has 'label %default'", "missing 'label %default'")
    testcheck.check(string.strstr(buf, "label %case0") is not None, "has 'label %case0'", "missing 'label %case0'")


# ============================================================
# 测试 18: Select
# ============================================================
def test_select(pool: memhub.MemPool | t.CPtr):
    testcheck.section("Test 18: Select")
    core: llvmlite.LLVMTypeCore | t.CPtr = llvmlite.LLVMTypeCore(pool)
    mcore: llvmlite.LLVMModuleCore | t.CPtr = llvmlite.LLVMModuleCore(pool)
    ty_i32: llvmlite.LLVMType | t.CPtr = core.Int32()

    mod: llvmlite.Module | t.CPtr = mcore.NewModule("test_select")
    func: llvmlite.Function | t.CPtr = mcore.CreateFunction(mod, "sel_test", ty_i32)
    mcore.AddParam(func, ty_i32, "%a")
    mcore.AddParam(func, ty_i32, "%b")
    entry: llvmlite.BasicBlock | t.CPtr = mcore.CreateBlock(func, "entry")
    builder: llvmlite.IRBuilder | t.CPtr = mcore.NewBuilder(func)
    llvmlite.position_at_end(builder, entry)

    v_a: llvmlite.Value | t.CPtr = mcore.SSAValue(ty_i32, "%a")
    v_b: llvmlite.Value | t.CPtr = mcore.SSAValue(ty_i32, "%b")
    v_cond: llvmlite.Value | t.CPtr = llvmlite.build_icmp(builder, llvmlite.ICMP_SLT, v_a, v_b)
    v_sel: llvmlite.Value | t.CPtr = llvmlite.build_select(builder, v_cond, v_a, v_b)
    llvmlite.build_ret(builder, v_sel)

    buf: t.CChar | t.CPtr = pool.alloc(4096)
    buf[0] = 0
    mcore.PrintFunction(buf, 4096, func)
    testcheck.info(buf)

    testcheck.check(string.strstr(buf, "select i1") is not None, "has 'select i1'", "missing 'select i1'")


# ============================================================
# 测试 19: 全局变量 (字符串常量 + 整数)
# ============================================================
def test_globals(pool: memhub.MemPool | t.CPtr):
    testcheck.section("Test 19: Global Variables")
    core: llvmlite.LLVMTypeCore | t.CPtr = llvmlite.LLVMTypeCore(pool)
    mcore: llvmlite.LLVMModuleCore | t.CPtr = llvmlite.LLVMModuleCore(pool)
    ty_i32: llvmlite.LLVMType | t.CPtr = core.Int32()
    ty_void: llvmlite.LLVMType | t.CPtr = core.Void()

    mod: llvmlite.Module | t.CPtr = mcore.NewModule("test_globals")
    llvmlite.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: llvmlite.Function | t.CPtr = mcore.CreateFunction(mod, "use_global", ty_void)
    entry: llvmlite.BasicBlock | t.CPtr = mcore.CreateBlock(func, "entry")
    builder: llvmlite.IRBuilder | t.CPtr = mcore.NewBuilder(func)
    llvmlite.position_at_end(builder, entry)
    llvmlite.build_ret_void(builder)

    buf: t.CChar | t.CPtr = pool.alloc(8192)
    buf[0] = 0
    mcore.PrintModule(buf, 8192, mod)
    testcheck.info(buf)

    testcheck.check(string.strstr(buf, "@.str =") is not None, "has '@.str ='", "missing '@.str ='")
    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, "c\"hello") is not None, "has 'c\"hello'", "missing string content")
    testcheck.check(string.strstr(buf, "@counter =") is not None, "has '@counter ='", "missing '@counter ='")
    testcheck.check(string.strstr(buf, "global i32 0") is not None, "has 'global i32 0'", "missing 'global i32 0'")


# ============================================================
# 测试 20: 函数与参数属性
# ============================================================
def test_attributes(pool: memhub.MemPool | t.CPtr):
    testcheck.section("Test 20: Function & Param Attributes")
    core: llvmlite.LLVMTypeCore | t.CPtr = llvmlite.LLVMTypeCore(pool)
    mcore: llvmlite.LLVMModuleCore | t.CPtr = llvmlite.LLVMModuleCore(pool)
    ty_i32: llvmlite.LLVMType | t.CPtr = core.Int32()
    ty_i8ptr: llvmlite.LLVMType | t.CPtr = core.Ptr(core.Int8())

    mod: llvmlite.Module | t.CPtr = mcore.NewModule("test_attrs")
    func: llvmlite.Function | t.CPtr = mcore.CreateFunction(mod, "attr_test", ty_i32)

    # 参数 0: i32 noundef %x
    p0: llvmlite.Param | t.CPtr = mcore.AddParam(func, ty_i32, "%x")
    mcore.ParamSetAttrs(p0, "noundef")

    # 参数 1: i8* nocapture %p
    p1: llvmlite.Param | t.CPtr = mcore.AddParam(func, ty_i8ptr, "%p")
    mcore.ParamSetAttrs(p1, "nocapture")

    # 函数属性: nounwind
    mcore.FunctionSetAttrs(func, "nounwind")

    entry: llvmlite.BasicBlock | t.CPtr = mcore.CreateBlock(func, "entry")
    builder: llvmlite.IRBuilder | t.CPtr = mcore.NewBuilder(func)
    llvmlite.position_at_end(builder, entry)
    v_x: llvmlite.Value | t.CPtr = mcore.SSAValue(ty_i32, "%x")
    llvmlite.build_ret(builder, v_x)

    buf: t.CChar | t.CPtr = pool.alloc(4096)
    buf[0] = 0
    mcore.PrintFunction(buf, 4096, func)
    testcheck.info(buf)

    testcheck.check(string.strstr(buf, "noundef i32") is not None, "has 'noundef i32'", "missing 'noundef i32'")
    testcheck.check(string.strstr(buf, "nocapture i8*") is not None, "has 'nocapture i8*'", "missing 'nocapture i8*'")
    testcheck.check(string.strstr(buf, ") nounwind") is not None, "has ') nounwind'", "missing ') nounwind'")


# ============================================================
# 测试 21: 原子操作 (atomicrmw / cmpxchg)
# ============================================================
def test_atomic(pool: memhub.MemPool | t.CPtr):
    testcheck.section("Test 21: Atomic Ops")
    core: llvmlite.LLVMTypeCore | t.CPtr = llvmlite.LLVMTypeCore(pool)
    mcore: llvmlite.LLVMModuleCore | t.CPtr = llvmlite.LLVMModuleCore(pool)
    ty_i32: llvmlite.LLVMType | t.CPtr = core.Int32()
    ty_i32ptr: llvmlite.LLVMType | t.CPtr = core.Ptr(ty_i32)

    mod: llvmlite.Module | t.CPtr = mcore.NewModule("test_atomic")
    func: llvmlite.Function | t.CPtr = mcore.CreateFunction(mod, "atomic_test", ty_i32)
    mcore.AddParam(func, ty_i32ptr, "%p")
    entry: llvmlite.BasicBlock | t.CPtr = mcore.CreateBlock(func, "entry")
    builder: llvmlite.IRBuilder | t.CPtr = mcore.NewBuilder(func)
    llvmlite.position_at_end(builder, entry)

    v_p: llvmlite.Value | t.CPtr = mcore.SSAValue(ty_i32ptr, "%p")
    v_1: llvmlite.Value | t.CPtr = mcore.ConstInt32(1)
    # atomicrmw add i32* %p, i32 1 monotonic
    v_r: llvmlite.Value | t.CPtr = llvmlite.build_atomicrmw(builder, llvmlite.ATOMIC_ADD,
                                                            v_p, v_1, llvmlite.ATOMIC_ORDER_MONOTONIC)
    llvmlite.build_ret(builder, v_r)

    buf: t.CChar | t.CPtr = 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.MemPool | t.CPtr):
    testcheck.section("Test 22: Inline ASM & Unreachable")
    core: llvmlite.LLVMTypeCore | t.CPtr = llvmlite.LLVMTypeCore(pool)
    mcore: llvmlite.LLVMModuleCore | t.CPtr = llvmlite.LLVMModuleCore(pool)
    ty_void: llvmlite.LLVMType | t.CPtr = core.Void()

    mod: llvmlite.Module | t.CPtr = mcore.NewModule("test_asm")
    func: llvmlite.Function | t.CPtr = mcore.CreateFunction(mod, "asm_test", ty_void)
    entry: llvmlite.BasicBlock | t.CPtr = mcore.CreateBlock(func, "entry")
    trap_blk: llvmlite.BasicBlock | t.CPtr = mcore.CreateBlock(func, "trap")
    builder: llvmlite.IRBuilder | t.CPtr = mcore.NewBuilder(func)

    # entry: call void asm sideeffect "nop", ""(); br label %trap
    llvmlite.position_at_end(builder, entry)
    llvmlite.build_inline_asm(builder, ty_void, "nop", "", 1)
    llvmlite.build_br(builder, trap_blk)

    # trap: unreachable
    llvmlite.position_at_end(builder, trap_blk)
    llvmlite.build_unreachable(builder)

    buf: t.CChar | t.CPtr = pool.alloc(4096)
    buf[0] = 0
    mcore.PrintFunction(buf, 4096, func)
    testcheck.info(buf)

    testcheck.check(string.strstr(buf, "asm sideeffect") is not None, "has 'asm sideeffect'", "missing 'asm sideeffect'")
    testcheck.check(string.strstr(buf, "unreachable") is not None, "has 'unreachable'", "missing 'unreachable'")


# ============================================================
# 测试 23: SSA 验证 - 合法函数通过
# ============================================================
def test_verify_valid(pool: memhub.MemPool | t.CPtr):
    testcheck.section("Test 23: Verify Valid Function")
    core: llvmlite.LLVMTypeCore | t.CPtr = llvmlite.LLVMTypeCore(pool)
    mcore: llvmlite.LLVMModuleCore | t.CPtr = llvmlite.LLVMModuleCore(pool)
    ty_i32: llvmlite.LLVMType | t.CPtr = core.Int32()

    mod: llvmlite.Module | t.CPtr = mcore.NewModule("verify_valid")
    func: llvmlite.Function | t.CPtr = mcore.CreateFunction(mod, "add", ty_i32)
    mcore.AddParam(func, ty_i32, "%a")
    mcore.AddParam(func, ty_i32, "%b")
    entry: llvmlite.BasicBlock | t.CPtr = mcore.CreateBlock(func, "entry")
    builder: llvmlite.IRBuilder | t.CPtr = mcore.NewBuilder(func)
    llvmlite.position_at_end(builder, entry)
    v_a: llvmlite.Value | t.CPtr = mcore.SSAValue(ty_i32, "%a")
    v_b: llvmlite.Value | t.CPtr = mcore.SSAValue(ty_i32, "%b")
    v_c: llvmlite.Value | t.CPtr = llvmlite.build_add(builder, v_a, v_b)
    llvmlite.build_ret(builder, v_c)

    result: llvmlite.VerifyResult | t.CPtr = mcore.NewVerifyResult(4096)
    err_count: t.CInt = mcore.VerifyFunction(func, result)
    testcheck.check(err_count == 0,
                    "valid add function: 0 errors",
                    "valid function should pass verification")
    testcheck.check(result.ErrorCode == llvmlite.VERIFY_OK,
                    "error code = VERIFY_OK",
                    "wrong error code for valid function")


# ============================================================
# 测试 24: SSA 验证 - 缺少终止指令
# ============================================================
def test_verify_no_terminator(pool: memhub.MemPool | t.CPtr):
    testcheck.section("Test 24: Verify Missing Terminator")
    core: llvmlite.LLVMTypeCore | t.CPtr = llvmlite.LLVMTypeCore(pool)
    mcore: llvmlite.LLVMModuleCore | t.CPtr = llvmlite.LLVMModuleCore(pool)
    ty_i32: llvmlite.LLVMType | t.CPtr = core.Int32()

    mod: llvmlite.Module | t.CPtr = mcore.NewModule("verify_noterm")
    func: llvmlite.Function | t.CPtr = mcore.CreateFunction(mod, "noterm", ty_i32)
    mcore.AddParam(func, ty_i32, "%a")
    entry: llvmlite.BasicBlock | t.CPtr = mcore.CreateBlock(func, "entry")
    builder: llvmlite.IRBuilder | t.CPtr = mcore.NewBuilder(func)
    llvmlite.position_at_end(builder, entry)
    v_a: llvmlite.Value | t.CPtr = mcore.SSAValue(ty_i32, "%a")
    llvmlite.build_add(builder, v_a, v_a)  # 无 ret

    result: llvmlite.VerifyResult | t.CPtr = mcore.NewVerifyResult(4096)
    err_count: t.CInt = mcore.VerifyFunction(func, result)
    testcheck.check(err_count > 0,
                    "missing terminator detected",
                    "should detect missing terminator")
    testcheck.check(result.ErrorCode == llvmlite.VERIFY_ERR_NO_TERMINATOR,
                    "error code = NO_TERMINATOR",
                    "wrong error code for missing terminator")


# ============================================================
# 测试 25: SSA 验证 - 重复定义
# ============================================================
def test_verify_duplicate_def(pool: memhub.MemPool | t.CPtr):
    testcheck.section("Test 25: Verify Duplicate Definition")
    core: llvmlite.LLVMTypeCore | t.CPtr = llvmlite.LLVMTypeCore(pool)
    mcore: llvmlite.LLVMModuleCore | t.CPtr = llvmlite.LLVMModuleCore(pool)
    ty_i32: llvmlite.LLVMType | t.CPtr = core.Int32()

    mod: llvmlite.Module | t.CPtr = mcore.NewModule("verify_dup")
    func: llvmlite.Function | t.CPtr = mcore.CreateFunction(mod, "dup_test", ty_i32)
    mcore.AddParam(func, ty_i32, "%a")
    entry: llvmlite.BasicBlock | t.CPtr = mcore.CreateBlock(func, "entry")
    builder: llvmlite.IRBuilder | t.CPtr = mcore.NewBuilder(func)
    llvmlite.position_at_end(builder, entry)
    v_a: llvmlite.Value | t.CPtr = mcore.SSAValue(ty_i32, "%a")
    v_c: llvmlite.Value | t.CPtr = llvmlite.build_add(builder, v_a, v_a)

    # 手动追加重复定义行 "%0 = add i32 %a, %a"
    dup_text: t.CChar | t.CPtr = pool.alloc(64)
    string.strcpy(dup_text, "%0 = add i32 %a, %a")
    llvmlite.block_append_text(pool, entry, dup_text)

    llvmlite.build_ret(builder, v_c)

    result: llvmlite.VerifyResult | t.CPtr = mcore.NewVerifyResult(4096)
    err_count: t.CInt = mcore.VerifyFunction(func, result)
    testcheck.check(err_count > 0,
                    "duplicate definition detected",
                    "should detect duplicate definition")
    testcheck.check(result.ErrorCode == llvmlite.VERIFY_ERR_DUPLICATE_DEF,
                    "error code = DUPLICATE_DEF",
                    "wrong error code for duplicate def")


# ============================================================
# 测试 26: SSA 验证 - 未定义引用
# ============================================================
def test_verify_undef_use(pool: memhub.MemPool | t.CPtr):
    testcheck.section("Test 26: Verify Undefined Use")
    core: llvmlite.LLVMTypeCore | t.CPtr = llvmlite.LLVMTypeCore(pool)
    mcore: llvmlite.LLVMModuleCore | t.CPtr = llvmlite.LLVMModuleCore(pool)
    ty_i32: llvmlite.LLVMType | t.CPtr = core.Int32()

    mod: llvmlite.Module | t.CPtr = mcore.NewModule("verify_undef")
    func: llvmlite.Function | t.CPtr = mcore.CreateFunction(mod, "undef_test", ty_i32)
    mcore.AddParam(func, ty_i32, "%a")
    entry: llvmlite.BasicBlock | t.CPtr = mcore.CreateBlock(func, "entry")

    # 手动追加含未定义引用的行 "%0 = add i32 %ghost, %a"
    line1: t.CChar | t.CPtr = pool.alloc(64)
    string.strcpy(line1, "%0 = add i32 %ghost, %a")
    llvmlite.block_append_text(pool, entry, line1)

    # 手动追加终止指令
    line2: t.CChar | t.CPtr = pool.alloc(64)
    string.strcpy(line2, "ret i32 %0")
    llvmlite.block_append_text(pool, entry, line2)
    entry.IsTerminated = 1

    result: llvmlite.VerifyResult | t.CPtr = mcore.NewVerifyResult(4096)
    err_count: t.CInt = mcore.VerifyFunction(func, result)
    testcheck.check(err_count > 0,
                    "undefined use detected",
                    "should detect undefined use")
    testcheck.check(result.ErrorCode == llvmlite.VERIFY_ERR_UNDEFINED_USE,
                    "error code = UNDEFINED_USE",
                    "wrong error code for undefined use")


# ============================================================
# 测试 27: SSA 验证 - 模块级验证（含 phi/分支，验证块标签修复）
# ============================================================
def test_verify_module(pool: memhub.MemPool | t.CPtr):
    testcheck.section("Test 27: Verify Module (phi/labels)")
    core: llvmlite.LLVMTypeCore | t.CPtr = llvmlite.LLVMTypeCore(pool)
    mcore: llvmlite.LLVMModuleCore | t.CPtr = llvmlite.LLVMModuleCore(pool)
    ty_i32: llvmlite.LLVMType | t.CPtr = core.Int32()

    mod: llvmlite.Module | t.CPtr = mcore.NewModule("verify_module")

    # 函数 1: 简单 add（合法）
    func1: llvmlite.Function | t.CPtr = mcore.CreateFunction(mod, "add", ty_i32)
    mcore.AddParam(func1, ty_i32, "%a")
    mcore.AddParam(func1, ty_i32, "%b")
    entry1: llvmlite.BasicBlock | t.CPtr = mcore.CreateBlock(func1, "entry")
    builder1: llvmlite.IRBuilder | t.CPtr = mcore.NewBuilder(func1)
    llvmlite.position_at_end(builder1, entry1)
    v_a: llvmlite.Value | t.CPtr = mcore.SSAValue(ty_i32, "%a")
    v_b: llvmlite.Value | t.CPtr = mcore.SSAValue(ty_i32, "%b")
    v_c: llvmlite.Value | t.CPtr = llvmlite.build_add(builder1, v_a, v_b)
    llvmlite.build_ret(builder1, v_c)

    # 函数 2: 含 phi 与分支（合法，验证块标签不被误报为未定义）
    func2: llvmlite.Function | t.CPtr = mcore.CreateFunction(mod, "phi_test", ty_i32)
    f2_entry: llvmlite.BasicBlock | t.CPtr = mcore.CreateBlock(func2, "entry")
    then_blk: llvmlite.BasicBlock | t.CPtr = mcore.CreateBlock(func2, "then")
    else_blk: llvmlite.BasicBlock | t.CPtr = mcore.CreateBlock(func2, "else")
    merge: llvmlite.BasicBlock | t.CPtr = mcore.CreateBlock(func2, "merge")
    builder2: llvmlite.IRBuilder | t.CPtr = mcore.NewBuilder(func2)

    # entry: br label %then
    llvmlite.position_at_end(builder2, f2_entry)
    llvmlite.build_br(builder2, then_blk)

    # then: br label %merge
    llvmlite.position_at_end(builder2, then_blk)
    v_1: llvmlite.Value | t.CPtr = mcore.ConstInt32(1)
    llvmlite.build_br(builder2, merge)

    # else: br label %merge
    llvmlite.position_at_end(builder2, else_blk)
    v_2: llvmlite.Value | t.CPtr = mcore.ConstInt32(2)
    llvmlite.build_br(builder2, merge)

    # merge: %r = phi i32 [1, %then], [2, %else]; ret i32 %r
    llvmlite.position_at_end(builder2, merge)
    inc1: llvmlite.PhiIncoming | t.CPtr = llvmlite.new_phi_incoming(pool, v_1, then_blk)
    inc2: llvmlite.PhiIncoming | t.CPtr = llvmlite.new_phi_incoming(pool, v_2, else_blk)
    inc1.Next = inc2
    v_r: llvmlite.Value | t.CPtr = llvmlite.build_phi(builder2, ty_i32, inc1, 2)
    llvmlite.build_ret(builder2, v_r)

    result: llvmlite.VerifyResult | t.CPtr = mcore.NewVerifyResult(4096)
    err_count: t.CInt = 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 == llvmlite.VERIFY_OK,
                    "error code = VERIFY_OK",
                    "wrong error code for valid module")


def main() -> int:
    testcheck.begin("LLvmLiteTest: llvmlite 库（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.MemPool | t.CPtr = memhub.MemPool(pool_mem, POOL_SIZE)
    if pool is None:
        stdio.printf("FAIL: memhub.MemPool 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()
