// File: skeeto[P]elisp-ffi/ffi-glue.cc
// Function: operator<<(std::ostream&, Value const&)
std::ostream &operator<<(std::ostream &out, const Value &v) {
    if (v.type == &ffi_type_uint8) {
        out << static_cast<unsigned int>(v.value.u8);
    } else if (v.type == &ffi_type_uint16) {
        out << v.value.u16;
    } else if (v.type == &ffi_type_uint32) {
        out << v.value.u32;
    } else if (v.type == &ffi_type_uint64) {
        out << v.value.u64;
    } else if (v.type == &ffi_type_sint8) {
        out << static_cast<int>(v.value.s8);
    } else if (v.type == &ffi_type_sint16) {
        out << v.value.s16;
    } else if (v.type == &ffi_type_sint32) {
        out << v.value.s32;
    } else if (v.type == &ffi_type_sint64) {
        out << v.value.s64;
    } else if (v.type == &ffi_type_float) {
        float value = v.value.f;
        if(std::isnan(value)) {
            out << "0.0e+NaN";
        } else if(std::isinf(value)) {
            if(value < 0) {
                out << "-1.0e+INF";
            } else {
                out << "1.0e+INF";
            }
        } else {
            out << value;
        }
    } else if (v.type == &ffi_type_double) {
        double value = v.value.d;
        if(std::isnan(value)) {
            out << "0.0e+NaN";
        } else if(std::isinf(value)) {
            if(value < 0) {
                out << "-1.0e+INF";
            } else {
                out << "1.0e+INF";
            }
        } else {
            out << value;
        }
    } else if (v.type == &ffi_type_pointer) {
        out << "\\" << v.value.ptr;
    } else if (v.type == &ffi_type_void) {
        out << ":void";
    }
    out << "\n$";
    return out;
}

// Assembly:
pushq %rbp
movq %rsp, %rbp
subq $0x20, %rsp
movq %rdi, -0x8(%rbp)
movq %rsi, -0x10(%rbp)
movq -0x10(%rbp), %rax
movq 0x8b55(%rip), %rcx      # 0xafb0
cmpq %rcx, (%rax)
jne 0x2476
movq -0x8(%rbp), %rdi
movq -0x10(%rbp), %rax
movzbl 0x8(%rax), %esi
callq 0x2240
jmp 0x2710
movq -0x10(%rbp), %rax
movq 0x8acf(%rip), %rcx      # 0xaf50
cmpq %rcx, (%rax)
jne 0x249c
movq -0x8(%rbp), %rdi
movq -0x10(%rbp), %rax
movzwl 0x8(%rax), %esi
callq 0x2290
jmp 0x270e
movq -0x10(%rbp), %rax
movq 0x8b29(%rip), %rcx      # 0xafd0
cmpq %rcx, (%rax)
jne 0x24c1
movq -0x8(%rbp), %rdi
movq -0x10(%rbp), %rax
movl 0x8(%rax), %esi
callq 0x2240
jmp 0x270c
movq -0x10(%rbp), %rax
movq 0x8ac4(%rip), %rcx      # 0xaf90
cmpq %rcx, (%rax)
jne 0x24e7
movq -0x8(%rbp), %rdi
movq -0x10(%rbp), %rax
movq 0x8(%rax), %rsi
callq 0x2080
jmp 0x270a
movq -0x10(%rbp), %rax
movq 0x8ace(%rip), %rcx      # 0xafc0
cmpq %rcx, (%rax)
jne 0x250d
movq -0x8(%rbp), %rdi
movq -0x10(%rbp), %rax
movsbl 0x8(%rax), %esi
callq 0x22a0
jmp 0x2708
movq -0x10(%rbp), %rax
movq 0x8a60(%rip), %rcx      # 0xaf78
cmpq %rcx, (%rax)
jne 0x2533
movq -0x8(%rbp), %rdi
movq -0x10(%rbp), %rax
movswl 0x8(%rax), %esi
callq 0x2190
jmp 0x2706
movq -0x10(%rbp), %rax
movq 0x8a42(%rip), %rcx      # 0xaf80
cmpq %rcx, (%rax)
jne 0x2558
movq -0x8(%rbp), %rdi
movq -0x10(%rbp), %rax
movl 0x8(%rax), %esi
callq 0x22a0
jmp 0x2704
movq -0x10(%rbp), %rax
movq 0x8a05(%rip), %rcx      # 0xaf68
cmpq %rcx, (%rax)
jne 0x257e
movq -0x8(%rbp), %rdi
movq -0x10(%rbp), %rax
movq 0x8(%rax), %rsi
callq 0x22d0
jmp 0x2702
movq -0x10(%rbp), %rax
movq 0x89ff(%rip), %rcx      # 0xaf88
cmpq %rcx, (%rax)
jne 0x2614
movq -0x10(%rbp), %rax
movss 0x8(%rax), %xmm0
movss %xmm0, -0x14(%rbp)
movss -0x14(%rbp), %xmm0
callq 0x2a90
testb $0x1, %al
jne 0x25b0
jmp 0x25c2
movq -0x8(%rbp), %rdi
leaq 0x4cd9(%rip), %rsi      # 0x7294
callq 0x21b0
jmp 0x260f
movss -0x14(%rbp), %xmm0
callq 0x2ab0
testb $0x1, %al
jne 0x25d2
jmp 0x25ff
xorps %xmm0, %xmm0
ucomiss -0x14(%rbp), %xmm0
jbe 0x25ed
movq -0x8(%rbp), %rdi
leaq 0x4cb7(%rip), %rsi      # 0x729d
callq 0x21b0
jmp 0x25fd
movq -0x8(%rbp), %rdi
leaq 0x4ca6(%rip), %rsi      # 0x729e
callq 0x21b0
jmp 0x260d
movq -0x8(%rbp), %rdi
movss -0x14(%rbp), %xmm0
callq 0x2130
jmp 0x260f
jmp 0x2700
movq -0x10(%rbp), %rax
movq 0x8939(%rip), %rcx      # 0xaf58
cmpq %rcx, (%rax)
jne 0x26a8
movq -0x10(%rbp), %rax
movsd 0x8(%rax), %xmm0
movsd %xmm0, -0x20(%rbp)
movsd -0x20(%rbp), %xmm0
callq 0x2ae0
testb $0x1, %al
jne 0x2646
jmp 0x2658
movq -0x8(%rbp), %rdi
leaq 0x4c43(%rip), %rsi      # 0x7294
callq 0x21b0
jmp 0x26a6
movsd -0x20(%rbp), %xmm0
callq 0x2b00
testb $0x1, %al
jne 0x2668
jmp 0x2696
xorps %xmm0, %xmm0
ucomisd -0x20(%rbp), %xmm0
jbe 0x2684
movq -0x8(%rbp), %rdi
leaq 0x4c20(%rip), %rsi      # 0x729d
callq 0x21b0
jmp 0x2694
movq -0x8(%rbp), %rdi
leaq 0x4c0f(%rip), %rsi      # 0x729e
callq 0x21b0
jmp 0x26a4
movq -0x8(%rbp), %rdi
movsd -0x20(%rbp), %xmm0
callq 0x22f0
jmp 0x26a6
jmp 0x26fe
movq -0x10(%rbp), %rax
movq 0x8925(%rip), %rcx      # 0xafd8
cmpq %rcx, (%rax)
jne 0x26da
movq -0x8(%rbp), %rdi
leaq 0x4be4(%rip), %rsi      # 0x72a7
callq 0x21b0
movq %rax, %rdi
movq -0x10(%rbp), %rax
movq 0x8(%rax), %rsi
callq 0x2150
jmp 0x26fc
movq -0x10(%rbp), %rax
movq 0x88c3(%rip), %rcx      # 0xafa8
cmpq %rcx, (%rax)
jne 0x26fa
movq -0x8(%rbp), %rdi
leaq 0x4bb4(%rip), %rsi      # 0x72a9
callq 0x21b0
jmp 0x26fc
jmp 0x26fe
jmp 0x2700
jmp 0x2702
jmp 0x2704
jmp 0x2706
jmp 0x2708
jmp 0x270a
jmp 0x270c
jmp 0x270e
jmp 0x2710
movq -0x8(%rbp), %rdi
leaq 0x4bf4(%rip), %rsi      # 0x730f
callq 0x21b0
movq -0x8(%rbp), %rax
addq $0x20, %rsp
popq %rbp
retq
nopw (%rax,%rax)