// File: /workspace/github_cpp_makefile_star2_O2/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 %r15
pushq %r14
pushq %r13
pushq %r12
pushq %rbx
cmpl $0x2, 0x30(%rsp)
jne 0x4872
movq %rdx, %r14
movq %rdi, %rbx
leaq 0x30(%rsp), %r15
movq 0x142e0(%rip), %r12     # 0x18a28
leaq 0x1(%r12), %rax
movq %rax, 0x142d4(%rip)     # 0x18a28
callq 0x44e4
leaq 0xa8b7(%rip), %rdi      # 0xf017
movq %r12, %rsi
xorl %eax, %eax
callq 0x42fe
movq 0x18(%r15), %rsi
leaq 0xaa84(%rip), %rdi      # 0xf1f9
xorl %eax, %eax
callq 0x42fe
movq 0x142a5(%rip), %r15     # 0x18a28
leaq 0x1(%r15), %rax
movq %rax, 0x1429a(%rip)     # 0x18a28
callq 0x44e4
leaq 0xa892(%rip), %rdi      # 0xf02c
movq %r15, %rsi
movq %r12, %rdx
xorl %eax, %eax
callq 0x42fe
movq 0x48(%r14), %r12
testq %r12, %r12
je 0x47e5
movq 0x14271(%rip), %r13     # 0x18a28
leaq 0x1(%r13), %rax
movq %rax, 0x14266(%rip)     # 0x18a28
callq 0x44e4
shrq $0x3, %r12
leaq 0xa883(%rip), %rdi      # 0xf055
movq %r13, %rsi
movq %r15, %rdx
movq %r12, %rcx
xorl %eax, %eax
callq 0x42fe
movq %r13, %r15
movq 0x1423c(%rip), %r12     # 0x18a28
leaq 0x1(%r12), %rax
movq %rax, 0x14230(%rip)     # 0x18a28
callq 0x44e4
leaq 0xa881(%rip), %rdi      # 0xf085
movq %r12, %rsi
movq %r15, %rdx
xorl %eax, %eax
callq 0x42fe
movq 0x14210(%rip), %r15     # 0x18a28
leaq 0x1(%r15), %rax
movl $0x2, (%rbx)
movq %r15, 0x18(%rbx)
andq $0x0, 0x8(%rbx)
movq %rax, 0x141f6(%rip)     # 0x18a28
andl $0x0, 0x10(%rbx)
callq 0x44e4
leaq 0xa861(%rip), %rdi      # 0xf0a3
movq %r15, %rsi
movq %r12, %rdx
xorl %eax, %eax
callq 0x42fe
movq %r14, %rsi
callq 0x469f
leaq 0xac0a(%rip), %rdi      # 0xf468
xorl %eax, %eax
callq 0x42fe
movq %rbx, %rax
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
retq
leaq 0xa741(%rip), %rdi      # 0xefba
leaq 0xa655(%rip), %rsi      # 0xeed5
leaq 0xa751(%rip), %rcx      # 0xefd8
movl $0xc8, %edx
callq 0x20b0