// File: /workspace/github_cpp_makefile_star2_O1/baziotis[P]minijava-cpp/typecheck.cpp
// Function: MainTypeCheckVisitor::visit(Method*, char const*)
void MainTypeCheckVisitor::visit(Method *method, const char *class_name) {
    LOG_SCOPE;
    debug_print("MainTypeCheck::Method %s\n", method->id);
    this->curr_method = method;

    __expr_context.method = method;

    bool is_main_method = method->id == main_method_string;

    cgen_start_method(method, class_name, is_main_method);

    if (is_main_method && type_transitively_extends_Main(this, class_name))
    {
        typecheck_error(method->loc, "In type: `", class_name,
                        "` you can't name a method `main` because "
                        "the type transitively extends `Main` class.");
    }

    for (int i = 0; i < __expr_context.nesting_level; ++i) {
      for (int j = 0; j < __expr_context.if_bufs[i].len; ++j) {
        __expr_context.if_bufs[i][j].assigned = false;
      }
      for (int j = 0; j < __expr_context.else_bufs[i].len; ++j) {
        __expr_context.else_bufs[i][j].assigned = false;
      }
    }
    __expr_context.nesting_level = 0;


    for (Statement *stmt : method->stmts) {
        stmt->accept(this);
    }
    // An undefined return expression may actually end up here.
    // Check parse.cpp
    // A null expression may also come here because of the `main()` method.
    if (!is_main_method && !method->ret_expr->is_undefined()) {
        assert(method->ret_expr);
        Type *ret_type = method->ret_expr->accept(this);
        if (ret_type->kind != TY::UNDEFINED) {
          assert(ret_type);
          assert(method->ret_type);
          llvalue_t ret_val = __expr_context.llval;
          if (!compatible_types(method->ret_type, ret_type)) {
              location_t loc_here = method->ret_expr->loc;
              typecheck_error(loc_here, "The type: `", ret_type->name(),
                              "` of the return expression does not match the ",
                              "return type: `", method->ret_type->name(),
                              "` of method: `", method->id, "`");
          } else {
              llvm_ret(ret_type, ret_val);
          }
        }
    }
    this->curr_method = NULL;

    cgen_end_method(is_main_method);

    // Free arena for objects of function lifetime
    deallocate(MEM::FUNC);
}

// Assembly:
pushq %rbp
pushq %r15
pushq %r14
pushq %r13
pushq %r12
pushq %rbx
subq $0x38, %rsp
movq %rdx, %r15
movq %rsi, %r14
movq %rdi, %rbx
leaq 0x27(%rsp), %rdi
callq 0x34d0
movq (%r14), %rsi
leaq 0x837e(%rip), %rdi      # 0x129b5
xorl %eax, %eax
callq 0x3541
movq %r14, 0x78(%rbx)
leaq 0xf36f(%rip), %rax      # 0x199b8
movq %r14, 0x28(%rax)
movq (%r14), %rbp
leaq 0xf3f1(%rip), %rax      # 0x19a48
movq (%rax), %r13
xorl %edx, %edx
cmpq %r13, %rbp
sete %dl
movq %r14, %rdi
movq %r15, %rsi
callq 0x59bd
cmpq %r13, %rbp
je 0xa7a1
movq %r13, 0x30(%rsp)
leaq 0xf336(%rip), %r10      # 0x199b8
movslq 0x30(%r10), %rax
testq %rax, %rax
jle 0xa6e6
movq 0x50(%r10), %rcx
movq 0x68(%r10), %rdx
xorl %esi, %esi
leaq (%rsi,%rsi,2), %rdi
movq 0x8(%rcx,%rdi,8), %r8
testq %r8, %r8
je 0xa6bc
leaq (%rcx,%rdi,8), %r9
movq 0x10(%r9), %r9
addq $0x20, %r9
movb $0x0, (%r9)
addq $0x28, %r9
decq %r8
jne 0xa6af
movq 0x8(%rdx,%rdi,8), %r8
testq %r8, %r8
je 0xa6de
leaq (%rdx,%rdi,8), %rdi
movq 0x10(%rdi), %rdi
addq $0x20, %rdi
movb $0x0, (%rdi)
addq $0x28, %rdi
decq %r8
jne 0xa6d2
incq %rsi
cmpq %rax, %rsi
jne 0xa695
movl $0x0, 0x30(%r10)
movq 0x60(%r14), %r15
testq %r15, %r15
je 0xa719
movq 0x68(%r14), %r13
shlq $0x3, %r15
xorl %r12d, %r12d
movq (%r13,%r12), %rdi
movq (%rdi), %rax
movq %rbx, %rsi
callq *0x18(%rax)
addq $0x8, %r12
cmpq %r12, %r15
jne 0xa702
movq %rbp, %r12
movq 0x30(%rsp), %rbp
cmpq %rbp, %r12
je 0xa90b
movq 0x70(%r14), %rsi
cmpl $0x0, 0x4(%rsi)
je 0xa90b
testq %rsi, %rsi
je 0xa994
movq %rbx, %rdi
callq 0xaa90
movq %rax, %r15
cmpl $0x0, 0x4(%rax)
je 0xa90b
testq %r15, %r15
je 0xa9d2
movq 0x8(%r14), %rdi
testq %rdi, %rdi
je 0xa9f1
movq %r15, %rsi
callq 0xaa4c
testb %al, %al
je 0xa7fc
leaq 0xf235(%rip), %rax      # 0x199b8
movups 0x8(%rax), %xmm0
movups 0x18(%rax), %xmm1
movups %xmm1, 0x10(%rsp)
movups %xmm0, (%rsp)
movq %r15, %rdi
callq 0x5c5e
jmp 0xa90b
movq 0x30(%rbx), %rcx
testq %rcx, %rcx
je 0xa7f5
testq %r15, %r15
je 0xaa10
imull $0x5f5e505, %r15d, %edx # imm = 0x5F5E505
imulq %rcx, %rdx
shrq $0x20, %rdx
movq 0x38(%rbx), %rdi
xorl %eax, %eax
movq %rdx, %rsi
movq (%rdi,%rsi,8), %r8
cmpq %r15, %r8
je 0xa944
testq %r8, %r8
je 0xa94c
incq %rsi
cmpq %rcx, %rsi
cmoveq %rax, %rsi
cmpq %rdx, %rsi
jne 0xa7cb
jmp 0xa94c
xorl %eax, %eax
jmp 0xa94c
movq 0x70(%r14), %rax
movl (%rax), %r13d
movq %r15, %rdi
callq 0x84fa
movq %rax, %r15
movq 0x8(%r14), %rdi
callq 0x84fa
movq (%r14), %rcx
movq %rcx, 0x28(%rsp)
incl 0x11263(%rip)           # 0x1ba88
movq %rax, %r14
leaq 0xf211(%rip), %rax      # 0x19a40
movq (%rax), %rsi
leaq 0x64bd(%rip), %rdi      # 0x10cf6
movl %r13d, %edx
xorl %eax, %eax
callq 0x2030
leaq 0xf1ee(%rip), %r13      # 0x19a38
cmpb $0x1, 0x1(%r13)
jne 0xa85f
leaq 0x942a(%rip), %rdi      # 0x13c82
xorl %eax, %eax
callq 0x2030
cmpb $0x1, 0x1(%r13)
jne 0xa874
leaq 0x6492(%rip), %rdi      # 0x10cff
xorl %eax, %eax
callq 0x2030
leaq 0x5b39(%rip), %rdi      # 0x103b4
leaq 0x93ee(%rip), %rsi      # 0x13c70
xorl %eax, %eax
callq 0x2030
cmpb $0x1, 0x1(%r13)
jne 0xa89e
leaq 0x5c6e(%rip), %rdi      # 0x10505
xorl %eax, %eax
callq 0x2030
cmpb $0x1, 0x1(%r13)
jne 0xa8b3
leaq 0x5c59(%rip), %rdi      # 0x10505
xorl %eax, %eax
callq 0x2030
leaq 0x5afa(%rip), %r13      # 0x103b4
leaq 0x81c9(%rip), %rsi      # 0x12a8a
movq %r13, %rdi
xorl %eax, %eax
callq 0x2030
movq %r13, %rdi
movq %r15, %rsi
xorl %eax, %eax
callq 0x2030
leaq 0x81b7(%rip), %rdi      # 0x12a96
leaq 0x81df(%rip), %rsi      # 0x12ac5
leaq 0x81e7(%rip), %rcx      # 0x12ad4
leaq 0x717d(%rip), %r9       # 0x11a71
movq %r14, %rdx
movq 0x28(%rsp), %r8
callq 0xeafe
movl $0xa, %edi
callq 0x2160
xorl %edi, %edi
cmpq %rbp, %r12
sete %dil
movq $0x0, 0x78(%rbx)
callq 0x5b3d
movl $0x4, %edi
callq 0x240c
leaq 0x27(%rsp), %rdi
callq 0x34e4
addq $0x38, %rsp
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq
movq 0x40(%rbx), %rax
movq (%rax,%rsi,8), %rax
testq %rax, %rax
je 0xa9b3
movq 0x20(%rbx), %rcx
movq 0x8(%rcx), %rcx
movq 0x78(%rax), %rax
testq %rax, %rax
je 0xa676
cmpq %rcx, 0x8(%rax)
jne 0xa959
testq %rax, %rax
je 0xa676
movl 0x50(%r14), %edi
leaq 0x804f(%rip), %rsi      # 0x129cf
leaq 0x8053(%rip), %rcx      # 0x129da
movq %r15, %rdx
callq 0x9b13
jmp 0xa676
leaq 0x8094(%rip), %rdi      # 0x12a2f
leaq 0x7aec(%rip), %rsi      # 0x1248e
leaq 0x8097(%rip), %rcx      # 0x12a40
movl $0x33e, %edx            # imm = 0x33E
callq 0x20b0
leaq 0x82e6(%rip), %rdi      # 0x12ca0
leaq 0x7acd(%rip), %rsi      # 0x1248e
leaq 0x90c8(%rip), %rcx      # 0x13a90
movl $0x30f, %edx            # imm = 0x30F
callq 0x20b0
leaq 0x80a8(%rip), %rdi      # 0x12a81
leaq 0x7aae(%rip), %rsi      # 0x1248e
leaq 0x8059(%rip), %rcx      # 0x12a40
movl $0x341, %edx            # imm = 0x341
callq 0x20b0
leaq 0x8081(%rip), %rdi      # 0x12a79
leaq 0x7a8f(%rip), %rsi      # 0x1248e
leaq 0x803a(%rip), %rcx      # 0x12a40
movl $0x342, %edx            # imm = 0x342
callq 0x20b0
leaq 0x8dfd(%rip), %rdi      # 0x13814
leaq 0x8dfa(%rip), %rsi      # 0x13818
leaq 0x8e02(%rip), %rcx      # 0x13827
movl $0x5e, %edx
callq 0x20b0
jmp 0xaa37
jmp 0xaa37
jmp 0xaa37
jmp 0xaa37
movq %rax, %rbx
leaq 0x27(%rsp), %rdi
callq 0x34e4
movq %rbx, %rdi
callq 0x21c0