// File: /workspace/github_cpp_makefile_star2_O1/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 0x4df0
movq %rdx, %r14
movq %rdi, %rbx
leaq 0x40(%rsp), %r13
movq 0x14de2(%rip), %r15     # 0x19a28
leaq 0x1(%r15), %rax
movq %rax, 0x14dd7(%rip)     # 0x19a28
movl $0x4, %ebp
leaq 0xc47d(%rip), %r12      # 0x110da
movq %r12, %rdi
xorl %eax, %eax
callq 0x479d
decl %ebp
jne 0x4c5d
leaq 0xc455(%rip), %rdi      # 0x110c7
movq %r15, %rsi
xorl %eax, %eax
callq 0x479d
movq 0x18(%r13), %rsi
leaq 0xc622(%rip), %rdi      # 0x112a9
xorl %eax, %eax
callq 0x479d
movq 0x14d93(%rip), %r12     # 0x19a28
leaq 0x1(%r12), %rax
movq %rax, 0x14d87(%rip)     # 0x19a28
movl $0x4, %ebp
leaq 0xc42d(%rip), %r13      # 0x110da
movq %r13, %rdi
xorl %eax, %eax
callq 0x479d
decl %ebp
jne 0x4cad
leaq 0xc41a(%rip), %rdi      # 0x110dc
movq %r12, %rsi
movq %r15, %rdx
xorl %eax, %eax
callq 0x479d
movq 0x48(%r14), %r13
testq %r13, %r13
je 0x4d2b
movq %r14, (%rsp)
movq 0x14d45(%rip), %r15     # 0x19a28
leaq 0x1(%r15), %rax
movq %rax, 0x14d3a(%rip)     # 0x19a28
movl $0x4, %r14d
leaq 0xc3df(%rip), %rbp      # 0x110da
movq %rbp, %rdi
xorl %eax, %eax
callq 0x479d
decl %r14d
jne 0x4cfb
shrq $0x3, %r13
leaq 0xc3f0(%rip), %rdi      # 0x11105
movq %r15, %rsi
movq %r12, %rdx
movq %r13, %rcx
xorl %eax, %eax
callq 0x479d
movq (%rsp), %r14
jmp 0x4d2e
movq %r12, %r15
movq 0x14cf3(%rip), %r12     # 0x19a28
leaq 0x1(%r12), %rax
movq %rax, 0x14ce7(%rip)     # 0x19a28
movl $0x4, %ebp
leaq 0xc38d(%rip), %r13      # 0x110da
movq %r13, %rdi
xorl %eax, %eax
callq 0x479d
decl %ebp
jne 0x4d4d
leaq 0xc3d3(%rip), %rdi      # 0x11135
movq %r12, %rsi
movq %r15, %rdx
xorl %eax, %eax
callq 0x479d
movq 0x14cb2(%rip), %r15     # 0x19a28
leaq 0x1(%r15), %rax
movq %rax, 0x14ca7(%rip)     # 0x19a28
movl $0x0, 0x10(%rbx)
movl $0x2, (%rbx)
movq %r15, 0x18(%rbx)
movq $0x0, 0x8(%rbx)
movl $0x4, %ebp
leaq 0xc334(%rip), %r13      # 0x110da
movq %r13, %rdi
xorl %eax, %eax
callq 0x479d
decl %ebp
jne 0x4da6
leaq 0xc398(%rip), %rdi      # 0x11153
movq %r15, %rsi
movq %r12, %rdx
xorl %eax, %eax
callq 0x479d
movq %r14, %rsi
callq 0x4b96
leaq 0xc741(%rip), %rdi      # 0x11518
xorl %eax, %eax
callq 0x479d
movq %rbx, %rax
addq $0x8, %rsp
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq
leaq 0xc273(%rip), %rdi      # 0x1106a
leaq 0xc187(%rip), %rsi      # 0x10f85
leaq 0xc283(%rip), %rcx      # 0x11088
movl $0xc8, %edx
callq 0x20b0