// File: /workspace/github_c_makefile_star2_O2/been-jamming[P]MinimalCC/compile.c
// Function: compile_function
void compile_function(char **c, char *identifier_name, char *arguments, unsigned int identifier_length, unsigned int num_arguments, FILE *output_file){
	variable *var;
	variable *local_var;
	unsigned int current_argument = 0;

	num_vars = 0;
	variables_size = 0;
	return_type = EMPTY_TYPE;
	parse_type(&return_type, c, identifier_name, arguments, identifier_length, num_arguments);

	if(!identifier_name){
		snprintf(error_message, sizeof(error_message), "Expected identifier name");
		do_error(1);
	}
	skip_whitespace(c);
	if(peek_type(&return_type) != type_function){
		skip_whitespace(c);
		if(**c != ';'){
			snprintf(error_message, sizeof(error_message), "Expected ';'");
			do_error(1);
		}
		++*c;
		var = read_dictionary(global_variables, identifier_name, 0);
		if(var){
			snprintf(error_message, sizeof(error_message), "Duplicate definitions of non-function data");
			do_error(1);
		}
		var = malloc(sizeof(variable));
		var->var_type = return_type;
		var->varname = malloc(strlen(identifier_name) + 1);
		var->leave_as_address = 0;
		strcpy(var->varname, identifier_name);
		write_dictionary(&global_variables, var->varname, var, 0);
		fprintf(output_file, ".data\n.align 2\n%s:\n.space %d\n.text\n", identifier_name, align4(type_size(&return_type, 0)));
	} else {
		if(!*identifier_name){
			snprintf(error_message, sizeof(error_message), "Expected function name");
			do_error(1);
		}
		var = read_dictionary(global_variables, identifier_name, 0);
		if(!var){
			var = malloc(sizeof(variable));
			var->var_type = return_type;
			var->varname = malloc(strlen(identifier_name) + 1);
			var->leave_as_address = 1;
			strcpy(var->varname, identifier_name);
			write_dictionary(&global_variables, var->varname, var, 0);
		} else {
			if(!types_equal(&(var->var_type), &return_type)){
				snprintf(error_message, sizeof(error_message), "Incompatible function definitions");
				do_error(1);
			}
		}
		if(**c != '{'){
			if(**c != ';'){
				snprintf(error_message, sizeof(error_message), "Expected '{' or ';' instead of '%c'", **c);
				do_error(1);
			}
			++*c;
			return;
		}
		++*c;
		local_variables[0] = malloc(sizeof(dictionary));
		*local_variables[0] = create_dictionary(NULL);
		fprintf(output_file, "\n.globl %s\n%s:\n", identifier_name, identifier_name);
		pop_type(&return_type);
		while(peek_type(&return_type) != type_returns){
			if(current_argument >= num_arguments){
				snprintf(error_message, sizeof(error_message), "Too many arguments!");
				do_error(1);
			}
			if(read_dictionary(*local_variables[0], arguments, 0)){
				snprintf(error_message, sizeof(error_message), "Duplicate argument names");
				do_error(1);
			}
			local_var = malloc(sizeof(variable));
			local_var->var_type = get_argument_type(&return_type);
			local_var->varname = malloc(strlen(arguments) + 1);
			strcpy(local_var->varname, arguments);
			local_var->stack_pos = variables_size;
			write_dictionary(local_variables[0], local_var->varname, local_var, 0);
			variables_size += 4;
			arguments += identifier_length;
			current_argument++;
			num_vars++;
		}
		pop_type(&return_type);
		if(peek_type(&return_type) == type_function){
			snprintf(error_message, sizeof(error_message), "Function cannot return function");
			do_error(1);
		}
		num_args = num_vars;
		compile_block(c, 1, output_file);
		++*c;
		var->num_args = num_vars;
		fprintf(output_file, "lw $ra, %d($sp)\n", 4 + num_args*4);
		fprintf(output_file, "jr $ra\n");
	}
}

// Assembly:
pushq %rbp
pushq %r15
pushq %r14
pushq %r13
pushq %r12
pushq %rbx
subq $0xb8, %rsp
movq %r9, 0x50(%rsp)
movl %r8d, %ebp
movl %ecx, %r14d
movq %rdx, %r15
andl $0x0, 0x6ae6(%rip)      # 0xc3d0
leaq 0x6957(%rip), %rax      # 0xc248
andl $0x0, (%rax)
movq %rsi, %r12
movq %rdi, %rbx
leaq 0x6e57(%rip), %rax      # 0xc758
movups (%rax), %xmm0
movups 0x10(%rax), %xmm1
movups 0x20(%rax), %xmm2
movups 0x30(%rax), %xmm3
movups %xmm0, 0x6cf1(%rip)     # 0xc608
movups %xmm1, 0x6cfa(%rip)     # 0xc618
movups %xmm2, 0x6d03(%rip)     # 0xc628
movups %xmm3, 0x6d0c(%rip)     # 0xc638
leaq 0x6cd5(%rip), %rdi      # 0xc608
movq %rbx, %rsi
movq %r12, %rdx
movq %r15, %rcx
movl %r14d, %r8d
movl %ebp, %r9d
callq 0x78de
testq %r12, %r12
je 0x5d9f
movq %rbx, %rdi
callq 0x7549
leaq 0x6ca9(%rip), %rdi      # 0xc608
callq 0x7603
cmpl $0x5, %eax
jne 0x59e1
cmpb $0x0, (%r12)
je 0x5db6
leaq 0x6905(%rip), %rsi      # 0xc280
pushq $0x9
popq %rcx
movq %rsp, %rdi
rep  movsq (%rsi), %es:(%rdi)
movq %r12, %rdi
xorl %esi, %esi
callq 0x6ff5
testq %rax, %rax
je 0x5ad3
movq %rax, 0x60(%rsp)
movq %rax, %rdi
addq $0x8, %rdi
leaq 0x6c5e(%rip), %rsi      # 0xc608
callq 0x7653
testb %al, %al
jne 0x5b5a
movups 0x32cd(%rip), %xmm0     # 0x8c8b
movaps %xmm0, 0x6b2b(%rip)     # 0xc4f0
movups 0x32af(%rip), %xmm0     # 0x8c7b
movaps %xmm0, 0x6b0d(%rip)     # 0xc4e0
movw $0x73, 0x6b24(%rip)     # 0xc500
jmp 0x5d97
movq %rbx, %rdi
callq 0x7549
movq (%rbx), %rax
cmpb $0x3b, (%rax)
jne 0x5dd7
movq 0x50(%rsp), %r13
incq %rax
movq %rax, (%rbx)
leaq 0x6879(%rip), %rsi      # 0xc280
pushq $0x9
popq %rcx
movq %rsp, %rdi
rep  movsq (%rsi), %es:(%rdi)
movq %r12, %rdi
xorl %esi, %esi
callq 0x6ff5
testq %rax, %rax
jne 0x5dfb
pushq $0x50
popq %rdi
callq 0x1140
movq %rax, %rbx
movups 0x6bd3(%rip), %xmm0     # 0xc608
movups %xmm0, 0x8(%rax)
movups 0x6bd8(%rip), %xmm0     # 0xc618
movups %xmm0, 0x18(%rax)
movups 0x6bdd(%rip), %xmm0     # 0xc628
movups %xmm0, 0x28(%rax)
movups 0x6be2(%rip), %xmm0     # 0xc638
movups %xmm0, 0x38(%rax)
leaq 0x6ba7(%rip), %r14      # 0xc608
movq %r12, %rdi
callq 0x1090
leaq 0x1(%rax), %rdi
callq 0x1140
movq %rax, %r15
movq %rax, (%rbx)
movb $0x0, 0x48(%rbx)
movq %rax, %rdi
movq %r12, %rsi
callq 0x1050
leaq 0x67f2(%rip), %rdi      # 0xc280
movq %r15, %rsi
movq %rbx, %rdx
xorl %ecx, %ecx
callq 0x7098
movq %r14, %rdi
xorl %esi, %esi
callq 0x1756
movl %eax, %edi
callq 0x2908
leaq 0x318d(%rip), %rsi      # 0x8c40
movq %r13, %rdi
movq %r12, %rdx
movl %eax, %ecx
xorl %eax, %eax
addq $0xb8, %rsp
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
jmp 0x1100
pushq $0x50
popq %rdi
callq 0x1140
movl %r14d, 0x58(%rsp)
movq %rax, %r14
movups 0x6b1e(%rip), %xmm0     # 0xc608
movups %xmm0, 0x8(%rax)
movups 0x6b23(%rip), %xmm0     # 0xc618
movups %xmm0, 0x18(%rax)
movups 0x6b28(%rip), %xmm0     # 0xc628
movups %xmm0, 0x28(%rax)
movups 0x6b2d(%rip), %xmm0     # 0xc638
movups %xmm0, 0x38(%rax)
movq %r12, %rdi
callq 0x1090
leaq 0x1(%rax), %rdi
callq 0x1140
movq %rbx, %r13
movq %rax, %rbx
movq %rax, (%r14)
movb $0x1, 0x48(%r14)
movq %rax, %rdi
movq %r12, %rsi
callq 0x1050
leaq 0x6740(%rip), %rdi      # 0xc280
movq %rbx, %rsi
movq %r13, %rbx
movq %r14, 0x60(%rsp)
movq %r14, %rdx
movl 0x58(%rsp), %r14d
xorl %ecx, %ecx
callq 0x7098
movq (%rbx), %rax
movzbl (%rax), %ecx
cmpl $0x3b, %ecx
je 0x5cbc
cmpl $0x7b, %ecx
jne 0x5e23
incq %rax
movq %rbx, 0x68(%rsp)
movq %rax, (%rbx)
pushq $0x48
popq %rdi
callq 0x1140
movq %rax, %rbx
leaq 0x6741(%rip), %rax      # 0xc2d0
movq %rbx, (%rax)
leaq 0x70(%rsp), %r13
movq %r13, %rdi
xorl %esi, %esi
callq 0x6f30
pushq $0x9
popq %rcx
movq %rbx, %rdi
movq %r13, %rsi
rep  movsq (%rsi), %es:(%rdi)
leaq 0x310d(%rip), %rsi      # 0x8cc1
movq 0x50(%rsp), %rdi
movq %r12, %rdx
movq %r12, %rcx
xorl %eax, %eax
callq 0x1100
leaq 0x6a3b(%rip), %r12      # 0xc608
movq %r12, %rdi
callq 0x761b
movl %r14d, %eax
movq %rax, 0x58(%rsp)
movq %r12, %rdi
callq 0x7603
cmpl $0x6, %eax
je 0x5cc7
subl $0x1, %ebp
jb 0x5d61
leaq 0x66d2(%rip), %r14      # 0xc2d0
movq (%r14), %rsi
pushq $0x9
popq %rcx
movq %rsp, %rdi
rep  movsq (%rsi), %es:(%rdi)
movq %r15, %rdi
xorl %esi, %esi
callq 0x6ff5
testq %rax, %rax
jne 0x5d7b
pushq $0x50
popq %rdi
callq 0x1140
movq %rax, %rbx
leaq 0x70(%rsp), %rdi
movq %r12, %rsi
callq 0x7755
movups 0x70(%rsp), %xmm0
movups 0x80(%rsp), %xmm1
movups 0x90(%rsp), %xmm2
movups 0xa0(%rsp), %xmm3
movups %xmm3, 0x38(%rbx)
movups %xmm2, 0x28(%rbx)
movups %xmm1, 0x18(%rbx)
movups %xmm0, 0x8(%rbx)
movq %r15, %rdi
callq 0x1090
leaq 0x1(%rax), %rdi
callq 0x1140
movq %rax, %r13
movq %rax, (%rbx)
movq %rax, %rdi
movq %r15, %rsi
callq 0x1050
leaq 0x65bd(%rip), %r14      # 0xc248
movl (%r14), %eax
movl %eax, 0x48(%rbx)
leaq 0x6638(%rip), %rax      # 0xc2d0
movq (%rax), %rdi
movq %r13, %rsi
movq %rbx, %rdx
xorl %ecx, %ecx
callq 0x7098
addl $0x4, (%r14)
addq 0x58(%rsp), %r15
incl 0x6719(%rip)            # 0xc3d0
jmp 0x5bdd
incq %rax
movq %rax, (%rbx)
jmp 0x5d4f
leaq 0x693a(%rip), %rbx      # 0xc608
movq %rbx, %rdi
callq 0x761b
movq %rbx, %rdi
callq 0x7603
cmpl $0x5, %eax
je 0x5e45
movl 0x66e3(%rip), %eax      # 0xc3d0
movl %eax, 0x66e1(%rip)      # 0xc3d4
pushq $0x1
popq %rsi
movq 0x68(%rsp), %r14
movq %r14, %rdi
movq 0x50(%rsp), %rbx
movq %rbx, %rdx
callq 0x5e5f
incq (%r14)
movl 0x66bc(%rip), %eax      # 0xc3d0
movq 0x60(%rsp), %rcx
movl %eax, 0x4c(%rcx)
movl 0x66b2(%rip), %eax      # 0xc3d4
leal 0x4(,%rax,4), %edx
leaq 0x2fee(%rip), %rsi      # 0x8d1e
movq %rbx, %rdi
xorl %eax, %eax
callq 0x1100
leaq 0x2fee(%rip), %rdi      # 0x8d2f
pushq $0x7
popq %rsi
pushq $0x1
popq %rdx
movq %rbx, %rcx
callq 0x1190
addq $0xb8, %rsp
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq
movups 0x2f69(%rip), %xmm0     # 0x8cd1
movaps %xmm0, 0x6771(%rip)     # 0xc4e0
movl $0x217374, 0x6777(%rip) # imm = 0x217374
jmp 0x5d97
movups 0x2f6c(%rip), %xmm0     # 0x8cee
movups %xmm0, 0x6760(%rip)     # 0xc4e9
movups 0x2f55(%rip), %xmm0     # 0x8ce5
movaps %xmm0, 0x6749(%rip)     # 0xc4e0
pushq $0x1
popq %rdi
callq 0x56c5
movups 0x2e5f(%rip), %xmm0     # 0x8c05
movups %xmm0, 0x673c(%rip)     # 0xc4e9
movups 0x2e48(%rip), %xmm0     # 0x8bfc
jmp 0x5d90
movups 0x2ea7(%rip), %xmm0     # 0x8c64
movaps %xmm0, 0x671c(%rip)     # 0xc4e0
movabsq $0x656d616e206e6f, %rax # imm = 0x656D616E206E6F
movq %rax, 0x671a(%rip)      # 0xc4ef
jmp 0x5d97
movabsq $0x273b2720646574, %rax # imm = 0x273B2720646574
movq %rax, 0x66fd(%rip)      # 0xc4e5
movabsq $0x6465746365707845, %rax # imm = 0x6465746365707845
movq %rax, 0x66e7(%rip)      # 0xc4e0
jmp 0x5d97
movups 0x2e2e(%rip), %xmm0     # 0x8c30
movups %xmm0, 0x66f2(%rip)     # 0xc4fb
movups 0x2e15(%rip), %xmm0     # 0x8c25
movaps %xmm0, 0x66d9(%rip)     # 0xc4f0
movups 0x2df7(%rip), %xmm0     # 0x8c15
jmp 0x5d90
movsbl %cl, %ecx
leaq 0x66b3(%rip), %rdi      # 0xc4e0
leaq 0x2e69(%rip), %rdx      # 0x8c9d
movl $0x100, %esi            # imm = 0x100
xorl %eax, %eax
callq 0x10c0
jmp 0x5d97
movups 0x2ec2(%rip), %xmm0     # 0x8d0e
movaps %xmm0, 0x669d(%rip)     # 0xc4f0
movups 0x2ea4(%rip), %xmm0     # 0x8cfe
jmp 0x5d90