// File: /workspace/github_c_makefile_star2_O2/ryvnf[P]czc/type.c
// Function: type_from_func_ast
static struct type *type_from_func_ast(struct ast *ast)
{
    assert(ast->tag == FUNC_EXPR);

    struct ast *param_list = ast_ast(ast, 0);

    size_t n_params = 0;
    struct ast **param_asts = ast_asts(param_list, &n_params);

    struct type *param_types[n_params];
    bool is_vararg = false;

    for (size_t i = 0; i < n_params; i++) {
        if (param_asts[i]->tag == DECL) {
            param_types[i] = type_from_ast(ast_ast(param_asts[i], 1));
        } else if (param_asts[i]->tag == VARARG_TYPE) {
            is_vararg = true;
            n_params--;
            break;
        } else {
            param_types[i] = type_from_ast(param_asts[i]);
        }

        if (is_void_type(param_types[i]))
            fatal(param_asts[i]->loc, "function parameter cannot be of void type");

        if (is_extern_type(param_types[i]))
            fatal(param_asts[i]->loc, "function parameter cannot be of incomplete type");

        if (is_array_type(param_types[i]))
            fatal(param_asts[i]->loc, "function parameter cannot be of array type");

        if (is_func_type(param_types[i]))
            fatal(param_asts[i]->loc, "function parameter cannot be of function type");
    }

    struct ast *ret_ast = ast_ast(ast, 1);
    struct type *ret_type = type_from_ast(ret_ast);

    if (is_extern_type(ret_type))
        fatal(ret_ast->loc, "function return value cannot be of incomplete type");

    if (is_array_type(ret_type))
        fatal(ret_ast->loc, "function return value cannot be of array type");

    if (is_func_type(ret_type))
        fatal(ret_ast->loc, "function return value cannot be of function type");

    return new_func_type(ret_type, n_params, param_types, is_vararg);
}

// Assembly:
pushq %rbp
movq %rsp, %rbp
pushq %r15
pushq %r14
pushq %r13
pushq %r12
pushq %rbx
subq $0x18, %rsp
cmpl $0x4302, (%rdi)         # imm = 0x4302
jne 0xabe6
xorl %r13d, %r13d
movq %rdi, -0x40(%rbp)
xorl %esi, %esi
callq 0x26ce
leaq -0x30(%rbp), %rbx
andq $0x0, (%rbx)
movq %rax, %rdi
movq %rbx, %rsi
callq 0x270b
movq %rax, %r15
movq %rsp, -0x38(%rbp)
movq (%rbx), %rax
movq %rsp, %rbx
leaq 0xf(,%rax,8), %rax
andq $-0x10, %rax
subq %rax, %rbx
movq %rbx, %rsp
pushq $0x1
popq %r12
movq -0x30(%rbp), %r14
cmpq %r14, %r13
jae 0xab3e
movq (%r15,%r13,8), %rdi
movl (%rdi), %eax
cmpl $0x4000, %eax           # imm = 0x4000
je 0xaafd
cmpl $0x6, %eax
jne 0xab08
jmp 0xab36
movq %r12, %rsi
callq 0x26ce
movq %rax, %rdi
callq 0xa849
movq %rax, (%rbx,%r13,8)
movl (%rax), %eax
testb $0x1, %al
jne 0xabae
btl $0x9, %eax
jb 0xab9d
testb $0x10, %al
jne 0xabbf
testb $0x20, %al
jne 0xabd0
incq %r13
jmp 0xaae0
leaq -0x1(%r14), %rax
movq %rax, -0x30(%rbp)
pushq $0x1
popq %rsi
movq -0x40(%rbp), %rdi
callq 0x26ce
movq %rax, %r15
movq %rax, %rdi
callq 0xa849
movl (%rax), %ecx
btl $0x9, %ecx
jb 0xac0e
testb $0x10, %cl
jne 0xac1b
testb $0x20, %cl
jne 0xac28
xorl %ecx, %ecx
cmpq %r14, %r13
setb %cl
movq -0x30(%rbp), %rsi
movq %rax, %rdi
movq %rbx, %rdx
callq 0xa6a9
movq -0x38(%rbp), %rsp
leaq -0x28(%rbp), %rsp
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq
movq (%r15,%r13,8), %rax
movq 0x8(%rax), %rdi
leaq 0x1f36(%rip), %rsi      # 0xcae2
jmp 0xabdf
movq (%r15,%r13,8), %rax
movq 0x8(%rax), %rdi
leaq 0x1efb(%rip), %rsi      # 0xcab8
jmp 0xabdf
movq (%r15,%r13,8), %rax
movq 0x8(%rax), %rdi
leaq 0x1f44(%rip), %rsi      # 0xcb12
jmp 0xabdf
movq (%r15,%r13,8), %rax
movq 0x8(%rax), %rdi
leaq 0x1f5e(%rip), %rsi      # 0xcb3d
xorl %eax, %eax
callq 0x4a05
leaq 0x5bf(%rip), %rdi       # 0xb1ac
leaq 0x1d96(%rip), %rsi      # 0xc98a
leaq 0x1e94(%rip), %rcx      # 0xca8f
leaq 0x1ea3(%rip), %r8       # 0xcaa5
movl $0x114, %edx            # imm = 0x114
xorl %eax, %eax
callq 0x4918
movq 0x8(%r15), %rdi
leaq 0x1f52(%rip), %rsi      # 0xcb6b
jmp 0xabdf
movq 0x8(%r15), %rdi
leaq 0x1f78(%rip), %rsi      # 0xcb9e
jmp 0xabdf
movq 0x8(%r15), %rdi
leaq 0x1f99(%rip), %rsi      # 0xcbcc
jmp 0xabdf