// File: baziotis[P]minijava-cpp/typecheck.cpp
// Function: MainTypeCheckVisitor::visit(AssignmentStatement*)
void MainTypeCheckVisitor::visit(AssignmentStatement *asgn_stmt) {
    LOG_SCOPE;
    debug_print("MainTypeCheck::AssignmentStatement\n");
    assert(this->curr_method);
    assert(this->curr_class);
    Local *lhs = lookup_local(asgn_stmt->id, this->curr_method, this->curr_class);
    if (!lhs) {
        // Of course, with variable we mean also parameter and field.
        typecheck_error(asgn_stmt->loc, "In assignment statement, variable: `",
                        asgn_stmt->id, "` is not defined");
        return;
    }
    poison_stmt(lhs->type);
    assert(asgn_stmt->rhs);
    Type *rhs_type = asgn_stmt->rhs->accept(this);
    poison_stmt(rhs_type);
    if (!compatible_types(lhs->type, rhs_type)) {
        typecheck_error(asgn_stmt->loc, "Incompatible types: `",
                        rhs_type->name(), "` can't be converted to `",
                        lhs->type->name(), "`");
        return;
    }
    /// Codegen ///
    llvalue_t rhs_val = __expr_context.llval;
    llvalue_t ptr;
    if (lhs->kind == (int)LOCAL_KIND::FIELD) {
        ptr = cgen_get_field_ptr(lhs);
    }
    // Bitcast the value to the type of the lhs
    if (lhs->type != rhs_type) {
        rhs_val = cgen_cast_value(rhs_val , rhs_type, lhs->type);
    }
    // Store the value: Handle fields separately.
    if (lhs->kind == (int)LOCAL_KIND::FIELD) {
        llvm_store(lhs->type, rhs_val, ptr);
    } else {
        // Just set `rhs_val` as the new llvalue.
        lhs->llval = rhs_val;
    }
    // Track assignment only for parameters and variables
    if (__expr_context.nesting_level && lhs->kind != (int)LOCAL_KIND::FIELD) {
        TrackAssignment tasgn;
        tasgn.assigned = true;
        tasgn.llval = lhs->llval;
        if (__expr_context.in_if) {
            __expr_context.if_bufs[__expr_context.nesting_level - 1][lhs->index] = tasgn;
        } else {
            __expr_context.else_bufs[__expr_context.nesting_level - 1][lhs->index] = tasgn;
        }
    }
    /// End of Codegen ///
}

// Assembly:
pushq %rbp
movq %rsp, %rbp
subq $0x1f0, %rsp            # imm = 0x1F0
movq %rdi, -0x8(%rbp)
movq %rsi, -0x10(%rbp)
movq -0x8(%rbp), %rax
movq %rax, -0x160(%rbp)
leaq -0x11(%rbp), %rdi
callq 0x3da0
leaq 0xab1c(%rip), %rdi      # 0x1c50a
xorl %eax, %eax
callq 0x3e60
jmp 0x119f7
movq -0x160(%rbp), %rax
cmpq $0x0, 0x78(%rax)
je 0x11a07
jmp 0x11a40
leaq 0xa43e(%rip), %rdi      # 0x1be4c
leaq 0x9d49(%rip), %rsi      # 0x1b75e
movl $0x5c8, %edx            # imm = 0x5C8
leaq 0xab0d(%rip), %rcx      # 0x1c52e
callq 0x20d0
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x20(%rbp)
movl %eax, -0x24(%rbp)
leaq -0x11(%rbp), %rdi
callq 0x3dd0
jmp 0x11ed3
movq -0x160(%rbp), %rax
cmpq $0x0, 0x80(%rax)
je 0x11a53
jmp 0x11a72
leaq 0xa404(%rip), %rdi      # 0x1be5e
leaq 0x9cfd(%rip), %rsi      # 0x1b75e
movl $0x5c9, %edx            # imm = 0x5C9
leaq 0xaac1(%rip), %rcx      # 0x1c52e
callq 0x20d0
movq -0x160(%rbp), %rax
movq -0x10(%rbp), %rcx
movq 0x10(%rcx), %rdi
movq 0x78(%rax), %rsi
movq 0x80(%rax), %rdx
callq 0x11490
movq %rax, -0x168(%rbp)
jmp 0x11a9a
movq -0x168(%rbp), %rax
movq %rax, -0x30(%rbp)
cmpq $0x0, -0x30(%rbp)
jne 0x11ae2
movq -0x10(%rbp), %rax
movl 0xc(%rax), %eax
movl %eax, -0x34(%rbp)
movq -0x10(%rbp), %rax
movq 0x10(%rax), %rdx
movl -0x34(%rbp), %edi
leaq 0xaa9e(%rip), %rsi      # 0x1c566
leaq 0xaabc(%rip), %rcx      # 0x1c58b
callq 0xda80
jmp 0x11ad6
movl $0x1, -0x38(%rbp)
jmp 0x11ec1
movq -0x30(%rbp), %rax
movq 0x8(%rax), %rax
cmpl $0x0, 0x4(%rax)
jne 0x11afc
movl $0x1, -0x38(%rbp)
jmp 0x11ec1
movq -0x10(%rbp), %rax
cmpq $0x0, 0x18(%rax)
je 0x11b09
jmp 0x11b28
leaq 0xabb8(%rip), %rdi      # 0x1c6c8
leaq 0x9c47(%rip), %rsi      # 0x1b75e
movl $0x5d2, %edx            # imm = 0x5D2
leaq 0xaa0b(%rip), %rcx      # 0x1c52e
callq 0x20d0
movq -0x160(%rbp), %rsi
movq -0x10(%rbp), %rax
movq 0x18(%rax), %rdi
callq 0x16490
movq %rax, -0x170(%rbp)
jmp 0x11b45
movq -0x170(%rbp), %rax
movq %rax, -0x40(%rbp)
movq -0x40(%rbp), %rax
cmpl $0x0, 0x4(%rax)
jne 0x11b66
movl $0x1, -0x38(%rbp)
jmp 0x11ec1
movq -0x30(%rbp), %rax
movq 0x8(%rax), %rdi
movq -0x40(%rbp), %rsi
callq 0xebe0
movb %al, -0x171(%rbp)
jmp 0x11b7f
movb -0x171(%rbp), %al
testb $0x1, %al
jne 0x11bf6
jmp 0x11b8b
movq -0x10(%rbp), %rax
movl 0xc(%rax), %eax
movl %eax, -0x44(%rbp)
movq -0x40(%rbp), %rdi
callq 0xc180
movq %rax, -0x180(%rbp)
jmp 0x11ba7
movq -0x30(%rbp), %rax
movq 0x8(%rax), %rdi
callq 0xc180
movq %rax, -0x188(%rbp)
jmp 0x11bbd
movq -0x188(%rbp), %r8
movq -0x180(%rbp), %rdx
movl -0x44(%rbp), %edi
leaq 0xa9c7(%rip), %rsi      # 0x1c59c
leaq 0xa9d6(%rip), %rcx      # 0x1c5b2
leaq 0x914a(%rip), %r9       # 0x1ad2d
callq 0xdb00
jmp 0x11bea
movl $0x1, -0x38(%rbp)
jmp 0x11ec1
leaq 0x12dcb(%rip), %rax     # 0x249c8
movq 0x8(%rax), %rcx
movq %rcx, -0x68(%rbp)
movq 0x10(%rax), %rcx
movq %rcx, -0x60(%rbp)
movq 0x18(%rax), %rcx
movq %rcx, -0x58(%rbp)
movq 0x20(%rax), %rax
movq %rax, -0x50(%rbp)
leaq -0x88(%rbp), %rdi
callq 0x7840
movq -0x30(%rbp), %rax
movsbl 0x38(%rax), %eax
cmpl $0x2, %eax
jne 0x11c77
movq -0x30(%rbp), %rsi
leaq -0xa8(%rbp), %rdi
callq 0x6460
jmp 0x11c48
movq -0xa8(%rbp), %rax
movq %rax, -0x88(%rbp)
movq -0xa0(%rbp), %rax
movq %rax, -0x80(%rbp)
movq -0x98(%rbp), %rax
movq %rax, -0x78(%rbp)
movq -0x90(%rbp), %rax
movq %rax, -0x70(%rbp)
movq -0x30(%rbp), %rax
movq 0x8(%rax), %rax
cmpq -0x40(%rbp), %rax
je 0x11cf9
movups -0x68(%rbp), %xmm0
movups -0x58(%rbp), %xmm1
movaps %xmm1, -0xe0(%rbp)
movaps %xmm0, -0xf0(%rbp)
movq -0x40(%rbp), %rsi
movq -0x30(%rbp), %rax
movq 0x8(%rax), %rdx
movaps -0xf0(%rbp), %xmm0
movaps -0xe0(%rbp), %xmm1
movq %rsp, %rax
movups %xmm1, 0x10(%rax)
movups %xmm0, (%rax)
leaq -0xc8(%rbp), %rdi
callq 0x7630
jmp 0x11ccd
movq -0xc8(%rbp), %rax
movq %rax, -0x68(%rbp)
movq -0xc0(%rbp), %rax
movq %rax, -0x60(%rbp)
movq -0xb8(%rbp), %rax
movq %rax, -0x58(%rbp)
movq -0xb0(%rbp), %rax
movq %rax, -0x50(%rbp)
movq -0x30(%rbp), %rax
movsbl 0x38(%rax), %eax
cmpl $0x2, %eax
jne 0x11d74
movq -0x30(%rbp), %rax
movq 0x8(%rax), %rdi
movups -0x68(%rbp), %xmm0
movups -0x58(%rbp), %xmm1
movaps %xmm1, -0x100(%rbp)
movaps %xmm0, -0x110(%rbp)
movups -0x88(%rbp), %xmm0
movups -0x78(%rbp), %xmm1
movaps %xmm1, -0x120(%rbp)
movaps %xmm0, -0x130(%rbp)
movaps -0x130(%rbp), %xmm0
movaps -0x120(%rbp), %xmm1
movq %rsp, %rax
movups %xmm1, 0x30(%rax)
movups %xmm0, 0x20(%rax)
movaps -0x110(%rbp), %xmm0
movaps -0x100(%rbp), %xmm1
movups %xmm1, 0x10(%rax)
movups %xmm0, (%rax)
callq 0x7200
jmp 0x11d72
jmp 0x11d98
movq -0x30(%rbp), %rax
movq -0x68(%rbp), %rcx
movq %rcx, 0x10(%rax)
movq -0x60(%rbp), %rcx
movq %rcx, 0x18(%rax)
movq -0x58(%rbp), %rcx
movq %rcx, 0x20(%rax)
movq -0x50(%rbp), %rcx
movq %rcx, 0x28(%rax)
leaq 0x12c29(%rip), %rax     # 0x249c8
cmpl $0x0, 0x30(%rax)
je 0x11eba
movq -0x30(%rbp), %rax
movsbl 0x38(%rax), %eax
cmpl $0x2, %eax
je 0x11eba
leaq -0x158(%rbp), %rdi
callq 0x167b0
movb $0x1, -0x138(%rbp)
movq -0x30(%rbp), %rax
movq 0x10(%rax), %rcx
movq %rcx, -0x158(%rbp)
movq 0x18(%rax), %rcx
movq %rcx, -0x150(%rbp)
movq 0x20(%rax), %rcx
movq %rcx, -0x148(%rbp)
movq 0x28(%rax), %rax
movq %rax, -0x140(%rbp)
leaq 0x12bc4(%rip), %rax     # 0x249c8
testb $0x1, 0x38(%rax)
je 0x11e62
leaq 0x12bb7(%rip), %rdi     # 0x249c8
movl 0x30(%rdi), %eax
decl %eax
movslq %eax, %rsi
addq $0x40, %rdi
callq 0x16410
movq %rax, -0x190(%rbp)
jmp 0x11e2b
movq -0x190(%rbp), %rdi
movq -0x30(%rbp), %rax
movq 0x30(%rax), %rsi
callq 0x16430
movq %rax, -0x198(%rbp)
jmp 0x11e48
movq -0x198(%rbp), %rdi
leaq -0x158(%rbp), %rsi
movl $0x21, %edx
callq 0x2100
jmp 0x11eb8
leaq 0x12b5f(%rip), %rdi     # 0x249c8
movl 0x30(%rdi), %eax
decl %eax
movslq %eax, %rsi
addq $0x58, %rdi
callq 0x16410
movq %rax, -0x1a0(%rbp)
jmp 0x11e83
movq -0x1a0(%rbp), %rdi
movq -0x30(%rbp), %rax
movq 0x30(%rax), %rsi
callq 0x16430
movq %rax, -0x1a8(%rbp)
jmp 0x11ea0
movq -0x1a8(%rbp), %rdi
leaq -0x158(%rbp), %rsi
movl $0x21, %edx
callq 0x2100
jmp 0x11eba
movl $0x0, -0x38(%rbp)
leaq -0x11(%rbp), %rdi
callq 0x3dd0
addq $0x1f0, %rsp            # imm = 0x1F0
popq %rbp
retq
movq -0x20(%rbp), %rdi
callq 0x21c0
nopl (%rax)