// File: /workspace/github_cpp_makefile_star2_O3/baziotis[P]minijava-cpp/llvm.cpp
// Function: cgen_get_virtual_method(Type*, llvalue_t, Method*)
llvalue_t cgen_get_virtual_method(Type *base_obj_ty, llvalue_t base_obj, Method *method) {
    assert(base_obj.kind == LLVALUE::REG);
    long i8ppp = gen_reg();
    print_codegen_indentation();
    // Bitcast the object pointer to i8***.
    // Note that the vptr is a i8**. So, with this bitcast,
    // and just loading a i8**, we get the vptr.
    emit("%%%ld = bitcast i8* ", i8ppp);
    emit("%%%ld to i8***\n", base_obj.reg);
    long vptr = gen_reg();
    print_codegen_indentation();
    // Get the vptr
    emit("%%%ld = load i8**, i8*** %%%ld, align 8\n", vptr, i8ppp);
    // Go to the correct offset in the virtual table.
    long gep = vptr;
    size_t offset = method->offset;
    if (offset) {
        gep = gen_reg();
        print_codegen_indentation();
        // offset / 8 because the type is i8**. So, a pointer
        // and because GEP works like C pointers, +1 in a pointer
        // is +8 actual.
        emit("%%%ld = getelementptr i8*, i8** %%%ld, i32 %zd\n",
             gep, vptr, offset / 8);
    }
    long vmethod_i8 = gen_reg();
    print_codegen_indentation();
    // Load the pointer for the method.
    emit("%%%ld = load i8*, i8** %%%ld\n", vmethod_i8, gep);
    llvalue_t vmethod = register_llv(gen_reg(), {});
    print_codegen_indentation();
    // Finally, bitcast this pointer to the type of the method.
    emit("%%%ld = bitcast i8* %%%ld to ", vmethod.reg, vmethod_i8);
    emit_vmethod_signature(base_obj_ty, method);
    emit("\n");
    return vmethod;
}

// Assembly:
pushq %rbp
pushq %r15
pushq %r14
pushq %r13
pushq %r12
pushq %rbx
pushq %rax
cmpl $0x2, 0x40(%rsp)
jne 0x4dfc
movq %rdx, %r14
movq %rdi, %rbx
leaq 0x40(%rsp), %r13
movq 0x15dd6(%rip), %r15     # 0x1aa28
leaq 0x1(%r15), %rax
movq %rax, 0x15dcb(%rip)     # 0x1aa28
movl $0x4, %ebp
leaq 0xd3ed(%rip), %r12      # 0x12056
movq %r12, %rdi
xorl %eax, %eax
callq 0x47a5
decl %ebp
jne 0x4c69
leaq 0xd3c5(%rip), %rdi      # 0x12043
movq %r15, %rsi
xorl %eax, %eax
callq 0x47a5
movq 0x18(%r13), %rsi
leaq 0xd592(%rip), %rdi      # 0x12225
xorl %eax, %eax
callq 0x47a5
movq 0x15d87(%rip), %r12     # 0x1aa28
leaq 0x1(%r12), %rax
movq %rax, 0x15d7b(%rip)     # 0x1aa28
movl $0x4, %ebp
leaq 0xd39d(%rip), %r13      # 0x12056
movq %r13, %rdi
xorl %eax, %eax
callq 0x47a5
decl %ebp
jne 0x4cb9
leaq 0xd38a(%rip), %rdi      # 0x12058
movq %r12, %rsi
movq %r15, %rdx
xorl %eax, %eax
callq 0x47a5
movq 0x48(%r14), %r13
testq %r13, %r13
je 0x4d37
movq %r14, (%rsp)
movq 0x15d39(%rip), %r15     # 0x1aa28
leaq 0x1(%r15), %rax
movq %rax, 0x15d2e(%rip)     # 0x1aa28
movl $0x4, %r14d
leaq 0xd34f(%rip), %rbp      # 0x12056
movq %rbp, %rdi
xorl %eax, %eax
callq 0x47a5
decl %r14d
jne 0x4d07
shrq $0x3, %r13
leaq 0xd360(%rip), %rdi      # 0x12081
movq %r15, %rsi
movq %r12, %rdx
movq %r13, %rcx
xorl %eax, %eax
callq 0x47a5
movq (%rsp), %r14
jmp 0x4d3a
movq %r12, %r15
movq 0x15ce7(%rip), %r12     # 0x1aa28
leaq 0x1(%r12), %rax
movq %rax, 0x15cdb(%rip)     # 0x1aa28
movl $0x4, %ebp
leaq 0xd2fd(%rip), %r13      # 0x12056
movq %r13, %rdi
xorl %eax, %eax
callq 0x47a5
decl %ebp
jne 0x4d59
leaq 0xd343(%rip), %rdi      # 0x120b1
movq %r12, %rsi
movq %r15, %rdx
xorl %eax, %eax
callq 0x47a5
movq 0x15ca6(%rip), %r15     # 0x1aa28
leaq 0x1(%r15), %rax
movq %rax, 0x15c9b(%rip)     # 0x1aa28
movl $0x2, (%rbx)
movq %r15, 0x18(%rbx)
movq $0x0, 0x8(%rbx)
movl $0x0, 0x10(%rbx)
movl $0x4, %ebp
leaq 0xd2a4(%rip), %r13      # 0x12056
movq %r13, %rdi
xorl %eax, %eax
callq 0x47a5
decl %ebp
jne 0x4db2
leaq 0xd308(%rip), %rdi      # 0x120cf
movq %r15, %rsi
movq %r12, %rdx
xorl %eax, %eax
callq 0x47a5
movq %r14, %rsi
callq 0x4b9e
leaq 0xd6b1(%rip), %rdi      # 0x12494
xorl %eax, %eax
callq 0x47a5
movq %rbx, %rax
addq $0x8, %rsp
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq
leaq 0xd1e3(%rip), %rdi      # 0x11fe6
leaq 0xd0f7(%rip), %rsi      # 0x11f01
leaq 0xd1f3(%rip), %rcx      # 0x12004
movl $0xc8, %edx
callq 0x20b0