// File: /workspace/github_c_makefile_star2_O0/Ihsoh[P]ilang/compiler/frontend/semantics.c
// Function: check_va
static void _check_va(
	ParserContext *ctx,
	ParserASTNode *node
) {
	assert(ctx);
	assert(node);
	assert(node->type == FE_NODE_STAT_VA_START
			|| node->type == FE_NODE_STAT_VA_END
			|| node->type == FE_NODE_STAT_VA_COPY
			|| node->type == FE_NODE_EXPR_VA_ARG);

	ParserSymbol *func_symbol = _get_func_symbol_by_node(ctx, node);
	ParserASTNode *params_node = FE_FUNC_SYMBOL_GET_PARAMS_NODE(func_symbol);

	// __va_*类语句或操作符应当在包含有“...”参数的函数内使用。
	if (params_node->nchilds == 0
			|| params_node->childs[params_node->nchilds - 1]->type != FE_NODE_FUNC_PARAMS_ELLIPSIS_ITEM) {
		_SYNERR_NODE(
			ctx,
			node,
			"function parameters does not have '...'."
		);
	}

	// 如果函数包含“...”，那么参数个数至少大于等于2个，因为“...”不能作为函数的第一个参数。
	assert(params_node->nchilds >= 2);

	// “...”的前一个参数必须是基本类型或者指针类型。
	ParserASTNode *penult_param_node = params_node->childs[params_node->nchilds - 2];
	ParserASTNode *penult_param_type_node = penult_param_node->childs[1];
	uint8_t penult_param_type = _get_type_by_type_node(ctx, penult_param_type_node);
	if (!_is_primitive_type(penult_param_type)
			&& !_is_pointer_type(penult_param_type)) {
		_SYNERR_NODE(
			ctx,
			node,
			"function penult parameter type must be primitive type or pointer type "
			"when use va_* statement or expression operator."
		);
	}
}

// Assembly:
pushq %rbp
movq %rsp, %rbp
subq $0x840, %rsp            # imm = 0x840
movq %rdi, -0x8(%rbp)
movq %rsi, -0x10(%rbp)
cmpq $0x0, -0x8(%rbp)
je 0x5f26c
jmp 0x5f28b
leaq 0x1d2e3(%rip), %rdi     # 0x7c556
leaq 0x1efd0(%rip), %rsi     # 0x7e24a
movl $0x673, %edx            # imm = 0x673
leaq 0x21c05(%rip), %rcx     # 0x80e8b
callq 0x30a0
cmpq $0x0, -0x10(%rbp)
je 0x5f294
jmp 0x5f2b3
leaq 0x16d38(%rip), %rdi     # 0x75fd3
leaq 0x1efa8(%rip), %rsi     # 0x7e24a
movl $0x674, %edx            # imm = 0x674
leaq 0x21bdd(%rip), %rcx     # 0x80e8b
callq 0x30a0
movq -0x10(%rbp), %rax
cmpl $0xbd0, (%rax)          # imm = 0xBD0
je 0x5f2e3
movq -0x10(%rbp), %rax
cmpl $0xbd1, (%rax)          # imm = 0xBD1
je 0x5f2e3
movq -0x10(%rbp), %rax
cmpl $0xbd2, (%rax)          # imm = 0xBD2
je 0x5f2e3
movq -0x10(%rbp), %rax
cmpl $0xece, (%rax)          # imm = 0xECE
jne 0x5f2e5
jmp 0x5f304
leaq 0x21bd0(%rip), %rdi     # 0x80ebc
leaq 0x1ef57(%rip), %rsi     # 0x7e24a
movl $0x678, %edx            # imm = 0x678
leaq 0x21b8c(%rip), %rcx     # 0x80e8b
callq 0x30a0
movq -0x8(%rbp), %rdi
movq -0x10(%rbp), %rsi
callq 0x4dbf0
movq %rax, -0x18(%rbp)
movq -0x18(%rbp), %rax
movq 0x30(%rax), %rax
movq %rax, -0x20(%rbp)
movq -0x20(%rbp), %rax
cmpl $0x0, 0x44(%rax)
je 0x5f34c
movq -0x20(%rbp), %rax
movq 0x48(%rax), %rax
movq -0x20(%rbp), %rcx
movl 0x44(%rcx), %ecx
subl $0x1, %ecx
movslq %ecx, %rcx
movq (%rax,%rcx,8), %rax
cmpl $0xa03, (%rax)          # imm = 0xA03
je 0x5f37a
leaq -0x420(%rbp), %rdi
leaq 0x21bf6(%rip), %rsi     # 0x80f50
movb $0x0, %al
callq 0x3160
movq -0x8(%rbp), %rax
movq 0x58(%rax), %rax
movq -0x8(%rbp), %rdi
movq -0x10(%rbp), %rsi
leaq -0x420(%rbp), %rdx
callq *%rax
movq -0x20(%rbp), %rax
cmpl $0x2, 0x44(%rax)
jl 0x5f386
jmp 0x5f3a5
leaq 0x18a71(%rip), %rdi     # 0x77dfe
leaq 0x1eeb6(%rip), %rsi     # 0x7e24a
movl $0x688, %edx            # imm = 0x688
leaq 0x21aeb(%rip), %rcx     # 0x80e8b
callq 0x30a0
movq -0x20(%rbp), %rax
movq 0x48(%rax), %rax
movq -0x20(%rbp), %rcx
movl 0x44(%rcx), %ecx
subl $0x2, %ecx
movslq %ecx, %rcx
movq (%rax,%rcx,8), %rax
movq %rax, -0x428(%rbp)
movq -0x428(%rbp), %rax
movq 0x48(%rax), %rax
movq 0x8(%rax), %rax
movq %rax, -0x430(%rbp)
movq -0x8(%rbp), %rdi
movq -0x430(%rbp), %rsi
callq 0x4d750
movb %al, -0x431(%rbp)
movzbl -0x431(%rbp), %edi
callq 0x4d470
testb $0x1, %al
jne 0x5f43f
movzbl -0x431(%rbp), %edi
callq 0x4d4c0
testb $0x1, %al
jne 0x5f43f
leaq -0x840(%rbp), %rdi
leaq 0x21b5a(%rip), %rsi     # 0x80f79
movb $0x0, %al
callq 0x3160
movq -0x8(%rbp), %rax
movq 0x58(%rax), %rax
movq -0x8(%rbp), %rdi
movq -0x10(%rbp), %rsi
leaq -0x840(%rbp), %rdx
callq *%rax
addq $0x840, %rsp            # imm = 0x840
popq %rbp
retq
nopl (%rax,%rax)