// File: /workspace/github_c_makefile_star2_O0/jtuu[P]quesler/src/compiler.c
// Function: function
static Function* function(void) {
    int ret = alloc_register();

    if (ret < 0) {
        error_alloc_register();
        return NULL;
    }

    uint8_t reg = (uint8_t) ret;

    begin_scope();

    Function* func = malloc(sizeof(Function));
    func->name = parser.previous;
    func->arity = 0;

    define_function(func);

    bool is_entry_function = false;

    if (func->name.length == entry_function_name_len && 
            !strncmp(func->name.start, entry_function_name, entry_function_name_len)) {
        parser.entry_function_exists = true;
        func->label = entry_point_label;
        set_label_here(entry_point_label);
        is_entry_function = true;
    } else {
        func->label = put_label_here();
    }

    parser.current_function_label = func->label;

    uint8_t param_registers[UINT8_MAX];

    consume(TOKEN_LEFT_PAREN, "Expected '(' after function name");
    if (!check(TOKEN_RIGHT_PAREN)) {
        do {
            param_registers[func->arity++] = (uint8_t) parse_variable("Expected function parameter name");
        } while (match(TOKEN_COMMA));
    }
    consume(TOKEN_RIGHT_PAREN, "Expected ')' after function parameters");

    consume(TOKEN_LEFT_BRACE, "Expected '{' before function body");

    if (!is_entry_function) {
        // ret addr
        emit_stack_pop(reg);
    }

    for (size_t i = func->arity; i != 0; i--) {
        Local* local = &current->locals[current->local_count - (func->arity - i) - 1];
        define_variable(param_registers[i - 1], local);
        local->initialized = true;
    }

    if (!is_entry_function) {
        emit_stack_push(reg);
    }

    free_register(reg);

    block();

    // implicit return
    if (is_entry_function) {
        emit_opcode(OP_RET);
    } else {
        emit_void_return();
    }

    end_scope();

    return func;
}

// Assembly:
pushq %rbp
movq %rsp, %rbp
subq $0x130, %rsp            # imm = 0x130
callq 0x5bc0
movl %eax, -0xc(%rbp)
cmpl $0x0, -0xc(%rbp)
jge 0x656b
callq 0x5c30
movq $0x0, -0x8(%rbp)
jmp 0x678b
movl -0xc(%rbp), %eax
movb %al, -0xd(%rbp)
callq 0x67a0
movl $0x38, %edi
callq 0x4120
movq %rax, -0x18(%rbp)
movq -0x18(%rbp), %rdi
leaq 0x13019(%rip), %rsi     # 0x195a8
addq $0x28, %rsi
movl $0x28, %edx
callq 0x4110
movq -0x18(%rbp), %rax
movq $0x0, 0x30(%rax)
movq -0x18(%rbp), %rdi
callq 0x67c0
movb $0x0, -0x19(%rbp)
movq -0x18(%rbp), %rax
movq 0x10(%rax), %rax
cmpq 0x12b13(%rip), %rax     # 0x190d8
jne 0x660f
movq -0x18(%rbp), %rax
movq 0x8(%rax), %rdi
movq 0x12afa(%rip), %rsi     # 0x190d0
movq 0x12afb(%rip), %rdx     # 0x190d8
callq 0x4050
cmpl $0x0, %eax
jne 0x660f
movb $0x1, 0x13142(%rip)     # 0x19730
movq 0x12f9b(%rip), %rcx     # 0x19590
movq -0x18(%rbp), %rax
movq %rcx, 0x28(%rax)
movq 0x12f8c(%rip), %rdi     # 0x19590
callq 0x6040
movb $0x1, -0x19(%rbp)
jmp 0x661f
callq 0x68e0
movq %rax, %rcx
movq -0x18(%rbp), %rax
movq %rcx, 0x28(%rax)
movq -0x18(%rbp), %rax
movq 0x28(%rax), %rax
movq %rax, 0x13122(%rip)     # 0x19750
xorl %edi, %edi
leaq 0x5d92(%rip), %rsi      # 0xc3c9
callq 0x57f0
movl $0x1, %edi
callq 0x5e80
testb $0x1, %al
jne 0x6684
jmp 0x664c
leaq 0x5d97(%rip), %rdi      # 0xc3ea
callq 0x6900
movb %al, %cl
movq -0x18(%rbp), %rdx
movq 0x30(%rdx), %rax
movq %rax, %rsi
addq $0x1, %rsi
movq %rsi, 0x30(%rdx)
movb %cl, -0x120(%rbp,%rax)
movl $0x4, %edi
callq 0x5710
testb $0x1, %al
jne 0x664c
jmp 0x6684
movl $0x1, %edi
leaq 0x5d7b(%rip), %rsi      # 0xc40b
callq 0x57f0
movl $0x2, %edi
leaq 0x5d91(%rip), %rsi      # 0xc432
callq 0x57f0
testb $0x1, -0x19(%rbp)
jne 0x66b5
movzbl -0xd(%rbp), %edi
callq 0x5cb0
movq -0x18(%rbp), %rax
movq 0x30(%rax), %rax
movq %rax, -0x128(%rbp)
cmpq $0x0, -0x128(%rbp)
je 0x674a
movq 0x12eb3(%rip), %rax     # 0x19588
movq 0x12eac(%rip), %rcx     # 0x19588
movq 0x3000(%rcx), %rcx
movq -0x18(%rbp), %rdx
movq 0x30(%rdx), %rdx
subq -0x128(%rbp), %rdx
subq %rdx, %rcx
subq $0x1, %rcx
imulq $0x30, %rcx, %rcx
addq %rcx, %rax
movq %rax, -0x130(%rbp)
movq -0x128(%rbp), %rax
subq $0x1, %rax
movb -0x120(%rbp,%rax), %al
movq -0x130(%rbp), %rsi
movzbl %al, %edi
callq 0x6950
movq -0x130(%rbp), %rax
movb $0x1, 0x2c(%rax)
movq -0x128(%rbp), %rax
addq $-0x1, %rax
movq %rax, -0x128(%rbp)
jmp 0x66c4
testb $0x1, -0x19(%rbp)
jne 0x6759
movzbl -0xd(%rbp), %edi
callq 0x5b30
movzbl -0xd(%rbp), %edi
callq 0x5c50
callq 0x69a0
testb $0x1, -0x19(%rbp)
je 0x6779
movl $0x1, %edi
callq 0x5ce0
jmp 0x677e
callq 0x6a00
callq 0x6a30
movq -0x18(%rbp), %rax
movq %rax, -0x8(%rbp)
movq -0x8(%rbp), %rax
addq $0x130, %rsp            # imm = 0x130
popq %rbp
retq
nopl (%rax,%rax)