// File: baziotis[P]minijava-cpp/typecheck.cpp
// Function: MainTypeCheckVisitor::visit(ArrayAssignmentStatement*)
void MainTypeCheckVisitor::visit(ArrayAssignmentStatement *arr_asgn_stmt) {
    LOG_SCOPE;
    debug_print("MainTypeCheck::ArrayAssignmentStatement\n");
    assert(this->curr_method);
    assert(this->curr_class);
    Local *arr = lookup_local(arr_asgn_stmt->id, this->curr_method, this->curr_class);
    bool is_correct = true;
    if (!arr) {
        typecheck_error(arr_asgn_stmt->loc, "In array assignment statement, array: `",
                        arr_asgn_stmt->id, "` is not defined");
        is_correct = false;
    }
    assert(arr_asgn_stmt->index);
    Type *index_type = arr_asgn_stmt->index->accept(this);
    poison_stmt(index_type);
    llvalue_t index = __expr_context.llval;
    if (index_type != this->type_table.int_type) {
        typecheck_error(arr_asgn_stmt->loc, "In array assignment statement, the ",
                        "index expression must have `int` type but has: `",
                        index_type->name(), "`");
        is_correct = false;
    }
    assert(arr_asgn_stmt->rhs);
    Type *rhs_type = arr_asgn_stmt->rhs->accept(this);
    poison_stmt(rhs_type);
    llvalue_t rhs_val = __expr_context.llval;
    if (rhs_type != this->type_table.int_type) {
        typecheck_error(arr_asgn_stmt->loc, "In array assignment statement, the ",
                        "right-hand-side expression must have `int` type but has: `",
                        rhs_type->name(), "`");
        is_correct = false;
    }
    if (!is_correct) {
        return;
    }
    /// Codegen ///
    // Get the pointer
    llvalue_t ptr;
    if (arr->kind == (int)LOCAL_KIND::FIELD) {
        ptr = cgen_get_field_ptr(arr);
        ptr = llvm_load(this->type_table.int_arr_type, ptr);
    } else {
        ptr = arr->llval;
    }
    // Store the value (by taking into consideration
    // that the first element is used to save the length).
    if (index.kind == LLVALUE::CONST) {
        index.val += 1;
    } else {
        index = llvm_op('+', index, const_llv(1, {}));
    }
    ptr = llvm_getelementptr_i32(ptr, index);
    assert(rhs_type == this->type_table.int_type);
    llvm_store(rhs_type, rhs_val, ptr);
    /// End of Codegen ///
}

// Assembly:
pushq %rbp
movq %rsp, %rbp
subq $0x2a0, %rsp            # imm = 0x2A0
movq %rdi, -0x8(%rbp)
movq %rsi, -0x10(%rbp)
movq -0x8(%rbp), %rax
movq %rax, -0x238(%rbp)
leaq -0x11(%rbp), %rdi
callq 0x3da0
leaq 0xa6be(%rip), %rdi      # 0x1c5cc
xorl %eax, %eax
callq 0x3e60
jmp 0x11f17
movq -0x238(%rbp), %rax
cmpq $0x0, 0x78(%rax)
je 0x11f27
jmp 0x11f60
leaq 0x9f1e(%rip), %rdi      # 0x1be4c
leaq 0x9829(%rip), %rsi      # 0x1b75e
movl $0x5fd, %edx            # imm = 0x5FD
leaq 0xa6b4(%rip), %rcx      # 0x1c5f5
callq 0x20d0
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x20(%rbp)
movl %eax, -0x24(%rbp)
leaq -0x11(%rbp), %rdi
callq 0x3dd0
jmp 0x1251f
movq -0x238(%rbp), %rax
cmpq $0x0, 0x80(%rax)
je 0x11f73
jmp 0x11f92
leaq 0x9ee4(%rip), %rdi      # 0x1be5e
leaq 0x97dd(%rip), %rsi      # 0x1b75e
movl $0x5fe, %edx            # imm = 0x5FE
leaq 0xa668(%rip), %rcx      # 0x1c5f5
callq 0x20d0
movq -0x238(%rbp), %rax
movq -0x10(%rbp), %rcx
movq 0x10(%rcx), %rdi
movq 0x78(%rax), %rsi
movq 0x80(%rax), %rdx
callq 0x11490
movq %rax, -0x240(%rbp)
jmp 0x11fba
movq -0x240(%rbp), %rax
movq %rax, -0x30(%rbp)
movb $0x1, -0x31(%rbp)
cmpq $0x0, -0x30(%rbp)
jne 0x11ffe
movq -0x10(%rbp), %rax
movl 0xc(%rax), %eax
movl %eax, -0x38(%rbp)
movq -0x10(%rbp), %rax
movq 0x10(%rax), %rdx
movl -0x38(%rbp), %edi
leaq 0xa646(%rip), %rsi      # 0x1c632
leaq 0xa598(%rip), %rcx      # 0x1c58b
callq 0xda80
jmp 0x11ffa
movb $0x0, -0x31(%rbp)
movq -0x10(%rbp), %rax
cmpq $0x0, 0x18(%rax)
je 0x1200b
jmp 0x1202a
leaq 0xa648(%rip), %rdi      # 0x1c65a
leaq 0x9745(%rip), %rsi      # 0x1b75e
movl $0x606, %edx            # imm = 0x606
leaq 0xa5d0(%rip), %rcx      # 0x1c5f5
callq 0x20d0
movq -0x238(%rbp), %rsi
movq -0x10(%rbp), %rax
movq 0x18(%rax), %rdi
callq 0x16490
movq %rax, -0x248(%rbp)
jmp 0x12047
movq -0x248(%rbp), %rax
movq %rax, -0x40(%rbp)
movq -0x40(%rbp), %rax
cmpl $0x0, 0x4(%rax)
jne 0x12068
movl $0x1, -0x44(%rbp)
jmp 0x1250d
movq -0x238(%rbp), %rcx
leaq 0x12952(%rip), %rax     # 0x249c8
movq 0x8(%rax), %rdx
movq %rdx, -0x68(%rbp)
movq 0x10(%rax), %rdx
movq %rdx, -0x60(%rbp)
movq 0x18(%rax), %rdx
movq %rdx, -0x58(%rbp)
movq 0x20(%rax), %rax
movq %rax, -0x50(%rbp)
movq -0x40(%rbp), %rax
cmpq 0x10(%rcx), %rax
je 0x120e6
movq -0x10(%rbp), %rax
movl 0xc(%rax), %eax
movl %eax, -0x6c(%rbp)
movq -0x40(%rbp), %rdi
callq 0xc180
movq %rax, -0x250(%rbp)
jmp 0x120bc
movq -0x250(%rbp), %rcx
movl -0x6c(%rbp), %edi
leaq 0xa5a2(%rip), %rsi      # 0x1c66f
leaq 0xa5bf(%rip), %rdx      # 0x1c693
leaq 0x8c52(%rip), %r8       # 0x1ad2d
callq 0xcca0
jmp 0x120e2
movb $0x0, -0x31(%rbp)
movq -0x10(%rbp), %rax
cmpq $0x0, 0x20(%rax)
je 0x120f3
jmp 0x12112
leaq 0xa5ca(%rip), %rdi      # 0x1c6c4
leaq 0x965d(%rip), %rsi      # 0x1b75e
movl $0x610, %edx            # imm = 0x610
leaq 0xa4e8(%rip), %rcx      # 0x1c5f5
callq 0x20d0
movq -0x238(%rbp), %rsi
movq -0x10(%rbp), %rax
movq 0x20(%rax), %rdi
callq 0x16490
movq %rax, -0x258(%rbp)
jmp 0x1212f
movq -0x258(%rbp), %rax
movq %rax, -0x78(%rbp)
movq -0x78(%rbp), %rax
cmpl $0x0, 0x4(%rax)
jne 0x12150
movl $0x1, -0x44(%rbp)
jmp 0x1250d
movq -0x238(%rbp), %rcx
leaq 0x1286a(%rip), %rax     # 0x249c8
movq 0x8(%rax), %rdx
movq %rdx, -0x98(%rbp)
movq 0x10(%rax), %rdx
movq %rdx, -0x90(%rbp)
movq 0x18(%rax), %rdx
movq %rdx, -0x88(%rbp)
movq 0x20(%rax), %rax
movq %rax, -0x80(%rbp)
movq -0x78(%rbp), %rax
cmpq 0x10(%rcx), %rax
je 0x121dd
movq -0x10(%rbp), %rax
movl 0xc(%rax), %eax
movl %eax, -0x9c(%rbp)
movq -0x78(%rbp), %rdi
callq 0xc180
movq %rax, -0x260(%rbp)
jmp 0x121b0
movq -0x260(%rbp), %rcx
movl -0x9c(%rbp), %edi
leaq 0xa4ab(%rip), %rsi      # 0x1c66f
leaq 0xa50c(%rip), %rdx      # 0x1c6d7
leaq 0x8b5b(%rip), %r8       # 0x1ad2d
callq 0xcca0
jmp 0x121d9
movb $0x0, -0x31(%rbp)
testb $0x1, -0x31(%rbp)
jne 0x121ef
movl $0x1, -0x44(%rbp)
jmp 0x1250d
leaq -0xc0(%rbp), %rdi
callq 0x7840
movq -0x30(%rbp), %rax
movsbl 0x38(%rax), %eax
cmpl $0x2, %eax
jne 0x122c1
movq -0x30(%rbp), %rsi
leaq -0xe0(%rbp), %rdi
callq 0x6460
jmp 0x1221e
movq -0x238(%rbp), %rax
movups -0xe0(%rbp), %xmm0
movups -0xd0(%rbp), %xmm1
movaps %xmm1, -0xb0(%rbp)
movaps %xmm0, -0xc0(%rbp)
movq 0x18(%rax), %rsi
movaps -0xc0(%rbp), %xmm0
movaps -0xb0(%rbp), %xmm1
movaps %xmm1, -0x110(%rbp)
movaps %xmm0, -0x120(%rbp)
movaps -0x120(%rbp), %xmm0
movaps -0x110(%rbp), %xmm1
movq %rsp, %rax
movups %xmm1, 0x10(%rax)
movups %xmm0, (%rax)
leaq -0x100(%rbp), %rdi
callq 0x69a0
jmp 0x12287
movq -0x100(%rbp), %rax
movq %rax, -0xc0(%rbp)
movq -0xf8(%rbp), %rax
movq %rax, -0xb8(%rbp)
movq -0xf0(%rbp), %rax
movq %rax, -0xb0(%rbp)
movq -0xe8(%rbp), %rax
movq %rax, -0xa8(%rbp)
jmp 0x122f1
movq -0x30(%rbp), %rax
movq 0x10(%rax), %rcx
movq %rcx, -0xc0(%rbp)
movq 0x18(%rax), %rcx
movq %rcx, -0xb8(%rbp)
movq 0x20(%rax), %rcx
movq %rcx, -0xb0(%rbp)
movq 0x28(%rax), %rax
movq %rax, -0xa8(%rbp)
cmpl $0x1, -0x68(%rbp)
jne 0x12305
movl -0x50(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x50(%rbp)
jmp 0x123bd
movups -0x68(%rbp), %xmm0
movups -0x58(%rbp), %xmm1
movaps %xmm1, -0x150(%rbp)
movaps %xmm0, -0x160(%rbp)
movq $0x0, -0x190(%rbp)
movl $0x0, -0x188(%rbp)
movq -0x190(%rbp), %rdx
movl -0x188(%rbp), %ecx
leaq -0x180(%rbp), %rdi
movl $0x1, %esi
callq 0x5b20
jmp 0x12350
movups -0x180(%rbp), %xmm0
movups -0x170(%rbp), %xmm1
movq %rsp, %rax
movups %xmm1, 0x30(%rax)
movups %xmm0, 0x20(%rax)
movaps -0x160(%rbp), %xmm0
movaps -0x150(%rbp), %xmm1
movups %xmm1, 0x10(%rax)
movups %xmm0, (%rax)
leaq -0x140(%rbp), %rdi
movl $0x2b, %esi
callq 0x5f70
jmp 0x12391
movq -0x140(%rbp), %rax
movq %rax, -0x68(%rbp)
movq -0x138(%rbp), %rax
movq %rax, -0x60(%rbp)
movq -0x130(%rbp), %rax
movq %rax, -0x58(%rbp)
movq -0x128(%rbp), %rax
movq %rax, -0x50(%rbp)
movaps -0xc0(%rbp), %xmm0
movaps -0xb0(%rbp), %xmm1
movaps %xmm1, -0x1c0(%rbp)
movaps %xmm0, -0x1d0(%rbp)
movups -0x68(%rbp), %xmm0
movups -0x58(%rbp), %xmm1
movaps %xmm1, -0x1e0(%rbp)
movaps %xmm0, -0x1f0(%rbp)
movaps -0x1f0(%rbp), %xmm0
movaps -0x1e0(%rbp), %xmm1
movq %rsp, %rax
movups %xmm1, 0x30(%rax)
movups %xmm0, 0x20(%rax)
movaps -0x1d0(%rbp), %xmm0
movaps -0x1c0(%rbp), %xmm1
movups %xmm1, 0x10(%rax)
movups %xmm0, (%rax)
leaq -0x1b0(%rbp), %rdi
callq 0x68b0
jmp 0x1242b
movq -0x238(%rbp), %rcx
movq -0x1b0(%rbp), %rax
movq %rax, -0xc0(%rbp)
movq -0x1a8(%rbp), %rax
movq %rax, -0xb8(%rbp)
movq -0x1a0(%rbp), %rax
movq %rax, -0xb0(%rbp)
movq -0x198(%rbp), %rax
movq %rax, -0xa8(%rbp)
movq -0x78(%rbp), %rax
cmpq 0x10(%rcx), %rax
jne 0x12476
jmp 0x12495
leaq 0xa295(%rip), %rdi      # 0x1c712
leaq 0x92da(%rip), %rsi      # 0x1b75e
movl $0x62e, %edx            # imm = 0x62E
leaq 0xa165(%rip), %rcx      # 0x1c5f5
callq 0x20d0
movq -0x78(%rbp), %rdi
movups -0x98(%rbp), %xmm0
movups -0x88(%rbp), %xmm1
movaps %xmm1, -0x200(%rbp)
movaps %xmm0, -0x210(%rbp)
movaps -0xc0(%rbp), %xmm0
movaps -0xb0(%rbp), %xmm1
movaps %xmm1, -0x220(%rbp)
movaps %xmm0, -0x230(%rbp)
movaps -0x230(%rbp), %xmm0
movaps -0x220(%rbp), %xmm1
movq %rsp, %rax
movups %xmm1, 0x30(%rax)
movups %xmm0, 0x20(%rax)
movaps -0x210(%rbp), %xmm0
movaps -0x200(%rbp), %xmm1
movups %xmm1, 0x10(%rax)
movups %xmm0, (%rax)
callq 0x7200
jmp 0x12506
movl $0x0, -0x44(%rbp)
leaq -0x11(%rbp), %rdi
callq 0x3dd0
addq $0x2a0, %rsp            # imm = 0x2A0
popq %rbp
retq
movq -0x20(%rbp), %rdi
callq 0x21c0
nopl (%rax,%rax)