il: add Elem instruction for bounds-checked element access

c1192d4f0b959d146685b7f4e89ca444c856f6e2c4ca6b393687ef86093bd2bf
Add a single IL instruction that fuses bounds checking with element
pointer computation: elem %dst %base %idx %len stride

The backend lowers this to: bltu idx, len, +8 / ebreak / mul+add.
The verifier checks it locally -- base must be Ptr, result is Ptr,
no CFG analysis needed.

The lowerer emits Elem for all user-facing array/slice indexing
(lowerElemPtr). Internal lowerer operations (loops, append, delete)
continue using plain add ptr since their bounds are guaranteed by
construction. Constant-index array access (validated at compile time
by the resolver) also uses plain add ptr.

- il.rad: Add Elem variant to Instr (at end for bootstrap compat)
- il/printer.rad: Print elem instruction
- il/verify.rad: Verify Elem base is Ptr, result is Ptr
- rv64/isel.rad: Code generation with inline bounds check
- lower.rad: Emit Elem instead of separate br.ult + emitElem
- Regenerate 14 affected .ril test snapshots
Alexis Sellier committed ago 1 parent f583c417
lib/std/arch/rv64/isel.rad +20 -0
777 777
            emitMv(s, ecallRd, super::A0);
778 778
        },
779 779
        case il::Instr::Ebreak => {
780 780
            emit::emit(s.e, encode::ebreak());
781 781
        },
782 +
        case il::Instr::Elem { dst, base, idx, len, stride } => {
783 +
            // Bounds check: trap if idx >= len.
784 +
            let rsIdx = resolveVal(s, super::SCRATCH1, idx);
785 +
            let rsLen = resolveVal(s, super::SCRATCH2, len);
786 +
            emit::emit(s.e, encode::bltu(rsIdx, rsLen, 8));
787 +
            emit::emit(s.e, encode::ebreak());
788 +
789 +
            // Compute byte offset into SCRATCH1: idx * stride.
790 +
            let rs = resolveVal(s, super::SCRATCH1, idx);
791 +
            if stride == 1 {
792 +
                emitMv(s, super::SCRATCH1, rs);
793 +
            } else {
794 +
                emit::loadImm(s.e, super::SCRATCH2, stride as i64);
795 +
                emit::emit(s.e, encode::mul(super::SCRATCH1, rs, super::SCRATCH2));
796 +
            }
797 +
            // dst = base + SCRATCH1.
798 +
            let rsBase = getSrcReg(s, base, super::SCRATCH2);
799 +
            let rd = getDstReg(s, dst, super::SCRATCH2);
800 +
            emit::emit(s.e, encode::add(rd, rsBase, super::SCRATCH1));
801 +
        },
782 802
    }
783 803
}
784 804
785 805
/// Check if a value is an immediate that's already correctly extended.
786 806
/// `loadImm` produces the exact 64-bit value; this checks whether that value
lib/std/lang/il.rad +28 -0
63 63
//! |------------------------|------------------------------------------|
64 64
//! | `Reserve`              | Stack allocation (local provenance)      |
65 65
//! | `Copy(DataSym)`        | Global/static data address               |
66 66
//! | `Copy(FnAddr)`         | Function address (code section)          |
67 67
//! | `Load` with `typ: Ptr` | Derived from an existing pointer         |
68 +
//! | `Elem`                 | Bounds-checked element pointer           |
68 69
//! | `BinOp::Add` on `Ptr`  | Pointer arithmetic (derived)             |
69 70
//! | `Call` returning `Ptr`  | Callee-produced pointer                 |
70 71
//! | Block parameter         | Merges pointer values from predecessors  |
71 72
//! | `WordToPtr`            | Explicit escape hatch (trusted code)     |
72 73
//!
336 337
    /// Environment call: `ecall %dst <num> <a0> <a1> <a2> <a3>;`
337 338
    Ecall { dst: Reg, num: Val, a0: Val, a1: Val, a2: Val, a3: Val },
338 339
    /// Environment break: `ebreak;`.
339 340
    /// Triggers a breakpoint exception for debugging.
340 341
    Ebreak,
342 +
343 +
    //////////////////////
344 +
    // Checked memory   //
345 +
    //////////////////////
346 +
347 +
    /// Bounds-checked element pointer: `elem %dst %base <idx> <len> <stride>;`
348 +
    /// Computes `base + idx * stride` after asserting `idx < len`.
349 +
    /// Traps if the index is out of bounds. Result is always `Ptr`.
350 +
    /// The verifier can check this instruction locally without CFG analysis.
351 +
    Elem {
352 +
        /// Destination register (element pointer).
353 +
        dst: Reg,
354 +
        /// Base pointer (array/slice data).
355 +
        base: Reg,
356 +
        /// Index value.
357 +
        idx: Val,
358 +
        /// Length bound (element count).
359 +
        len: Val,
360 +
        /// Element stride in bytes.
361 +
        stride: u32,
362 +
    },
341 363
}
342 364
343 365
//////////////////////////
344 366
// Blocks and Functions //
345 367
//////////////////////////
455 477
        case Instr::Sext { dst, .. } => return dst,
456 478
        case Instr::PtrToWord { dst, .. } => return dst,
457 479
        case Instr::WordToPtr { dst, .. } => return dst,
458 480
        case Instr::Call { dst, .. } => return dst,
459 481
        case Instr::Ecall { dst, .. } => return dst,
482 +
        case Instr::Elem { dst, .. } => return dst,
460 483
        else => return nil,
461 484
    }
462 485
}
463 486
464 487
/// Check if an instruction is a function call.
547 570
            withReg(a2, f, ctx);
548 571
            withReg(a3, f, ctx);
549 572
        },
550 573
        case Instr::Unreachable,
551 574
             Instr::Ebreak => {},
575 +
        case Instr::Elem { base, idx, len, .. } => {
576 +
            f(base, ctx);
577 +
            withReg(idx, f, ctx);
578 +
            withReg(len, f, ctx);
579 +
        },
552 580
    }
553 581
}
554 582
555 583
/// Call callback if value is a register.
556 584
fn withReg(val: Val, callback: fn(Reg, *mut opaque), ctx: *mut opaque) {
lib/std/lang/il/printer.rad +12 -0
371 371
            writeVal(out, a, a3);
372 372
        }
373 373
        case super::Instr::Ebreak => {
374 374
            write(out, "ebreak");
375 375
        }
376 +
        case super::Instr::Elem { dst, base, idx, len, stride } => {
377 +
            write(out, "elem ");
378 +
            writeReg(out, a, dst);
379 +
            write(out, " ");
380 +
            writeReg(out, a, base);
381 +
            write(out, " ");
382 +
            writeVal(out, a, idx);
383 +
            write(out, " ");
384 +
            writeVal(out, a, len);
385 +
            write(out, " ");
386 +
            write(out, formatU32(a, stride));
387 +
        }
376 388
    }
377 389
}
378 390
379 391
/// Write a typed binary operation: `op type %dst %a %b`.
380 392
fn writeTypedBinOp(
lib/std/lang/il/verify.rad +18 -31
109 109
        regTypes[i] = RegType::Undef;
110 110
    }
111 111
112 112
    // Type function parameters.
113 113
    for param in func.params {
114 -
        if param.value.n < MAX_REGS {
115 -
            if let case super::Type::Ptr = param.type {
116 -
                regTypes[param.value.n] = RegType::Ptr;
117 -
            } else {
118 -
                regTypes[param.value.n] = RegType::Word(param.type);
119 -
            }
120 -
        }
114 +
        setReg(&mut regTypes[..], param.value, regTypeFromIl(param.type));
121 115
    }
122 116
123 117
    // Walk blocks.
124 118
    for block, blockIdx in func.blocks {
125 119
        // Type block parameters.
126 120
        for param in block.params {
127 -
            if param.value.n < MAX_REGS {
128 -
                if let case super::Type::Ptr = param.type {
129 -
                    regTypes[param.value.n] = RegType::Ptr;
130 -
                } else {
131 -
                    regTypes[param.value.n] = RegType::Word(param.type);
132 -
                }
133 -
            }
121 +
            setReg(&mut regTypes[..], param.value, regTypeFromIl(param.type));
134 122
        }
135 123
136 124
        // Check each instruction.
137 125
        for instr, instrIdx in block.instrs {
138 126
            verifyInstr(
158 146
        case super::Instr::Reserve { dst, .. } => {
159 147
            // Reserve always produces a pointer.
160 148
            setReg(regs, dst, RegType::Ptr);
161 149
        }
162 150
        case super::Instr::Load { typ, dst, src, .. } => {
163 -
            // Base must be Ptr.
164 151
            checkPtrBase(func, blockIdx, instrIdx, regs, src, errors, a, "load base");
165 -
            // Result type depends on the load type.
166 -
            if let case super::Type::Ptr = typ {
167 -
                setReg(regs, dst, RegType::Ptr);
168 -
            } else {
169 -
                setReg(regs, dst, RegType::Word(typ));
170 -
            }
152 +
            setReg(regs, dst, regTypeFromIl(typ));
171 153
        }
172 154
        case super::Instr::Sload { typ, dst, src, .. } => {
173 155
            checkPtrBase(func, blockIdx, instrIdx, regs, src, errors, a, "sload base");
174 -
            if let case super::Type::Ptr = typ {
175 -
                setReg(regs, dst, RegType::Ptr);
176 -
            } else {
177 -
                setReg(regs, dst, RegType::Word(typ));
178 -
            }
156 +
            setReg(regs, dst, regTypeFromIl(typ));
179 157
        }
180 158
        case super::Instr::Store { dst, .. } => {
181 159
            checkPtrBase(func, blockIdx, instrIdx, regs, dst, errors, a, "store base");
182 160
        }
183 161
        case super::Instr::Blit { dst, src, .. } => {
224 202
            *wtpCount += 1;
225 203
            setReg(regs, dst, RegType::Ptr);
226 204
        }
227 205
        case super::Instr::Call { retTy, dst, .. } => {
228 206
            if let d = dst {
229 -
                if let case super::Type::Ptr = retTy {
230 -
                    setReg(regs, d, RegType::Ptr);
231 -
                } else {
232 -
                    setReg(regs, d, RegType::Word(retTy));
233 -
                }
207 +
                setReg(regs, d, regTypeFromIl(retTy));
234 208
            }
235 209
        }
236 210
        case super::Instr::Ecall { dst, .. } => {
237 211
            // Ecall returns a word value.
238 212
            setReg(regs, dst, RegType::Word(super::Type::W64));
239 213
        }
214 +
        case super::Instr::Elem { dst, base, .. } => {
215 +
            // Bounds-checked element pointer: base must be Ptr, result is Ptr.
216 +
            checkPtrBase(func, blockIdx, instrIdx, regs, base, errors, a, "elem base");
217 +
            setReg(regs, dst, RegType::Ptr);
218 +
        }
240 219
        case super::Instr::Ret { .. },
241 220
             super::Instr::Jmp { .. },
242 221
             super::Instr::Br { .. },
243 222
             super::Instr::Switch { .. },
244 223
             super::Instr::Unreachable,
251 230
    if reg.n < regs.len {
252 231
        regs[reg.n] = typ;
253 232
    }
254 233
}
255 234
235 +
/// Convert an IL type to a RegType.
236 +
fn regTypeFromIl(typ: super::Type) -> RegType {
237 +
    if let case super::Type::Ptr = typ {
238 +
        return RegType::Ptr;
239 +
    }
240 +
    return RegType::Word(typ);
241 +
}
242 +
256 243
/// Check that a register used as a memory base has type Ptr.
257 244
fn checkPtrBase(
258 245
    func: *super::Fn,
259 246
    blockIdx: u32,
260 247
    instrIdx: u32,
lib/std/lang/lower.rad +22 -11
4922 4922
    let baseVal = try lowerExpr(self, container);
4923 4923
    let baseReg = emitValToReg(self, baseVal);
4924 4924
4925 4925
    let mut dataReg = baseReg;
4926 4926
    let mut elemType: resolver::Type = undefined;
4927 +
    let mut lenVal: il::Val = undefined;
4928 +
    let mut needsBoundsCheck = true;
4927 4929
4928 4930
    match subjectTy {
4929 4931
        case resolver::Type::Slice { item, .. } => {
4930 4932
            elemType = *item;
4931 -
            let sliceLen = loadSliceLen(self, baseReg);
4932 -
            // Runtime safety check: index must be strictly less than slice length.
4933 -
            try emitTrapUnlessCmp(self, il::CmpOp::Ult, il::Type::W32, indexVal, sliceLen);
4934 -
4933 +
            lenVal = loadSliceLen(self, baseReg);
4935 4934
            dataReg = loadSlicePtr(self, baseReg);
4936 4935
        }
4937 4936
        case resolver::Type::Array(arrInfo) => {
4938 4937
            elemType = *arrInfo.item;
4939 -
            // Runtime safety check: index must be strictly less than array length.
4940 -
            // Skip when the index is a compile-time constant, since we check
4941 -
            // that in the resolver.
4942 -
            if not resolver::isConstExpr(self.low.resolver, index) {
4943 -
                let arrLen = il::Val::Imm(arrInfo.length as i64);
4944 -
                try emitTrapUnlessCmp(self, il::CmpOp::Ult, il::Type::W32, indexVal, arrLen);
4938 +
            lenVal = il::Val::Imm(arrInfo.length as i64);
4939 +
            // Skip bounds check when the index is a compile-time constant,
4940 +
            // since the resolver already validated it.
4941 +
            if resolver::isConstExpr(self.low.resolver, index) {
4942 +
                needsBoundsCheck = false;
4945 4943
            }
4946 4944
        }
4947 4945
        else => throw LowerError::ExpectedSliceOrArray,
4948 4946
    }
4949 4947
    let elemLayout = resolver::getTypeLayout(elemType);
4950 -
    let elemReg = emitElem(self, elemLayout.size, dataReg, indexVal);
4951 4948
4949 +
    if needsBoundsCheck {
4950 +
        // Emit a single bounds-checked element pointer instruction.
4951 +
        let elemReg = nextReg(self);
4952 +
        emit(self, il::Instr::Elem {
4953 +
            dst: elemReg,
4954 +
            base: dataReg,
4955 +
            idx: indexVal,
4956 +
            len: lenVal,
4957 +
            stride: elemLayout.size,
4958 +
        });
4959 +
        return ElemPtrResult { elemReg, elemType };
4960 +
    }
4961 +
    // Constant index: no bounds check needed, use plain pointer arithmetic.
4962 +
    let elemReg = emitElem(self, elemLayout.size, dataReg, indexVal);
4952 4963
    return ElemPtrResult { elemReg, elemType };
4953 4964
}
4954 4965
4955 4966
/// Lower a dereference expression.
4956 4967
/// Handles both pointer deref (`*ptr`) and record deref (`*r` on single-field
test/tests/array.aggregate.stride.ril +12 -42
1 1
fn w32 $arrayOfRecords(ptr %0, w32 %1) {
2 2
  @entry0
3 -
    br.ult w32 %1 3 @guard#pass1 @guard#trap2;
4 -
  @guard#pass1
5 -
    mul w64 %2 %1 8;
6 -
    add ptr %3 %0 %2;
7 -
    sload w32 %4 %3 0;
8 -
    ret %4;
9 -
  @guard#trap2
10 -
    ebreak;
11 -
    unreachable;
3 +
    elem %2 %0 %1 3 8;
4 +
    sload w32 %3 %2 0;
5 +
    ret %3;
12 6
}
13 7
14 8
fn ptr $addressOfRecord(ptr %0, w32 %1) {
15 9
  @entry0
16 -
    br.ult w32 %1 3 @guard#pass1 @guard#trap2;
17 -
  @guard#pass1
18 -
    mul w64 %2 %1 8;
19 -
    add ptr %3 %0 %2;
20 -
    ret %3;
21 -
  @guard#trap2
22 -
    ebreak;
23 -
    unreachable;
10 +
    elem %2 %0 %1 3 8;
11 +
    ret %2;
24 12
}
25 13
26 14
fn w32 $arrayOfArrays(ptr %0, w32 %1) {
27 15
  @entry0
28 -
    br.ult w32 %1 3 @guard#pass1 @guard#trap2;
29 -
  @guard#pass1
30 -
    mul w64 %2 %1 16;
31 -
    add ptr %3 %0 %2;
32 -
    sload w32 %4 %3 0;
33 -
    ret %4;
34 -
  @guard#trap2
35 -
    ebreak;
36 -
    unreachable;
16 +
    elem %2 %0 %1 3 16;
17 +
    sload w32 %3 %2 0;
18 +
    ret %3;
37 19
}
38 20
39 21
fn w32 $nestedLargeStride(ptr %0, w32 %1, w32 %2) {
40 22
  @entry0
41 -
    br.ult w32 %1 3 @guard#pass1 @guard#trap2;
42 -
  @guard#pass1
43 -
    mul w64 %3 %1 16;
44 -
    add ptr %4 %0 %3;
45 -
    br.ult w32 %2 2 @guard#pass3 @guard#trap4;
46 -
  @guard#trap2
47 -
    ebreak;
48 -
    unreachable;
49 -
  @guard#pass3
50 -
    mul w64 %5 %2 8;
51 -
    add ptr %6 %4 %5;
52 -
    sload w32 %7 %6 4;
53 -
    ret %7;
54 -
  @guard#trap4
55 -
    ebreak;
56 -
    unreachable;
23 +
    elem %3 %0 %1 3 16;
24 +
    elem %4 %3 %2 2 8;
25 +
    sload w32 %5 %4 4;
26 +
    ret %5;
57 27
}
test/tests/byte.load.store.ril +2 -12
17 17
    ret;
18 18
}
19 19
20 20
fn w8 $byteArrayAccess(ptr %0, w32 %1) {
21 21
  @entry0
22 -
    br.ult w32 %1 4 @guard#pass1 @guard#trap2;
23 -
  @guard#pass1
24 -
    add ptr %2 %0 %1;
22 +
    elem %2 %0 %1 4 1;
25 23
    load w8 %3 %2 0;
26 24
    ret %3;
27 -
  @guard#trap2
28 -
    ebreak;
29 -
    unreachable;
30 25
}
31 26
32 27
fn w8 $byteSliceAccess(ptr %0, w32 %1) {
33 28
  @entry0
34 29
    load w32 %2 %0 8;
35 -
    br.ult w32 %1 %2 @guard#pass1 @guard#trap2;
36 -
  @guard#pass1
37 30
    load ptr %3 %0 0;
38 -
    add ptr %4 %3 %1;
31 +
    elem %4 %3 %1 %2 1;
39 32
    load w8 %5 %4 0;
40 33
    ret %5;
41 -
  @guard#trap2
42 -
    ebreak;
43 -
    unreachable;
44 34
}
test/tests/const.slice.of.slices.ril +4 -10
43 43
    add ptr %4 %2 %3;
44 44
    load w32 %5 %4 8;
45 45
    add w32 %6 %1 %5;
46 46
    copy %7 $GROUPS;
47 47
    load w32 %8 %7 8;
48 -
    br.ult w32 1 %8 @guard#pass1 @guard#trap2;
49 -
  @guard#pass1
50 48
    load ptr %9 %7 0;
51 -
    mul w64 %10 1 16;
52 -
    add ptr %11 %9 %10;
53 -
    load w32 %12 %11 8;
54 -
    add w32 %13 %6 %12;
55 -
    ret %13;
56 -
  @guard#trap2
57 -
    ebreak;
58 -
    unreachable;
49 +
    elem %10 %9 1 %8 16;
50 +
    load w32 %11 %10 8;
51 +
    add w32 %12 %6 %11;
52 +
    ret %12;
59 53
}
test/tests/literal.slice.record.ril +6 -16
11 11
    reserve %1 16 8;
12 12
    store ptr %0 %1 0;
13 13
    store w32 2 %1 8;
14 14
    store w32 2 %1 12;
15 15
    load w32 %2 %1 8;
16 -
    br.ult w32 0 %2 @guard#pass1 @guard#trap2;
17 -
  @guard#pass1
18 16
    load ptr %3 %1 0;
19 -
    sload w32 %4 %3 0;
20 -
    load w32 %5 %1 8;
21 -
    br.ult w32 1 %5 @guard#pass3 @guard#trap4;
22 -
  @guard#trap2
23 -
    ebreak;
24 -
    unreachable;
25 -
  @guard#pass3
26 -
    load ptr %6 %1 0;
27 -
    mul w64 %7 1 8;
28 -
    add ptr %8 %6 %7;
17 +
    elem %4 %3 0 %2 8;
18 +
    sload w32 %5 %4 0;
19 +
    load w32 %6 %1 8;
20 +
    load ptr %7 %1 0;
21 +
    elem %8 %7 1 %6 8;
29 22
    sload w32 %9 %8 4;
30 -
    add w32 %10 %4 %9;
23 +
    add w32 %10 %5 %9;
31 24
    ret %10;
32 -
  @guard#trap4
33 -
    ebreak;
34 -
    unreachable;
35 25
}
test/tests/loop.mutable.ril +6 -12
13 13
    jmp @loop1(0, 1, %0);
14 14
  @loop1(w32 %2, w32 %3, ptr %4)
15 15
    br.ult w32 %2 %1 @body2 @merge3;
16 16
  @body2
17 17
    load w32 %5 %4 8;
18 -
    br.ult w32 %2 %5 @guard#pass4 @guard#trap5;
18 +
    load ptr %6 %4 0;
19 +
    elem %7 %6 %2 %5 4;
20 +
    load w32 %8 %7 0;
21 +
    call w32 %9 $max(%3, %8);
22 +
    add w32 %10 %2 1;
23 +
    jmp @loop1(%10, %9, %4);
19 24
  @merge3
20 25
    ret %3;
21 -
  @guard#pass4
22 -
    load ptr %6 %4 0;
23 -
    mul w64 %7 %2 4;
24 -
    add ptr %8 %6 %7;
25 -
    load w32 %9 %8 0;
26 -
    call w32 %10 $max(%3, %9);
27 -
    add w32 %11 %2 1;
28 -
    jmp @loop1(%11, %10, %4);
29 -
  @guard#trap5
30 -
    ebreak;
31 -
    unreachable;
32 26
}
test/tests/opt.slice.npo.ril +30 -43
78 78
    ret 34;
79 79
  @assert.fail3
80 80
    unreachable;
81 81
  @assert.ok4
82 82
    load w32 %6 %3 8;
83 -
    br.ult w32 0 %6 @guard#pass7 @guard#trap8;
83 +
    load ptr %7 %3 0;
84 +
    elem %8 %7 0 %6 1;
85 +
    load w8 %9 %8 0;
86 +
    br.eq w8 %9 10 @assert.ok6 @assert.fail5;
84 87
  @assert.fail5
85 88
    unreachable;
86 89
  @assert.ok6
87 -
    load w32 %9 %3 8;
88 -
    br.ult w32 1 %9 @guard#pass11 @guard#trap12;
89 -
  @guard#pass7
90 -
    load ptr %7 %3 0;
91 -
    load w8 %8 %7 0;
92 -
    br.eq w8 %8 10 @assert.ok6 @assert.fail5;
93 -
  @guard#trap8
94 -
    ebreak;
95 -
    unreachable;
96 -
  @assert.fail9
97 -
    unreachable;
98 -
  @assert.ok10
99 -
    jmp @merge13;
100 -
  @guard#pass11
101 -
    load ptr %10 %3 0;
102 -
    add ptr %11 %10 1;
103 -
    load w8 %12 %11 0;
104 -
    br.eq w8 %12 20 @assert.ok10 @assert.fail9;
105 -
  @guard#trap12
106 -
    ebreak;
90 +
    load w32 %10 %3 8;
91 +
    load ptr %11 %3 0;
92 +
    elem %12 %11 1 %10 1;
93 +
    load w8 %13 %12 0;
94 +
    br.eq w8 %13 20 @assert.ok8 @assert.fail7;
95 +
  @assert.fail7
107 96
    unreachable;
108 -
  @merge13
109 -
    reserve %13 16 8;
110 -
    store ptr 0 %13 0;
111 -
    store w32 0 %13 8;
112 -
    store w32 0 %13 12;
97 +
  @assert.ok8
98 +
    jmp @merge9;
99 +
  @merge9
113 100
    reserve %14 16 8;
114 -
    blit %14 %13 16;
115 -
    load ptr %15 %14 0;
116 -
    br.ne w32 %15 0 @then14 @else15;
117 -
  @then14
101 +
    store ptr 0 %14 0;
102 +
    store w32 0 %14 8;
103 +
    store w32 0 %14 12;
104 +
    reserve %15 16 8;
105 +
    blit %15 %14 16;
106 +
    load ptr %16 %15 0;
107 +
    br.ne w32 %16 0 @then10 @else11;
108 +
  @then10
118 109
    ret 35;
119 -
  @else15
120 -
    jmp @merge16;
121 -
  @merge16
110 +
  @else11
111 +
    jmp @merge12;
112 +
  @merge12
122 113
    ret 0;
123 114
}
124 115
125 116
fn w8 $checkLetElse() {
126 117
  @entry0
194 185
    blit %8 %5 16;
195 186
    load ptr %9 %8 0;
196 187
    br.ne w32 %9 0 @then5 @else6;
197 188
  @then5
198 189
    load w32 %10 %8 8;
199 -
    br.ult w32 0 %10 @guard#pass9 @guard#trap10;
190 +
    load ptr %11 %8 0;
191 +
    elem %12 %11 0 %10 1;
192 +
    load w8 %13 %12 0;
193 +
    br.eq w8 %13 42 @assert.ok8 @assert.fail7;
200 194
  @else6
201 195
    ret 53;
202 196
  @assert.fail7
203 197
    unreachable;
204 198
  @assert.ok8
205 -
    jmp @merge11;
206 -
  @guard#pass9
207 -
    load ptr %11 %8 0;
208 -
    load w8 %12 %11 0;
209 -
    br.eq w8 %12 42 @assert.ok8 @assert.fail7;
210 -
  @guard#trap10
211 -
    ebreak;
212 -
    unreachable;
213 -
  @merge11
199 +
    jmp @merge9;
200 +
  @merge9
214 201
    ret 0;
215 202
}
216 203
217 204
fn w8 $checkMatch() {
218 205
  @entry0
test/tests/ptr.addressof.ril +2 -8
1 1
fn ptr $addressOfElem(ptr %0, w32 %1) {
2 2
  @entry0
3 -
    br.ult w32 %1 4 @guard#pass1 @guard#trap2;
4 -
  @guard#pass1
5 -
    mul w64 %2 %1 4;
6 -
    add ptr %3 %0 %2;
7 -
    ret %3;
8 -
  @guard#trap2
9 -
    ebreak;
10 -
    unreachable;
3 +
    elem %2 %0 %1 4 4;
4 +
    ret %2;
11 5
}
test/tests/ptr.deref.ril +3 -9
13 13
}
14 14
15 15
fn w32 $derefSliceIndex(ptr %0) {
16 16
  @entry0
17 17
    load w32 %1 %0 8;
18 -
    br.ult w32 2 %1 @guard#pass1 @guard#trap2;
19 -
  @guard#pass1
20 18
    load ptr %2 %0 0;
21 -
    mul w64 %3 2 4;
22 -
    add ptr %4 %2 %3;
23 -
    sload w32 %5 %4 0;
24 -
    ret %5;
25 -
  @guard#trap2
26 -
    ebreak;
27 -
    unreachable;
19 +
    elem %3 %2 2 %1 4;
20 +
    sload w32 %4 %3 0;
21 +
    ret %4;
28 22
}
29 23
30 24
fn w32 $derefBinop(w32 %0, w32 %1) {
31 25
  @entry0
32 26
    reserve %2 4 4;
test/tests/ptr.subscript.assign.ril +2 -8
1 1
fn w64 $subscriptAssign(ptr %0, w32 %1, w32 %2) {
2 2
  @entry0
3 3
    load w32 %3 %0 8;
4 -
    br.ult w32 %1 %3 @guard#pass1 @guard#trap2;
5 -
  @guard#pass1
6 4
    load ptr %4 %0 0;
7 -
    mul w64 %5 %1 4;
8 -
    add ptr %6 %4 %5;
9 -
    store w32 %2 %6 0;
5 +
    elem %5 %4 %1 %3 4;
6 +
    store w32 %2 %5 0;
10 7
    ret;
11 -
  @guard#trap2
12 -
    ebreak;
13 -
    unreachable;
14 8
}
test/tests/slice.append.ril +476 -563
23 23
    br.ult w32 %9 %8 @assert.fail1 @assert.ok2;
24 24
  @assert.fail1
25 25
    unreachable;
26 26
  @assert.ok2
27 27
    load w32 %10 %0 8;
28 -
    br.ult w32 %7 %10 @guard#pass3 @guard#trap4;
29 -
  @guard#pass3
30 28
    load ptr %11 %0 0;
31 -
    add ptr %12 %11 %7;
29 +
    elem %12 %11 %7 %10 1;
32 30
    store w32 %8 %0 16;
33 31
    ret %12;
34 -
  @guard#trap4
35 -
    ebreak;
36 -
    unreachable;
37 32
}
38 33
39 34
fn ptr $arenaAllocFn(ptr %0, w32 %1, w32 %2) {
40 35
  @entry0
41 36
    call ptr %3 $arenaAlloc(%0, %1, %2);
177 172
    br.ne w32 %77 4 @then18 @merge19;
178 173
  @then18
179 174
    ret 2;
180 175
  @merge19
181 176
    load w32 %78 %8 8;
182 -
    br.ult w32 0 %78 @guard#pass22 @guard#trap23;
177 +
    load ptr %79 %8 0;
178 +
    elem %80 %79 0 %78 4;
179 +
    sload w32 %81 %80 0;
180 +
    br.ne w32 %81 10 @then20 @merge21;
183 181
  @then20
184 182
    ret 3;
185 183
  @merge21
186 -
    load w32 %81 %8 8;
187 -
    br.ult w32 1 %81 @guard#pass26 @guard#trap27;
188 -
  @guard#pass22
189 -
    load ptr %79 %8 0;
190 -
    sload w32 %80 %79 0;
191 -
    br.ne w32 %80 10 @then20 @merge21;
192 -
  @guard#trap23
193 -
    ebreak;
194 -
    unreachable;
195 -
  @then24
184 +
    load w32 %82 %8 8;
185 +
    load ptr %83 %8 0;
186 +
    elem %84 %83 1 %82 4;
187 +
    sload w32 %85 %84 0;
188 +
    br.ne w32 %85 20 @then22 @merge23;
189 +
  @then22
196 190
    ret 4;
197 -
  @merge25
191 +
  @merge23
198 192
    load w32 %86 %8 8;
199 -
    br.ult w32 2 %86 @guard#pass30 @guard#trap31;
200 -
  @guard#pass26
201 -
    load ptr %82 %8 0;
202 -
    mul w64 %83 1 4;
203 -
    add ptr %84 %82 %83;
204 -
    sload w32 %85 %84 0;
205 -
    br.ne w32 %85 20 @then24 @merge25;
206 -
  @guard#trap27
207 -
    ebreak;
208 -
    unreachable;
209 -
  @then28
210 -
    ret 5;
211 -
  @merge29
212 -
    load w32 %93 %8 8;
213 -
    load w32 %94 %8 12;
214 -
    br.ult w32 %93 %94 @append.store32 @append.grow33;
215 -
  @guard#pass30
216 193
    load ptr %87 %8 0;
217 -
    mul w64 %88 2 4;
218 -
    add ptr %89 %87 %88;
219 -
    sload w32 %90 %89 0;
220 -
    br.ne w32 %90 30 @then28 @merge29;
221 -
  @guard#trap31
222 -
    ebreak;
223 -
    unreachable;
224 -
  @append.store32
225 -
    load ptr %108 %8 0;
226 -
    mul w64 %109 %93 4;
227 -
    add ptr %110 %108 %109;
228 -
    store w32 40 %110 0;
229 -
    add w32 %111 %93 1;
230 -
    store w32 %111 %8 8;
231 -
    load w32 %114 %8 8;
232 -
    br.ne w32 %114 4 @then37 @merge38;
233 -
  @append.grow33
234 -
    shl w32 %95 %94 1;
235 -
    or w32 %96 %95 1;
236 -
    load ptr %97 %5 0;
237 -
    load ptr %98 %5 8;
238 -
    mul w32 %99 %96 4;
239 -
    call ptr %100 %97(%98, %99, 4);
240 -
    load ptr %101 %8 0;
241 -
    mul w32 %102 %93 4;
242 -
    jmp @append34(0);
243 -
  @append34(w32 %103)
244 -
    br.ult w32 %103 %102 @append35 @append36;
245 -
  @append35
246 -
    add ptr %104 %101 %103;
247 -
    load w8 %105 %104 0;
248 -
    add ptr %106 %100 %103;
249 -
    store w8 %105 %106 0;
250 -
    add w32 %107 %103 1;
251 -
    jmp @append34(%107);
252 -
  @append36
253 -
    store ptr %100 %8 0;
254 -
    store w32 %96 %8 12;
255 -
    jmp @append.store32;
256 -
  @then37
194 +
    elem %88 %87 2 %86 4;
195 +
    sload w32 %89 %88 0;
196 +
    br.ne w32 %89 30 @then24 @merge25;
197 +
  @then24
198 +
    ret 5;
199 +
  @merge25
200 +
    load w32 %92 %8 8;
201 +
    load w32 %93 %8 12;
202 +
    br.ult w32 %92 %93 @append.store26 @append.grow27;
203 +
  @append.store26
204 +
    load ptr %107 %8 0;
205 +
    mul w64 %108 %92 4;
206 +
    add ptr %109 %107 %108;
207 +
    store w32 40 %109 0;
208 +
    add w32 %110 %92 1;
209 +
    store w32 %110 %8 8;
210 +
    load w32 %113 %8 8;
211 +
    br.ne w32 %113 4 @then31 @merge32;
212 +
  @append.grow27
213 +
    shl w32 %94 %93 1;
214 +
    or w32 %95 %94 1;
215 +
    load ptr %96 %5 0;
216 +
    load ptr %97 %5 8;
217 +
    mul w32 %98 %95 4;
218 +
    call ptr %99 %96(%97, %98, 4);
219 +
    load ptr %100 %8 0;
220 +
    mul w32 %101 %92 4;
221 +
    jmp @append28(0);
222 +
  @append28(w32 %102)
223 +
    br.ult w32 %102 %101 @append29 @append30;
224 +
  @append29
225 +
    add ptr %103 %100 %102;
226 +
    load w8 %104 %103 0;
227 +
    add ptr %105 %99 %102;
228 +
    store w8 %104 %105 0;
229 +
    add w32 %106 %102 1;
230 +
    jmp @append28(%106);
231 +
  @append30
232 +
    store ptr %99 %8 0;
233 +
    store w32 %95 %8 12;
234 +
    jmp @append.store26;
235 +
  @then31
257 236
    ret 6;
258 -
  @merge38
259 -
    load w32 %115 %8 12;
260 -
    br.ne w32 %115 4 @then39 @merge40;
261 -
  @then39
237 +
  @merge32
238 +
    load w32 %114 %8 12;
239 +
    br.ne w32 %114 4 @then33 @merge34;
240 +
  @then33
262 241
    ret 7;
263 -
  @merge40
264 -
    load w32 %118 %8 8;
265 -
    load w32 %119 %8 12;
266 -
    br.ult w32 %118 %119 @append.store41 @append.grow42;
267 -
  @append.store41
268 -
    load ptr %133 %8 0;
269 -
    mul w64 %134 %118 4;
270 -
    add ptr %135 %133 %134;
271 -
    store w32 50 %135 0;
272 -
    add w32 %136 %118 1;
273 -
    store w32 %136 %8 8;
274 -
    load w32 %139 %8 8;
275 -
    br.ne w32 %139 5 @then46 @merge47;
276 -
  @append.grow42
277 -
    shl w32 %120 %119 1;
278 -
    or w32 %121 %120 1;
279 -
    load ptr %122 %5 0;
280 -
    load ptr %123 %5 8;
281 -
    mul w32 %124 %121 4;
282 -
    call ptr %125 %122(%123, %124, 4);
283 -
    load ptr %126 %8 0;
284 -
    mul w32 %127 %118 4;
285 -
    jmp @append43(0);
286 -
  @append43(w32 %128)
287 -
    br.ult w32 %128 %127 @append44 @append45;
288 -
  @append44
289 -
    add ptr %129 %126 %128;
290 -
    load w8 %130 %129 0;
291 -
    add ptr %131 %125 %128;
292 -
    store w8 %130 %131 0;
293 -
    add w32 %132 %128 1;
294 -
    jmp @append43(%132);
295 -
  @append45
296 -
    store ptr %125 %8 0;
297 -
    store w32 %121 %8 12;
298 -
    jmp @append.store41;
299 -
  @then46
242 +
  @merge34
243 +
    load w32 %117 %8 8;
244 +
    load w32 %118 %8 12;
245 +
    br.ult w32 %117 %118 @append.store35 @append.grow36;
246 +
  @append.store35
247 +
    load ptr %132 %8 0;
248 +
    mul w64 %133 %117 4;
249 +
    add ptr %134 %132 %133;
250 +
    store w32 50 %134 0;
251 +
    add w32 %135 %117 1;
252 +
    store w32 %135 %8 8;
253 +
    load w32 %138 %8 8;
254 +
    br.ne w32 %138 5 @then40 @merge41;
255 +
  @append.grow36
256 +
    shl w32 %119 %118 1;
257 +
    or w32 %120 %119 1;
258 +
    load ptr %121 %5 0;
259 +
    load ptr %122 %5 8;
260 +
    mul w32 %123 %120 4;
261 +
    call ptr %124 %121(%122, %123, 4);
262 +
    load ptr %125 %8 0;
263 +
    mul w32 %126 %117 4;
264 +
    jmp @append37(0);
265 +
  @append37(w32 %127)
266 +
    br.ult w32 %127 %126 @append38 @append39;
267 +
  @append38
268 +
    add ptr %128 %125 %127;
269 +
    load w8 %129 %128 0;
270 +
    add ptr %130 %124 %127;
271 +
    store w8 %129 %130 0;
272 +
    add w32 %131 %127 1;
273 +
    jmp @append37(%131);
274 +
  @append39
275 +
    store ptr %124 %8 0;
276 +
    store w32 %120 %8 12;
277 +
    jmp @append.store35;
278 +
  @then40
300 279
    ret 8;
301 -
  @merge47
302 -
    load w32 %140 %8 12;
303 -
    br.ne w32 %140 9 @then48 @merge49;
304 -
  @then48
280 +
  @merge41
281 +
    load w32 %139 %8 12;
282 +
    br.ne w32 %139 9 @then42 @merge43;
283 +
  @then42
305 284
    ret 9;
306 -
  @merge49
307 -
    load w32 %141 %8 8;
308 -
    br.ult w32 4 %141 @guard#pass52 @guard#trap53;
309 -
  @then50
285 +
  @merge43
286 +
    load w32 %140 %8 8;
287 +
    load ptr %141 %8 0;
288 +
    elem %142 %141 4 %140 4;
289 +
    sload w32 %143 %142 0;
290 +
    br.ne w32 %143 50 @then44 @merge45;
291 +
  @then44
310 292
    ret 10;
311 -
  @merge51
312 -
    load w32 %146 %8 8;
313 -
    br.ult w32 0 %146 @guard#pass56 @guard#trap57;
314 -
  @guard#pass52
315 -
    load ptr %142 %8 0;
316 -
    mul w64 %143 4 4;
317 -
    add ptr %144 %142 %143;
318 -
    sload w32 %145 %144 0;
319 -
    br.ne w32 %145 50 @then50 @merge51;
320 -
  @guard#trap53
321 -
    ebreak;
322 -
    unreachable;
323 -
  @then54
293 +
  @merge45
294 +
    load w32 %144 %8 8;
295 +
    load ptr %145 %8 0;
296 +
    elem %146 %145 0 %144 4;
297 +
    sload w32 %147 %146 0;
298 +
    br.ne w32 %147 10 @then46 @merge47;
299 +
  @then46
324 300
    ret 11;
325 -
  @merge55
326 -
    load w32 %149 %8 8;
327 -
    br.ult w32 3 %149 @guard#pass60 @guard#trap61;
328 -
  @guard#pass56
329 -
    load ptr %147 %8 0;
330 -
    sload w32 %148 %147 0;
331 -
    br.ne w32 %148 10 @then54 @merge55;
332 -
  @guard#trap57
333 -
    ebreak;
334 -
    unreachable;
335 -
  @then58
301 +
  @merge47
302 +
    load w32 %148 %8 8;
303 +
    load ptr %149 %8 0;
304 +
    elem %150 %149 3 %148 4;
305 +
    sload w32 %151 %150 0;
306 +
    br.ne w32 %151 40 @then48 @merge49;
307 +
  @then48
336 308
    ret 12;
337 -
  @merge59
338 -
    reserve %164 16 8;
339 -
    store ptr %7 %164 0;
340 -
    store w32 0 %164 8;
341 -
    store w32 0 %164 12;
342 -
    load w32 %167 %164 8;
343 -
    load w32 %168 %164 12;
344 -
    br.ult w32 %167 %168 @append.store62 @append.grow63;
345 -
  @guard#pass60
346 -
    load ptr %150 %8 0;
347 -
    mul w64 %151 3 4;
348 -
    add ptr %152 %150 %151;
349 -
    sload w32 %153 %152 0;
350 -
    br.ne w32 %153 40 @then58 @merge59;
351 -
  @guard#trap61
352 -
    ebreak;
353 -
    unreachable;
354 -
  @append.store62
355 -
    load ptr %182 %164 0;
356 -
    mul w64 %183 %167 4;
357 -
    add ptr %184 %182 %183;
358 -
    store w32 99 %184 0;
359 -
    add w32 %185 %167 1;
360 -
    store w32 %185 %164 8;
361 -
    load w32 %188 %164 8;
362 -
    br.ne w32 %188 1 @then67 @merge68;
363 -
  @append.grow63
364 -
    shl w32 %169 %168 1;
365 -
    or w32 %170 %169 1;
366 -
    load ptr %171 %5 0;
367 -
    load ptr %172 %5 8;
368 -
    mul w32 %173 %170 4;
369 -
    call ptr %174 %171(%172, %173, 4);
370 -
    load ptr %175 %164 0;
371 -
    mul w32 %176 %167 4;
372 -
    jmp @append64(0);
373 -
  @append64(w32 %177)
374 -
    br.ult w32 %177 %176 @append65 @append66;
375 -
  @append65
376 -
    add ptr %178 %175 %177;
377 -
    load w8 %179 %178 0;
378 -
    add ptr %180 %174 %177;
379 -
    store w8 %179 %180 0;
380 -
    add w32 %181 %177 1;
381 -
    jmp @append64(%181);
382 -
  @append66
383 -
    store ptr %174 %164 0;
384 -
    store w32 %170 %164 12;
385 -
    jmp @append.store62;
386 -
  @then67
309 +
  @merge49
310 +
    reserve %162 16 8;
311 +
    store ptr %7 %162 0;
312 +
    store w32 0 %162 8;
313 +
    store w32 0 %162 12;
314 +
    load w32 %165 %162 8;
315 +
    load w32 %166 %162 12;
316 +
    br.ult w32 %165 %166 @append.store50 @append.grow51;
317 +
  @append.store50
318 +
    load ptr %180 %162 0;
319 +
    mul w64 %181 %165 4;
320 +
    add ptr %182 %180 %181;
321 +
    store w32 99 %182 0;
322 +
    add w32 %183 %165 1;
323 +
    store w32 %183 %162 8;
324 +
    load w32 %186 %162 8;
325 +
    br.ne w32 %186 1 @then55 @merge56;
326 +
  @append.grow51
327 +
    shl w32 %167 %166 1;
328 +
    or w32 %168 %167 1;
329 +
    load ptr %169 %5 0;
330 +
    load ptr %170 %5 8;
331 +
    mul w32 %171 %168 4;
332 +
    call ptr %172 %169(%170, %171, 4);
333 +
    load ptr %173 %162 0;
334 +
    mul w32 %174 %165 4;
335 +
    jmp @append52(0);
336 +
  @append52(w32 %175)
337 +
    br.ult w32 %175 %174 @append53 @append54;
338 +
  @append53
339 +
    add ptr %176 %173 %175;
340 +
    load w8 %177 %176 0;
341 +
    add ptr %178 %172 %175;
342 +
    store w8 %177 %178 0;
343 +
    add w32 %179 %175 1;
344 +
    jmp @append52(%179);
345 +
  @append54
346 +
    store ptr %172 %162 0;
347 +
    store w32 %168 %162 12;
348 +
    jmp @append.store50;
349 +
  @then55
387 350
    ret 13;
388 -
  @merge68
389 -
    load w32 %189 %164 12;
390 -
    br.ne w32 %189 1 @then69 @merge70;
391 -
  @then69
351 +
  @merge56
352 +
    load w32 %187 %162 12;
353 +
    br.ne w32 %187 1 @then57 @merge58;
354 +
  @then57
392 355
    ret 14;
393 -
  @merge70
394 -
    load w32 %190 %164 8;
395 -
    br.ult w32 0 %190 @guard#pass73 @guard#trap74;
396 -
  @then71
356 +
  @merge58
357 +
    load w32 %188 %162 8;
358 +
    load ptr %189 %162 0;
359 +
    elem %190 %189 0 %188 4;
360 +
    sload w32 %191 %190 0;
361 +
    br.ne w32 %191 99 @then59 @merge60;
362 +
  @then59
397 363
    ret 15;
398 -
  @merge72
399 -
    load w32 %195 %8 8;
400 -
    load ptr %196 %8 0;
401 -
    jmp @loop75(0, 0);
402 -
  @guard#pass73
403 -
    load ptr %191 %164 0;
404 -
    sload w32 %192 %191 0;
405 -
    br.ne w32 %192 99 @then71 @merge72;
406 -
  @guard#trap74
407 -
    ebreak;
408 -
    unreachable;
409 -
  @loop75(w32 %197, w32 %201)
410 -
    br.slt w32 %197 %195 @body76 @merge77;
411 -
  @body76
412 -
    mul w64 %198 %197 4;
413 -
    add ptr %199 %196 %198;
414 -
    sload w32 %200 %199 0;
415 -
    add w32 %202 %201 %200;
416 -
    add w32 %203 %197 1;
417 -
    jmp @loop75(%203, %202);
418 -
  @merge77
419 -
    br.ne w32 %201 150 @then78 @merge79;
420 -
  @then78
364 +
  @merge60
365 +
    load w32 %194 %8 8;
366 +
    load ptr %195 %8 0;
367 +
    jmp @loop61(0, 0);
368 +
  @loop61(w32 %196, w32 %200)
369 +
    br.slt w32 %196 %194 @body62 @merge63;
370 +
  @body62
371 +
    mul w64 %197 %196 4;
372 +
    add ptr %198 %195 %197;
373 +
    sload w32 %199 %198 0;
374 +
    add w32 %201 %200 %199;
375 +
    add w32 %202 %196 1;
376 +
    jmp @loop61(%202, %201);
377 +
  @merge63
378 +
    br.ne w32 %200 150 @then64 @merge65;
379 +
  @then64
421 380
    ret 16;
422 -
  @merge79
423 -
    call ptr %217 $arenaAlloc(%3, 2, 1);
424 -
    reserve %218 16 8;
425 -
    store ptr %217 %218 0;
426 -
    store w32 0 %218 8;
427 -
    store w32 2 %218 12;
428 -
    load w32 %222 %218 8;
429 -
    load w32 %223 %218 12;
430 -
    br.ult w32 %222 %223 @append.store80 @append.grow81;
431 -
  @append.store80
432 -
    load ptr %237 %218 0;
433 -
    add ptr %238 %237 %222;
434 -
    store w8 171 %238 0;
435 -
    add w32 %239 %222 1;
436 -
    store w32 %239 %218 8;
437 -
    load w32 %244 %218 8;
438 -
    load w32 %245 %218 12;
439 -
    br.ult w32 %244 %245 @append.store85 @append.grow86;
440 -
  @append.grow81
441 -
    shl w32 %224 %223 1;
442 -
    or w32 %225 %224 1;
443 -
    load ptr %226 %5 0;
444 -
    load ptr %227 %5 8;
445 -
    mul w32 %228 %225 1;
446 -
    call ptr %229 %226(%227, %228, 1);
447 -
    load ptr %230 %218 0;
448 -
    mul w32 %231 %222 1;
449 -
    jmp @append82(0);
450 -
  @append82(w32 %232)
451 -
    br.ult w32 %232 %231 @append83 @append84;
452 -
  @append83
453 -
    add ptr %233 %230 %232;
454 -
    load w8 %234 %233 0;
455 -
    add ptr %235 %229 %232;
456 -
    store w8 %234 %235 0;
457 -
    add w32 %236 %232 1;
458 -
    jmp @append82(%236);
459 -
  @append84
460 -
    store ptr %229 %218 0;
461 -
    store w32 %225 %218 12;
462 -
    jmp @append.store80;
463 -
  @append.store85
464 -
    load ptr %259 %218 0;
465 -
    add ptr %260 %259 %244;
466 -
    store w8 205 %260 0;
467 -
    add w32 %261 %244 1;
468 -
    store w32 %261 %218 8;
469 -
    load w32 %264 %218 8;
470 -
    br.ne w32 %264 2 @then90 @merge91;
471 -
  @append.grow86
472 -
    shl w32 %246 %245 1;
473 -
    or w32 %247 %246 1;
474 -
    load ptr %248 %5 0;
475 -
    load ptr %249 %5 8;
476 -
    mul w32 %250 %247 1;
477 -
    call ptr %251 %248(%249, %250, 1);
478 -
    load ptr %252 %218 0;
479 -
    mul w32 %253 %244 1;
480 -
    jmp @append87(0);
481 -
  @append87(w32 %254)
482 -
    br.ult w32 %254 %253 @append88 @append89;
483 -
  @append88
484 -
    add ptr %255 %252 %254;
485 -
    load w8 %256 %255 0;
486 -
    add ptr %257 %251 %254;
487 -
    store w8 %256 %257 0;
488 -
    add w32 %258 %254 1;
489 -
    jmp @append87(%258);
490 -
  @append89
491 -
    store ptr %251 %218 0;
492 -
    store w32 %247 %218 12;
493 -
    jmp @append.store85;
494 -
  @then90
381 +
  @merge65
382 +
    call ptr %216 $arenaAlloc(%3, 2, 1);
383 +
    reserve %217 16 8;
384 +
    store ptr %216 %217 0;
385 +
    store w32 0 %217 8;
386 +
    store w32 2 %217 12;
387 +
    load w32 %221 %217 8;
388 +
    load w32 %222 %217 12;
389 +
    br.ult w32 %221 %222 @append.store66 @append.grow67;
390 +
  @append.store66
391 +
    load ptr %236 %217 0;
392 +
    add ptr %237 %236 %221;
393 +
    store w8 171 %237 0;
394 +
    add w32 %238 %221 1;
395 +
    store w32 %238 %217 8;
396 +
    load w32 %243 %217 8;
397 +
    load w32 %244 %217 12;
398 +
    br.ult w32 %243 %244 @append.store71 @append.grow72;
399 +
  @append.grow67
400 +
    shl w32 %223 %222 1;
401 +
    or w32 %224 %223 1;
402 +
    load ptr %225 %5 0;
403 +
    load ptr %226 %5 8;
404 +
    mul w32 %227 %224 1;
405 +
    call ptr %228 %225(%226, %227, 1);
406 +
    load ptr %229 %217 0;
407 +
    mul w32 %230 %221 1;
408 +
    jmp @append68(0);
409 +
  @append68(w32 %231)
410 +
    br.ult w32 %231 %230 @append69 @append70;
411 +
  @append69
412 +
    add ptr %232 %229 %231;
413 +
    load w8 %233 %232 0;
414 +
    add ptr %234 %228 %231;
415 +
    store w8 %233 %234 0;
416 +
    add w32 %235 %231 1;
417 +
    jmp @append68(%235);
418 +
  @append70
419 +
    store ptr %228 %217 0;
420 +
    store w32 %224 %217 12;
421 +
    jmp @append.store66;
422 +
  @append.store71
423 +
    load ptr %258 %217 0;
424 +
    add ptr %259 %258 %243;
425 +
    store w8 205 %259 0;
426 +
    add w32 %260 %243 1;
427 +
    store w32 %260 %217 8;
428 +
    load w32 %263 %217 8;
429 +
    br.ne w32 %263 2 @then76 @merge77;
430 +
  @append.grow72
431 +
    shl w32 %245 %244 1;
432 +
    or w32 %246 %245 1;
433 +
    load ptr %247 %5 0;
434 +
    load ptr %248 %5 8;
435 +
    mul w32 %249 %246 1;
436 +
    call ptr %250 %247(%248, %249, 1);
437 +
    load ptr %251 %217 0;
438 +
    mul w32 %252 %243 1;
439 +
    jmp @append73(0);
440 +
  @append73(w32 %253)
441 +
    br.ult w32 %253 %252 @append74 @append75;
442 +
  @append74
443 +
    add ptr %254 %251 %253;
444 +
    load w8 %255 %254 0;
445 +
    add ptr %256 %250 %253;
446 +
    store w8 %255 %256 0;
447 +
    add w32 %257 %253 1;
448 +
    jmp @append73(%257);
449 +
  @append75
450 +
    store ptr %250 %217 0;
451 +
    store w32 %246 %217 12;
452 +
    jmp @append.store71;
453 +
  @then76
495 454
    ret 17;
496 -
  @merge91
497 -
    load w32 %265 %218 8;
498 -
    br.ult w32 0 %265 @guard#pass94 @guard#trap95;
499 -
  @then92
500 -
    ret 18;
501 -
  @merge93
502 -
    load w32 %268 %218 8;
503 -
    br.ult w32 1 %268 @guard#pass98 @guard#trap99;
504 -
  @guard#pass94
505 -
    load ptr %266 %218 0;
455 +
  @merge77
456 +
    load w32 %264 %217 8;
457 +
    load ptr %265 %217 0;
458 +
    elem %266 %265 0 %264 1;
506 459
    load w8 %267 %266 0;
507 -
    br.ne w8 %267 171 @then92 @merge93;
508 -
  @guard#trap95
509 -
    ebreak;
510 -
    unreachable;
511 -
  @then96
512 -
    ret 19;
513 -
  @merge97
514 -
    load w32 %274 %218 8;
515 -
    load w32 %275 %218 12;
516 -
    br.ult w32 %274 %275 @append.store100 @append.grow101;
517 -
  @guard#pass98
518 -
    load ptr %269 %218 0;
519 -
    add ptr %270 %269 1;
460 +
    br.ne w8 %267 171 @then78 @merge79;
461 +
  @then78
462 +
    ret 18;
463 +
  @merge79
464 +
    load w32 %268 %217 8;
465 +
    load ptr %269 %217 0;
466 +
    elem %270 %269 1 %268 1;
520 467
    load w8 %271 %270 0;
521 -
    br.ne w8 %271 205 @then96 @merge97;
522 -
  @guard#trap99
523 -
    ebreak;
524 -
    unreachable;
525 -
  @append.store100
526 -
    load ptr %289 %218 0;
468 +
    br.ne w8 %271 205 @then80 @merge81;
469 +
  @then80
470 +
    ret 19;
471 +
  @merge81
472 +
    load w32 %274 %217 8;
473 +
    load w32 %275 %217 12;
474 +
    br.ult w32 %274 %275 @append.store82 @append.grow83;
475 +
  @append.store82
476 +
    load ptr %289 %217 0;
527 477
    add ptr %290 %289 %274;
528 478
    store w8 239 %290 0;
529 479
    add w32 %291 %274 1;
530 -
    store w32 %291 %218 8;
531 -
    load w32 %294 %218 8;
532 -
    br.ne w32 %294 3 @then105 @merge106;
533 -
  @append.grow101
480 +
    store w32 %291 %217 8;
481 +
    load w32 %294 %217 8;
482 +
    br.ne w32 %294 3 @then87 @merge88;
483 +
  @append.grow83
534 484
    shl w32 %276 %275 1;
535 485
    or w32 %277 %276 1;
536 486
    load ptr %278 %5 0;
537 487
    load ptr %279 %5 8;
538 488
    mul w32 %280 %277 1;
539 489
    call ptr %281 %278(%279, %280, 1);
540 -
    load ptr %282 %218 0;
490 +
    load ptr %282 %217 0;
541 491
    mul w32 %283 %274 1;
542 -
    jmp @append102(0);
543 -
  @append102(w32 %284)
544 -
    br.ult w32 %284 %283 @append103 @append104;
545 -
  @append103
492 +
    jmp @append84(0);
493 +
  @append84(w32 %284)
494 +
    br.ult w32 %284 %283 @append85 @append86;
495 +
  @append85
546 496
    add ptr %285 %282 %284;
547 497
    load w8 %286 %285 0;
548 498
    add ptr %287 %281 %284;
549 499
    store w8 %286 %287 0;
550 500
    add w32 %288 %284 1;
551 -
    jmp @append102(%288);
552 -
  @append104
553 -
    store ptr %281 %218 0;
554 -
    store w32 %277 %218 12;
555 -
    jmp @append.store100;
556 -
  @then105
501 +
    jmp @append84(%288);
502 +
  @append86
503 +
    store ptr %281 %217 0;
504 +
    store w32 %277 %217 12;
505 +
    jmp @append.store82;
506 +
  @then87
557 507
    ret 20;
558 -
  @merge106
559 -
    load w32 %295 %218 12;
560 -
    br.ne w32 %295 5 @then107 @merge108;
561 -
  @then107
508 +
  @merge88
509 +
    load w32 %295 %217 12;
510 +
    br.ne w32 %295 5 @then89 @merge90;
511 +
  @then89
562 512
    ret 21;
563 -
  @merge108
564 -
    load w32 %296 %218 8;
565 -
    br.ult w32 2 %296 @guard#pass111 @guard#trap112;
566 -
  @then109
567 -
    ret 22;
568 -
  @merge110
569 -
    load w32 %300 %218 8;
570 -
    br.ult w32 0 %300 @guard#pass115 @guard#trap116;
571 -
  @guard#pass111
572 -
    load ptr %297 %218 0;
573 -
    add ptr %298 %297 2;
513 +
  @merge90
514 +
    load w32 %296 %217 8;
515 +
    load ptr %297 %217 0;
516 +
    elem %298 %297 2 %296 1;
574 517
    load w8 %299 %298 0;
575 -
    br.ne w8 %299 239 @then109 @merge110;
576 -
  @guard#trap112
577 -
    ebreak;
578 -
    unreachable;
579 -
  @then113
518 +
    br.ne w8 %299 239 @then91 @merge92;
519 +
  @then91
520 +
    ret 22;
521 +
  @merge92
522 +
    load w32 %300 %217 8;
523 +
    load ptr %301 %217 0;
524 +
    elem %302 %301 0 %300 1;
525 +
    load w8 %303 %302 0;
526 +
    br.ne w8 %303 171 @then93 @merge94;
527 +
  @then93
580 528
    ret 23;
581 -
  @merge114
582 -
    mul w32 %309 4 2;
583 -
    call ptr %310 $arenaAlloc(%3, %309, 4);
584 -
    reserve %311 16 8;
585 -
    store ptr %310 %311 0;
586 -
    store w32 0 %311 8;
587 -
    store w32 2 %311 12;
588 -
    load w32 %314 %311 8;
589 -
    load w32 %315 %311 12;
590 -
    br.ult w32 %314 %315 @append.store117 @append.grow118;
591 -
  @guard#pass115
592 -
    load ptr %301 %218 0;
593 -
    load w8 %302 %301 0;
594 -
    br.ne w8 %302 171 @then113 @merge114;
595 -
  @guard#trap116
596 -
    ebreak;
529 +
  @merge94
530 +
    mul w32 %310 4 2;
531 +
    call ptr %311 $arenaAlloc(%3, %310, 4);
532 +
    reserve %312 16 8;
533 +
    store ptr %311 %312 0;
534 +
    store w32 0 %312 8;
535 +
    store w32 2 %312 12;
536 +
    load w32 %315 %312 8;
537 +
    load w32 %316 %312 12;
538 +
    br.ult w32 %315 %316 @append.store95 @append.grow96;
539 +
  @append.store95
540 +
    load ptr %330 %312 0;
541 +
    mul w64 %331 %315 4;
542 +
    add ptr %332 %330 %331;
543 +
    store w32 42 %332 0;
544 +
    add w32 %333 %315 1;
545 +
    store w32 %333 %312 8;
546 +
    blit %312 %312 16;
547 +
    load w32 %336 %312 8;
548 +
    br.eq w32 %336 1 @assert.ok101 @assert.fail100;
549 +
  @append.grow96
550 +
    shl w32 %317 %316 1;
551 +
    or w32 %318 %317 1;
552 +
    load ptr %319 %5 0;
553 +
    load ptr %320 %5 8;
554 +
    mul w32 %321 %318 4;
555 +
    call ptr %322 %319(%320, %321, 4);
556 +
    load ptr %323 %312 0;
557 +
    mul w32 %324 %315 4;
558 +
    jmp @append97(0);
559 +
  @append97(w32 %325)
560 +
    br.ult w32 %325 %324 @append98 @append99;
561 +
  @append98
562 +
    add ptr %326 %323 %325;
563 +
    load w8 %327 %326 0;
564 +
    add ptr %328 %322 %325;
565 +
    store w8 %327 %328 0;
566 +
    add w32 %329 %325 1;
567 +
    jmp @append97(%329);
568 +
  @append99
569 +
    store ptr %322 %312 0;
570 +
    store w32 %318 %312 12;
571 +
    jmp @append.store95;
572 +
  @assert.fail100
597 573
    unreachable;
598 -
  @append.store117
599 -
    load ptr %329 %311 0;
600 -
    mul w64 %330 %314 4;
601 -
    add ptr %331 %329 %330;
602 -
    store w32 42 %331 0;
603 -
    add w32 %332 %314 1;
604 -
    store w32 %332 %311 8;
605 -
    blit %311 %311 16;
606 -
    load w32 %335 %311 8;
607 -
    br.eq w32 %335 1 @assert.ok123 @assert.fail122;
608 -
  @append.grow118
609 -
    shl w32 %316 %315 1;
610 -
    or w32 %317 %316 1;
611 -
    load ptr %318 %5 0;
612 -
    load ptr %319 %5 8;
613 -
    mul w32 %320 %317 4;
614 -
    call ptr %321 %318(%319, %320, 4);
615 -
    load ptr %322 %311 0;
616 -
    mul w32 %323 %314 4;
617 -
    jmp @append119(0);
618 -
  @append119(w32 %324)
619 -
    br.ult w32 %324 %323 @append120 @append121;
620 -
  @append120
621 -
    add ptr %325 %322 %324;
622 -
    load w8 %326 %325 0;
623 -
    add ptr %327 %321 %324;
624 -
    store w8 %326 %327 0;
625 -
    add w32 %328 %324 1;
626 -
    jmp @append119(%328);
627 -
  @append121
628 -
    store ptr %321 %311 0;
629 -
    store w32 %317 %311 12;
630 -
    jmp @append.store117;
631 -
  @assert.fail122
574 +
  @assert.ok101
575 +
    load w32 %337 %312 8;
576 +
    load ptr %338 %312 0;
577 +
    elem %339 %338 0 %337 4;
578 +
    sload w32 %340 %339 0;
579 +
    br.eq w32 %340 42 @assert.ok103 @assert.fail102;
580 +
  @assert.fail102
632 581
    unreachable;
633 -
  @assert.ok123
634 -
    load w32 %336 %311 8;
635 -
    br.ult w32 0 %336 @guard#pass126 @guard#trap127;
636 -
  @assert.fail124
582 +
  @assert.ok103
583 +
    load w32 %343 %312 8;
584 +
    load w32 %344 %312 12;
585 +
    br.ult w32 %343 %344 @append.store104 @append.grow105;
586 +
  @append.store104
587 +
    load ptr %358 %312 0;
588 +
    mul w64 %359 %343 4;
589 +
    add ptr %360 %358 %359;
590 +
    store w32 43 %360 0;
591 +
    add w32 %361 %343 1;
592 +
    store w32 %361 %312 8;
593 +
    blit %312 %312 16;
594 +
    load w32 %364 %312 8;
595 +
    br.eq w32 %364 2 @assert.ok110 @assert.fail109;
596 +
  @append.grow105
597 +
    shl w32 %345 %344 1;
598 +
    or w32 %346 %345 1;
599 +
    load ptr %347 %5 0;
600 +
    load ptr %348 %5 8;
601 +
    mul w32 %349 %346 4;
602 +
    call ptr %350 %347(%348, %349, 4);
603 +
    load ptr %351 %312 0;
604 +
    mul w32 %352 %343 4;
605 +
    jmp @append106(0);
606 +
  @append106(w32 %353)
607 +
    br.ult w32 %353 %352 @append107 @append108;
608 +
  @append107
609 +
    add ptr %354 %351 %353;
610 +
    load w8 %355 %354 0;
611 +
    add ptr %356 %350 %353;
612 +
    store w8 %355 %356 0;
613 +
    add w32 %357 %353 1;
614 +
    jmp @append106(%357);
615 +
  @append108
616 +
    store ptr %350 %312 0;
617 +
    store w32 %346 %312 12;
618 +
    jmp @append.store104;
619 +
  @assert.fail109
637 620
    unreachable;
638 -
  @assert.ok125
639 -
    load w32 %341 %311 8;
640 -
    load w32 %342 %311 12;
641 -
    br.ult w32 %341 %342 @append.store128 @append.grow129;
642 -
  @guard#pass126
643 -
    load ptr %337 %311 0;
644 -
    sload w32 %338 %337 0;
645 -
    br.eq w32 %338 42 @assert.ok125 @assert.fail124;
646 -
  @guard#trap127
647 -
    ebreak;
648 -
    unreachable;
649 -
  @append.store128
650 -
    load ptr %356 %311 0;
651 -
    mul w64 %357 %341 4;
652 -
    add ptr %358 %356 %357;
653 -
    store w32 43 %358 0;
654 -
    add w32 %359 %341 1;
655 -
    store w32 %359 %311 8;
656 -
    blit %311 %311 16;
657 -
    load w32 %362 %311 8;
658 -
    br.eq w32 %362 2 @assert.ok134 @assert.fail133;
659 -
  @append.grow129
660 -
    shl w32 %343 %342 1;
661 -
    or w32 %344 %343 1;
662 -
    load ptr %345 %5 0;
663 -
    load ptr %346 %5 8;
664 -
    mul w32 %347 %344 4;
665 -
    call ptr %348 %345(%346, %347, 4);
666 -
    load ptr %349 %311 0;
667 -
    mul w32 %350 %341 4;
668 -
    jmp @append130(0);
669 -
  @append130(w32 %351)
670 -
    br.ult w32 %351 %350 @append131 @append132;
671 -
  @append131
672 -
    add ptr %352 %349 %351;
673 -
    load w8 %353 %352 0;
674 -
    add ptr %354 %348 %351;
675 -
    store w8 %353 %354 0;
676 -
    add w32 %355 %351 1;
677 -
    jmp @append130(%355);
678 -
  @append132
679 -
    store ptr %348 %311 0;
680 -
    store w32 %344 %311 12;
681 -
    jmp @append.store128;
682 -
  @assert.fail133
683 -
    unreachable;
684 -
  @assert.ok134
685 -
    load w32 %363 %311 8;
686 -
    br.ult w32 0 %363 @guard#pass135 @guard#trap136;
687 -
  @guard#pass135
688 -
    load ptr %364 %311 0;
689 -
    load w32 %367 %311 8;
690 -
    load w32 %368 %311 12;
691 -
    br.ult w32 %367 %368 @append.store137 @append.grow138;
692 -
  @guard#trap136
693 -
    ebreak;
694 -
    unreachable;
695 -
  @append.store137
696 -
    load ptr %382 %311 0;
697 -
    mul w64 %383 %367 4;
698 -
    add ptr %384 %382 %383;
699 -
    store w32 44 %384 0;
700 -
    add w32 %385 %367 1;
701 -
    store w32 %385 %311 8;
702 -
    blit %311 %311 16;
703 -
    load w32 %388 %311 8;
704 -
    br.eq w32 %388 3 @assert.ok143 @assert.fail142;
705 -
  @append.grow138
706 -
    shl w32 %369 %368 1;
707 -
    or w32 %370 %369 1;
708 -
    load ptr %371 %5 0;
709 -
    load ptr %372 %5 8;
710 -
    mul w32 %373 %370 4;
711 -
    call ptr %374 %371(%372, %373, 4);
712 -
    load ptr %375 %311 0;
713 -
    mul w32 %376 %367 4;
714 -
    jmp @append139(0);
715 -
  @append139(w32 %377)
716 -
    br.ult w32 %377 %376 @append140 @append141;
717 -
  @append140
718 -
    add ptr %378 %375 %377;
719 -
    load w8 %379 %378 0;
720 -
    add ptr %380 %374 %377;
721 -
    store w8 %379 %380 0;
722 -
    add w32 %381 %377 1;
723 -
    jmp @append139(%381);
724 -
  @append141
725 -
    store ptr %374 %311 0;
726 -
    store w32 %370 %311 12;
727 -
    jmp @append.store137;
728 -
  @assert.fail142
729 -
    unreachable;
730 -
  @assert.ok143
731 -
    load w32 %389 %311 12;
732 -
    br.eq w32 %389 5 @assert.ok145 @assert.fail144;
733 -
  @assert.fail144
734 -
    unreachable;
735 -
  @assert.ok145
736 -
    load w32 %390 %311 8;
737 -
    br.ult w32 0 %390 @guard#pass146 @guard#trap147;
738 -
  @guard#pass146
739 -
    load ptr %391 %311 0;
740 -
    br.ne ptr %364 %391 @assert.ok149 @assert.fail148;
741 -
  @guard#trap147
742 -
    ebreak;
743 -
    unreachable;
744 -
  @assert.fail148
621 +
  @assert.ok110
622 +
    load w32 %365 %312 8;
623 +
    load ptr %366 %312 0;
624 +
    elem %367 %366 0 %365 4;
625 +
    load w32 %370 %312 8;
626 +
    load w32 %371 %312 12;
627 +
    br.ult w32 %370 %371 @append.store111 @append.grow112;
628 +
  @append.store111
629 +
    load ptr %385 %312 0;
630 +
    mul w64 %386 %370 4;
631 +
    add ptr %387 %385 %386;
632 +
    store w32 44 %387 0;
633 +
    add w32 %388 %370 1;
634 +
    store w32 %388 %312 8;
635 +
    blit %312 %312 16;
636 +
    load w32 %391 %312 8;
637 +
    br.eq w32 %391 3 @assert.ok117 @assert.fail116;
638 +
  @append.grow112
639 +
    shl w32 %372 %371 1;
640 +
    or w32 %373 %372 1;
641 +
    load ptr %374 %5 0;
642 +
    load ptr %375 %5 8;
643 +
    mul w32 %376 %373 4;
644 +
    call ptr %377 %374(%375, %376, 4);
645 +
    load ptr %378 %312 0;
646 +
    mul w32 %379 %370 4;
647 +
    jmp @append113(0);
648 +
  @append113(w32 %380)
649 +
    br.ult w32 %380 %379 @append114 @append115;
650 +
  @append114
651 +
    add ptr %381 %378 %380;
652 +
    load w8 %382 %381 0;
653 +
    add ptr %383 %377 %380;
654 +
    store w8 %382 %383 0;
655 +
    add w32 %384 %380 1;
656 +
    jmp @append113(%384);
657 +
  @append115
658 +
    store ptr %377 %312 0;
659 +
    store w32 %373 %312 12;
660 +
    jmp @append.store111;
661 +
  @assert.fail116
745 662
    unreachable;
746 -
  @assert.ok149
747 -
    load w32 %394 %311 8;
748 -
    br.ult w32 0 %394 @guard#pass152 @guard#trap153;
749 -
  @assert.fail150
663 +
  @assert.ok117
664 +
    load w32 %392 %312 12;
665 +
    br.eq w32 %392 5 @assert.ok119 @assert.fail118;
666 +
  @assert.fail118
750 667
    unreachable;
751 -
  @assert.ok151
752 -
    load w32 %397 %311 8;
753 -
    br.ult w32 1 %397 @guard#pass156 @guard#trap157;
754 -
  @guard#pass152
755 -
    load ptr %395 %311 0;
756 -
    sload w32 %396 %395 0;
757 -
    br.eq w32 %396 42 @assert.ok151 @assert.fail150;
758 -
  @guard#trap153
759 -
    ebreak;
668 +
  @assert.ok119
669 +
    load w32 %393 %312 8;
670 +
    load ptr %394 %312 0;
671 +
    elem %395 %394 0 %393 4;
672 +
    br.ne ptr %367 %395 @assert.ok121 @assert.fail120;
673 +
  @assert.fail120
760 674
    unreachable;
761 -
  @assert.fail154
762 -
    unreachable;
763 -
  @assert.ok155
764 -
    load w32 %402 %311 8;
765 -
    br.ult w32 2 %402 @guard#pass160 @guard#trap161;
766 -
  @guard#pass156
767 -
    load ptr %398 %311 0;
768 -
    mul w64 %399 1 4;
769 -
    add ptr %400 %398 %399;
675 +
  @assert.ok121
676 +
    load w32 %398 %312 8;
677 +
    load ptr %399 %312 0;
678 +
    elem %400 %399 0 %398 4;
770 679
    sload w32 %401 %400 0;
771 -
    br.eq w32 %401 43 @assert.ok155 @assert.fail154;
772 -
  @guard#trap157
773 -
    ebreak;
680 +
    br.eq w32 %401 42 @assert.ok123 @assert.fail122;
681 +
  @assert.fail122
774 682
    unreachable;
775 -
  @assert.fail158
683 +
  @assert.ok123
684 +
    load w32 %402 %312 8;
685 +
    load ptr %403 %312 0;
686 +
    elem %404 %403 1 %402 4;
687 +
    sload w32 %405 %404 0;
688 +
    br.eq w32 %405 43 @assert.ok125 @assert.fail124;
689 +
  @assert.fail124
776 690
    unreachable;
777 -
  @assert.ok159
778 -
    ret 0;
779 -
  @guard#pass160
780 -
    load ptr %403 %311 0;
781 -
    mul w64 %404 2 4;
782 -
    add ptr %405 %403 %404;
783 -
    sload w32 %406 %405 0;
784 -
    br.eq w32 %406 44 @assert.ok159 @assert.fail158;
785 -
  @guard#trap161
786 -
    ebreak;
691 +
  @assert.ok125
692 +
    load w32 %406 %312 8;
693 +
    load ptr %407 %312 0;
694 +
    elem %408 %407 2 %406 4;
695 +
    sload w32 %409 %408 0;
696 +
    br.eq w32 %409 44 @assert.ok127 @assert.fail126;
697 +
  @assert.fail126
787 698
    unreachable;
699 +
  @assert.ok127
700 +
    ret 0;
788 701
}
test/tests/slice.delete.ril +117 -165
40 40
    br.ne w32 %17 4 @then6 @merge7;
41 41
  @then6
42 42
    ret 1;
43 43
  @merge7
44 44
    load w32 %18 %1 8;
45 -
    br.ult w32 0 %18 @guard#pass10 @guard#trap11;
45 +
    load ptr %19 %1 0;
46 +
    elem %20 %19 0 %18 4;
47 +
    sload w32 %21 %20 0;
48 +
    br.ne w32 %21 10 @then8 @merge9;
46 49
  @then8
47 50
    ret 2;
48 51
  @merge9
49 -
    load w32 %21 %1 8;
50 -
    br.ult w32 1 %21 @guard#pass14 @guard#trap15;
51 -
  @guard#pass10
52 -
    load ptr %19 %1 0;
53 -
    sload w32 %20 %19 0;
54 -
    br.ne w32 %20 10 @then8 @merge9;
55 -
  @guard#trap11
56 -
    ebreak;
57 -
    unreachable;
58 -
  @then12
52 +
    load w32 %22 %1 8;
53 +
    load ptr %23 %1 0;
54 +
    elem %24 %23 1 %22 4;
55 +
    sload w32 %25 %24 0;
56 +
    br.ne w32 %25 20 @then10 @merge11;
57 +
  @then10
59 58
    ret 3;
60 -
  @merge13
59 +
  @merge11
61 60
    load w32 %26 %1 8;
62 -
    br.ult w32 2 %26 @guard#pass18 @guard#trap19;
63 -
  @guard#pass14
64 -
    load ptr %22 %1 0;
65 -
    mul w64 %23 1 4;
66 -
    add ptr %24 %22 %23;
67 -
    sload w32 %25 %24 0;
68 -
    br.ne w32 %25 20 @then12 @merge13;
69 -
  @guard#trap15
70 -
    ebreak;
71 -
    unreachable;
72 -
  @then16
73 -
    ret 4;
74 -
  @merge17
75 -
    load w32 %31 %1 8;
76 -
    br.ult w32 3 %31 @guard#pass22 @guard#trap23;
77 -
  @guard#pass18
78 61
    load ptr %27 %1 0;
79 -
    mul w64 %28 2 4;
80 -
    add ptr %29 %27 %28;
81 -
    sload w32 %30 %29 0;
82 -
    br.ne w32 %30 40 @then16 @merge17;
83 -
  @guard#trap19
84 -
    ebreak;
85 -
    unreachable;
86 -
  @then20
62 +
    elem %28 %27 2 %26 4;
63 +
    sload w32 %29 %28 0;
64 +
    br.ne w32 %29 40 @then12 @merge13;
65 +
  @then12
66 +
    ret 4;
67 +
  @merge13
68 +
    load w32 %30 %1 8;
69 +
    load ptr %31 %1 0;
70 +
    elem %32 %31 3 %30 4;
71 +
    sload w32 %33 %32 0;
72 +
    br.ne w32 %33 50 @then14 @merge15;
73 +
  @then14
87 74
    ret 5;
88 -
  @merge21
89 -
    load w32 %36 %1 8;
90 -
    br.ult w32 0 %36 @guard#pass24 @guard#trap25;
91 -
  @guard#pass22
92 -
    load ptr %32 %1 0;
93 -
    mul w64 %33 3 4;
94 -
    add ptr %34 %32 %33;
95 -
    sload w32 %35 %34 0;
96 -
    br.ne w32 %35 50 @then20 @merge21;
97 -
  @guard#trap23
98 -
    ebreak;
99 -
    unreachable;
100 -
  @guard#pass24
101 -
    load ptr %37 %1 0;
102 -
    add ptr %38 %37 4;
103 -
    sub w32 %39 %36 0;
104 -
    sub w32 %40 %39 1;
105 -
    mul w32 %41 %40 4;
106 -
    jmp @delete26(0);
107 -
  @guard#trap25
75 +
  @merge15
76 +
    load w32 %34 %1 8;
77 +
    br.ult w32 0 %34 @guard#pass16 @guard#trap17;
78 +
  @guard#pass16
79 +
    load ptr %35 %1 0;
80 +
    add ptr %36 %35 4;
81 +
    sub w32 %37 %34 0;
82 +
    sub w32 %38 %37 1;
83 +
    mul w32 %39 %38 4;
84 +
    jmp @delete18(0);
85 +
  @guard#trap17
108 86
    ebreak;
109 87
    unreachable;
110 -
  @delete26(w32 %42)
111 -
    br.ult w32 %42 %41 @delete27 @delete28;
112 -
  @delete27
113 -
    add ptr %43 %38 %42;
114 -
    load w8 %44 %43 0;
115 -
    add ptr %45 %37 %42;
116 -
    store w8 %44 %45 0;
117 -
    add w32 %46 %42 1;
118 -
    jmp @delete26(%46);
119 -
  @delete28
120 -
    sub w32 %47 %36 1;
121 -
    store w32 %47 %1 8;
122 -
    load w32 %49 %1 8;
123 -
    br.ne w32 %49 3 @then29 @merge30;
124 -
  @then29
88 +
  @delete18(w32 %40)
89 +
    br.ult w32 %40 %39 @delete19 @delete20;
90 +
  @delete19
91 +
    add ptr %41 %36 %40;
92 +
    load w8 %42 %41 0;
93 +
    add ptr %43 %35 %40;
94 +
    store w8 %42 %43 0;
95 +
    add w32 %44 %40 1;
96 +
    jmp @delete18(%44);
97 +
  @delete20
98 +
    sub w32 %45 %34 1;
99 +
    store w32 %45 %1 8;
100 +
    load w32 %47 %1 8;
101 +
    br.ne w32 %47 3 @then21 @merge22;
102 +
  @then21
125 103
    ret 6;
126 -
  @merge30
127 -
    load w32 %50 %1 8;
128 -
    br.ult w32 0 %50 @guard#pass33 @guard#trap34;
129 -
  @then31
104 +
  @merge22
105 +
    load w32 %48 %1 8;
106 +
    load ptr %49 %1 0;
107 +
    elem %50 %49 0 %48 4;
108 +
    sload w32 %51 %50 0;
109 +
    br.ne w32 %51 20 @then23 @merge24;
110 +
  @then23
130 111
    ret 7;
131 -
  @merge32
132 -
    load w32 %53 %1 8;
133 -
    br.ult w32 1 %53 @guard#pass37 @guard#trap38;
134 -
  @guard#pass33
135 -
    load ptr %51 %1 0;
136 -
    sload w32 %52 %51 0;
137 -
    br.ne w32 %52 20 @then31 @merge32;
138 -
  @guard#trap34
139 -
    ebreak;
140 -
    unreachable;
141 -
  @then35
112 +
  @merge24
113 +
    load w32 %52 %1 8;
114 +
    load ptr %53 %1 0;
115 +
    elem %54 %53 1 %52 4;
116 +
    sload w32 %55 %54 0;
117 +
    br.ne w32 %55 40 @then25 @merge26;
118 +
  @then25
142 119
    ret 8;
143 -
  @merge36
144 -
    load w32 %58 %1 8;
145 -
    br.ult w32 2 %58 @guard#pass41 @guard#trap42;
146 -
  @guard#pass37
147 -
    load ptr %54 %1 0;
148 -
    mul w64 %55 1 4;
149 -
    add ptr %56 %54 %55;
150 -
    sload w32 %57 %56 0;
151 -
    br.ne w32 %57 40 @then35 @merge36;
152 -
  @guard#trap38
153 -
    ebreak;
154 -
    unreachable;
155 -
  @then39
120 +
  @merge26
121 +
    load w32 %56 %1 8;
122 +
    load ptr %57 %1 0;
123 +
    elem %58 %57 2 %56 4;
124 +
    sload w32 %59 %58 0;
125 +
    br.ne w32 %59 50 @then27 @merge28;
126 +
  @then27
156 127
    ret 9;
157 -
  @merge40
158 -
    load w32 %63 %1 8;
159 -
    br.ult w32 2 %63 @guard#pass43 @guard#trap44;
160 -
  @guard#pass41
161 -
    load ptr %59 %1 0;
162 -
    mul w64 %60 2 4;
163 -
    add ptr %61 %59 %60;
164 -
    sload w32 %62 %61 0;
165 -
    br.ne w32 %62 50 @then39 @merge40;
166 -
  @guard#trap42
167 -
    ebreak;
168 -
    unreachable;
169 -
  @guard#pass43
170 -
    load ptr %64 %1 0;
171 -
    mul w64 %65 2 4;
172 -
    add ptr %66 %64 %65;
173 -
    add ptr %67 %66 4;
174 -
    sub w32 %68 %63 2;
175 -
    sub w32 %69 %68 1;
176 -
    mul w32 %70 %69 4;
177 -
    jmp @delete45(0);
178 -
  @guard#trap44
128 +
  @merge28
129 +
    load w32 %60 %1 8;
130 +
    br.ult w32 2 %60 @guard#pass29 @guard#trap30;
131 +
  @guard#pass29
132 +
    load ptr %61 %1 0;
133 +
    mul w64 %62 2 4;
134 +
    add ptr %63 %61 %62;
135 +
    add ptr %64 %63 4;
136 +
    sub w32 %65 %60 2;
137 +
    sub w32 %66 %65 1;
138 +
    mul w32 %67 %66 4;
139 +
    jmp @delete31(0);
140 +
  @guard#trap30
179 141
    ebreak;
180 142
    unreachable;
181 -
  @delete45(w32 %71)
182 -
    br.ult w32 %71 %70 @delete46 @delete47;
183 -
  @delete46
184 -
    add ptr %72 %67 %71;
185 -
    load w8 %73 %72 0;
186 -
    add ptr %74 %66 %71;
187 -
    store w8 %73 %74 0;
188 -
    add w32 %75 %71 1;
189 -
    jmp @delete45(%75);
190 -
  @delete47
191 -
    sub w32 %76 %63 1;
192 -
    store w32 %76 %1 8;
193 -
    load w32 %78 %1 8;
194 -
    br.ne w32 %78 2 @then48 @merge49;
195 -
  @then48
143 +
  @delete31(w32 %68)
144 +
    br.ult w32 %68 %67 @delete32 @delete33;
145 +
  @delete32
146 +
    add ptr %69 %64 %68;
147 +
    load w8 %70 %69 0;
148 +
    add ptr %71 %63 %68;
149 +
    store w8 %70 %71 0;
150 +
    add w32 %72 %68 1;
151 +
    jmp @delete31(%72);
152 +
  @delete33
153 +
    sub w32 %73 %60 1;
154 +
    store w32 %73 %1 8;
155 +
    load w32 %75 %1 8;
156 +
    br.ne w32 %75 2 @then34 @merge35;
157 +
  @then34
196 158
    ret 10;
197 -
  @merge49
198 -
    load w32 %79 %1 8;
199 -
    br.ult w32 0 %79 @guard#pass52 @guard#trap53;
200 -
  @then50
159 +
  @merge35
160 +
    load w32 %76 %1 8;
161 +
    load ptr %77 %1 0;
162 +
    elem %78 %77 0 %76 4;
163 +
    sload w32 %79 %78 0;
164 +
    br.ne w32 %79 20 @then36 @merge37;
165 +
  @then36
201 166
    ret 11;
202 -
  @merge51
203 -
    load w32 %82 %1 8;
204 -
    br.ult w32 1 %82 @guard#pass56 @guard#trap57;
205 -
  @guard#pass52
206 -
    load ptr %80 %1 0;
207 -
    sload w32 %81 %80 0;
208 -
    br.ne w32 %81 20 @then50 @merge51;
209 -
  @guard#trap53
210 -
    ebreak;
211 -
    unreachable;
212 -
  @then54
167 +
  @merge37
168 +
    load w32 %80 %1 8;
169 +
    load ptr %81 %1 0;
170 +
    elem %82 %81 1 %80 4;
171 +
    sload w32 %83 %82 0;
172 +
    br.ne w32 %83 40 @then38 @merge39;
173 +
  @then38
213 174
    ret 12;
214 -
  @merge55
215 -
    load w32 %87 %1 12;
216 -
    br.ne w32 %87 5 @then58 @merge59;
217 -
  @guard#pass56
218 -
    load ptr %83 %1 0;
219 -
    mul w64 %84 1 4;
220 -
    add ptr %85 %83 %84;
221 -
    sload w32 %86 %85 0;
222 -
    br.ne w32 %86 40 @then54 @merge55;
223 -
  @guard#trap57
224 -
    ebreak;
225 -
    unreachable;
226 -
  @then58
175 +
  @merge39
176 +
    load w32 %84 %1 12;
177 +
    br.ne w32 %84 5 @then40 @merge41;
178 +
  @then40
227 179
    ret 13;
228 -
  @merge59
180 +
  @merge41
229 181
    ret 0;
230 182
}
test/tests/slice.index.ril +3 -9
1 1
fn w32 $sliceIndex(ptr %0, w32 %1) {
2 2
  @entry0
3 3
    load w32 %2 %0 8;
4 -
    br.ult w32 %1 %2 @guard#pass1 @guard#trap2;
5 -
  @guard#pass1
6 4
    load ptr %3 %0 0;
7 -
    mul w64 %4 %1 4;
8 -
    add ptr %5 %3 %4;
9 -
    sload w32 %6 %5 0;
10 -
    ret %6;
11 -
  @guard#trap2
12 -
    ebreak;
13 -
    unreachable;
5 +
    elem %4 %3 %1 %2 4;
6 +
    sload w32 %5 %4 0;
7 +
    ret %5;
14 8
}
test/tests/slice.mutable.ril +23 -65
1 1
fn w64 $mutSliceStore(ptr %0, w32 %1, w32 %2) {
2 2
  @entry0
3 3
    load w32 %3 %0 8;
4 -
    br.ult w32 %1 %3 @guard#pass1 @guard#trap2;
5 -
  @guard#pass1
6 4
    load ptr %4 %0 0;
7 -
    mul w64 %5 %1 4;
8 -
    add ptr %6 %4 %5;
9 -
    store w32 %2 %6 0;
5 +
    elem %5 %4 %1 %3 4;
6 +
    store w32 %2 %5 0;
10 7
    ret;
11 -
  @guard#trap2
12 -
    ebreak;
13 -
    unreachable;
14 8
}
15 9
16 10
fn w64 $mutSliceIncrement(ptr %0, w32 %1) {
17 11
  @entry0
18 12
    load w32 %2 %0 8;
19 -
    br.ult w32 %1 %2 @guard#pass1 @guard#trap2;
20 -
  @guard#pass1
21 13
    load ptr %3 %0 0;
22 -
    mul w64 %4 %1 4;
23 -
    add ptr %5 %3 %4;
24 -
    sload w32 %6 %5 0;
25 -
    add w32 %7 %6 1;
26 -
    load w32 %8 %0 8;
27 -
    br.ult w32 %1 %8 @guard#pass3 @guard#trap4;
28 -
  @guard#trap2
29 -
    ebreak;
30 -
    unreachable;
31 -
  @guard#pass3
32 -
    load ptr %9 %0 0;
33 -
    mul w64 %10 %1 4;
34 -
    add ptr %11 %9 %10;
35 -
    store w32 %7 %11 0;
14 +
    elem %4 %3 %1 %2 4;
15 +
    sload w32 %5 %4 0;
16 +
    add w32 %6 %5 1;
17 +
    load w32 %7 %0 8;
18 +
    load ptr %8 %0 0;
19 +
    elem %9 %8 %1 %7 4;
20 +
    store w32 %6 %9 0;
36 21
    ret;
37 -
  @guard#trap4
38 -
    ebreak;
39 -
    unreachable;
40 22
}
41 23
42 24
fn w64 $mutSliceSwap(ptr %0, w32 %1, w32 %2) {
43 25
  @entry0
44 26
    load w32 %3 %0 8;
45 -
    br.ult w32 %1 %3 @guard#pass1 @guard#trap2;
46 -
  @guard#pass1
47 27
    load ptr %4 %0 0;
48 -
    mul w64 %5 %1 4;
49 -
    add ptr %6 %4 %5;
50 -
    sload w32 %7 %6 0;
51 -
    load w32 %8 %0 8;
52 -
    br.ult w32 %2 %8 @guard#pass3 @guard#trap4;
53 -
  @guard#trap2
54 -
    ebreak;
55 -
    unreachable;
56 -
  @guard#pass3
57 -
    load ptr %9 %0 0;
58 -
    mul w64 %10 %2 4;
59 -
    add ptr %11 %9 %10;
60 -
    sload w32 %12 %11 0;
61 -
    load w32 %13 %0 8;
62 -
    br.ult w32 %1 %13 @guard#pass5 @guard#trap6;
63 -
  @guard#trap4
64 -
    ebreak;
65 -
    unreachable;
66 -
  @guard#pass5
67 -
    load ptr %14 %0 0;
68 -
    mul w64 %15 %1 4;
69 -
    add ptr %16 %14 %15;
70 -
    store w32 %12 %16 0;
71 -
    load w32 %17 %0 8;
72 -
    br.ult w32 %2 %17 @guard#pass7 @guard#trap8;
73 -
  @guard#trap6
74 -
    ebreak;
75 -
    unreachable;
76 -
  @guard#pass7
77 -
    load ptr %18 %0 0;
78 -
    mul w64 %19 %2 4;
79 -
    add ptr %20 %18 %19;
80 -
    store w32 %7 %20 0;
28 +
    elem %5 %4 %1 %3 4;
29 +
    sload w32 %6 %5 0;
30 +
    load w32 %7 %0 8;
31 +
    load ptr %8 %0 0;
32 +
    elem %9 %8 %2 %7 4;
33 +
    sload w32 %10 %9 0;
34 +
    load w32 %11 %0 8;
35 +
    load ptr %12 %0 0;
36 +
    elem %13 %12 %1 %11 4;
37 +
    store w32 %10 %13 0;
38 +
    load w32 %14 %0 8;
39 +
    load ptr %15 %0 0;
40 +
    elem %16 %15 %2 %14 4;
41 +
    store w32 %6 %16 0;
81 42
    ret;
82 -
  @guard#trap8
83 -
    ebreak;
84 -
    unreachable;
85 43
}
test/tests/trait.supertrait.ril +13 -33
22 22
  @while1(w32 %3, ptr %4, ptr %6)
23 23
    load w32 %5 %4 8;
24 24
    br.ult w32 %3 %5 @and#then4 @and#else5;
25 25
  @body2
26 26
    sload w32 %11 %6 32;
27 -
    br.ult w32 %11 32 @guard#pass7 @guard#trap8;
27 +
    elem %12 %6 %11 32 1;
28 +
    load w8 %13 %12 0;
29 +
    load w32 %16 %4 8;
30 +
    load ptr %17 %4 0;
31 +
    elem %18 %17 %3 %16 1;
32 +
    store w8 %13 %18 0;
33 +
    sload w32 %19 %6 32;
34 +
    add w32 %20 %19 1;
35 +
    store w32 %20 %6 32;
36 +
    add w32 %21 %3 1;
37 +
    jmp @while1(%21, %4, %6);
28 38
  @merge3
29 39
    ret %3;
30 40
  @and#then4
31 41
    sload w32 %7 %6 32;
32 42
    sload w32 %8 %6 36;
34 44
    jmp @and#end6(%9);
35 45
  @and#else5
36 46
    jmp @and#end6(0);
37 47
  @and#end6(w8 %2)
38 48
    br.ne w32 %2 0 @body2 @merge3;
39 -
  @guard#pass7
40 -
    add ptr %12 %6 %11;
41 -
    load w8 %13 %12 0;
42 -
    load w32 %16 %4 8;
43 -
    br.ult w32 %3 %16 @guard#pass9 @guard#trap10;
44 -
  @guard#trap8
45 -
    ebreak;
46 -
    unreachable;
47 -
  @guard#pass9
48 -
    load ptr %17 %4 0;
49 -
    add ptr %18 %17 %3;
50 -
    store w8 %13 %18 0;
51 -
    sload w32 %19 %6 32;
52 -
    add w32 %20 %19 1;
53 -
    store w32 %20 %6 32;
54 -
    add w32 %21 %3 1;
55 -
    jmp @while1(%21, %4, %6);
56 -
  @guard#trap10
57 -
    ebreak;
58 -
    unreachable;
59 49
}
60 50
61 51
fn w32 $"Socket::write"(ptr %0, ptr %1) {
62 52
  @entry0
63 53
    jmp @while1(0, %1, %0);
73 63
  @then4
74 64
    sload w32 %7 %5 72;
75 65
    ret %7;
76 66
  @merge5
77 67
    load w32 %8 %3 8;
78 -
    br.ult w32 %2 %8 @guard#pass6 @guard#trap7;
79 -
  @guard#pass6
80 68
    load ptr %9 %3 0;
81 -
    add ptr %10 %9 %2;
69 +
    elem %10 %9 %2 %8 1;
82 70
    load w8 %11 %10 0;
83 71
    sload w32 %12 %5 72;
84 72
    add ptr %13 %5 40;
85 -
    br.ult w32 %12 32 @guard#pass8 @guard#trap9;
86 -
  @guard#trap7
87 -
    ebreak;
88 -
    unreachable;
89 -
  @guard#pass8
90 -
    add ptr %14 %13 %12;
73 +
    elem %14 %13 %12 32 1;
91 74
    store w8 %11 %14 0;
92 75
    sload w32 %15 %5 72;
93 76
    add w32 %16 %15 1;
94 77
    store w32 %16 %5 72;
95 78
    add w32 %17 %2 1;
96 79
    jmp @while1(%17, %3, %5);
97 -
  @guard#trap9
98 -
    ebreak;
99 -
    unreachable;
100 80
}
101 81
102 82
fn w32 $"Socket::flush"(ptr %0) {
103 83
  @entry0
104 84
    sload w32 %1 %0 72;