// File: /workspace/github_c_makefile_star2_O0/Ihsoh[P]ilang/compiler/frontend/semantics.c
// Function: func
static void _func(
	ParserContext *ctx,
	ParserASTNode *node
) {
	assert(ctx);
	assert(node);
	assert(node->type == FE_NODE_FUNC);

	ParserASTNode *node_identifier = NULL;
	ParserASTNode *node_func_params = NULL;
	ParserASTNode *node_type = NULL;
	ParserASTNode *node_body = NULL;

	if (node->nchilds == 3) {
		node_identifier = node->childs[0];
		node_func_params = node->childs[1];
		node_body = node->childs[2];
	} else if (node->nchilds == 4) {
		node_identifier = node->childs[0];
		node_func_params = node->childs[1];
		node_type = node->childs[2];
		node_body = node->childs[3];
	} else {
		assert(0);
	}

	if (node_func_params->nchilds >= 1
			&& node_func_params->childs[0]->type == FE_NODE_FUNC_PARAMS_ELLIPSIS_ITEM) {
		_SYNERR_NODE(
			ctx,
			node_func_params->childs[0],
			"first function parameter cannot be '...'."
		);
	}

	for (int i = 0; i < node_func_params->nchilds; i++) {
		ParserASTNode *node_func_param = node_func_params->childs[i];
		if (node_func_param->type == FE_NODE_FUNC_PARAMS_ITEM) {
			ParserASTNode *node_func_param_id = node_func_param->childs[0];
			ParserASTNode *node_func_param_type = node_func_param->childs[1];

			uint8_t param_type = 0;
			_type(ctx, node_func_param_type, &param_type);
			if (!_is_primitive_type(param_type)
					&& !_is_pointer_type(param_type)
					&& param_type != FE_TYPE_VA_LIST) {
				_SYNERR_NODE(
					ctx,
					node_func_param_type,
					"function parameter type must be primitive type or pointer type or __va_list type."
				);
			}

			ParserSymbol *symbol = fe_parser_add_var_symbol_to_node(
				ctx,
				node,
				node_func_param_id->token,
				param_type,
				node_func_param_type
			);

			FE_FUNC_PARAM_AST_NODE_SET_SYMBOL(node_func_param, symbol);
		}
	}

	if (node_type != NULL) {
		uint8_t return_type = 0;
		_type(ctx, node_type, &return_type);
		if (!_is_primitive_type(return_type)
				&& !_is_pointer_type(return_type)) {
			_SYNERR_NODE(
				ctx,
				node_type,
				"function return type must be primitive type or pointer type."
			);
		}
	}

	ParserASTNode *node_parent = node->parent;
	assert(node_parent);

	ParserSymbol *symbol = NULL;
	if (node_body->type == FE_NODE_DUMMY) {
		symbol = fe_parser_add_func_symbol_to_node(
			ctx, node_parent, node_identifier->token, node_func_params, node_type, true
		);

		FE_FUNC_AST_NODE_SET_SYMBOL(node, symbol);
	} else {
		symbol = parser_get_symbol_from_node(
			ctx, node_parent, FE_SYM_FUNC, node_identifier->token
		);

		if (symbol != NULL
				&& FE_FUNC_SYMBOL_GET_DUMMY(symbol)) {
			ParserASTNode *func_type_node = _NEW_NODE(ctx, FE_NODE_TYPE_FUNC, NULL);
			parser_add_child(ctx, func_type_node, node_func_params);
			if (node_type != NULL) {
				parser_add_child(ctx, func_type_node, node_type);
			}

			if (!_is_compatible_func_type(ctx, func_type_node, FE_FUNC_SYMBOL_GET_FUNC_TYPE_NODE(symbol), true)) {
				_SYNERR_TOKEN(
					ctx,
					node_identifier->token,
					"function declaration signature and function implementation signature are not matched."
				);
			}

			FE_FUNC_SYMBOL_SET_DUMMY(symbol, false);
		} else {
			symbol = fe_parser_add_func_symbol_to_node(
				ctx, node_parent, node_identifier->token, node_func_params, node_type, false
			);
		}

		assert(symbol);
		FE_FUNC_AST_NODE_SET_SYMBOL(node, symbol);

		for (int i = 0; i < node_func_params->nchilds; i++) {
			ParserASTNode *node_func_param = node_func_params->childs[i];
			if (node_func_param->type == FE_NODE_FUNC_PARAMS_ITEM) {
				FE_VAR_SYMBOL_SET_FUNC_SYMBOL(
					FE_FUNC_PARAM_AST_NODE_GET_SYMBOL(node_func_param),
					symbol
				);
			}
		}

		_func_process_label(ctx, node_body);

		_stats_block(ctx, node_body);
	}
}

// Assembly:
pushq %rbp
movq %rsp, %rbp
subq $0xca0, %rsp            # imm = 0xCA0
movq %rdi, -0x8(%rbp)
movq %rsi, -0x10(%rbp)
cmpq $0x0, -0x8(%rbp)
je 0x4e44c
jmp 0x4e46b
leaq 0x2e103(%rip), %rdi     # 0x7c556
leaq 0x2fdf0(%rip), %rsi     # 0x7e24a
movl $0x14d8, %edx           # imm = 0x14D8
leaq 0x31fef(%rip), %rcx     # 0x80455
callq 0x30a0
cmpq $0x0, -0x10(%rbp)
je 0x4e474
jmp 0x4e493
leaq 0x27b58(%rip), %rdi     # 0x75fd3
leaq 0x2fdc8(%rip), %rsi     # 0x7e24a
movl $0x14d9, %edx           # imm = 0x14D9
leaq 0x31fc7(%rip), %rcx     # 0x80455
callq 0x30a0
movq -0x10(%rbp), %rax
cmpl $0xa00, (%rax)          # imm = 0xA00
jne 0x4e4a1
jmp 0x4e4c0
leaq 0x27cab(%rip), %rdi     # 0x76153
leaq 0x2fd9b(%rip), %rsi     # 0x7e24a
movl $0x14da, %edx           # imm = 0x14DA
leaq 0x31f9a(%rip), %rcx     # 0x80455
callq 0x30a0
movq $0x0, -0x18(%rbp)
movq $0x0, -0x20(%rbp)
movq $0x0, -0x28(%rbp)
movq $0x0, -0x30(%rbp)
movq -0x10(%rbp), %rax
cmpl $0x3, 0x44(%rax)
jne 0x4e51b
movq -0x10(%rbp), %rax
movq 0x48(%rax), %rax
movq (%rax), %rax
movq %rax, -0x18(%rbp)
movq -0x10(%rbp), %rax
movq 0x48(%rax), %rax
movq 0x8(%rax), %rax
movq %rax, -0x20(%rbp)
movq -0x10(%rbp), %rax
movq 0x48(%rax), %rax
movq 0x10(%rax), %rax
movq %rax, -0x30(%rbp)
jmp 0x4e587
movq -0x10(%rbp), %rax
cmpl $0x4, 0x44(%rax)
jne 0x4e566
movq -0x10(%rbp), %rax
movq 0x48(%rax), %rax
movq (%rax), %rax
movq %rax, -0x18(%rbp)
movq -0x10(%rbp), %rax
movq 0x48(%rax), %rax
movq 0x8(%rax), %rax
movq %rax, -0x20(%rbp)
movq -0x10(%rbp), %rax
movq 0x48(%rax), %rax
movq 0x10(%rax), %rax
movq %rax, -0x28(%rbp)
movq -0x10(%rbp), %rax
movq 0x48(%rax), %rax
movq 0x18(%rax), %rax
movq %rax, -0x30(%rbp)
jmp 0x4e585
leaq 0x23eee(%rip), %rdi     # 0x7245b
leaq 0x2fcd6(%rip), %rsi     # 0x7e24a
movl $0x14eb, %edx           # imm = 0x14EB
leaq 0x31ed5(%rip), %rcx     # 0x80455
callq 0x30a0
jmp 0x4e587
movq -0x20(%rbp), %rax
cmpl $0x1, 0x44(%rax)
jl 0x4e5d9
movq -0x20(%rbp), %rax
movq 0x48(%rax), %rax
movq (%rax), %rax
cmpl $0xa03, (%rax)          # imm = 0xA03
jne 0x4e5d9
leaq -0x430(%rbp), %rdi
leaq 0x31ed0(%rip), %rsi     # 0x80482
movb $0x0, %al
callq 0x3160
movq -0x8(%rbp), %rax
movq 0x58(%rax), %rax
movq -0x8(%rbp), %rdi
movq -0x20(%rbp), %rcx
movq 0x48(%rcx), %rcx
movq (%rcx), %rsi
leaq -0x430(%rbp), %rdx
callq *%rax
movl $0x0, -0x434(%rbp)
movl -0x434(%rbp), %eax
movq -0x20(%rbp), %rcx
cmpl 0x44(%rcx), %eax
jge 0x4e720
movq -0x20(%rbp), %rax
movq 0x48(%rax), %rax
movslq -0x434(%rbp), %rcx
movq (%rax,%rcx,8), %rax
movq %rax, -0x440(%rbp)
movq -0x440(%rbp), %rax
cmpl $0xa02, (%rax)          # imm = 0xA02
jne 0x4e70a
movq -0x440(%rbp), %rax
movq 0x48(%rax), %rax
movq (%rax), %rax
movq %rax, -0x448(%rbp)
movq -0x440(%rbp), %rax
movq 0x48(%rax), %rax
movq 0x8(%rax), %rax
movq %rax, -0x450(%rbp)
movb $0x0, -0x451(%rbp)
movq -0x8(%rbp), %rdi
movq -0x450(%rbp), %rsi
leaq -0x451(%rbp), %rdx
callq 0x4f0d0
movzbl -0x451(%rbp), %edi
callq 0x4d470
testb $0x1, %al
jne 0x4e6c9
movzbl -0x451(%rbp), %edi
callq 0x4d4c0
testb $0x1, %al
jne 0x4e6c9
movzbl -0x451(%rbp), %eax
cmpl $0xc, %eax
je 0x4e6c9
leaq -0x860(%rbp), %rdi
leaq 0x31e06(%rip), %rsi     # 0x804ac
movb $0x0, %al
callq 0x3160
movq -0x8(%rbp), %rax
movq 0x58(%rax), %rax
movq -0x8(%rbp), %rdi
movq -0x450(%rbp), %rsi
leaq -0x860(%rbp), %rdx
callq *%rax
movq -0x8(%rbp), %rdi
movq -0x10(%rbp), %rsi
movq -0x448(%rbp), %rax
movq 0x10(%rax), %rdx
movb -0x451(%rbp), %al
movq -0x450(%rbp), %r8
movzbl %al, %ecx
callq 0x42d60
movq %rax, -0x868(%rbp)
movq -0x868(%rbp), %rcx
movq -0x440(%rbp), %rax
movq %rcx, 0x60(%rax)
jmp 0x4e70c
movl -0x434(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x434(%rbp)
jmp 0x4e5e3
cmpq $0x0, -0x28(%rbp)
je 0x4e792
movb $0x0, -0x869(%rbp)
movq -0x8(%rbp), %rdi
movq -0x28(%rbp), %rsi
leaq -0x869(%rbp), %rdx
callq 0x4f0d0
movzbl -0x869(%rbp), %edi
callq 0x4d470
testb $0x1, %al
jne 0x4e790
movzbl -0x869(%rbp), %edi
callq 0x4d4c0
testb $0x1, %al
jne 0x4e790
leaq -0xc70(%rbp), %rdi
leaq 0x31d8e(%rip), %rsi     # 0x804fe
movb $0x0, %al
callq 0x3160
movq -0x8(%rbp), %rax
movq 0x58(%rax), %rax
movq -0x8(%rbp), %rdi
movq -0x28(%rbp), %rsi
leaq -0xc70(%rbp), %rdx
callq *%rax
jmp 0x4e792
movq -0x10(%rbp), %rax
movq 0x30(%rax), %rax
movq %rax, -0xc78(%rbp)
cmpq $0x0, -0xc78(%rbp)
je 0x4e7ad
jmp 0x4e7cc
leaq 0x2fbe3(%rip), %rdi     # 0x7e397
leaq 0x2fa8f(%rip), %rsi     # 0x7e24a
movl $0x1523, %edx           # imm = 0x1523
leaq 0x31c8e(%rip), %rcx     # 0x80455
callq 0x30a0
movq $0x0, -0xc80(%rbp)
movq -0x30(%rbp), %rax
cmpl $0x900, (%rax)          # imm = 0x900
jne 0x4e824
movq -0x8(%rbp), %rdi
movq -0xc78(%rbp), %rsi
movq -0x18(%rbp), %rax
movq 0x10(%rax), %rdx
movq -0x20(%rbp), %rcx
movq -0x28(%rbp), %r8
movl $0x1, %r9d
callq 0x431a0
movq %rax, -0xc80(%rbp)
movq -0xc80(%rbp), %rcx
movq -0x10(%rbp), %rax
movq %rcx, 0x60(%rax)
jmp 0x4e9ed
movq -0x8(%rbp), %rdi
movq -0xc78(%rbp), %rsi
movq -0x18(%rbp), %rax
movq 0x10(%rax), %rcx
movl $0x3, %edx
callq 0x82f0
movq %rax, -0xc80(%rbp)
cmpq $0x0, -0xc80(%rbp)
je 0x4e904
movq -0xc80(%rbp), %rax
testb $0x1, 0x50(%rax)
je 0x4e904
movq -0x8(%rbp), %rdi
movl $0x430, %esi            # imm = 0x430
leaq 0x26939(%rip), %rdx     # 0x751b0
xorl %eax, %eax
movl %eax, %ecx
callq 0x58210
movq %rax, -0xc88(%rbp)
movq -0x8(%rbp), %rdi
movq -0xc88(%rbp), %rsi
movq -0x20(%rbp), %rdx
callq 0x7e20
cmpq $0x0, -0x28(%rbp)
je 0x4e8b6
movq -0x8(%rbp), %rdi
movq -0xc88(%rbp), %rsi
movq -0x28(%rbp), %rdx
callq 0x7e20
movq -0x8(%rbp), %rdi
movq -0xc88(%rbp), %rsi
movq -0xc80(%rbp), %rax
movq 0x40(%rax), %rdx
movl $0x1, %ecx
callq 0x5cc00
testb $0x1, %al
jne 0x4e8f7
movq -0x8(%rbp), %rax
movq 0x50(%rax), %rax
movq -0x8(%rbp), %rdi
movq -0x18(%rbp), %rcx
movq 0x10(%rcx), %rsi
leaq 0x31c46(%rip), %rdx     # 0x8053b
callq *%rax
movq -0xc80(%rbp), %rax
movb $0x0, 0x50(%rax)
jmp 0x4e92e
movq -0x8(%rbp), %rdi
movq -0xc78(%rbp), %rsi
movq -0x18(%rbp), %rax
movq 0x10(%rax), %rdx
movq -0x20(%rbp), %rcx
movq -0x28(%rbp), %r8
xorl %r9d, %r9d
callq 0x431a0
movq %rax, -0xc80(%rbp)
cmpq $0x0, -0xc80(%rbp)
je 0x4e93a
jmp 0x4e959
leaq 0x27837(%rip), %rdi     # 0x76178
leaq 0x2f902(%rip), %rsi     # 0x7e24a
movl $0x1548, %edx           # imm = 0x1548
leaq 0x31b01(%rip), %rcx     # 0x80455
callq 0x30a0
movq -0xc80(%rbp), %rcx
movq -0x10(%rbp), %rax
movq %rcx, 0x60(%rax)
movl $0x0, -0xc8c(%rbp)
movl -0xc8c(%rbp), %eax
movq -0x20(%rbp), %rcx
cmpl 0x44(%rcx), %eax
jge 0x4e9d3
movq -0x20(%rbp), %rax
movq 0x48(%rax), %rax
movslq -0xc8c(%rbp), %rcx
movq (%rax,%rcx,8), %rax
movq %rax, -0xc98(%rbp)
movq -0xc98(%rbp), %rax
cmpl $0xa02, (%rax)          # imm = 0xA02
jne 0x4e9c0
movq -0xc80(%rbp), %rcx
movq -0xc98(%rbp), %rax
movq 0x60(%rax), %rax
movq %rcx, 0x40(%rax)
jmp 0x4e9c2
movl -0xc8c(%rbp), %eax
addl $0x1, %eax
movl %eax, -0xc8c(%rbp)
jmp 0x4e972
movq -0x8(%rbp), %rdi
movq -0x30(%rbp), %rsi
callq 0x5d320
movq -0x8(%rbp), %rdi
movq -0x30(%rbp), %rsi
callq 0x5d3d0
addq $0xca0, %rsp            # imm = 0xCA0
popq %rbp
retq
nopw %cs:(%rax,%rax)