fn w32 $replace(w64 %0, w64 %1) {
  @entry0
    load w64 %2 %0 0;
    store w64 %1 %0 0;
    load w32 %3 %2 0;
    ret %3;
}

fn w32 $follow(w64 %0, w64 %1) {
  @entry0
    load w32 %2 %1 0;
    ret %2;
}

fn w32 $followSlice(w64 %0, w64 %1) {
  @entry0
    reserve %2 16 8;
    blit %2 %0 16;
    load w32 %3 %2 8;
    br.ult w32 0 %3 @guard#pass3 @guard#trap4;
  @assert.fail1
    unreachable;
  @assert.ok2
    blit %2 %1 16;
    load w32 %6 %2 8;
    br.ult w32 0 %6 @guard#pass5 @guard#trap6;
  @guard#pass3
    load w64 %4 %2 0;
    load w32 %5 %4 0;
    br.eq w32 %5 20 @assert.ok2 @assert.fail1;
  @guard#trap4
    ebreak;
    unreachable;
  @guard#pass5
    load w64 %7 %2 0;
    load w32 %8 %7 0;
    ret %8;
  @guard#trap6
    ebreak;
    unreachable;
}

fn w64 $followCell(w64 %0, w64 %1) {
  @entry0
    store w32 20 %0 0;
    store w32 22 %1 0;
    ret;
}

fn w32 $main() {
  @entry0
    reserve %0 4 4;
    store w32 20 %0 0;
    reserve %1 4 4;
    store w32 22 %1 0;
    reserve %2 8 8;
    store w64 %0 %2 0;
    call w32 %3 $replace(%2, %1);
    load w64 %4 %2 0;
    call w32 %5 $follow(%0, %4);
    add w32 %6 %3 %5;
    reserve %7 4 4;
    store w32 20 %7 0;
    reserve %8 4 4;
    store w32 22 %8 0;
    reserve %9 16 8;
    store w64 %7 %9 0;
    store w32 1 %9 8;
    store w32 1 %9 12;
    reserve %10 16 8;
    store w64 %8 %10 0;
    store w32 1 %10 8;
    store w32 1 %10 12;
    reserve %11 16 8;
    blit %11 %9 16;
    call w32 %12 $followSlice(%11, %10);
    br.eq w32 %12 22 @assert.ok2 @assert.fail1;
  @assert.fail1
    unreachable;
  @assert.ok2
    reserve %13 4 4;
    store w32 0 %13 0;
    reserve %14 4 4;
    store w32 0 %14 0;
    call w64 $followCell(%13, %14);
    load w32 %15 %13 0;
    br.eq w32 %15 20 @assert.ok4 @assert.fail3;
  @assert.fail3
    unreachable;
  @assert.ok4
    load w32 %16 %14 0;
    br.eq w32 %16 22 @assert.ok6 @assert.fail5;
  @assert.fail5
    unreachable;
  @assert.ok6
    load w32 %17 %13 0;
    br.eq w32 %17 20 @assert.ok8 @assert.fail7;
  @assert.fail7
    unreachable;
  @assert.ok8
    load w32 %18 %14 0;
    br.eq w32 %18 22 @assert.ok10 @assert.fail9;
  @assert.fail9
    unreachable;
  @assert.ok10
    ret %6;
}
