lower: use Elem for all user-facing memory access patterns

0202a0380dcb379a73befc5729f8e41733a8ebda6c23435318a0d2e51d50ce29
Use the bounds-checked Elem instruction for for-loop element access
and slice delete, replacing the previous emitElem (unchecked pointer
arithmetic). This makes all user-facing array/slice access verifiable
without CFG analysis.

- for-loop body: emit Elem instead of emitElem for element binding
- slice delete: replace separate emitTrapUnlessCmp + emitElem with Elem
- verifier: Elem produces Ptr(stride) so subsequent load/store at
  offset 0 with size <= stride is bounds-checked

The remaining emitElem call sites are internal lowerer operations
(array fill, byte copy, slice append store, slice re-slicing,
constant-index array access) where bounds are guaranteed by
construction.
Alexis Sellier committed ago 1 parent 6a612093
lib/std/lang/il/verify.rad +3 -2
230 230
                setReg(ctx.regs, d, regTypeFromIl(retTy));
231 231
            }
232 232
        }
233 233
        case super::Instr::Ecall { dst, .. } =>
234 234
            setReg(ctx.regs, dst, RegType::Word(super::Type::W64)),
235 -
        case super::Instr::Elem { dst, base, .. } => {
235 +
        case super::Instr::Elem { dst, base, stride, .. } => {
236 236
            checkPtrBase(ctx, base, "elem base");
237 -
            setReg(ctx.regs, dst, RegType::Ptr(UNKNOWN_BOUND));
237 +
            // After Elem, the pointer is valid for `stride` bytes.
238 +
            setReg(ctx.regs, dst, RegType::Ptr(stride));
238 239
        }
239 240
        case super::Instr::Ret { .. },
240 241
             super::Instr::Jmp { .. },
241 242
             super::Instr::Br { .. },
242 243
             super::Instr::Switch { .. },
lib/std/lang/lower.rad +16 -8
5345 5345
    }
5346 5346
    // Switch to loop body.
5347 5347
    try switchToAndSeal(self, bodyBlock);
5348 5348
5349 5349
    // Emit element binding, only for collections.
5350 -
    // Reads the element at the current index.
5351 -
    if let case ForIter::Collection { valVar, idxVar, dataReg, elemType, .. } = *iter {
5350 +
    // Reads the element at the current index using a bounds-checked `elem`
5351 +
    // instruction so the verifier can validate the access locally.
5352 +
    if let case ForIter::Collection { valVar, idxVar, dataReg, lengthVal, elemType } = *iter {
5352 5353
        if let v = valVar {
5353 5354
            let curIdx = try useVar(self, idxVar);
5354 -
            let elemReg = emitElem(self, resolver::getTypeLayout(*elemType).size, dataReg, curIdx);
5355 +
            let elemLayout = resolver::getTypeLayout(*elemType);
5356 +
            let elemReg = nextReg(self);
5357 +
5358 +
            emit(self, il::Instr::Elem {
5359 +
                dst: elemReg,
5360 +
                base: dataReg,
5361 +
                idx: curIdx,
5362 +
                len: lengthVal,
5363 +
                stride: elemLayout.size,
5364 +
            });
5355 5365
            let val = emitRead(self, elemReg, 0, *elemType);
5356 5366
5357 5367
            defVar(self, v, val);
5358 5368
        }
5359 5369
    }
6367 6377
    let sliceReg = emitValToReg(self, sliceVal);
6368 6378
6369 6379
    // Lower the index argument.
6370 6380
    let indexVal = try lowerExpr(self, call.args[0]);
6371 6381
6372 -
    // Load len and bounds-check: index must be smaller than length.
6382 +
    // Load len and data pointer, then bounds-check via Elem.
6373 6383
    let lenVal = loadSliceLen(self, sliceReg);
6374 -
    try emitTrapUnlessCmp(self, il::CmpOp::Ult, il::Type::W32, indexVal, lenVal);
6375 -
6376 -
    // Compute the destination and source for the shift.
6377 6384
    let ptrReg = loadSlicePtr(self, sliceReg);
6378 -
    let dst = emitElem(self, stride, ptrReg, indexVal);
6385 +
    let dst = nextReg(self);
6386 +
    emit(self, il::Instr::Elem { dst, base: ptrReg, idx: indexVal, len: lenVal, stride });
6379 6387
6380 6388
    // `src = dst + stride`.
6381 6389
    let src = emitPtrOffset(self, dst, stride as i32);
6382 6390
6383 6391
    // Move `(len - index - 1) * stride`.
test/tests/average.ril +9 -10
1 1
fn w32 $average(ptr %0) {
2 2
  @entry0
3 3
    load w32 %1 %0 8;
4 4
    load ptr %2 %0 0;
5 5
    jmp @loop1(0, 0);
6 -
  @loop1(w32 %3, w32 %7)
6 +
  @loop1(w32 %3, w32 %6)
7 7
    br.slt w32 %3 %1 @body2 @merge3;
8 8
  @body2
9 -
    mul w64 %4 %3 4;
10 -
    add ptr %5 %2 %4;
11 -
    load w32 %6 %5 0;
12 -
    add w32 %8 %7 %6;
13 -
    add w32 %9 %3 1;
14 -
    jmp @loop1(%9, %8);
9 +
    elem %4 %2 %3 %1 4;
10 +
    load w32 %5 %4 0;
11 +
    add w32 %7 %6 %5;
12 +
    add w32 %8 %3 1;
13 +
    jmp @loop1(%8, %7);
15 14
  @merge3
16 -
    load w32 %11 %0 8;
17 -
    udiv w32 %12 %7 %11;
18 -
    ret %12;
15 +
    load w32 %10 %0 8;
16 +
    udiv w32 %11 %6 %10;
17 +
    ret %11;
19 18
}
test/tests/const.array.ril +8 -9
7 7
8 8
fn w32 $main() {
9 9
  @entry0
10 10
    copy %0 $NUMBERS;
11 11
    jmp @loop1(0, 0);
12 -
  @loop1(w32 %1, w32 %5)
12 +
  @loop1(w32 %1, w32 %4)
13 13
    br.slt w32 %1 4 @body2 @merge3;
14 14
  @body2
15 -
    mul w64 %2 %1 4;
16 -
    add ptr %3 %0 %2;
17 -
    sload w32 %4 %3 0;
18 -
    add w32 %6 %5 %4;
19 -
    add w32 %7 %1 1;
20 -
    jmp @loop1(%7, %6);
15 +
    elem %2 %0 %1 4 4;
16 +
    sload w32 %3 %2 0;
17 +
    add w32 %5 %4 %3;
18 +
    add w32 %6 %1 1;
19 +
    jmp @loop1(%6, %5);
21 20
  @merge3
22 -
    sub w32 %8 %5 10;
23 -
    ret %8;
21 +
    sub w32 %7 %4 10;
22 +
    ret %7;
24 23
}
test/tests/loop.for.array.ril +8 -9
1 1
fn w32 $forArrayIndexed(ptr %0) {
2 2
  @entry0
3 3
    jmp @loop1(0, 0);
4 -
  @loop1(w32 %1, w32 %5)
4 +
  @loop1(w32 %1, w32 %4)
5 5
    br.slt w32 %1 3 @body2 @merge3;
6 6
  @body2
7 -
    mul w64 %2 %1 4;
8 -
    add ptr %3 %0 %2;
9 -
    sload w32 %4 %3 0;
10 -
    add w32 %6 %4 %1;
11 -
    add w32 %7 %5 %6;
12 -
    add w32 %8 %1 1;
13 -
    jmp @loop1(%8, %7);
7 +
    elem %2 %0 %1 3 4;
8 +
    sload w32 %3 %2 0;
9 +
    add w32 %5 %3 %1;
10 +
    add w32 %6 %4 %5;
11 +
    add w32 %7 %1 1;
12 +
    jmp @loop1(%7, %6);
14 13
  @merge3
15 -
    ret %5;
14 +
    ret %4;
16 15
}
test/tests/loop.for.continue.ril +11 -12
18 18
}
19 19
20 20
fn w32 $forContinueArray(ptr %0) {
21 21
  @entry0
22 22
    jmp @loop1(0, 0);
23 -
  @loop1(w32 %1, w32 %5)
23 +
  @loop1(w32 %1, w32 %4)
24 24
    br.slt w32 %1 4 @body2 @merge3;
25 25
  @body2
26 -
    mul w64 %2 %1 4;
27 -
    add ptr %3 %0 %2;
28 -
    sload w32 %4 %3 0;
29 -
    br.eq w32 %4 0 @then4 @merge5;
26 +
    elem %2 %0 %1 4 4;
27 +
    sload w32 %3 %2 0;
28 +
    br.eq w32 %3 0 @then4 @merge5;
30 29
  @merge3
31 -
    ret %5;
30 +
    ret %4;
32 31
  @then4
33 -
    jmp @step6(%5);
32 +
    jmp @step6(%4);
34 33
  @merge5
35 -
    add w32 %6 %5 %4;
36 -
    jmp @step6(%6);
37 -
  @step6(w32 %9)
38 -
    add w32 %8 %1 1;
39 -
    jmp @loop1(%8, %9);
34 +
    add w32 %5 %4 %3;
35 +
    jmp @step6(%5);
36 +
  @step6(w32 %8)
37 +
    add w32 %7 %1 1;
38 +
    jmp @loop1(%7, %8);
40 39
}
test/tests/loop.for.slice.ril +8 -9
1 1
fn w32 $forSliceIndexed(ptr %0) {
2 2
  @entry0
3 3
    load w32 %1 %0 8;
4 4
    load ptr %2 %0 0;
5 5
    jmp @loop1(0, 0);
6 -
  @loop1(w32 %3, w32 %7)
6 +
  @loop1(w32 %3, w32 %6)
7 7
    br.slt w32 %3 %1 @body2 @merge3;
8 8
  @body2
9 -
    mul w64 %4 %3 4;
10 -
    add ptr %5 %2 %4;
11 -
    sload w32 %6 %5 0;
12 -
    add w32 %8 %6 %3;
13 -
    add w32 %9 %7 %8;
14 -
    add w32 %10 %3 1;
15 -
    jmp @loop1(%10, %9);
9 +
    elem %4 %2 %3 %1 4;
10 +
    sload w32 %5 %4 0;
11 +
    add w32 %7 %5 %3;
12 +
    add w32 %8 %6 %7;
13 +
    add w32 %9 %3 1;
14 +
    jmp @loop1(%9, %8);
16 15
  @merge3
17 -
    ret %7;
16 +
    ret %6;
18 17
}
test/tests/slice.append.ril +241 -242
363 363
    ret 15;
364 364
  @merge60
365 365
    load w32 %194 %8 8;
366 366
    load ptr %195 %8 0;
367 367
    jmp @loop61(0, 0);
368 -
  @loop61(w32 %196, w32 %200)
368 +
  @loop61(w32 %196, w32 %199)
369 369
    br.slt w32 %196 %194 @body62 @merge63;
370 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);
371 +
    elem %197 %195 %196 %194 4;
372 +
    sload w32 %198 %197 0;
373 +
    add w32 %200 %199 %198;
374 +
    add w32 %201 %196 1;
375 +
    jmp @loop61(%201, %200);
377 376
  @merge63
378 -
    br.ne w32 %200 150 @then64 @merge65;
377 +
    br.ne w32 %199 150 @then64 @merge65;
379 378
  @then64
380 379
    ret 16;
381 380
  @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;
381 +
    call ptr %215 $arenaAlloc(%3, 2, 1);
382 +
    reserve %216 16 8;
383 +
    store ptr %215 %216 0;
384 +
    store w32 0 %216 8;
385 +
    store w32 2 %216 12;
386 +
    load w32 %220 %216 8;
387 +
    load w32 %221 %216 12;
388 +
    br.ult w32 %220 %221 @append.store66 @append.grow67;
390 389
  @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;
390 +
    load ptr %235 %216 0;
391 +
    add ptr %236 %235 %220;
392 +
    store w8 171 %236 0;
393 +
    add w32 %237 %220 1;
394 +
    store w32 %237 %216 8;
395 +
    load w32 %242 %216 8;
396 +
    load w32 %243 %216 12;
397 +
    br.ult w32 %242 %243 @append.store71 @append.grow72;
399 398
  @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;
399 +
    shl w32 %222 %221 1;
400 +
    or w32 %223 %222 1;
401 +
    load ptr %224 %5 0;
402 +
    load ptr %225 %5 8;
403 +
    mul w32 %226 %223 1;
404 +
    call ptr %227 %224(%225, %226, 1);
405 +
    load ptr %228 %216 0;
406 +
    mul w32 %229 %220 1;
408 407
    jmp @append68(0);
409 -
  @append68(w32 %231)
410 -
    br.ult w32 %231 %230 @append69 @append70;
408 +
  @append68(w32 %230)
409 +
    br.ult w32 %230 %229 @append69 @append70;
411 410
  @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);
411 +
    add ptr %231 %228 %230;
412 +
    load w8 %232 %231 0;
413 +
    add ptr %233 %227 %230;
414 +
    store w8 %232 %233 0;
415 +
    add w32 %234 %230 1;
416 +
    jmp @append68(%234);
418 417
  @append70
419 -
    store ptr %228 %217 0;
420 -
    store w32 %224 %217 12;
418 +
    store ptr %227 %216 0;
419 +
    store w32 %223 %216 12;
421 420
    jmp @append.store66;
422 421
  @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;
422 +
    load ptr %257 %216 0;
423 +
    add ptr %258 %257 %242;
424 +
    store w8 205 %258 0;
425 +
    add w32 %259 %242 1;
426 +
    store w32 %259 %216 8;
427 +
    load w32 %262 %216 8;
428 +
    br.ne w32 %262 2 @then76 @merge77;
430 429
  @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;
430 +
    shl w32 %244 %243 1;
431 +
    or w32 %245 %244 1;
432 +
    load ptr %246 %5 0;
433 +
    load ptr %247 %5 8;
434 +
    mul w32 %248 %245 1;
435 +
    call ptr %249 %246(%247, %248, 1);
436 +
    load ptr %250 %216 0;
437 +
    mul w32 %251 %242 1;
439 438
    jmp @append73(0);
440 -
  @append73(w32 %253)
441 -
    br.ult w32 %253 %252 @append74 @append75;
439 +
  @append73(w32 %252)
440 +
    br.ult w32 %252 %251 @append74 @append75;
442 441
  @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);
442 +
    add ptr %253 %250 %252;
443 +
    load w8 %254 %253 0;
444 +
    add ptr %255 %249 %252;
445 +
    store w8 %254 %255 0;
446 +
    add w32 %256 %252 1;
447 +
    jmp @append73(%256);
449 448
  @append75
450 -
    store ptr %250 %217 0;
451 -
    store w32 %246 %217 12;
449 +
    store ptr %249 %216 0;
450 +
    store w32 %245 %216 12;
452 451
    jmp @append.store71;
453 452
  @then76
454 453
    ret 17;
455 454
  @merge77
456 -
    load w32 %264 %217 8;
457 -
    load ptr %265 %217 0;
458 -
    elem %266 %265 0 %264 1;
459 -
    load w8 %267 %266 0;
460 -
    br.ne w8 %267 171 @then78 @merge79;
455 +
    load w32 %263 %216 8;
456 +
    load ptr %264 %216 0;
457 +
    elem %265 %264 0 %263 1;
458 +
    load w8 %266 %265 0;
459 +
    br.ne w8 %266 171 @then78 @merge79;
461 460
  @then78
462 461
    ret 18;
463 462
  @merge79
464 -
    load w32 %268 %217 8;
465 -
    load ptr %269 %217 0;
466 -
    elem %270 %269 1 %268 1;
467 -
    load w8 %271 %270 0;
468 -
    br.ne w8 %271 205 @then80 @merge81;
463 +
    load w32 %267 %216 8;
464 +
    load ptr %268 %216 0;
465 +
    elem %269 %268 1 %267 1;
466 +
    load w8 %270 %269 0;
467 +
    br.ne w8 %270 205 @then80 @merge81;
469 468
  @then80
470 469
    ret 19;
471 470
  @merge81
472 -
    load w32 %274 %217 8;
473 -
    load w32 %275 %217 12;
474 -
    br.ult w32 %274 %275 @append.store82 @append.grow83;
471 +
    load w32 %273 %216 8;
472 +
    load w32 %274 %216 12;
473 +
    br.ult w32 %273 %274 @append.store82 @append.grow83;
475 474
  @append.store82
476 -
    load ptr %289 %217 0;
477 -
    add ptr %290 %289 %274;
478 -
    store w8 239 %290 0;
479 -
    add w32 %291 %274 1;
480 -
    store w32 %291 %217 8;
481 -
    load w32 %294 %217 8;
482 -
    br.ne w32 %294 3 @then87 @merge88;
475 +
    load ptr %288 %216 0;
476 +
    add ptr %289 %288 %273;
477 +
    store w8 239 %289 0;
478 +
    add w32 %290 %273 1;
479 +
    store w32 %290 %216 8;
480 +
    load w32 %293 %216 8;
481 +
    br.ne w32 %293 3 @then87 @merge88;
483 482
  @append.grow83
484 -
    shl w32 %276 %275 1;
485 -
    or w32 %277 %276 1;
486 -
    load ptr %278 %5 0;
487 -
    load ptr %279 %5 8;
488 -
    mul w32 %280 %277 1;
489 -
    call ptr %281 %278(%279, %280, 1);
490 -
    load ptr %282 %217 0;
491 -
    mul w32 %283 %274 1;
483 +
    shl w32 %275 %274 1;
484 +
    or w32 %276 %275 1;
485 +
    load ptr %277 %5 0;
486 +
    load ptr %278 %5 8;
487 +
    mul w32 %279 %276 1;
488 +
    call ptr %280 %277(%278, %279, 1);
489 +
    load ptr %281 %216 0;
490 +
    mul w32 %282 %273 1;
492 491
    jmp @append84(0);
493 -
  @append84(w32 %284)
494 -
    br.ult w32 %284 %283 @append85 @append86;
492 +
  @append84(w32 %283)
493 +
    br.ult w32 %283 %282 @append85 @append86;
495 494
  @append85
496 -
    add ptr %285 %282 %284;
497 -
    load w8 %286 %285 0;
498 -
    add ptr %287 %281 %284;
499 -
    store w8 %286 %287 0;
500 -
    add w32 %288 %284 1;
501 -
    jmp @append84(%288);
495 +
    add ptr %284 %281 %283;
496 +
    load w8 %285 %284 0;
497 +
    add ptr %286 %280 %283;
498 +
    store w8 %285 %286 0;
499 +
    add w32 %287 %283 1;
500 +
    jmp @append84(%287);
502 501
  @append86
503 -
    store ptr %281 %217 0;
504 -
    store w32 %277 %217 12;
502 +
    store ptr %280 %216 0;
503 +
    store w32 %276 %216 12;
505 504
    jmp @append.store82;
506 505
  @then87
507 506
    ret 20;
508 507
  @merge88
509 -
    load w32 %295 %217 12;
510 -
    br.ne w32 %295 5 @then89 @merge90;
508 +
    load w32 %294 %216 12;
509 +
    br.ne w32 %294 5 @then89 @merge90;
511 510
  @then89
512 511
    ret 21;
513 512
  @merge90
514 -
    load w32 %296 %217 8;
515 -
    load ptr %297 %217 0;
516 -
    elem %298 %297 2 %296 1;
517 -
    load w8 %299 %298 0;
518 -
    br.ne w8 %299 239 @then91 @merge92;
513 +
    load w32 %295 %216 8;
514 +
    load ptr %296 %216 0;
515 +
    elem %297 %296 2 %295 1;
516 +
    load w8 %298 %297 0;
517 +
    br.ne w8 %298 239 @then91 @merge92;
519 518
  @then91
520 519
    ret 22;
521 520
  @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;
521 +
    load w32 %299 %216 8;
522 +
    load ptr %300 %216 0;
523 +
    elem %301 %300 0 %299 1;
524 +
    load w8 %302 %301 0;
525 +
    br.ne w8 %302 171 @then93 @merge94;
527 526
  @then93
528 527
    ret 23;
529 528
  @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;
529 +
    mul w32 %309 4 2;
530 +
    call ptr %310 $arenaAlloc(%3, %309, 4);
531 +
    reserve %311 16 8;
532 +
    store ptr %310 %311 0;
533 +
    store w32 0 %311 8;
534 +
    store w32 2 %311 12;
535 +
    load w32 %314 %311 8;
536 +
    load w32 %315 %311 12;
537 +
    br.ult w32 %314 %315 @append.store95 @append.grow96;
539 538
  @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;
539 +
    load ptr %329 %311 0;
540 +
    mul w64 %330 %314 4;
541 +
    add ptr %331 %329 %330;
542 +
    store w32 42 %331 0;
543 +
    add w32 %332 %314 1;
544 +
    store w32 %332 %311 8;
545 +
    blit %311 %311 16;
546 +
    load w32 %335 %311 8;
547 +
    br.eq w32 %335 1 @assert.ok101 @assert.fail100;
549 548
  @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;
549 +
    shl w32 %316 %315 1;
550 +
    or w32 %317 %316 1;
551 +
    load ptr %318 %5 0;
552 +
    load ptr %319 %5 8;
553 +
    mul w32 %320 %317 4;
554 +
    call ptr %321 %318(%319, %320, 4);
555 +
    load ptr %322 %311 0;
556 +
    mul w32 %323 %314 4;
558 557
    jmp @append97(0);
559 -
  @append97(w32 %325)
560 -
    br.ult w32 %325 %324 @append98 @append99;
558 +
  @append97(w32 %324)
559 +
    br.ult w32 %324 %323 @append98 @append99;
561 560
  @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);
561 +
    add ptr %325 %322 %324;
562 +
    load w8 %326 %325 0;
563 +
    add ptr %327 %321 %324;
564 +
    store w8 %326 %327 0;
565 +
    add w32 %328 %324 1;
566 +
    jmp @append97(%328);
568 567
  @append99
569 -
    store ptr %322 %312 0;
570 -
    store w32 %318 %312 12;
568 +
    store ptr %321 %311 0;
569 +
    store w32 %317 %311 12;
571 570
    jmp @append.store95;
572 571
  @assert.fail100
573 572
    unreachable;
574 573
  @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;
574 +
    load w32 %336 %311 8;
575 +
    load ptr %337 %311 0;
576 +
    elem %338 %337 0 %336 4;
577 +
    sload w32 %339 %338 0;
578 +
    br.eq w32 %339 42 @assert.ok103 @assert.fail102;
580 579
  @assert.fail102
581 580
    unreachable;
582 581
  @assert.ok103
583 -
    load w32 %343 %312 8;
584 -
    load w32 %344 %312 12;
585 -
    br.ult w32 %343 %344 @append.store104 @append.grow105;
582 +
    load w32 %342 %311 8;
583 +
    load w32 %343 %311 12;
584 +
    br.ult w32 %342 %343 @append.store104 @append.grow105;
586 585
  @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;
586 +
    load ptr %357 %311 0;
587 +
    mul w64 %358 %342 4;
588 +
    add ptr %359 %357 %358;
589 +
    store w32 43 %359 0;
590 +
    add w32 %360 %342 1;
591 +
    store w32 %360 %311 8;
592 +
    blit %311 %311 16;
593 +
    load w32 %363 %311 8;
594 +
    br.eq w32 %363 2 @assert.ok110 @assert.fail109;
596 595
  @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;
596 +
    shl w32 %344 %343 1;
597 +
    or w32 %345 %344 1;
598 +
    load ptr %346 %5 0;
599 +
    load ptr %347 %5 8;
600 +
    mul w32 %348 %345 4;
601 +
    call ptr %349 %346(%347, %348, 4);
602 +
    load ptr %350 %311 0;
603 +
    mul w32 %351 %342 4;
605 604
    jmp @append106(0);
606 -
  @append106(w32 %353)
607 -
    br.ult w32 %353 %352 @append107 @append108;
605 +
  @append106(w32 %352)
606 +
    br.ult w32 %352 %351 @append107 @append108;
608 607
  @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);
608 +
    add ptr %353 %350 %352;
609 +
    load w8 %354 %353 0;
610 +
    add ptr %355 %349 %352;
611 +
    store w8 %354 %355 0;
612 +
    add w32 %356 %352 1;
613 +
    jmp @append106(%356);
615 614
  @append108
616 -
    store ptr %350 %312 0;
617 -
    store w32 %346 %312 12;
615 +
    store ptr %349 %311 0;
616 +
    store w32 %345 %311 12;
618 617
    jmp @append.store104;
619 618
  @assert.fail109
620 619
    unreachable;
621 620
  @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;
621 +
    load w32 %364 %311 8;
622 +
    load ptr %365 %311 0;
623 +
    elem %366 %365 0 %364 4;
624 +
    load w32 %369 %311 8;
625 +
    load w32 %370 %311 12;
626 +
    br.ult w32 %369 %370 @append.store111 @append.grow112;
628 627
  @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;
628 +
    load ptr %384 %311 0;
629 +
    mul w64 %385 %369 4;
630 +
    add ptr %386 %384 %385;
631 +
    store w32 44 %386 0;
632 +
    add w32 %387 %369 1;
633 +
    store w32 %387 %311 8;
634 +
    blit %311 %311 16;
635 +
    load w32 %390 %311 8;
636 +
    br.eq w32 %390 3 @assert.ok117 @assert.fail116;
638 637
  @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;
638 +
    shl w32 %371 %370 1;
639 +
    or w32 %372 %371 1;
640 +
    load ptr %373 %5 0;
641 +
    load ptr %374 %5 8;
642 +
    mul w32 %375 %372 4;
643 +
    call ptr %376 %373(%374, %375, 4);
644 +
    load ptr %377 %311 0;
645 +
    mul w32 %378 %369 4;
647 646
    jmp @append113(0);
648 -
  @append113(w32 %380)
649 -
    br.ult w32 %380 %379 @append114 @append115;
647 +
  @append113(w32 %379)
648 +
    br.ult w32 %379 %378 @append114 @append115;
650 649
  @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);
650 +
    add ptr %380 %377 %379;
651 +
    load w8 %381 %380 0;
652 +
    add ptr %382 %376 %379;
653 +
    store w8 %381 %382 0;
654 +
    add w32 %383 %379 1;
655 +
    jmp @append113(%383);
657 656
  @append115
658 -
    store ptr %377 %312 0;
659 -
    store w32 %373 %312 12;
657 +
    store ptr %376 %311 0;
658 +
    store w32 %372 %311 12;
660 659
    jmp @append.store111;
661 660
  @assert.fail116
662 661
    unreachable;
663 662
  @assert.ok117
664 -
    load w32 %392 %312 12;
665 -
    br.eq w32 %392 5 @assert.ok119 @assert.fail118;
663 +
    load w32 %391 %311 12;
664 +
    br.eq w32 %391 5 @assert.ok119 @assert.fail118;
666 665
  @assert.fail118
667 666
    unreachable;
668 667
  @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;
668 +
    load w32 %392 %311 8;
669 +
    load ptr %393 %311 0;
670 +
    elem %394 %393 0 %392 4;
671 +
    br.ne ptr %366 %394 @assert.ok121 @assert.fail120;
673 672
  @assert.fail120
674 673
    unreachable;
675 674
  @assert.ok121
676 -
    load w32 %398 %312 8;
677 -
    load ptr %399 %312 0;
678 -
    elem %400 %399 0 %398 4;
679 -
    sload w32 %401 %400 0;
680 -
    br.eq w32 %401 42 @assert.ok123 @assert.fail122;
675 +
    load w32 %397 %311 8;
676 +
    load ptr %398 %311 0;
677 +
    elem %399 %398 0 %397 4;
678 +
    sload w32 %400 %399 0;
679 +
    br.eq w32 %400 42 @assert.ok123 @assert.fail122;
681 680
  @assert.fail122
682 681
    unreachable;
683 682
  @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;
683 +
    load w32 %401 %311 8;
684 +
    load ptr %402 %311 0;
685 +
    elem %403 %402 1 %401 4;
686 +
    sload w32 %404 %403 0;
687 +
    br.eq w32 %404 43 @assert.ok125 @assert.fail124;
689 688
  @assert.fail124
690 689
    unreachable;
691 690
  @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;
691 +
    load w32 %405 %311 8;
692 +
    load ptr %406 %311 0;
693 +
    elem %407 %406 2 %405 4;
694 +
    sload w32 %408 %407 0;
695 +
    br.eq w32 %408 44 @assert.ok127 @assert.fail126;
697 696
  @assert.fail126
698 697
    unreachable;
699 698
  @assert.ok127
700 699
    ret 0;
701 700
}
test/tests/slice.delete.ril +109 -125
9 9
    reserve %1 16 8;
10 10
    store ptr %0 %1 0;
11 11
    store w32 5 %1 8;
12 12
    store w32 5 %1 12;
13 13
    load w32 %2 %1 8;
14 -
    br.ult w32 2 %2 @guard#pass1 @guard#trap2;
15 -
  @guard#pass1
16 14
    load ptr %3 %1 0;
17 -
    mul w64 %4 2 4;
18 -
    add ptr %5 %3 %4;
19 -
    add ptr %6 %5 4;
20 -
    sub w32 %7 %2 2;
21 -
    sub w32 %8 %7 1;
22 -
    mul w32 %9 %8 4;
23 -
    jmp @delete3(0);
24 -
  @guard#trap2
25 -
    ebreak;
26 -
    unreachable;
27 -
  @delete3(w32 %10)
28 -
    br.ult w32 %10 %9 @delete4 @delete5;
29 -
  @delete4
30 -
    add ptr %11 %6 %10;
31 -
    load w8 %12 %11 0;
32 -
    add ptr %13 %5 %10;
33 -
    store w8 %12 %13 0;
34 -
    add w32 %14 %10 1;
35 -
    jmp @delete3(%14);
36 -
  @delete5
37 -
    sub w32 %15 %2 1;
38 -
    store w32 %15 %1 8;
15 +
    elem %4 %3 2 %2 4;
16 +
    add ptr %5 %4 4;
17 +
    sub w32 %6 %2 2;
18 +
    sub w32 %7 %6 1;
19 +
    mul w32 %8 %7 4;
20 +
    jmp @delete1(0);
21 +
  @delete1(w32 %9)
22 +
    br.ult w32 %9 %8 @delete2 @delete3;
23 +
  @delete2
24 +
    add ptr %10 %5 %9;
25 +
    load w8 %11 %10 0;
26 +
    add ptr %12 %4 %9;
27 +
    store w8 %11 %12 0;
28 +
    add w32 %13 %9 1;
29 +
    jmp @delete1(%13);
30 +
  @delete3
31 +
    sub w32 %14 %2 1;
32 +
    store w32 %14 %1 8;
33 +
    load w32 %16 %1 8;
34 +
    br.ne w32 %16 4 @then4 @merge5;
35 +
  @then4
36 +
    ret 1;
37 +
  @merge5
39 38
    load w32 %17 %1 8;
40 -
    br.ne w32 %17 4 @then6 @merge7;
39 +
    load ptr %18 %1 0;
40 +
    elem %19 %18 0 %17 4;
41 +
    sload w32 %20 %19 0;
42 +
    br.ne w32 %20 10 @then6 @merge7;
41 43
  @then6
42 -
    ret 1;
44 +
    ret 2;
43 45
  @merge7
44 -
    load w32 %18 %1 8;
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 +
    load w32 %21 %1 8;
47 +
    load ptr %22 %1 0;
48 +
    elem %23 %22 1 %21 4;
49 +
    sload w32 %24 %23 0;
50 +
    br.ne w32 %24 20 @then8 @merge9;
49 51
  @then8
50 -
    ret 2;
52 +
    ret 3;
51 53
  @merge9
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;
54 +
    load w32 %25 %1 8;
55 +
    load ptr %26 %1 0;
56 +
    elem %27 %26 2 %25 4;
57 +
    sload w32 %28 %27 0;
58 +
    br.ne w32 %28 40 @then10 @merge11;
57 59
  @then10
58 -
    ret 3;
60 +
    ret 4;
59 61
  @merge11
60 -
    load w32 %26 %1 8;
61 -
    load ptr %27 %1 0;
62 -
    elem %28 %27 2 %26 4;
63 -
    sload w32 %29 %28 0;
64 -
    br.ne w32 %29 40 @then12 @merge13;
62 +
    load w32 %29 %1 8;
63 +
    load ptr %30 %1 0;
64 +
    elem %31 %30 3 %29 4;
65 +
    sload w32 %32 %31 0;
66 +
    br.ne w32 %32 50 @then12 @merge13;
65 67
  @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
74 68
    ret 5;
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;
69 +
  @merge13
70 +
    load w32 %33 %1 8;
71 +
    load ptr %34 %1 0;
72 +
    elem %35 %34 0 %33 4;
80 73
    add ptr %36 %35 4;
81 -
    sub w32 %37 %34 0;
74 +
    sub w32 %37 %33 0;
82 75
    sub w32 %38 %37 1;
83 76
    mul w32 %39 %38 4;
84 -
    jmp @delete18(0);
85 -
  @guard#trap17
86 -
    ebreak;
87 -
    unreachable;
88 -
  @delete18(w32 %40)
89 -
    br.ult w32 %40 %39 @delete19 @delete20;
90 -
  @delete19
77 +
    jmp @delete14(0);
78 +
  @delete14(w32 %40)
79 +
    br.ult w32 %40 %39 @delete15 @delete16;
80 +
  @delete15
91 81
    add ptr %41 %36 %40;
92 82
    load w8 %42 %41 0;
93 83
    add ptr %43 %35 %40;
94 84
    store w8 %42 %43 0;
95 85
    add w32 %44 %40 1;
96 -
    jmp @delete18(%44);
97 -
  @delete20
98 -
    sub w32 %45 %34 1;
86 +
    jmp @delete14(%44);
87 +
  @delete16
88 +
    sub w32 %45 %33 1;
99 89
    store w32 %45 %1 8;
100 90
    load w32 %47 %1 8;
101 -
    br.ne w32 %47 3 @then21 @merge22;
102 -
  @then21
91 +
    br.ne w32 %47 3 @then17 @merge18;
92 +
  @then17
103 93
    ret 6;
104 -
  @merge22
94 +
  @merge18
105 95
    load w32 %48 %1 8;
106 96
    load ptr %49 %1 0;
107 97
    elem %50 %49 0 %48 4;
108 98
    sload w32 %51 %50 0;
109 -
    br.ne w32 %51 20 @then23 @merge24;
110 -
  @then23
99 +
    br.ne w32 %51 20 @then19 @merge20;
100 +
  @then19
111 101
    ret 7;
112 -
  @merge24
102 +
  @merge20
113 103
    load w32 %52 %1 8;
114 104
    load ptr %53 %1 0;
115 105
    elem %54 %53 1 %52 4;
116 106
    sload w32 %55 %54 0;
117 -
    br.ne w32 %55 40 @then25 @merge26;
118 -
  @then25
107 +
    br.ne w32 %55 40 @then21 @merge22;
108 +
  @then21
119 109
    ret 8;
120 -
  @merge26
110 +
  @merge22
121 111
    load w32 %56 %1 8;
122 112
    load ptr %57 %1 0;
123 113
    elem %58 %57 2 %56 4;
124 114
    sload w32 %59 %58 0;
125 -
    br.ne w32 %59 50 @then27 @merge28;
126 -
  @then27
115 +
    br.ne w32 %59 50 @then23 @merge24;
116 +
  @then23
127 117
    ret 9;
128 -
  @merge28
118 +
  @merge24
129 119
    load w32 %60 %1 8;
130 -
    br.ult w32 2 %60 @guard#pass29 @guard#trap30;
131 -
  @guard#pass29
132 120
    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
141 -
    ebreak;
142 -
    unreachable;
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
121 +
    elem %62 %61 2 %60 4;
122 +
    add ptr %63 %62 4;
123 +
    sub w32 %64 %60 2;
124 +
    sub w32 %65 %64 1;
125 +
    mul w32 %66 %65 4;
126 +
    jmp @delete25(0);
127 +
  @delete25(w32 %67)
128 +
    br.ult w32 %67 %66 @delete26 @delete27;
129 +
  @delete26
130 +
    add ptr %68 %63 %67;
131 +
    load w8 %69 %68 0;
132 +
    add ptr %70 %62 %67;
133 +
    store w8 %69 %70 0;
134 +
    add w32 %71 %67 1;
135 +
    jmp @delete25(%71);
136 +
  @delete27
137 +
    sub w32 %72 %60 1;
138 +
    store w32 %72 %1 8;
139 +
    load w32 %74 %1 8;
140 +
    br.ne w32 %74 2 @then28 @merge29;
141 +
  @then28
158 142
    ret 10;
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
143 +
  @merge29
144 +
    load w32 %75 %1 8;
145 +
    load ptr %76 %1 0;
146 +
    elem %77 %76 0 %75 4;
147 +
    sload w32 %78 %77 0;
148 +
    br.ne w32 %78 20 @then30 @merge31;
149 +
  @then30
166 150
    ret 11;
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
151 +
  @merge31
152 +
    load w32 %79 %1 8;
153 +
    load ptr %80 %1 0;
154 +
    elem %81 %80 1 %79 4;
155 +
    sload w32 %82 %81 0;
156 +
    br.ne w32 %82 40 @then32 @merge33;
157 +
  @then32
174 158
    ret 12;
175 -
  @merge39
176 -
    load w32 %84 %1 12;
177 -
    br.ne w32 %84 5 @then40 @merge41;
178 -
  @then40
159 +
  @merge33
160 +
    load w32 %83 %1 12;
161 +
    br.ne w32 %83 5 @then34 @merge35;
162 +
  @then34
179 163
    ret 13;
180 -
  @merge41
164 +
  @merge35
181 165
    ret 0;
182 166
}