// File: baziotis[P]minijava-cpp/llvm.cpp
// Function: llvm_call(Type*, Type*, llvalue_t, llvalue_t, Array<Type*, (MEM)4>, Array<llvalue_t, (MEM)4>)
llvalue_t llvm_call(Type *ret_type, Type *base_obj_ty, llvalue_t base_obj,
                    llvalue_t vmethod, FuncArr<Type*> types,
                    FuncArr<llvalue_t> values)
{
    llvalue_t v;
    v.kind = LLVALUE::REG;
    v.reg = gen_reg();
    print_codegen_indentation();
    emit("%%%ld = call ", v.reg);
    // Print the return type
    cgen_print_lltype(ret_type);
    emit(" ");  // space
    assert(vmethod.kind == LLVALUE::REG);
    // Print the register that points to the vmethod
    emit("%%%ld(i8* ", vmethod.reg);
    cgen_print_llvalue(base_obj);
    if (types.len) {
      emit(", ");
    }
    // Print the types of args along with the args themselves
    // as a comma-separate list
    assert(types.len == values.len);
    for (size_t i = 0; i != types.len; ++i) {
        cgen_print_lltype(types[i]);
        emit(" ");  // space
        cgen_print_llvalue(values[i]);
        if (i != types.len - 1) {
            emit(", ");
        }
    }
    emit(")\n");
    return v;
}

// Assembly:
pushq %rbp
movq %rsp, %rbp
subq $0xb0, %rsp
movq %rdi, -0x68(%rbp)
movq %rdi, %rax
movq %rax, -0x88(%rbp)
leaq 0x68(%rbp), %rax
movq %rax, -0x80(%rbp)
leaq 0x50(%rbp), %rax
movq %rax, -0x78(%rbp)
leaq 0x30(%rbp), %rax
movq %rax, -0x60(%rbp)
leaq 0x10(%rbp), %rax
movq %rax, -0x70(%rbp)
movq %rsi, -0x8(%rbp)
movq %rdx, -0x10(%rbp)
callq 0x7840
movq -0x68(%rbp), %rdi
movl $0x2, (%rdi)
callq 0x5a40
movq -0x68(%rbp), %rdi
movq %rax, 0x18(%rdi)
callq 0x5f30
movq -0x68(%rbp), %rdi
movq 0x18(%rdi), %rsi
leaq 0x13879(%rip), %rdi     # 0x1a77a
movb $0x0, %al
callq 0x5b70
movq -0x8(%rbp), %rdi
callq 0x6170
leaq 0x133ee(%rip), %rdi     # 0x1a306
movb $0x0, %al
callq 0x5b70
movq -0x60(%rbp), %rax
cmpl $0x2, (%rax)
jne 0x6f2a
jmp 0x6f49
leaq 0x13857(%rip), %rdi     # 0x1a788
leaq 0x13279(%rip), %rsi     # 0x1a1b1
movl $0x19b, %edx            # imm = 0x19B
leaq 0x13861(%rip), %rcx     # 0x1a7a5
callq 0x20d0
movq -0x60(%rbp), %rax
movq 0x18(%rax), %rsi
leaq 0x138ac(%rip), %rdi     # 0x1a804
movb $0x0, %al
callq 0x5b70
movq -0x70(%rbp), %rax
movq (%rax), %rcx
movq %rcx, -0x30(%rbp)
movq 0x8(%rax), %rcx
movq %rcx, -0x28(%rbp)
movq 0x10(%rax), %rcx
movq %rcx, -0x20(%rbp)
movq 0x18(%rax), %rax
movq %rax, -0x18(%rbp)
leaq -0x30(%rbp), %rax
xorl %edi, %edi
movq (%rax), %rcx
movq %rcx, (%rsp)
movq 0x8(%rax), %rcx
movq %rcx, 0x8(%rsp)
movq 0x10(%rax), %rcx
movq %rcx, 0x10(%rsp)
movq 0x18(%rax), %rax
movq %rax, 0x18(%rsp)
callq 0x5d40
movq -0x78(%rbp), %rax
cmpq $0x0, 0x8(%rax)
je 0x6fc8
leaq 0x150e1(%rip), %rdi     # 0x1c0a2
movb $0x0, %al
callq 0x5b70
movq -0x80(%rbp), %rcx
movq -0x78(%rbp), %rax
movq 0x8(%rax), %rax
cmpq 0x8(%rcx), %rax
jne 0x6fdc
jmp 0x6ffb
leaq 0x1382c(%rip), %rdi     # 0x1a80f
leaq 0x131c7(%rip), %rsi     # 0x1a1b1
movl $0x1a4, %edx            # imm = 0x1A4
leaq 0x137af(%rip), %rcx     # 0x1a7a5
callq 0x20d0
movq $0x0, -0x38(%rbp)
movq -0x78(%rbp), %rcx
movq -0x38(%rbp), %rax
cmpq 0x8(%rcx), %rax
je 0x70c7
movq -0x78(%rbp), %rdi
movq -0x38(%rbp), %rsi
callq 0x78a0
movq (%rax), %rdi
callq 0x6170
leaq 0x132d5(%rip), %rdi     # 0x1a306
movb $0x0, %al
callq 0x5b70
movq -0x80(%rbp), %rdi
movq -0x38(%rbp), %rsi
callq 0x7900
movq (%rax), %rcx
movq %rcx, -0x58(%rbp)
movq 0x8(%rax), %rcx
movq %rcx, -0x50(%rbp)
movq 0x10(%rax), %rcx
movq %rcx, -0x48(%rbp)
movq 0x18(%rax), %rax
movq %rax, -0x40(%rbp)
leaq -0x58(%rbp), %rax
xorl %edi, %edi
movq (%rax), %rcx
movq %rcx, (%rsp)
movq 0x8(%rax), %rcx
movq %rcx, 0x8(%rsp)
movq 0x10(%rax), %rcx
movq %rcx, 0x10(%rsp)
movq 0x18(%rax), %rax
movq %rax, 0x18(%rsp)
callq 0x5d40
movq -0x78(%rbp), %rcx
movq -0x38(%rbp), %rax
movq 0x8(%rcx), %rcx
subq $0x1, %rcx
cmpq %rcx, %rax
je 0x70b4
leaq 0x14ff5(%rip), %rdi     # 0x1c0a2
movb $0x0, %al
callq 0x5b70
jmp 0x70b6
movq -0x38(%rbp), %rax
addq $0x1, %rax
movq %rax, -0x38(%rbp)
jmp 0x7003
leaq 0x15368(%rip), %rdi     # 0x1c436
movb $0x0, %al
callq 0x5b70
movq -0x88(%rbp), %rax
addq $0xb0, %rsp
popq %rbp
retq
nopw %cs:(%rax,%rax)