// File: /workspace/github_cpp_makefile_star2_O1/baziotis[P]minijava-cpp/typecheck.cpp
// Function: MainTypeCheckVisitor::visit(WhileStatement*)
void MainTypeCheckVisitor::visit(WhileStatement *while_stmt) {
    LOG_SCOPE;
    debug_print("MainTypeCheck::WhileStatement\n");
    Type *cond = while_stmt->cond->accept(this);
    poison_stmt(cond);
    llvalue_t cond_val = __expr_context.llval;
    if (cond != this->type_table.bool_type) {
        typecheck_error(while_stmt->loc, "In while statement, the ",
                        "condition expression must have `boolean` type but has: `",
                        cond->name(), "`");
    }

    if (cond_val.kind == LLVALUE::CONST && cond_val.val == 0) {
        // Elide while body because of constant false condition.
        // Assume that the user does not even wants to typecheck it.
        return;
    }
    
    /// Codegen ///

    // Codegen loops as:
    /*
    predecessor:
        cond test code (branch to loop start or after_loop)
    loop_start:
        loop_body
        cond test code (again, branch to loop_start or after_loop)
    after_loop:

    That way, when we're in loop_body, we know whether we came from predecessor
    or from loop_start.
    Note: Here we have already generated the initial cond code when we
    typechecked it.
    */
    
    const char *pred_lbl_str = (while_stmt->pred_lbl == NULL) ?
                                __expr_context.curr_lbl.lbl : while_stmt->pred_lbl;
    while_stmt->pred_lbl = pred_lbl_str;
    llvm_label_t pred_lbl = {pred_lbl_str};
    llvm_label_t loop_lbl, after_loop_lbl;
    long lbl = gen_lbl();
    loop_lbl.construct("while", lbl);
    after_loop_lbl.construct("while_end", lbl);
    
    // Note: We have already tested if the `cond_val` is const with
    // false value. If we reach here and we have a const, then it's
    // definitely true in which case we don't generate the branch, we
    // just get to the loop.
    // However, note that we have to remember that for the while
    // so that we remember if we need to create a phi or not.
    bool generated_cond_branch = false;
    if (cond_val.kind != LLVALUE::CONST) {
        generated_cond_branch = true;
        llvm_branch_cond(cond_val, loop_lbl, after_loop_lbl);
    } else {
        llvm_branch(loop_lbl);
    }
    llvm_gen_lbl(loop_lbl);

    // There are 3 cases for a local inside a loop:
    // 1) No assignment to the local.
    // 2) We have at least one assignment and we have a use _after_ the _first_ assignment.
    // 3) We have at least one assignment and we have a use _before_ the _first_ assignment.

    // We want to insert a phi node for locals in case 3. To do that, we use the `track_buf`.
    // This keeps an `assigned` and `used` for every local. We then "visit" the whole
    // loop body and condition to track in what case we are. To do that, we use
    // an ordering in `assigned` and `used`. After finishing, either they're both
    // 0, or one is bigger than the other denoting the order.

    SerializedHashTable<Local*> locals = __expr_context.method->locals;
    FuncArr<WhileAssign> track_buf = get_track_buf(locals);

    // Track first the body and then the cond,
    // as the condition will be put on the bottom.
    track_while_assignment_for_stmt(while_stmt->body, track_buf);
    track_while_assignment_for_expr(while_stmt->cond, track_buf);

    /* -- Main algorithm for insert phi nodes --

    Assuming that we have an ordering now, we need to handle case 3) (from above)
    locals. For those we will insert a phi node at the start of the loop
    that decides between the previous value (the value before the loop) and
    the value inside the loop. Let's note some problems:
    1) We have to know the value inside the loop _before_ we actually generate
       the loop. This is kind of impossible so there are 2 ways:
       a) Generate the loop (say into a buffer), then read this IR, find the values
          and then regenerate the loop with the suitable phi nodes on the start.
       b) Generate the loop (but by disabling actual codegen, i.e. printing), find
          the values, generate the phi nodes and then regenerate the loop as it was
          never generated.
       We will do b) as it is of course way easier and faster. But that comes later.
       Before that we have to solve another problem:
    2) To do the first fake generation that was described 1b) above, we have to know
       the register that was assigned to the phi node, _before_ we can generate
       the phi node.
    
    To see both 1) and 2) into action, consider this:
        
       ```
       a = 3;
       while (a < 4) {
          a = a + 1;
       }
       ```
        
       That has to generate something like this:
       ```
           // ... (`a` has gotten constant value 3 here)
       while1:
           %1 = phi i32 [ 3, entry ], [ %2, while1 ]
           %2 = add i32 %1, 1
           %3 = icmp slt i32 %2, 4
           br i1 %3, label while1, label while_end1
       
       while_end1:
           // ...
       ```

       Note that to generate the phi node in %1, we have to know that `a`
       gets the llvalue %2. But, we can't know that _before_ we generate the body.
       So, let's say that we go to generate it. Well, to generate it, when we
       go to generate code for %2, we have to know that `a` has the llvalue %1.
       If we _don't_ somehow do that and do the generation normally, then when we
       generate code for %2, the value that will be assigned to `a` will be the
       constant value 3. And that's of course wrong code generation.

       To solve that we decide the register in which we will save the phi node
       before we actually. Because of the ordering (which remember, comes before all that),
       we know e.g. that we have to generate a phi node for `a`. At this point we can't
       generate the phi node, but we can decide that its value will be saved e.g. in %1.
       Then, we save the llvalue of `a` to be %1 (e.g. local->llval = ...). In that way,
       when we do the first fake generation of, when we go to generate %2, it uses %1
       as the llvalue of `a`. Then of course `a` gets as llvalue the %2.
       And _now_, after finishing the fake generation, we know that `a` got assigned
       as llvalue the %2. And so, we generate the phi node between the constant value
       3 (the previous value i.e. that before the loop) and %2 (the new value).

       Ok, to do all that we need 2 buffers:
       1) `previous_values` holds the values of the locals _before_ the loop.
       2) `new_assigned_values` holds the values that we assign a priori to the phi
          nodes that _will_ be generated.
    */

    FuncArr<llvalue_t> previous_values, new_assigned_values;
    previous_values.reserve(locals.len);
    new_assigned_values.reserve(locals.len);
    // Initialize the 2 buffers.
    for (Local *local : locals) {
        previous_values.push(local->llval);
        // DUMB VALUE
        new_assigned_values.push(const_llv(0, {}));
    }

    /// Decide for which locals we have to make a phi node
    /// and get a register for the phi node (that will be generated later).
    size_t i = 0;
    for (WhileAssign wa : track_buf) {
        assert(i < locals.len);
        // Either no use and no assignment or they are not equal (since
        // we should have ordering).
        assert((!wa.assigned && !wa.used) || (wa.used != wa.assigned));
        if (wa.assigned && wa.used && wa.used < wa.assigned) {
            Local *local = locals[i];
            new_assigned_values[i].kind = LLVALUE::REG;
            new_assigned_values[i].reg = gen_reg();
            local->llval = new_assigned_values[i];
        }
        ++i;
    }

    /// Do the fake generation (by disabling codegen).
    /// That requires some boilterplate to save and restore the state of registers
    /// and labels.

    assert(while_stmt->body);
    bool save_codegen = config.codegen;
    // TODO: We should have a save state / restore state.
    // Get the last register but we actually have to reset it immediately.
    long save_reg = gen_reg();
    set_reg(save_reg);
    long save_lbl = gen_lbl();
    set_lbl(save_lbl);
    config.codegen = false;
    while_stmt->body->accept(this);
    while_stmt->cond->accept(this);
    const char *last_lbl_str = (while_stmt->last_lbl == NULL) ?
                                __expr_context.curr_lbl.lbl : while_stmt->last_lbl;
    while_stmt->last_lbl = last_lbl_str;
    llvm_label_t last_lbl = {last_lbl_str};
    set_reg(save_reg);
    set_lbl(save_lbl);
    config.codegen = save_codegen;

    
    /// Now that we know the llvalue that the locals got in the loop,
    /// generate the phi nodes. Note that they're locals that might have been
    /// assigned but either never used or used after the assignment. In these
    /// cases we don't want to insert a phi node but we do want to restore their
    /// llvalue so that the actual code generation is correct.
    i = 0;
    for (WhileAssign wa : track_buf) {
        Local *local = wa.local;
        if (wa.assigned && wa.used && wa.used < wa.assigned) {
            long reg = new_assigned_values[i].reg;
            local->llval = while_phi_node(local->type, previous_values[i], local->llval,
                                          pred_lbl, last_lbl, reg);
        } else if (wa.assigned) {
            // Restore in the general case
            local->llval = previous_values[i];
        }
        ++i;
    }
    
    /// Do the actual code generation (note that we generate the cond on the
    /// bottom etc. - as described above on how while loops are generated / transformed).
    while_stmt->body->accept(this);
    while_stmt->cond->accept(this);
    cond_val = __expr_context.llval;
    llvm_branch_cond(cond_val, loop_lbl, after_loop_lbl);
    llvm_gen_lbl(after_loop_lbl);
    
    /// Last but not least, we want to generate a phi nodes for all
    /// the locals that were assigned inside the loop (regardless of the usage).
    /// Of course the phi will be between their before-loop-llvalue and the
    /// value they get assigned inside the loop.

    // Generate a phi node after the while. Do that only if the condition
    // was not known and so a conditional branch was inserted.
    if (generated_cond_branch) {
      i = 0;
      for (WhileAssign wa : track_buf) {
          Local *local = wa.local;
          llvalue_t prev_value = previous_values[i];
          llvalue_t new_value = local->llval;
          if (wa.assigned) {
              local->llval = llvm_phi_node(local->type, prev_value, new_value,
                                           pred_lbl, last_lbl);
          }
          ++i;
      }
    }
}

// Assembly:
pushq %rbp
pushq %r15
pushq %r14
pushq %r13
pushq %r12
pushq %rbx
subq $0x1c8, %rsp            # imm = 0x1C8
movq %rsi, %r14
movq %rdi, %rbx
leaq 0x4f(%rsp), %rdi
callq 0x34d0
leaq 0x53ae(%rip), %rdi      # 0x1357c
xorl %eax, %eax
callq 0x3541
movq 0x10(%r14), %rsi
movq %rbx, %rdi
callq 0xaa90
cmpl $0x0, 0x4(%rax)
je 0xe8f3
leaq 0xb7c6(%rip), %rdx      # 0x199b8
movl 0x8(%rdx), %r12d
movl 0x1c(%rdx), %ecx
movl %ecx, 0xf0(%rsp)
movups 0xc(%rdx), %xmm0
movaps %xmm0, 0xe0(%rsp)
movl 0x20(%rdx), %ebp
movl 0x24(%rdx), %r15d
movq %rbx, 0xb0(%rsp)
cmpq 0x8(%rbx), %rax
je 0xe24c
movl 0xc(%r14), %ebx
movq %rax, %rdi
callq 0x84fa
leaq 0x5367(%rip), %rsi      # 0x1359b
leaq 0x524d(%rip), %rdx      # 0x13488
leaq 0x382f(%rip), %r8       # 0x11a71
movl %ebx, %edi
movq %rax, %rcx
callq 0x8ccf
movl %r12d, %eax
xorl $0x1, %eax
orl %ebp, %eax
je 0xe8f3
movq 0x20(%r14), %r13
testq %r13, %r13
jne 0xe26d
leaq 0xb74e(%rip), %rax      # 0x199b8
movq (%rax), %r13
movq %r14, 0x50(%rsp)
movq %r13, 0x20(%r14)
xorl %eax, %eax
movq %rax, 0x60(%rsp)
movq %rax, 0x68(%rsp)
callq 0x4762
movq %rax, %r14
leaq 0x4044(%rip), %rsi      # 0x122d5
leaq 0x60(%rsp), %rdi
movq %rax, %rdx
callq 0xf112
leaq 0x530f(%rip), %rsi      # 0x135b4
leaq 0x68(%rsp), %rdi
movq %r14, %rdx
callq 0xf112
cmpl $0x1, %r12d
jne 0xe2c4
movq 0x60(%rsp), %rdi
callq 0x54bd
jmp 0xe321
movl %r12d, 0x120(%rsp)
movaps 0xe0(%rsp), %xmm0
movups %xmm0, 0x124(%rsp)
movl 0xf0(%rsp), %eax
movl %eax, 0x134(%rsp)
movl %ebp, 0x138(%rsp)
movl %r15d, 0x13c(%rsp)
movq 0x60(%rsp), %rdi
movq 0x68(%rsp), %rsi
movups 0x120(%rsp), %xmm0
movups 0x130(%rsp), %xmm1
movups %xmm1, 0x10(%rsp)
movups %xmm0, (%rsp)
callq 0x543c
movq 0x60(%rsp), %rdi
callq 0x541e
movl %r12d, 0xac(%rsp)
leaq 0xb67e(%rip), %rax      # 0x199b8
movq 0x28(%rax), %rax
movq 0x30(%rax), %rbx
movq 0x38(%rax), %r14
xorps %xmm0, %xmm0
leaq 0x90(%rsp), %rdi
movaps %xmm0, (%rdi)
movq $0x0, 0x10(%rdi)
movq %r14, %rsi
callq 0xfba6
movq %r14, 0x58(%rsp)
testq %r14, %r14
je 0xe39d
movq 0x58(%rsp), %rax
leaq (,%rax,8), %r15
xorl %r12d, %r12d
leaq 0x90(%rsp), %r14
movq (%rbx,%r12), %rsi
movq %r14, %rdi
xorl %edx, %edx
callq 0xf1fc
addq $0x8, %r12
cmpq %r12, %r15
jne 0xe386
movq %r13, 0xb8(%rsp)
movq 0x50(%rsp), %r14
movq 0x18(%r14), %rdi
movq 0xa0(%rsp), %rax
movq %rax, 0x10(%rsp)
movaps 0x90(%rsp), %xmm0
movups %xmm0, (%rsp)
callq 0xdecf
movq 0x10(%r14), %rdi
movq 0xa0(%rsp), %rax
movq %rax, 0x10(%rsp)
movaps 0x90(%rsp), %xmm0
movups %xmm0, (%rsp)
callq 0xdd81
xorl %eax, %eax
leaq 0xc0(%rsp), %rdi
movq %rax, 0x10(%rdi)
xorps %xmm0, %xmm0
movaps %xmm0, (%rdi)
movq %rax, 0x80(%rsp)
movaps %xmm0, 0x70(%rsp)
movq 0x58(%rsp), %r14
movq %r14, %rsi
callq 0xf266
leaq 0x70(%rsp), %rdi
movq %r14, %rsi
callq 0xf266
testq %r14, %r14
je 0xe4a8
movq 0x58(%rsp), %rax
leaq (,%rax,8), %r15
xorl %r12d, %r12d
leaq 0xc0(%rsp), %r13
leaq 0x1a8(%rsp), %rbp
leaq 0x70(%rsp), %r14
movq (%rbx,%r12), %rax
movups 0x10(%rax), %xmm0
movups 0x20(%rax), %xmm1
movups %xmm1, 0x10(%rsp)
movups %xmm0, (%rsp)
movq %r13, %rdi
callq 0xf03c
movq %rbp, %rdi
xorl %esi, %esi
xorl %edx, %edx
xorl %ecx, %ecx
callq 0x4789
movups 0x1a8(%rsp), %xmm0
movups 0x1b8(%rsp), %xmm1
movups %xmm1, 0x10(%rsp)
movups %xmm0, (%rsp)
movq %r14, %rdi
callq 0xf03c
addq $0x8, %r12
cmpq %r12, %r15
jne 0xe453
movq 0x98(%rsp), %r14
testq %r14, %r14
movq 0x58(%rsp), %rsi
je 0xe584
movq 0xa0(%rsp), %r13
shlq $0x4, %r14
xorl %ebp, %ebp
xorl %r15d, %r15d
cmpq %r15, %rsi
je 0xe92e
movb 0x8(%r13,%rbp,2), %al
movl %eax, %ecx
andb $0x3, %cl
testb $0xf, %al
je 0xe4f6
movl %eax, %edx
shrb $0x2, %dl
andb $0x3, %dl
cmpb %cl, %dl
je 0xe94d
testb %cl, %cl
je 0xe573
shrb $0x2, %al
andb $0x3, %al
sete %dl
cmpb %cl, %al
setae %al
orb %dl, %al
jne 0xe573
cmpq %r15, 0x78(%rsp)
jbe 0xe90f
movq (%rbx,%rbp), %r12
movq 0x80(%rsp), %rax
movl $0x2, (%rax,%rbp,4)
callq 0x4738
cmpq %r15, 0x78(%rsp)
jbe 0xe90f
movq 0x80(%rsp), %rcx
movq %rax, 0x18(%rcx,%rbp,4)
cmpq %r15, 0x78(%rsp)
jbe 0xe90f
movq 0x80(%rsp), %rax
movups (%rax,%rbp,4), %xmm0
movups 0x10(%rax,%rbp,4), %xmm1
movups %xmm1, 0x20(%r12)
movups %xmm0, 0x10(%r12)
movq 0x58(%rsp), %rsi
incq %r15
addq $0x8, %rbp
addq $-0x10, %r14
jne 0xe4cf
movq 0x50(%rsp), %rax
cmpq $0x0, 0x18(%rax)
je 0xe96c
leaq 0xb49d(%rip), %rbx      # 0x19a38
movb 0x4(%rbx), %r14b
callq 0x4738
movq 0xb0(%rsp), %r15
movq %rax, %r13
movq %rax, %rdi
callq 0x4730
callq 0x4762
movq %rax, %rbp
movq %rax, %rdi
callq 0x4757
movb $0x0, 0x4(%rbx)
movq 0x50(%rsp), %rax
movq 0x18(%rax), %rdi
movq (%rdi), %rax
movq %r15, %rsi
callq *0x18(%rax)
movq 0x50(%rsp), %rax
movq 0x10(%rax), %rsi
movq %r15, %rdi
callq 0xaa90
movq 0x50(%rsp), %rax
movq 0x28(%rax), %r12
testq %r12, %r12
jne 0xe606
leaq 0xb3b5(%rip), %rax      # 0x199b8
movq (%rax), %r12
movq 0x50(%rsp), %rax
movq %r12, 0x28(%rax)
movq %r13, %rdi
callq 0x4730
movq %rbp, %rdi
callq 0x4757
movb %r14b, 0x4(%rbx)
movq 0x98(%rsp), %rbx
testq %rbx, %rbx
je 0xe73c
movq 0xa0(%rsp), %r14
shlq $0x4, %rbx
addq %r14, %rbx
xorl %ebp, %ebp
xorl %r15d, %r15d
movb 0x8(%r14), %al
movl %eax, %ecx
andb $0x3, %cl
je 0xe728
movq (%r14), %r13
shrb $0x2, %al
andb $0x3, %al
sete %dl
cmpb %cl, %al
setae %al
orb %dl, %al
jne 0xe6ff
cmpq %r15, 0x78(%rsp)
jbe 0xe90f
cmpq %r15, 0xc8(%rsp)
jbe 0xe90f
movq 0x80(%rsp), %rax
movq 0x18(%rax,%rbp), %r8
movq 0x8(%r13), %rsi
movq 0xd0(%rsp), %rax
movups 0x10(%r13), %xmm0
movups 0x20(%r13), %xmm1
movups %xmm1, 0x30(%rsp)
movups %xmm0, 0x20(%rsp)
movups (%rax,%rbp), %xmm0
movups 0x10(%rax,%rbp), %xmm1
movups %xmm1, 0x10(%rsp)
movups %xmm0, (%rsp)
leaq 0x100(%rsp), %rdi
movq 0xb8(%rsp), %rdx
movq %r12, %rcx
callq 0x54f3
addq $0x10, %r13
movups 0x100(%rsp), %xmm0
movups 0x110(%rsp), %xmm1
movups %xmm1, 0x10(%r13)
movups %xmm0, (%r13)
jmp 0xe728
cmpq %r15, 0xc8(%rsp)
jbe 0xe90f
movq 0xd0(%rsp), %rax
movups (%rax,%rbp), %xmm0
movups 0x10(%rax,%rbp), %xmm1
movups %xmm1, 0x20(%r13)
movups %xmm0, 0x10(%r13)
incq %r15
addq $0x10, %r14
addq $0x20, %rbp
cmpq %rbx, %r14
jne 0xe648
movq 0x50(%rsp), %rax
movq 0x18(%rax), %rdi
movq (%rdi), %rax
movq 0xb0(%rsp), %rbx
movq %rbx, %rsi
callq *0x18(%rax)
movq 0x50(%rsp), %rax
movq 0x10(%rax), %rsi
movq %rbx, %rdi
callq 0xaa90
leaq 0xb24a(%rip), %rdx      # 0x199b8
movl 0x8(%rdx), %eax
movups 0xc(%rdx), %xmm0
movaps %xmm0, 0xe0(%rsp)
movl 0x1c(%rdx), %ecx
movl %ecx, 0xf0(%rsp)
movq 0x20(%rdx), %rdx
movl %eax, 0x140(%rsp)
movups %xmm0, 0x144(%rsp)
movl %ecx, 0x154(%rsp)
movq %rdx, 0x158(%rsp)
movq 0x60(%rsp), %rdi
movq 0x68(%rsp), %rsi
movups 0x140(%rsp), %xmm0
movups 0x150(%rsp), %xmm1
movups %xmm1, 0x10(%rsp)
movups %xmm0, (%rsp)
callq 0x543c
movq 0x68(%rsp), %rdi
callq 0x541e
cmpl $0x1, 0xac(%rsp)
je 0xe8f3
movq 0x98(%rsp), %rbx
testq %rbx, %rbx
je 0xe8f3
movq 0xa0(%rsp), %r15
shlq $0x4, %rbx
addq %r15, %rbx
movq $-0x1, %r13
xorl %ebp, %ebp
incq %r13
cmpq %r13, 0xc8(%rsp)
jbe 0xe90f
movq (%r15,%rbp), %r14
movb 0x8(%r15,%rbp), %al
movq 0xd0(%rsp), %rcx
movups (%rcx,%rbp,2), %xmm0
movups 0x10(%rcx,%rbp,2), %xmm1
movaps %xmm0, 0x100(%rsp)
movaps %xmm1, 0x110(%rsp)
movups 0x10(%r14), %xmm0
movups 0x20(%r14), %xmm1
movaps %xmm1, 0x170(%rsp)
movaps %xmm0, 0x160(%rsp)
testb $0x3, %al
je 0xe8de
movq 0x8(%r14), %rsi
movaps 0x160(%rsp), %xmm0
movaps 0x170(%rsp), %xmm1
movups %xmm1, 0x30(%rsp)
movups %xmm0, 0x20(%rsp)
movaps 0x100(%rsp), %xmm0
movaps 0x110(%rsp), %xmm1
movups %xmm1, 0x10(%rsp)
movups %xmm0, (%rsp)
leaq 0x188(%rsp), %rdi
movq 0xb8(%rsp), %rdx
movq %r12, %rcx
movq $-0x1, %r8
callq 0x54f3
addq $0x10, %r14
movups 0x188(%rsp), %xmm0
movups 0x198(%rsp), %xmm1
movups %xmm1, 0x10(%r14)
movups %xmm0, (%r14)
leaq (%r15,%rbp), %rax
addq $0x10, %rbp
addq $0x10, %rax
cmpq %rbx, %rax
jne 0xe812
leaq 0x4f(%rsp), %rdi
callq 0x34e4
addq $0x1c8, %rsp            # imm = 0x1C8
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq
leaq 0x2e80(%rip), %rdi      # 0x11796
leaq 0x2e81(%rip), %rsi      # 0x1179e
leaq 0x2e84(%rip), %rcx      # 0x117a8
movl $0x32, %edx
callq 0x20b0
leaq 0x4c89(%rip), %rdi      # 0x135be
leaq 0x3b52(%rip), %rsi      # 0x1248e
leaq 0x4c8a(%rip), %rcx      # 0x135cd
movl $0x88a, %edx            # imm = 0x88A
callq 0x20b0
leaq 0x4cac(%rip), %rdi      # 0x13600
leaq 0x3b33(%rip), %rsi      # 0x1248e
leaq 0x4c6b(%rip), %rcx      # 0x135cd
movl $0x88d, %edx            # imm = 0x88D
callq 0x20b0
leaq 0x4cc4(%rip), %rdi      # 0x13637
leaq 0x3b14(%rip), %rsi      # 0x1248e
leaq 0x4c4c(%rip), %rcx      # 0x135cd
movl $0x89b, %edx            # imm = 0x89B
callq 0x20b0
jmp 0xe9a3
jmp 0xe9a3
jmp 0xe9a3
jmp 0xe9a3
jmp 0xe9a3
jmp 0xe9a3
jmp 0xe9a3
jmp 0xe9a3
jmp 0xe9a3
jmp 0xe9a3
jmp 0xe9a3
jmp 0xe9a3
movq %rax, %rbx
leaq 0x4f(%rsp), %rdi
callq 0x34e4
movq %rbx, %rdi
callq 0x21c0