// File: /workspace/github_c_makefile_star2_O3/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, %r14d
movq %rdx, -0x58(%rbp)
movq %rsi, %r15
movq %rdi, %r13
imull $0x38, %ecx, %esi
xorl %edi, %edi
callq *(%r13)
movq %rax, %rbx
xorl %edi, %edi
movl $0x48, %esi
callq *(%r13)
movq %rax, %r12
movq %r13, %rdi
movq %r15, -0x50(%rbp)
movq %r15, %rsi
movl $0xffffffff, %edx       # imm = 0xFFFFFFFF
callq 0x8040
movq %rax, (%r12)
xorl %eax, %eax
movq %rax, 0x8(%r12)
movq %rbx, -0x40(%rbp)
movq %rbx, 0x10(%r12)
xorps %xmm0, %xmm0
movups %xmm0, 0x18(%r12)
movl $0x0, 0x28(%r12)
movl %r14d, 0x2c(%r12)
movq %rax, 0x30(%r12)
movq %r12, -0x30(%rbp)
movq %rax, 0x40(%r12)
testl %r14d, %r14d
jle 0x5cf3
movl %r14d, %eax
movq %rax, -0x48(%rbp)
leaq -0x160(%rbp), %r12
xorl %r15d, %r15d
movq %r13, -0x38(%rbp)
imulq $0x38, %r15, %rbx
movq -0x30(%rbp), %rax
movq -0x40(%rbp), %rsi
movq %rax, (%rsi,%rbx)
movq %r15, %rax
shlq $0x4, %rax
movq -0x58(%rbp), %rdx
movq 0x8(%rdx,%rax), %rcx
movq %rcx, 0x18(%rsi,%rbx)
movb $0x1, 0x20(%rsi,%rbx)
movq $0x0, 0x28(%rsi,%rbx)
movl $0x0, 0x30(%rsi,%rbx)
xorl %ecx, %ecx
movb %cl, 0x34(%rsi,%rbx)
movq (%r13), %rdi
movq (%rdx,%rax), %rsi
callq 0x519c
movq %rax, %r14
xorl %eax, %eax
movb %al, -0x160(%rbp)
movq -0x50(%rbp), %rsi
testq %rsi, %rsi
je 0x5bef
cmpb $0x0, (%rsi)
je 0x5bef
movq %r12, %rdi
callq 0x3280
movq %r12, %rdi
callq 0x3100
movw $0x2e, -0x160(%rbp,%rax)
movq %r14, %rdi
movl $0x34, %esi
callq 0x57da
testb %al, %al
je 0x5c04
xorl %eax, %eax
jmp 0x5c18
movq %r14, %rdi
callq 0x589c
movq -0x38(%rbp), %rdi
movq %rax, %rsi
callq 0x8040
addq -0x40(%rbp), %rbx
movq %rax, 0x8(%rbx)
movq %r12, %rdi
callq 0x3100
leaq (%rax,%rbp), %rsi
addq $-0x160, %rsi           # imm = 0xFEA0
movq %r14, %rdi
callq 0x58bb
movq %r14, %rdi
movl $0x2e, %esi
callq 0x57da
movq %r12, %rdi
callq 0x3100
movw $0x28, -0x160(%rbp,%rax)
movq %r14, %rdi
movl $0x2f, %esi
callq 0x57da
testb %al, %al
jne 0x5cb0
cmpb $0x0, 0x34(%rbx)
je 0x5c90
movq %r14, %rdi
movl $0x9, %esi
callq 0x57da
movq %r12, %rdi
callq 0x3100
movw $0x2c, -0x160(%rbp,%rax)
movq %r12, %rdi
callq 0x3100
leaq (%rax,%rbp), %rsi
addq $-0x160, %rsi           # imm = 0xFEA0
movq %r14, %rdi
callq 0x58bb
incb 0x34(%rbx)
jmp 0x5c5a
movq %r12, %rdi
callq 0x3100
movw $0x29, -0x160(%rbp,%rax)
movq -0x38(%rbp), %r13
movq %r13, %rdi
movq %r12, %rsi
movl $0xffffffff, %edx       # imm = 0xFFFFFFFF
callq 0x8040
movq %rax, 0x10(%rbx)
movq (%r13), %rdi
movq %r14, %rsi
callq 0x57cb
incq %r15
cmpq -0x48(%rbp), %r15
jne 0x5b6e
movq %r13, %rdi
movq -0x30(%rbp), %rbx
movq %rbx, %rsi
callq 0x5d17
movq %rbx, %rax
addq $0x138, %rsp            # imm = 0x138
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq