// File: /workspace/github_c_makefile_star2_O0/janet-lang[P]janet/src/core/ffi.c
// Function: sysv64_classify_ext
static JanetFFIWordSpec sysv64_classify_ext(JanetFFIType type, size_t shift) {
    switch (type.prim) {
        case JANET_FFI_TYPE_PTR:
        case JANET_FFI_TYPE_STRING:
        case JANET_FFI_TYPE_BOOL:
        case JANET_FFI_TYPE_INT8:
        case JANET_FFI_TYPE_INT16:
        case JANET_FFI_TYPE_INT32:
        case JANET_FFI_TYPE_INT64:
        case JANET_FFI_TYPE_UINT8:
        case JANET_FFI_TYPE_UINT16:
        case JANET_FFI_TYPE_UINT32:
        case JANET_FFI_TYPE_UINT64:
            return JANET_SYSV64_INTEGER;
        case JANET_FFI_TYPE_DOUBLE:
        case JANET_FFI_TYPE_FLOAT:
            return JANET_SYSV64_SSE;
        case JANET_FFI_TYPE_STRUCT: {
            JanetFFIStruct *st = type.st;
            if (st->size > 16) return JANET_SYSV64_MEMORY;
            if (!st->is_aligned) return JANET_SYSV64_MEMORY;
            JanetFFIWordSpec clazz = JANET_SYSV64_NO_CLASS;
            if (st->size > 8 && st->size <= 16) {
                /* map to pair classification */
                int has_int_lo = 0;
                int has_int_hi = 0;
                for (uint32_t i = 0; i < st->field_count; i++) {
                    JanetFFIWordSpec next_class = sysv64_classify_ext(st->fields[i].type, shift + st->fields[i].offset);
                    switch (next_class) {
                        default:
                            break;
                        case JANET_SYSV64_INTEGER:
                            if (shift + st->fields[i].offset + type_size(st->fields[i].type) <= 8) {
                                has_int_lo = 1;
                            } else {
                                has_int_hi = 2;
                            }
                            break;
                        case JANET_SYSV64_PAIR_INTINT:
                            has_int_lo = 1;
                            has_int_hi = 2;
                            break;
                        case JANET_SYSV64_PAIR_INTSSE:
                            has_int_lo = 1;
                            break;
                        case JANET_SYSV64_PAIR_SSEINT:
                            has_int_hi = 2;
                            break;
                            break;
                    }
                }
                switch (has_int_hi + has_int_lo) {
                    case 0:
                        clazz = JANET_SYSV64_PAIR_SSESSE;
                        break;
                    case 1:
                        clazz = JANET_SYSV64_PAIR_INTSSE;
                        break;
                    case 2:
                        clazz = JANET_SYSV64_PAIR_SSEINT;
                        break;
                    case 3:
                        clazz = JANET_SYSV64_PAIR_INTINT;
                        break;
                }
            } else {
                /* Normal struct classification */
                for (uint32_t i = 0; i < st->field_count; i++) {
                    JanetFFIWordSpec next_class = sysv64_classify_ext(st->fields[i].type, shift + st->fields[i].offset);
                    if (next_class != clazz) {
                        if (clazz == JANET_SYSV64_NO_CLASS) {
                            clazz = next_class;
                        } else if (clazz == JANET_SYSV64_MEMORY || next_class == JANET_SYSV64_MEMORY) {
                            clazz = JANET_SYSV64_MEMORY;
                        } else if (clazz == JANET_SYSV64_INTEGER || next_class == JANET_SYSV64_INTEGER) {
                            clazz = JANET_SYSV64_INTEGER;
                        } else {
                            clazz = JANET_SYSV64_SSE;
                        }
                    }
                }
            }
            return clazz;
        }
        case JANET_FFI_TYPE_VOID:
            return JANET_SYSV64_NO_CLASS;
        default:
            janet_panic("nyi");
            return JANET_SYSV64_NO_CLASS;
    }
}

// Assembly:
pushq %rbp
movq %rsp, %rbp
subq $0x70, %rsp
movq %rdi, -0x18(%rbp)
movq %rsi, -0x10(%rbp)
movq %rdx, -0x20(%rbp)
movl -0x10(%rbp), %eax
movq %rax, -0x50(%rbp)
subq $0xe, %rax
ja 0x35d34
movq -0x50(%rbp), %rax
leaq 0x52470(%rip), %rcx     # 0x87f20
movslq (%rcx,%rax,4), %rax
addq %rcx, %rax
jmpq *%rax
movl $0x0, -0x4(%rbp)
jmp 0x35d40
movl $0x1, -0x4(%rbp)
jmp 0x35d40
movq -0x18(%rbp), %rax
movq %rax, -0x28(%rbp)
movq -0x28(%rbp), %rax
cmpl $0x10, (%rax)
jbe 0x35aee
movl $0x8, -0x4(%rbp)
jmp 0x35d40
movq -0x28(%rbp), %rax
cmpl $0x0, 0xc(%rax)
jne 0x35b04
movl $0x8, -0x4(%rbp)
jmp 0x35d40
movl $0x7, -0x2c(%rbp)
movq -0x28(%rbp), %rax
cmpl $0x8, (%rax)
jbe 0x35c72
movq -0x28(%rbp), %rax
cmpl $0x10, (%rax)
ja 0x35c72
movl $0x0, -0x30(%rbp)
movl $0x0, -0x34(%rbp)
movl $0x0, -0x38(%rbp)
movl -0x38(%rbp), %eax
movq -0x28(%rbp), %rcx
cmpl 0x8(%rcx), %eax
jae 0x35c24
movq -0x28(%rbp), %rax
movl -0x38(%rbp), %ecx
leaq (%rcx,%rcx,2), %rcx
movq -0x20(%rbp), %rdx
movq 0x20(%rax,%rcx,8), %rsi
addq %rsi, %rdx
movq 0x10(%rax,%rcx,8), %rdi
movq 0x18(%rax,%rcx,8), %rsi
callq 0x35a80
movl %eax, -0x3c(%rbp)
movl -0x3c(%rbp), %eax
movq %rax, -0x58(%rbp)
subq $0x5, %rax
ja 0x35b94
movq -0x58(%rbp), %rax
leaq 0x523e1(%rip), %rcx     # 0x87f6c
movslq (%rcx,%rax,4), %rax
addq %rcx, %rax
jmpq *%rax
jmp 0x35c14
movq -0x20(%rbp), %rax
movq -0x28(%rbp), %rcx
addq $0x10, %rcx
movl -0x38(%rbp), %edx
imulq $0x18, %rdx, %rdx
addq %rdx, %rcx
addq 0x10(%rcx), %rax
movq %rax, -0x60(%rbp)
movq -0x28(%rbp), %rax
addq $0x10, %rax
movl -0x38(%rbp), %ecx
imulq $0x18, %rcx, %rcx
addq %rcx, %rax
movq (%rax), %rdi
movq 0x8(%rax), %rsi
callq 0x33060
movq %rax, %rcx
movq -0x60(%rbp), %rax
addq %rcx, %rax
cmpq $0x8, %rax
ja 0x35beb
movl $0x1, -0x30(%rbp)
jmp 0x35bf2
movl $0x2, -0x34(%rbp)
jmp 0x35c14
movl $0x1, -0x30(%rbp)
movl $0x2, -0x34(%rbp)
jmp 0x35c14
movl $0x1, -0x30(%rbp)
jmp 0x35c14
movl $0x2, -0x34(%rbp)
jmp 0x35c16
movl -0x38(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x38(%rbp)
jmp 0x35b3a
movl -0x34(%rbp), %eax
movl -0x30(%rbp), %ecx
addl %ecx, %eax
movl %eax, %ecx
movq %rcx, -0x68(%rbp)
subl $0x3, %eax
ja 0x35c6d
movq -0x68(%rbp), %rax
leaq 0x5231a(%rip), %rcx     # 0x87f5c
movslq (%rcx,%rax,4), %rax
addq %rcx, %rax
jmpq *%rax
movl $0x6, -0x2c(%rbp)
jmp 0x35c6d
movl $0x4, -0x2c(%rbp)
jmp 0x35c6d
movl $0x5, -0x2c(%rbp)
jmp 0x35c6d
movl $0x3, -0x2c(%rbp)
jmp 0x35d23
movl $0x0, -0x40(%rbp)
movl -0x40(%rbp), %eax
movq -0x28(%rbp), %rcx
cmpl 0x8(%rcx), %eax
jae 0x35d21
movq -0x28(%rbp), %rax
addq $0x10, %rax
movl -0x40(%rbp), %ecx
imulq $0x18, %rcx, %rcx
addq %rcx, %rax
movq -0x20(%rbp), %rdx
movq -0x28(%rbp), %rcx
addq $0x10, %rcx
movl -0x40(%rbp), %esi
imulq $0x18, %rsi, %rsi
addq %rsi, %rcx
addq 0x10(%rcx), %rdx
movq (%rax), %rdi
movq 0x8(%rax), %rsi
callq 0x35a80
movl %eax, -0x44(%rbp)
movl -0x44(%rbp), %eax
cmpl -0x2c(%rbp), %eax
je 0x35d11
cmpl $0x7, -0x2c(%rbp)
jne 0x35cda
movl -0x44(%rbp), %eax
movl %eax, -0x2c(%rbp)
jmp 0x35d0f
cmpl $0x8, -0x2c(%rbp)
je 0x35ce6
cmpl $0x8, -0x44(%rbp)
jne 0x35cef
movl $0x8, -0x2c(%rbp)
jmp 0x35d0d
cmpl $0x0, -0x2c(%rbp)
je 0x35cfb
cmpl $0x0, -0x44(%rbp)
jne 0x35d04
movl $0x0, -0x2c(%rbp)
jmp 0x35d0b
movl $0x1, -0x2c(%rbp)
jmp 0x35d0d
jmp 0x35d0f
jmp 0x35d11
jmp 0x35d13
movl -0x40(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x40(%rbp)
jmp 0x35c79
jmp 0x35d23
movl -0x2c(%rbp), %eax
movl %eax, -0x4(%rbp)
jmp 0x35d40
movl $0x7, -0x4(%rbp)
jmp 0x35d40
leaq 0x5359f(%rip), %rdi     # 0x892da
callq 0x1ad60
movl -0x4(%rbp), %eax
addq $0x70, %rsp
popq %rbp
retq
nopl (%rax)