// File: /workspace/github_c_makefile_star2_O0/Ihsoh[P]ilang/compiler/backend/semantics.c
// Function: var_with_parent
static void _var_with_parent(
	ParserContext *ctx,
	ParserASTNode *node,
	ParserASTNode *node_parent
) {
	assert(ctx);
	assert(node);
	assert(node->type == BE_NODE_VAR);
	assert(node->nchilds > 0);
	assert(node_parent);

	ParserASTNode *align_node = BE_VAR_AST_NODE_GET_ALIGN_NODE(node);
	int align = 0;
	if (align_node != NULL) {
		assert(align_node->nchilds == 1);
		switch (_get_node_catagory(align_node->childs[0]->type)) {
			case BE_SEM_NODE_CATEGORY_TYPE: {
				ParserASTNode *type_node = align_node->childs[0];
				_type(ctx, type_node, NULL);
				align = (int) _calc_type_align(ctx, node, type_node);
				assert(align >= 1);
				BE_VAR_AST_NODE_SET_ALIGN(node, align);
				break;
			}
			case BE_SEM_NODE_CATAGORY_EXPR: {
				ParserASTNode *expr_node = align_node->childs[0];
				_expr(ctx, expr_node);
				if (!BE_EXPR_AST_NODE_GET_CONSTANT(expr_node)) {
					_SYNERR_NODE(ctx, expr_node, "align parameter must be constant expression.");
				}
				align = _get_constexpr_int(ctx, expr_node);
				if (align <= 0) {
					_SYNERR_NODE(ctx, expr_node, "align parameter must be greater than 0.");
				}
				if (align != 1 && align % 2 != 0) {
					_SYNERR_NODE(ctx, expr_node, "align parameter is not a power of 2.");
				}
				BE_VAR_AST_NODE_SET_ALIGN(node, align);
				break;
			}
			default: {
				assert(0);
				break;
			}
		}
	}

	ParserSymbol *func_symbol = NULL;
	uint8_t var_scope_type = _get_var_scope_type(node, &func_symbol);
	BE_VAR_AST_NODE_SET_TYPE(node, var_scope_type);

	for (int i = 0; i < node->nchilds; i++) {
		ParserASTNode *node_var_item = node->childs[i];
		assert(node_var_item->type == BE_NODE_VAR_ITEM);
		assert(node_var_item->nchilds == 2 || node_var_item->nchilds == 3);

		ParserASTNode *node_id = node_var_item->childs[0];
		assert(node_id->type == BE_NODE_IDENTIFIER);

		ParserASTNode *node_type = node_var_item->childs[1];
		uint8_t var_type = 0;
		_type(ctx, node_type, &var_type);
		if (var_type == BE_TYPE_FUNC) {
			_SYNERR_NODE(
					ctx,
					node,
					"cannot define a function type variable, "
					"but can define a function pointer type(*function(...)) variable."
				);
		}

		size_t type_size = _calc_type_size(ctx, node, node_type);
		
		ParserSymbol *symbol = be_parser_add_var_symbol_to_node(
			ctx,
			node_parent,
			node_id->token,
			var_type,
			node_type,
			type_size
		);
		BE_VAR_SYMBOL_SET_FUNC_SYMBOL(symbol, func_symbol);
		if (align > 0) {
			BE_VAR_SYMBOL_SET_ALIGN(symbol, align);
		} else {
			BE_VAR_SYMBOL_SET_ALIGN(symbol, _calc_type_align(ctx, node, node_type));
		}
		BE_VAR_SYMBOL_SET_SCOPE_TYPE(symbol, var_scope_type);

		BE_VAR_ITEM_AST_NODE_SET_SYMBOL(node_var_item, symbol);

		if (node_var_item->nchilds == 3) {
			// 如果变量是结构体成员变量，则不被允许包含初始化表达式。
			if (var_scope_type == BE_VAR_TYPE_STRUCT_MEMBER) {
				_SYNERR_NODE(
					ctx,
					node,
					"struct member variable cannot contain initial expression."
				);
			}

			// 如果变量是局部变量，则不被允许包含初始化表达式。
			if (var_scope_type == BE_VAR_TYPE_LOCAL) {
				_SYNERR_NODE(
					ctx,
					node,
					"local variable cannot contain initial expression."
				);
			}

			ParserASTNode *node_expr = node_var_item->childs[2];

			// 插入一个cast节点进行类型强制转换。
			ParserASTNode *node_cast = be_parser_new_node(
				ctx, BE_NODE_EXPR_CAST, "BE_NODE_EXPR_CAST", NULL
			);
			parser_add_child(ctx, node_cast, node_type);
			parser_insert_node(ctx, &(node_expr->childs[0]), node_cast);

			_expr_wrapper(ctx, node_expr);

			// 如果变量是全局变量，则初始化表达式只允许常量表达式。
			bool const_expr = BE_EXPR_AST_NODE_GET_CONSTANT(node_expr);
			if (var_scope_type == BE_VAR_TYPE_GLOBAL && !const_expr) {
				_SYNERR_NODE(
					ctx,
					node,
					"variable initial expression must be constant expression."
				);
			}

			ParserASTNode *node_expr_type = BE_EXPR_AST_NODE_GET_TYPE_NODE(node_expr);
			if (!_is_compatible_type_for_assign(ctx, node_type, node_expr_type, false)) {
				_SYNERR_NODE(
					ctx,
					node,
					"incompatible initial expression."
				);
			}
		}

	}
}

// Assembly:
pushq %rbp
movq %rsp, %rbp
subq $0x20c0, %rsp           # imm = 0x20C0
movq %rdi, -0x8(%rbp)
movq %rsi, -0x10(%rbp)
movq %rdx, -0x18(%rbp)
cmpq $0x0, -0x8(%rbp)
je 0x4e900
jmp 0x4e91f
leaq 0x3185a(%rip), %rdi     # 0x80161
leaq 0x33f72(%rip), %rsi     # 0x82880
movl $0xe96, %edx            # imm = 0xE96
leaq 0x340c9(%rip), %rcx     # 0x829e3
callq 0x30a0
cmpq $0x0, -0x10(%rbp)
je 0x4e928
jmp 0x4e947
leaq 0x27c2d(%rip), %rdi     # 0x7655c
leaq 0x33f4a(%rip), %rsi     # 0x82880
movl $0xe97, %edx            # imm = 0xE97
leaq 0x340a1(%rip), %rcx     # 0x829e3
callq 0x30a0
movq -0x10(%rbp), %rax
cmpl $0xc00, (%rax)          # imm = 0xC00
jne 0x4e955
jmp 0x4e974
leaq 0x345b2(%rip), %rdi     # 0x82f0e
leaq 0x33f1d(%rip), %rsi     # 0x82880
movl $0xe98, %edx            # imm = 0xE98
leaq 0x34074(%rip), %rcx     # 0x829e3
callq 0x30a0
movq -0x10(%rbp), %rax
cmpl $0x0, 0x44(%rax)
jle 0x4e980
jmp 0x4e99f
leaq 0x27255(%rip), %rdi     # 0x75bdc
leaq 0x33ef2(%rip), %rsi     # 0x82880
movl $0xe99, %edx            # imm = 0xE99
leaq 0x34049(%rip), %rcx     # 0x829e3
callq 0x30a0
cmpq $0x0, -0x18(%rbp)
je 0x4e9a8
jmp 0x4e9c7
leaq 0x34028(%rip), %rdi     # 0x829d7
leaq 0x33eca(%rip), %rsi     # 0x82880
movl $0xe9a, %edx            # imm = 0xE9A
leaq 0x34021(%rip), %rcx     # 0x829e3
callq 0x30a0
movq -0x10(%rbp), %rax
movq 0x68(%rax), %rax
movq %rax, -0x20(%rbp)
movl $0x0, -0x24(%rbp)
cmpq $0x0, -0x20(%rbp)
je 0x4ebb4
movq -0x20(%rbp), %rax
cmpl $0x1, 0x44(%rax)
jne 0x4e9f1
jmp 0x4ea10
leaq 0x34034(%rip), %rdi     # 0x82a2c
leaq 0x33e81(%rip), %rsi     # 0x82880
movl $0xe9f, %edx            # imm = 0xE9F
leaq 0x33fd8(%rip), %rcx     # 0x829e3
callq 0x30a0
movq -0x20(%rbp), %rax
movq 0x48(%rax), %rax
movq (%rax), %rax
movl (%rax), %edi
callq 0x4efd0
movl %eax, %ecx
movl %ecx, -0x20b4(%rbp)
subl $0x1, %eax
je 0x4ea41
jmp 0x4ea31
movl -0x20b4(%rbp), %eax
subl $0x2, %eax
je 0x4eaab
jmp 0x4eb93
movq -0x20(%rbp), %rax
movq 0x48(%rax), %rax
movq (%rax), %rax
movq %rax, -0x30(%rbp)
movq -0x8(%rbp), %rdi
movq -0x30(%rbp), %rsi
xorl %eax, %eax
movl %eax, %edx
callq 0x4f020
movq -0x8(%rbp), %rdi
movq -0x10(%rbp), %rsi
movq -0x30(%rbp), %rdx
callq 0x4f0a0
movl %eax, -0x24(%rbp)
cmpl $0x1, -0x24(%rbp)
jl 0x4ea7d
jmp 0x4ea9c
leaq 0x33fc1(%rip), %rdi     # 0x82a45
leaq 0x33df5(%rip), %rsi     # 0x82880
movl $0xea5, %edx            # imm = 0xEA5
leaq 0x33f4c(%rip), %rcx     # 0x829e3
callq 0x30a0
movl -0x24(%rbp), %ecx
movq -0x10(%rbp), %rax
movl %ecx, 0x70(%rax)
jmp 0x4ebb2
movq -0x20(%rbp), %rax
movq 0x48(%rax), %rax
movq (%rax), %rax
movq %rax, -0x38(%rbp)
movq -0x8(%rbp), %rdi
movq -0x38(%rbp), %rsi
callq 0x4f400
movq -0x38(%rbp), %rax
testb $0x1, 0x70(%rax)
jne 0x4eaff
leaq -0x440(%rbp), %rdi
leaq 0x33f71(%rip), %rsi     # 0x82a50
movb $0x0, %al
callq 0x3160
movq -0x8(%rbp), %rax
movq 0x58(%rax), %rax
movq -0x8(%rbp), %rdi
movq -0x38(%rbp), %rsi
leaq -0x440(%rbp), %rdx
callq *%rax
movq -0x8(%rbp), %rdi
movq -0x38(%rbp), %rsi
callq 0x4f480
movl %eax, -0x24(%rbp)
cmpl $0x0, -0x24(%rbp)
jg 0x4eb43
leaq -0x840(%rbp), %rdi
leaq 0x33f5a(%rip), %rsi     # 0x82a7d
movb $0x0, %al
callq 0x3160
movq -0x8(%rbp), %rax
movq 0x58(%rax), %rax
movq -0x8(%rbp), %rdi
movq -0x38(%rbp), %rsi
leaq -0x840(%rbp), %rdx
callq *%rax
cmpl $0x1, -0x24(%rbp)
je 0x4eb87
movl -0x24(%rbp), %eax
movl $0x2, %ecx
cltd
idivl %ecx
cmpl $0x0, %edx
je 0x4eb87
leaq -0xc40(%rbp), %rdi
leaq 0x33f3e(%rip), %rsi     # 0x82aa5
movb $0x0, %al
callq 0x3160
movq -0x8(%rbp), %rax
movq 0x58(%rax), %rax
movq -0x8(%rbp), %rdi
movq -0x38(%rbp), %rsi
leaq -0xc40(%rbp), %rdx
callq *%rax
movl -0x24(%rbp), %ecx
movq -0x10(%rbp), %rax
movl %ecx, 0x70(%rax)
jmp 0x4ebb2
leaq 0x248c0(%rip), %rdi     # 0x7345a
leaq 0x33cdf(%rip), %rsi     # 0x82880
movl $0xeba, %edx            # imm = 0xEBA
leaq 0x33e36(%rip), %rcx     # 0x829e3
callq 0x30a0
jmp 0x4ebb4
movq $0x0, -0xc48(%rbp)
movq -0x10(%rbp), %rdi
leaq -0xc48(%rbp), %rsi
callq 0x4f4b0
movb %al, -0xc49(%rbp)
movb -0xc49(%rbp), %cl
movq -0x10(%rbp), %rax
movb %cl, 0x60(%rax)
movl $0x0, -0xc50(%rbp)
movl -0xc50(%rbp), %eax
movq -0x10(%rbp), %rcx
cmpl 0x44(%rcx), %eax
jge 0x4efb8
movq -0x10(%rbp), %rax
movq 0x48(%rax), %rax
movslq -0xc50(%rbp), %rcx
movq (%rax,%rcx,8), %rax
movq %rax, -0xc58(%rbp)
movq -0xc58(%rbp), %rax
cmpl $0xc01, (%rax)          # imm = 0xC01
jne 0x4ec2a
jmp 0x4ec49
leaq 0x26fbd(%rip), %rdi     # 0x75bee
leaq 0x33c48(%rip), %rsi     # 0x82880
movl $0xec6, %edx            # imm = 0xEC6
leaq 0x33d9f(%rip), %rcx     # 0x829e3
callq 0x30a0
movq -0xc58(%rbp), %rax
cmpl $0x2, 0x44(%rax)
je 0x4ec63
movq -0xc58(%rbp), %rax
cmpl $0x3, 0x44(%rax)
jne 0x4ec65
jmp 0x4ec84
leaq 0x26faa(%rip), %rdi     # 0x75c16
leaq 0x33c0d(%rip), %rsi     # 0x82880
movl $0xec7, %edx            # imm = 0xEC7
leaq 0x33d64(%rip), %rcx     # 0x829e3
callq 0x30a0
movq -0xc58(%rbp), %rax
movq 0x48(%rax), %rax
movq (%rax), %rax
movq %rax, -0xc60(%rbp)
movq -0xc60(%rbp), %rax
cmpl $0x200, (%rax)          # imm = 0x200
jne 0x4ecaa
jmp 0x4ecc9
leaq 0x282f1(%rip), %rdi     # 0x76fa2
leaq 0x33bc8(%rip), %rsi     # 0x82880
movl $0xeca, %edx            # imm = 0xECA
leaq 0x33d1f(%rip), %rcx     # 0x829e3
callq 0x30a0
movq -0xc58(%rbp), %rax
movq 0x48(%rax), %rax
movq 0x8(%rax), %rax
movq %rax, -0xc68(%rbp)
movb $0x0, -0xc69(%rbp)
movq -0x8(%rbp), %rdi
movq -0xc68(%rbp), %rsi
leaq -0xc69(%rbp), %rdx
callq 0x4f020
movzbl -0xc69(%rbp), %eax
cmpl $0xf, %eax
jne 0x4ed37
leaq -0x1070(%rbp), %rdi
leaq 0x33db3(%rip), %rsi     # 0x82aca
movb $0x0, %al
callq 0x3160
movq -0x8(%rbp), %rax
movq 0x58(%rax), %rax
movq -0x8(%rbp), %rdi
movq -0x10(%rbp), %rsi
leaq -0x1070(%rbp), %rdx
callq *%rax
movq -0x8(%rbp), %rdi
movq -0x10(%rbp), %rsi
movq -0xc68(%rbp), %rdx
callq 0x4d5a0
movq %rax, -0x1078(%rbp)
movq -0x8(%rbp), %rdi
movq -0x18(%rbp), %rsi
movq -0xc60(%rbp), %rax
movq 0x10(%rax), %rdx
movb -0xc69(%rbp), %al
movq -0xc68(%rbp), %r8
movq -0x1078(%rbp), %r9
movzbl %al, %ecx
callq 0x3e600
movq %rax, -0x1080(%rbp)
movq -0xc48(%rbp), %rcx
movq -0x1080(%rbp), %rax
movq %rcx, 0x40(%rax)
cmpl $0x0, -0x24(%rbp)
jle 0x4edaf
movl -0x24(%rbp), %ecx
movq -0x1080(%rbp), %rax
movl %ecx, 0x60(%rax)
jmp 0x4edcf
movq -0x8(%rbp), %rdi
movq -0x10(%rbp), %rsi
movq -0xc68(%rbp), %rdx
callq 0x4f0a0
movl %eax, %ecx
movq -0x1080(%rbp), %rax
movl %ecx, 0x60(%rax)
movb -0xc49(%rbp), %cl
movq -0x1080(%rbp), %rax
movb %cl, 0x78(%rax)
movq -0x1080(%rbp), %rcx
movq -0xc58(%rbp), %rax
movq %rcx, 0x60(%rax)
movq -0xc58(%rbp), %rax
cmpl $0x3, 0x44(%rax)
jne 0x4efa2
movzbl -0xc49(%rbp), %eax
cmpl $0x4, %eax
jne 0x4ee3c
leaq -0x1480(%rbp), %rdi
leaq 0x33d17(%rip), %rsi     # 0x82b33
movb $0x0, %al
callq 0x3160
movq -0x8(%rbp), %rax
movq 0x58(%rax), %rax
movq -0x8(%rbp), %rdi
movq -0x10(%rbp), %rsi
leaq -0x1480(%rbp), %rdx
callq *%rax
movzbl -0xc49(%rbp), %eax
cmpl $0x2, %eax
jne 0x4ee76
leaq -0x1880(%rbp), %rdi
leaq 0x33d17(%rip), %rsi     # 0x82b6d
movb $0x0, %al
callq 0x3160
movq -0x8(%rbp), %rax
movq 0x58(%rax), %rax
movq -0x8(%rbp), %rdi
movq -0x10(%rbp), %rsi
leaq -0x1880(%rbp), %rdx
callq *%rax
movq -0xc58(%rbp), %rax
movq 0x48(%rax), %rax
movq 0x10(%rax), %rax
movq %rax, -0x1888(%rbp)
movq -0x8(%rbp), %rdi
movl $0xec8, %esi            # imm = 0xEC8
leaq 0x317fb(%rip), %rdx     # 0x80697
xorl %eax, %eax
movl %eax, %ecx
callq 0x3d940
movq %rax, -0x1890(%rbp)
movq -0x8(%rbp), %rdi
movq -0x1890(%rbp), %rsi
movq -0xc68(%rbp), %rdx
callq 0x7e20
movq -0x8(%rbp), %rdi
movq -0x1888(%rbp), %rax
movq 0x48(%rax), %rsi
movq -0x1890(%rbp), %rdx
callq 0x7ce0
movq -0x8(%rbp), %rdi
movq -0x1888(%rbp), %rsi
callq 0x4f5d0
movq -0x1888(%rbp), %rax
movb 0x70(%rax), %al
andb $0x1, %al
movb %al, -0x1891(%rbp)
movzbl -0xc49(%rbp), %eax
cmpl $0x1, %eax
jne 0x4ef43
testb $0x1, -0x1891(%rbp)
jne 0x4ef43
leaq -0x1ca0(%rbp), %rdi
leaq 0x33c7c(%rip), %rsi     # 0x82b9f
movb $0x0, %al
callq 0x3160
movq -0x8(%rbp), %rax
movq 0x58(%rax), %rax
movq -0x8(%rbp), %rdi
movq -0x10(%rbp), %rsi
leaq -0x1ca0(%rbp), %rdx
callq *%rax
movq -0x1888(%rbp), %rax
movq 0x68(%rax), %rax
movq %rax, -0x1ca8(%rbp)
movq -0x8(%rbp), %rdi
movq -0xc68(%rbp), %rsi
movq -0x1ca8(%rbp), %rdx
xorl %ecx, %ecx
callq 0x4f6a0
testb $0x1, %al
jne 0x4efa0
leaq -0x20b0(%rbp), %rdi
leaq 0x33c58(%rip), %rsi     # 0x82bd8
movb $0x0, %al
callq 0x3160
movq -0x8(%rbp), %rax
movq 0x58(%rax), %rax
movq -0x8(%rbp), %rdi
movq -0x10(%rbp), %rsi
leaq -0x20b0(%rbp), %rdx
callq *%rax
jmp 0x4efa2
jmp 0x4efa4
movl -0xc50(%rbp), %eax
addl $0x1, %eax
movl %eax, -0xc50(%rbp)
jmp 0x4ebec
addq $0x20c0, %rsp           # imm = 0x20C0
popq %rbp
retq
nopw %cs:(%rax,%rax)