// File: /workspace/github_cpp_makefile_star2_O3/baziotis[P]minijava-cpp/typecheck.cpp
// Function: track_while_assignment_for_stmt(Statement*, Array<WhileAssign, (MEM)4>)
bool track_while_assignment_for_stmt(Statement *stmt, FuncArr<WhileAssign> track_buf) {
    // IMPORTANT: Be sure to first visit the usage, then
    // the assignment in assigments. For example, in
    // AssignmentStatement, we first want to visit the RHS,
    // then track the assignment because if we have say:
    // a = a + 1;
    // then, it counts as a usage before an assignment.
    switch (stmt->kind) {
    case STMT::UNDEFINED: assert(0);
    case STMT::BLOCK:
    {
        BlockStatement *block = (BlockStatement *)stmt;
        for (Statement *s : block->block) {
            track_while_assignment_for_stmt(s, track_buf);
        }
    } break;
    case STMT::ASGN:
    {
        AssignmentStatement *asgn = (AssignmentStatement *)stmt;
        track_while_assignment_for_expr(asgn->rhs, track_buf);
        for (WhileAssign& wa : track_buf) {
            Local *local = wa.local;
            if (asgn->id == local->id) {
                if (!wa.assigned) {
                    if (!wa.used) {
                        wa.assigned = 1;
                    } else {
                        wa.assigned = 2;
                    }
                }
                break;
            }
        }
    } break;
    case STMT::ARR_ASGN:
    {
        ArrayAssignmentStatement *arr_asgn = (ArrayAssignmentStatement *)stmt;
        track_while_assignment_for_expr(arr_asgn->index, track_buf);
        track_while_assignment_for_expr(arr_asgn->rhs, track_buf);

        for (WhileAssign& wa : track_buf) {
            Local *local = wa.local;
            if (arr_asgn->id == local->id) {
                if (!wa.assigned) {
                    if (!wa.used) {
                        wa.assigned = 1;
                    } else {
                        wa.assigned = 2;
                    }
                }
                break;
            }
        }
    } break;
    case STMT::IF:
    {
        IfStatement *if_stmt = (IfStatement *)stmt;
        track_while_assignment_for_expr(if_stmt->cond, track_buf);
        track_while_assignment_for_stmt(if_stmt->then, track_buf);
        track_while_assignment_for_stmt(if_stmt->else_, track_buf);
    } break;
    case STMT::WHILE:
    {
        WhileStatement *while_stmt = (WhileStatement *)stmt;
        track_while_assignment_for_expr(while_stmt->cond, track_buf);
        track_while_assignment_for_stmt(while_stmt->body, track_buf);
    } break;
    case STMT::PRINT:
    {
        PrintStatement *print_stmt = (PrintStatement *)stmt;
        track_while_assignment_for_expr(print_stmt->to_print, track_buf);
    } break;
    }
    return false;
}

// Assembly:
pushq %r15
pushq %r14
pushq %r13
pushq %r12
pushq %rbx
subq $0x50, %rsp
movq %rdi, %rbx
leaq 0x80(%rsp), %r14
leaq 0x4bb9(%rip), %r15      # 0x132fc
leaq 0x20(%rsp), %r12
leaq 0x38(%rsp), %r13
movl 0x8(%rbx), %eax
cmpq $0x6, %rax
ja 0xe900
movslq (%r15,%rax,4), %rax
addq %r15, %rax
jmpq *%rax
movq 0x10(%rbx), %rdi
movq 0x10(%r14), %rax
movq %rax, 0x10(%rsp)
movups (%r14), %xmm0
movups %xmm0, (%rsp)
callq 0xe5f1
movq 0x18(%rbx), %rdi
movq 0x10(%r14), %rax
movq %rax, 0x10(%rsp)
movups (%r14), %xmm0
movups %xmm0, (%rsp)
callq 0xe724
movl $0x20, %eax
movq %r12, %rcx
jmp 0xe7c3
movq 0x10(%rbx), %rdi
movq 0x10(%r14), %rax
movq %rax, 0x10(%rsp)
movups (%r14), %xmm0
movups %xmm0, (%rsp)
callq 0xe5f1
movl $0x18, %eax
movq %r13, %rcx
movq (%rbx,%rax), %rbx
movq 0x10(%r14), %rax
movq %rax, 0x10(%rcx)
movups (%r14), %xmm0
movups %xmm0, (%rcx)
jmp 0xe74d
movq 0x18(%rbx), %r15
testq %r15, %r15
je 0xe900
movq 0x20(%rbx), %rbx
shlq $0x3, %r15
xorl %r12d, %r12d
movq (%rbx,%r12), %rdi
movq 0x10(%r14), %rax
movq %rax, 0x10(%rsp)
movups (%r14), %xmm0
movups %xmm0, (%rsp)
callq 0xe724
addq $0x8, %r12
cmpq %r12, %r15
jne 0xe7f3
jmp 0xe900
movq 0x18(%rbx), %rdi
movq 0x10(%r14), %rax
movq %rax, 0x10(%rsp)
movups (%r14), %xmm0
movups %xmm0, (%rsp)
callq 0xe5f1
movq 0x8(%r14), %rdx
testq %rdx, %rdx
je 0xe900
movq 0x10(%r14), %rax
movq 0x10(%rbx), %rsi
shlq $0x4, %rdx
xorl %ecx, %ecx
movq (%rax,%rcx), %rdi
cmpq (%rdi), %rsi
je 0xe8e6
addq $0x10, %rcx
cmpq %rcx, %rdx
jne 0xe850
jmp 0xe900
movq 0x10(%rbx), %rdi
movq 0x10(%r14), %rax
movq %rax, 0x10(%rsp)
movups (%r14), %xmm0
movups %xmm0, (%rsp)
callq 0xe5f1
jmp 0xe900
movq 0x18(%rbx), %rdi
movq 0x10(%r14), %rax
movq %rax, 0x10(%rsp)
movups (%r14), %xmm0
movups %xmm0, (%rsp)
callq 0xe5f1
movq 0x20(%rbx), %rdi
movq 0x10(%r14), %rax
movq %rax, 0x10(%rsp)
movups (%r14), %xmm0
movups %xmm0, (%rsp)
callq 0xe5f1
movq 0x8(%r14), %rdx
testq %rdx, %rdx
je 0xe900
movq 0x10(%r14), %rax
movq 0x10(%rbx), %rsi
shlq $0x4, %rdx
xorl %ecx, %ecx
movq (%rax,%rcx), %rdi
cmpq (%rdi), %rsi
je 0xe8e6
addq $0x10, %rcx
cmpq %rcx, %rdx
jne 0xe8d2
jmp 0xe900
movb 0x8(%rax,%rcx), %dl
testb $0x3, %dl
jne 0xe900
testb $0xc, %dl
je 0xe8f9
orb $0x2, %dl
jmp 0xe8fc
orb $0x1, %dl
movb %dl, 0x8(%rax,%rcx)
xorl %eax, %eax
addq $0x50, %rsp
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
retq
leaq 0x4d0b(%rip), %rdi      # 0x13622
leaq 0x4ae0(%rip), %rsi      # 0x133fe
leaq 0x5b80(%rip), %rcx      # 0x144a5
movl $0x796, %edx            # imm = 0x796
callq 0x20b0