// File: /workspace/github_c_makefile_star2_O0/Ihsoh[P]ilang/compiler/backend/semantics.c
// Function: func
static void _func(
	ParserContext *ctx,
	ParserASTNode *node
) {
	assert(ctx);
	assert(node);
	assert(node->type == BE_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 == BE_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 == BE_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 != BE_TYPE_VA_LIST) {
				_SYNERR_NODE(
					ctx,
					node_func_param_type,
					"function parameter type must be primitive type or pointer type or __va_list type."
				);
			}

			size_t type_size = _calc_type_size(ctx, node, node_func_param_type);

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

			BE_VAR_SYMBOL_SET_SCOPE_TYPE(symbol, BE_VAR_TYPE_FUNC_PARAM);

			BE_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 == BE_NODE_DUMMY) {
		symbol = be_parser_add_func_symbol_to_node(
			ctx, node_parent, node_identifier->token, node_func_params, node_type, true
		);

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

		if (symbol != NULL
				&& BE_FUNC_SYMBOL_GET_DUMMY(symbol)) {
			ParserASTNode *func_type_node = _NEW_NODE(ctx, BE_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, BE_FUNC_SYMBOL_GET_FUNC_TYPE_NODE(symbol), true)) {
				_SYNERR_TOKEN(
					ctx,
					node_identifier->token,
					"function declaration signature and function implementation signature are not matched."
				);
			}

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

		assert(symbol);

		BE_FUNC_SYMBOL_SET_FUNC_NAME_NODE(symbol, node_identifier);

		BE_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 == BE_NODE_FUNC_PARAMS_ITEM) {
				BE_VAR_SYMBOL_SET_FUNC_SYMBOL(
					BE_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 $0xcb0, %rsp            # imm = 0xCB0
movq %rdi, -0x8(%rbp)
movq %rsi, -0x10(%rbp)
cmpq $0x0, -0x8(%rbp)
je 0x4e2ec
jmp 0x4e30b
leaq 0x31e6e(%rip), %rdi     # 0x80161
leaq 0x34586(%rip), %rsi     # 0x82880
movl $0x17a4, %edx           # imm = 0x17A4
leaq 0x3648b(%rip), %rcx     # 0x84791
callq 0x30a0
cmpq $0x0, -0x10(%rbp)
je 0x4e314
jmp 0x4e333
leaq 0x28241(%rip), %rdi     # 0x7655c
leaq 0x3455e(%rip), %rsi     # 0x82880
movl $0x17a5, %edx           # imm = 0x17A5
leaq 0x36463(%rip), %rcx     # 0x84791
callq 0x30a0
movq -0x10(%rbp), %rax
cmpl $0xa00, (%rax)          # imm = 0xA00
jne 0x4e341
jmp 0x4e360
leaq 0x27d3b(%rip), %rdi     # 0x76083
leaq 0x34531(%rip), %rsi     # 0x82880
movl $0x17a6, %edx           # imm = 0x17A6
leaq 0x36436(%rip), %rcx     # 0x84791
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 0x4e3bb
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 0x4e427
movq -0x10(%rbp), %rax
cmpl $0x4, 0x44(%rax)
jne 0x4e406
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 0x4e425
leaq 0x2504d(%rip), %rdi     # 0x7345a
leaq 0x3446c(%rip), %rsi     # 0x82880
movl $0x17b7, %edx           # imm = 0x17B7
leaq 0x36371(%rip), %rcx     # 0x84791
callq 0x30a0
jmp 0x4e427
movq -0x20(%rbp), %rax
cmpl $0x1, 0x44(%rax)
jl 0x4e479
movq -0x20(%rbp), %rax
movq 0x48(%rax), %rax
movq (%rax), %rax
cmpl $0xa03, (%rax)          # imm = 0xA03
jne 0x4e479
leaq -0x430(%rbp), %rdi
leaq 0x3636c(%rip), %rsi     # 0x847be
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 0x4e5ed
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 0x4e5d7
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 0x4f020
movzbl -0x451(%rbp), %edi
callq 0x4db40
testb $0x1, %al
jne 0x4e569
movzbl -0x451(%rbp), %edi
callq 0x4db90
testb $0x1, %al
jne 0x4e569
movzbl -0x451(%rbp), %eax
cmpl $0xc, %eax
je 0x4e569
leaq -0x860(%rbp), %rdi
leaq 0x362a2(%rip), %rsi     # 0x847e8
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 -0x450(%rbp), %rdx
callq 0x4d5a0
movq %rax, -0x868(%rbp)
movq -0x8(%rbp), %rdi
movq -0x10(%rbp), %rsi
movq -0x448(%rbp), %rax
movq 0x10(%rax), %rdx
movb -0x451(%rbp), %al
movq -0x450(%rbp), %r8
movq -0x868(%rbp), %r9
movzbl %al, %ecx
callq 0x3e600
movq %rax, -0x870(%rbp)
movq -0x870(%rbp), %rax
movb $0x3, 0x78(%rax)
movq -0x870(%rbp), %rcx
movq -0x440(%rbp), %rax
movq %rcx, 0x60(%rax)
jmp 0x4e5d9
movl -0x434(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x434(%rbp)
jmp 0x4e483
cmpq $0x0, -0x28(%rbp)
je 0x4e65f
movb $0x0, -0x871(%rbp)
movq -0x8(%rbp), %rdi
movq -0x28(%rbp), %rsi
leaq -0x871(%rbp), %rdx
callq 0x4f020
movzbl -0x871(%rbp), %edi
callq 0x4db40
testb $0x1, %al
jne 0x4e65d
movzbl -0x871(%rbp), %edi
callq 0x4db90
testb $0x1, %al
jne 0x4e65d
leaq -0xc80(%rbp), %rdi
leaq 0x361fd(%rip), %rsi     # 0x8483a
movb $0x0, %al
callq 0x3160
movq -0x8(%rbp), %rax
movq 0x58(%rax), %rax
movq -0x8(%rbp), %rdi
movq -0x28(%rbp), %rsi
leaq -0xc80(%rbp), %rdx
callq *%rax
jmp 0x4e65f
movq -0x10(%rbp), %rax
movq 0x30(%rax), %rax
movq %rax, -0xc88(%rbp)
cmpq $0x0, -0xc88(%rbp)
je 0x4e67a
jmp 0x4e699
leaq 0x34356(%rip), %rdi     # 0x829d7
leaq 0x341f8(%rip), %rsi     # 0x82880
movl $0x17f4, %edx           # imm = 0x17F4
leaq 0x360fd(%rip), %rcx     # 0x84791
callq 0x30a0
movq $0x0, -0xc90(%rbp)
movq -0x30(%rbp), %rax
cmpl $0x900, (%rax)          # imm = 0x900
jne 0x4e6f1
movq -0x8(%rbp), %rdi
movq -0xc88(%rbp), %rsi
movq -0x18(%rbp), %rax
movq 0x10(%rax), %rdx
movq -0x20(%rbp), %rcx
movq -0x28(%rbp), %r8
movl $0x1, %r9d
callq 0x3ea80
movq %rax, -0xc90(%rbp)
movq -0xc90(%rbp), %rcx
movq -0x10(%rbp), %rax
movq %rcx, 0x60(%rax)
jmp 0x4e8c9
movq -0x8(%rbp), %rdi
movq -0xc88(%rbp), %rsi
movq -0x18(%rbp), %rax
movq 0x10(%rax), %rcx
movl $0x3, %edx
callq 0x82f0
movq %rax, -0xc90(%rbp)
cmpq $0x0, -0xc90(%rbp)
je 0x4e7d1
movq -0xc90(%rbp), %rax
testb $0x1, 0x50(%rax)
je 0x4e7d1
movq -0x8(%rbp), %rdi
movl $0x430, %esi            # imm = 0x430
leaq 0x31931(%rip), %rdx     # 0x80075
xorl %eax, %eax
movl %eax, %ecx
callq 0x5b410
movq %rax, -0xc98(%rbp)
movq -0x8(%rbp), %rdi
movq -0xc98(%rbp), %rsi
movq -0x20(%rbp), %rdx
callq 0x7e20
cmpq $0x0, -0x28(%rbp)
je 0x4e783
movq -0x8(%rbp), %rdi
movq -0xc98(%rbp), %rsi
movq -0x28(%rbp), %rdx
callq 0x7e20
movq -0x8(%rbp), %rdi
movq -0xc98(%rbp), %rsi
movq -0xc90(%rbp), %rax
movq 0x40(%rax), %rdx
movl $0x1, %ecx
callq 0x5a7d0
testb $0x1, %al
jne 0x4e7c4
movq -0x8(%rbp), %rax
movq 0x50(%rax), %rax
movq -0x8(%rbp), %rdi
movq -0x18(%rbp), %rcx
movq 0x10(%rcx), %rsi
leaq 0x360b5(%rip), %rdx     # 0x84877
callq *%rax
movq -0xc90(%rbp), %rax
movb $0x0, 0x50(%rax)
jmp 0x4e7fb
movq -0x8(%rbp), %rdi
movq -0xc88(%rbp), %rsi
movq -0x18(%rbp), %rax
movq 0x10(%rax), %rdx
movq -0x20(%rbp), %rcx
movq -0x28(%rbp), %r8
xorl %r9d, %r9d
callq 0x3ea80
movq %rax, -0xc90(%rbp)
cmpq $0x0, -0xc90(%rbp)
je 0x4e807
jmp 0x4e826
leaq 0x2789a(%rip), %rdi     # 0x760a8
leaq 0x3406b(%rip), %rsi     # 0x82880
movl $0x1819, %edx           # imm = 0x1819
leaq 0x35f70(%rip), %rcx     # 0x84791
callq 0x30a0
movq -0x18(%rbp), %rcx
movq -0xc90(%rbp), %rax
movq %rcx, 0x58(%rax)
movq -0xc90(%rbp), %rcx
movq -0x10(%rbp), %rax
movq %rcx, 0x60(%rax)
movl $0x0, -0xc9c(%rbp)
movl -0xc9c(%rbp), %eax
movq -0x20(%rbp), %rcx
cmpl 0x44(%rcx), %eax
jge 0x4e8af
movq -0x20(%rbp), %rax
movq 0x48(%rax), %rax
movslq -0xc9c(%rbp), %rcx
movq (%rax,%rcx,8), %rax
movq %rax, -0xca8(%rbp)
movq -0xca8(%rbp), %rax
cmpl $0xa02, (%rax)          # imm = 0xA02
jne 0x4e89c
movq -0xc90(%rbp), %rcx
movq -0xca8(%rbp), %rax
movq 0x60(%rax), %rax
movq %rcx, 0x40(%rax)
jmp 0x4e89e
movl -0xc9c(%rbp), %eax
addl $0x1, %eax
movl %eax, -0xc9c(%rbp)
jmp 0x4e84e
movq -0x8(%rbp), %rdi
movq -0x30(%rbp), %rsi
callq 0x5b4a0
movq -0x8(%rbp), %rdi
movq -0x30(%rbp), %rsi
callq 0x5b550
addq $0xcb0, %rsp            # imm = 0xCB0
popq %rbp
retq
nopw %cs:(%rax,%rax)