1;; Test leaf function detection across different function types. 2;; This test verifies that the is_leaf detection works correctly for: 3;; - True leaf functions (no calls) 4;; - Non-leaf functions (with calls, call_indirect) 5 6test compile precise-output 7set unwind_info=false 8set preserve_frame_pointers=false 9target riscv64 10 11;; Test 1: Simple leaf function - just arithmetic operations 12function %simple_leaf(i32) -> i32 { 13block0(v0: i32): 14 v1 = iconst.i32 10 15 v2 = imul v0, v1 16 return v2 17} 18 19; VCode: 20; block0: 21; li a1,10 22; mulw a0,a0,a1 23; ret 24; 25; Disassembled: 26; block0: ; offset 0x0 27; addi a1, zero, 0xa 28; mulw a0, a0, a1 29; ret 30 31;; Test 2: Leaf function with multiple basic blocks and control flow 32function %leaf_with_branches(i32) -> i32 { 33block0(v0: i32): 34 v1 = iconst.i32 0 35 v2 = icmp sgt v0, v1 36 brif v2, block1, block2 37 38block1: 39 v3 = iconst.i32 2 40 v4 = imul v0, v3 41 jump block3(v4) 42 43block2: 44 v5 = isub v1, v0 45 jump block3(v5) 46 47block3(v6: i32): 48 return v6 49} 50 51; VCode: 52; block0: 53; li a1,0 54; sext.w a2,a0 55; bgt a2,zero,taken(label2),not_taken(label1) 56; block1: 57; subw a0,a1,a0 58; j label3 59; block2: 60; li a1,2 61; mulw a0,a0,a1 62; j label3 63; block3: 64; ret 65; 66; Disassembled: 67; block0: ; offset 0x0 68; mv a1, zero 69; sext.w a2, a0 70; bgtz a2, 0xc 71; block1: ; offset 0xc 72; subw a0, a1, a0 73; j 0xc 74; block2: ; offset 0x14 75; addi a1, zero, 2 76; mulw a0, a0, a1 77; block3: ; offset 0x1c 78; ret 79 80;; Test 3: Non-leaf function with direct call 81function %non_leaf_with_call(i32) -> i32 { 82 sig0 = (i32) -> i32 83 fn0 = colocated %simple_leaf sig0 84 85block0(v0: i32): 86 v1 = call fn0(v0) 87 return v1 88} 89 90; VCode: 91; addi sp,sp,-16 92; sd ra,8(sp) 93; sd fp,0(sp) 94; mv fp,sp 95; block0: 96; call %simple_leaf 97; ld ra,8(sp) 98; ld fp,0(sp) 99; addi sp,sp,16 100; ret 101; 102; Disassembled: 103; block0: ; offset 0x0 104; addi sp, sp, -0x10 105; sd ra, 8(sp) 106; sd s0, 0(sp) 107; mv s0, sp 108; block1: ; offset 0x10 109; auipc ra, 0 ; reloc_external RiscvCallPlt %simple_leaf 0 110; jalr ra 111; ld ra, 8(sp) 112; ld s0, 0(sp) 113; addi sp, sp, 0x10 114; ret 115 116;; Test 4: Non-leaf function with indirect call 117function %non_leaf_with_call_indirect(i32, i64) -> i32 { 118 sig0 = (i32) -> i32 119 120block0(v0: i32, v1: i64): 121 v2 = call_indirect sig0, v1(v0) 122 return v2 123} 124 125; VCode: 126; addi sp,sp,-16 127; sd ra,8(sp) 128; sd fp,0(sp) 129; mv fp,sp 130; block0: 131; callind a1 132; ld ra,8(sp) 133; ld fp,0(sp) 134; addi sp,sp,16 135; ret 136; 137; Disassembled: 138; block0: ; offset 0x0 139; addi sp, sp, -0x10 140; sd ra, 8(sp) 141; sd s0, 0(sp) 142; mv s0, sp 143; block1: ; offset 0x10 144; jalr a1 145; ld ra, 8(sp) 146; ld s0, 0(sp) 147; addi sp, sp, 0x10 148; ret 149 150;; Test 5: Leaf function with memory operations (should still be leaf) 151function %leaf_with_memory(i32, i64) -> i32 { 152block0(v0: i32, v1: i64): 153 store v0, v1 154 v2 = load.i32 v1 155 v3 = iconst.i32 1 156 v4 = iadd v2, v3 157 return v4 158} 159 160; VCode: 161; block0: 162; sw a0,0(a1) 163; lw a0,0(a1) 164; addiw a0,a0,1 165; ret 166; 167; Disassembled: 168; block0: ; offset 0x0 169; sw a0, 0(a1) ; trap: heap_oob 170; lw a0, 0(a1) ; trap: heap_oob 171; addiw a0, a0, 1 172; ret 173 174;; Test 6: Leaf function that looks like it might call but doesn't 175function %leaf_no_actual_calls(i32) -> i32 { 176block0(v0: i32): 177 v1 = iconst.i32 42 178 v2 = imul v0, v1 179 v3 = iconst.i32 7 180 v4 = udiv v2, v3 181 v5 = iconst.i32 3 182 v6 = band v4, v5 183 return v6 184} 185 186; VCode: 187; block0: 188; li a1,42 189; mulw a0,a0,a1 190; li a1,7 191; divuw a0,a0,a1 192; andi a0,a0,3 193; ret 194; 195; Disassembled: 196; block0: ; offset 0x0 197; addi a1, zero, 0x2a 198; mulw a0, a0, a1 199; addi a1, zero, 7 200; divuw a0, a0, a1 201; andi a0, a0, 3 202; ret 203