// File: baziotis[P]minijava-cpp/llvm.cpp
// Function: cgen_start_method(Method*, char const*, bool)
void cgen_start_method(Method *method, const char *class_name, bool is_main_method) {
    reset_lbl();
    // Emit function prototype
    emit("define ");
    cgen_print_lltype(method->ret_type);

    if (!is_main_method) {
      emit(" @%s__%s(", class_name, method->id);
    } else {
      emit(" @main(", class_name, method->id);
    }
    
    // Emit `this` pointer.
    size_t param_len = method->param_len;
    emit("i8* %%0");
    if (param_len)
      emit(", ");
    

    // Initialize parameters with registers and also
    // print them as part of the method prototype.
    // We're starting from 1, because register 0
    // is always reserved for the 'this' pointer.
    // Set a register _only_ for the parameters.
    size_t local_reg_counter = 1;
    size_t param_counter;
    for (param_counter = 0; param_counter < param_len; ++param_counter) {
        Local *local = method->locals[param_counter];
        // Print
        cgen_print_lltype(local->type);
        emit(" %%%ld", local_reg_counter);
        if (param_counter != param_len - 1) {
          emit(", ");
        }
        // Initialize
        local->kind = (int)LOCAL_KIND::PARAM;
        local->llval = register_llv(local_reg_counter, {});
        local->index = param_counter;
        ++local_reg_counter;
    }
    set_reg(local_reg_counter);

    // Start of body of method
    emit(") {\n");

    // Initialize locals. Locals initially get a
    // register that is a pointer to some memory
    // that can hold the value. It's only when they're
    // first used that the value is loaded into a reg.
    // So, initialize them with this pointer and also
    // generate allocas.
    size_t locals_len = method->locals.len;
    size_t var_counter = param_counter;
    for (; var_counter < locals_len; ++var_counter) {
        Local *local = method->locals[var_counter];
        local->kind = (int)LOCAL_KIND::VAR;
        local->index = var_counter;
        // Initialize all the values to 0.
        local->llval = const_llv(0, {});
    }

    llvm_label_t entry_lbl = llvm_label_t("entry");
    llvm_gen_lbl(entry_lbl);
}

// Assembly:
pushq %rbp
movq %rsp, %rbp
subq $0xc0, %rsp
movb %dl, %al
movq %rdi, -0x8(%rbp)
movq %rsi, -0x10(%rbp)
andb $0x1, %al
movb %al, -0x11(%rbp)
callq 0x5a70
leaq 0x1358b(%rip), %rdi     # 0x1a901
movb $0x0, %al
callq 0x5b70
movq -0x8(%rbp), %rax
movq 0x8(%rax), %rdi
callq 0x6170
testb $0x1, -0x11(%rbp)
jne 0x73ab
movq -0x10(%rbp), %rsi
movq -0x8(%rbp), %rax
movq (%rax), %rdx
leaq 0x13567(%rip), %rdi     # 0x1a909
movb $0x0, %al
callq 0x5b70
jmp 0x73c4
movq -0x10(%rbp), %rsi
movq -0x8(%rbp), %rax
movq (%rax), %rdx
leaq 0x13556(%rip), %rdi     # 0x1a913
movb $0x0, %al
callq 0x5b70
movq -0x8(%rbp), %rax
movq 0x10(%rax), %rax
movq %rax, -0x20(%rbp)
leaq 0x13544(%rip), %rdi     # 0x1a91b
movb $0x0, %al
callq 0x5b70
cmpq $0x0, -0x20(%rbp)
je 0x73f3
leaq 0x14cb6(%rip), %rdi     # 0x1c0a2
movb $0x0, %al
callq 0x5b70
movq $0x1, -0x28(%rbp)
movq $0x0, -0x30(%rbp)
movq -0x30(%rbp), %rax
cmpq -0x20(%rbp), %rax
jae 0x74df
movq -0x8(%rbp), %rdi
addq $0x18, %rdi
movq -0x30(%rbp), %rsi
callq 0x7870
movq (%rax), %rax
movq %rax, -0x38(%rbp)
movq -0x38(%rbp), %rax
movq 0x8(%rax), %rdi
callq 0x6170
movq -0x28(%rbp), %rsi
leaq 0x134e2(%rip), %rdi     # 0x1a923
movb $0x0, %al
callq 0x5b70
movq -0x30(%rbp), %rax
movq -0x20(%rbp), %rcx
subq $0x1, %rcx
cmpq %rcx, %rax
je 0x7467
leaq 0x14c42(%rip), %rdi     # 0x1c0a2
movb $0x0, %al
callq 0x5b70
movq -0x38(%rbp), %rax
movb $0x1, 0x38(%rax)
movq -0x28(%rbp), %rsi
movq $0x0, -0x68(%rbp)
movl $0x0, -0x60(%rbp)
movq -0x68(%rbp), %rdx
movl -0x60(%rbp), %ecx
leaq -0x58(%rbp), %rdi
callq 0x5ad0
movq -0x38(%rbp), %rax
movq -0x58(%rbp), %rcx
movq %rcx, 0x10(%rax)
movq -0x50(%rbp), %rcx
movq %rcx, 0x18(%rax)
movq -0x48(%rbp), %rcx
movq %rcx, 0x20(%rax)
movq -0x40(%rbp), %rcx
movq %rcx, 0x28(%rax)
movq -0x30(%rbp), %rcx
movq -0x38(%rbp), %rax
movq %rcx, 0x30(%rax)
movq -0x28(%rbp), %rax
addq $0x1, %rax
movq %rax, -0x28(%rbp)
movq -0x30(%rbp), %rax
addq $0x1, %rax
movq %rax, -0x30(%rbp)
jmp 0x7403
movq -0x28(%rbp), %rdi
callq 0x5a20
leaq 0x1343b(%rip), %rdi     # 0x1a92a
movb $0x0, %al
callq 0x5b70
movq -0x8(%rbp), %rax
movq 0x38(%rax), %rax
movq %rax, -0x70(%rbp)
movq -0x30(%rbp), %rax
movq %rax, -0x78(%rbp)
movq -0x78(%rbp), %rax
cmpq -0x70(%rbp), %rax
jae 0x75b5
movq -0x8(%rbp), %rdi
addq $0x18, %rdi
movq -0x78(%rbp), %rsi
callq 0x7870
movq (%rax), %rax
movq %rax, -0x80(%rbp)
movq -0x80(%rbp), %rax
movb $0x3, 0x38(%rax)
movq -0x78(%rbp), %rcx
movq -0x80(%rbp), %rax
movq %rcx, 0x30(%rax)
movq $0x0, -0xb0(%rbp)
movl $0x0, -0xa8(%rbp)
movq -0xb0(%rbp), %rdx
movl -0xa8(%rbp), %ecx
leaq -0xa0(%rbp), %rdi
xorl %esi, %esi
callq 0x5b20
movq -0x80(%rbp), %rax
movq -0xa0(%rbp), %rcx
movq %rcx, 0x10(%rax)
movq -0x98(%rbp), %rcx
movq %rcx, 0x18(%rax)
movq -0x90(%rbp), %rcx
movq %rcx, 0x20(%rax)
movq -0x88(%rbp), %rcx
movq %rcx, 0x28(%rax)
movq -0x78(%rbp), %rax
addq $0x1, %rax
movq %rax, -0x78(%rbp)
jmp 0x750a
leaq -0xb8(%rbp), %rdi
leaq 0x1336c(%rip), %rsi     # 0x1a92f
callq 0x7990
movq -0xb8(%rbp), %rax
movq %rax, -0xc0(%rbp)
movq -0xc0(%rbp), %rdi
callq 0x6c20
addq $0xc0, %rsp
popq %rbp
retq
nopl (%rax,%rax)