// File: /workspace/github_c_makefile_star2_O2/naleksiev[P]fin/src/fin_mod.c
// Function: fin_mod_create
fin_mod_t* fin_mod_create(fin_ctx_t* ctx, const char* name, fin_mod_func_desc_t* descs, int32_t descs_count) {
    fin_mod_func_t* funcs = (fin_mod_func_t*)ctx->alloc(NULL, sizeof(fin_mod_func_t) * descs_count);

    fin_mod_t* mod = (fin_mod_t*)ctx->alloc(NULL, sizeof(fin_mod_t));
    mod->name = fin_str_create(ctx, name, -1);
    mod->types = NULL;
    mod->funcs = funcs;
    mod->binds = NULL;
    mod->consts = NULL;
    mod->types_count = 0;
    mod->funcs_count = descs_count;
    mod->binds_count = 0;
    mod->consts_count = 0;
    mod->next = NULL;

    for (int32_t i=0; i<descs_count; i++) {
        funcs[i].mod = mod;
        funcs[i].func = descs[i].func;
        funcs[i].is_native = true;
        funcs[i].code = NULL;
        funcs[i].code_length = 0;
        funcs[i].args = 0;

        // ret_type name "(" arg? ("," arg)* ")"
        fin_lex_t* lex = fin_lex_create(ctx->alloc, descs[i].sign);

        char signature[256];
        signature[0] = '\0';

        if (name != NULL && name[0] != '\0') {
            strcat(signature, name);
            strcat(signature, ".");
        }

        if (fin_lex_match(lex, fin_lex_type_void))
            funcs[i].ret_type = NULL;
        else {
            fin_lex_str_t lex_str = fin_lex_consume_name(lex);
            funcs[i].ret_type = fin_str_create(ctx, lex_str.cstr, lex_str.len);
        }

        fin_lex_consume_name_to(lex, signature + strlen(signature));

        fin_lex_match(lex, fin_lex_type_l_paren);
        strcat(signature, "(");
        while (!fin_lex_match(lex, fin_lex_type_r_paren)) {
            if (funcs[i].args) {
                fin_lex_match(lex, fin_lex_type_comma);
                strcat(signature, ",");
            }
            fin_lex_consume_name_to(lex, signature + strlen(signature));
            funcs[i].args++;
        }
        strcat(signature, ")");
        funcs[i].sign = fin_str_create(ctx, signature, -1);

        fin_lex_destroy(ctx->alloc, lex);
    }

    fin_mod_register(ctx, mod);
    return mod;
}

// Assembly:
pushq %rbp
movq %rsp, %rbp
pushq %r15
pushq %r14
pushq %r13
pushq %r12
pushq %rbx
subq $0x138, %rsp            # imm = 0x138
movl %ecx, %ebx
movq %rdx, -0x50(%rbp)
movq %rsi, %r12
movq %rdi, %r14
imull $0x38, %ecx, %esi
xorl %edi, %edi
callq *(%r14)
movq %rax, %r13
pushq $0x48
popq %rsi
xorl %edi, %edi
callq *(%r14)
movq %rax, %r15
pushq $-0x1
popq %rdx
movq %r14, -0x30(%rbp)
movq %r14, %rdi
movq %r12, -0x38(%rbp)
movq %r12, %rsi
callq 0x781e
movq %rax, (%r15)
andq $0x0, 0x8(%r15)
movq %r13, -0x48(%rbp)
movq %r13, 0x10(%r15)
xorps %xmm0, %xmm0
movups %xmm0, 0x18(%r15)
andl $0x0, 0x28(%r15)
movl %ebx, 0x2c(%r15)
andq $0x0, 0x30(%r15)
movq %r15, -0x40(%rbp)
andq $0x0, 0x40(%r15)
testl %ebx, %ebx
movl $0x0, %eax
cmovlel %eax, %ebx
movq %rbx, -0x58(%rbp)
leaq -0x160(%rbp), %rbx
pushq $0x2f
popq %r15
xorl %ecx, %ecx
cmpq -0x58(%rbp), %rcx
je 0x5916
imulq $0x38, %rcx, %r13
movq -0x48(%rbp), %rsi
movq -0x40(%rbp), %rax
movq %rax, (%rsi,%r13)
movq %rcx, -0x60(%rbp)
movq %rcx, %rax
shlq $0x4, %rax
movq -0x50(%rbp), %rdx
movq 0x8(%rdx,%rax), %rcx
movq %rcx, 0x18(%rsi,%r13)
movb $0x1, 0x20(%rsi,%r13)
andq $0x0, 0x28(%rsi,%r13)
andl $0x0, 0x30(%rsi,%r13)
xorl %r12d, %r12d
movb %r12b, 0x34(%rsi,%r13)
movq -0x30(%rbp), %rcx
movq (%rcx), %rdi
movq (%rdx,%rax), %rsi
callq 0x4f40
movq %rax, %r14
movb %r12b, -0x160(%rbp)
cmpq $0x0, -0x38(%rbp)
je 0x5817
movq -0x38(%rbp), %rax
cmpb $0x0, (%rax)
je 0x5817
movq %rbx, %rdi
movq -0x38(%rbp), %rsi
callq 0x3280
movq %rbx, %rdi
callq 0x3100
movw $0x2e, -0x160(%rbp,%rax)
movq %r14, %rdi
pushq $0x34
popq %rsi
callq 0x5537
testb %al, %al
je 0x582a
xorl %eax, %eax
jmp 0x583e
movq %r14, %rdi
callq 0x55f7
movq -0x30(%rbp), %rdi
movq %rax, %rsi
callq 0x781e
pushq $0x9
popq %r12
addq -0x48(%rbp), %r13
movq %rax, 0x8(%r13)
movq %rbx, %rdi
callq 0x3100
leaq (%rax,%rbp), %rsi
addq $-0x160, %rsi           # imm = 0xFEA0
movq %r14, %rdi
callq 0x5616
movq %r14, %rdi
pushq $0x2e
popq %rsi
callq 0x5537
movq %rbx, %rdi
callq 0x3100
movw $0x28, -0x160(%rbp,%rax)
movq %r14, %rdi
movl %r15d, %esi
callq 0x5537
testb %al, %al
jne 0x58d6
cmpb $0x0, 0x34(%r13)
je 0x58b5
movq %r14, %rdi
movl %r12d, %esi
callq 0x5537
movq %rbx, %rdi
callq 0x3100
movw $0x2c, -0x160(%rbp,%rax)
movq %rbx, %rdi
callq 0x3100
leaq (%rax,%rbp), %rsi
addq $-0x160, %rsi           # imm = 0xFEA0
movq %r14, %rdi
callq 0x5616
incb 0x34(%r13)
jmp 0x5882
movq %rbx, %rdi
callq 0x3100
movw $0x29, -0x160(%rbp,%rax)
movq -0x30(%rbp), %r12
movq %r12, %rdi
movq %rbx, %rsi
pushq $-0x1
popq %rdx
callq 0x781e
movq %rax, 0x10(%r13)
movq (%r12), %rdi
movq %r14, %rsi
callq 0x5528
movq -0x60(%rbp), %rcx
incq %rcx
jmp 0x5782
movq -0x30(%rbp), %rdi
movq -0x40(%rbp), %rbx
movq %rbx, %rsi
callq 0x593b
movq %rbx, %rax
addq $0x138, %rsp            # imm = 0x138
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq