// File: /workspace/github_c_makefile_star2_O3/Ihsoh[P]ilang/compiler/frontend/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 == FE_NODE_VAR);
	assert(node->nchilds > 0);
	assert(node_parent);

	ParserASTNode *align_node = FE_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 FE_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);
				FE_VAR_AST_NODE_SET_ALIGN(node, align);
				break;
			}
			case FE_SEM_NODE_CATAGORY_EXPR: {
				ParserASTNode *expr_node = align_node->childs[0];
				_expr(ctx, expr_node);
				if (!FE_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.");
				}
				FE_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);
	FE_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 == FE_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 == FE_NODE_IDENTIFIER);

		ParserASTNode *node_type = node_var_item->childs[1];
		uint8_t var_type = 0;
		_type(ctx, node_type, &var_type);
		if (var_type == FE_TYPE_FUNC) {
			_SYNERR_NODE(
					ctx,
					node,
					"cannot define a function type variable, "
					"but can define a function pointer type(*function(...)) variable."
				);
		}
		
		ParserSymbol *symbol = fe_parser_add_var_symbol_to_node(
			ctx,
			node_parent,
			node_id->token,
			var_type,
			node_type
		);
		FE_VAR_SYMBOL_SET_FUNC_SYMBOL(symbol, func_symbol);
		if (align > 0) {
			FE_VAR_SYMBOL_SET_ALIGN(symbol, align);
		} else {
			FE_VAR_SYMBOL_SET_ALIGN(symbol, _calc_type_align(ctx, node, node_type));
		}

		FE_VAR_ITEM_AST_NODE_SET_SYMBOL(node_var_item, symbol);

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

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

			// 插入一个cast节点进行类型强制转换。
			ParserASTNode *node_cast = fe_parser_new_node(
				ctx, FE_NODE_EXPR_CAST, "FE_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 = FE_EXPR_AST_NODE_GET_CONSTANT(node_expr);
			if (var_scope_type == FE_VAR_TYPE_GLOBAL && !const_expr) {
				_SYNERR_NODE(
					ctx,
					node,
					"variable initial expression must be constant expression."
				);
			}

			ParserASTNode *node_expr_type = FE_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
pushq %r15
pushq %r14
pushq %r13
pushq %r12
pushq %rbx
subq $0x438, %rsp            # imm = 0x438
movq %rdx, -0x60(%rbp)
testq %rsi, %rsi
je 0x2b176
movq %rsi, %r13
cmpl $0xc00, (%rsi)          # imm = 0xC00
jne 0x2b195
cmpl $0x0, 0x44(%r13)
jle 0x2b1b4
movq %rdi, %r14
movq 0x68(%r13), %rax
testq %rax, %rax
je 0x2ad4d
cmpl $0x1, 0x44(%rax)
jne 0x2b1f2
movq 0x48(%rax), %rax
movq (%rax), %rbx
movzbl 0x1(%rbx), %eax
shll $0x8, %eax
xorl %ecx, %ecx
cmpl $0xe00, %eax            # imm = 0xE00
sete %cl
addl %ecx, %ecx
cmpl $0x400, %eax            # imm = 0x400
movl $0x1, %eax
cmovnel %ecx, %eax
cmpl $0x2, %eax
je 0x2ad55
cmpl $0x1, %eax
jne 0x2b211
movq %r14, %rdi
movq %rbx, %rsi
xorl %edx, %edx
callq 0x2b24f
movq %r14, %rdi
movq %r13, %rsi
movq %rbx, %rdx
callq 0x2b281
testq %rax, %rax
je 0x2b230
movq %rax, %r15
jmp 0x2ae21
xorl %r15d, %r15d
jmp 0x2ae25
movq %r14, %rdi
movq %rbx, %rsi
callq 0x2b6a7
cmpb $0x0, 0x70(%rbx)
jne 0x2ad97
movups 0x1fd41(%rip), %xmm0    # 0x4aaae
leaq -0x460(%rbp), %rdx
movups %xmm0, 0x1d(%rdx)
movups 0x1fd22(%rip), %xmm0    # 0x4aaa1
movaps %xmm0, 0x10(%rdx)
movups 0x1fd07(%rip), %xmm0    # 0x4aa91
movaps %xmm0, (%rdx)
movq %r14, %rdi
movq %rbx, %rsi
callq *0x58(%r14)
movq %rbx, %rdi
callq 0x31efb
movq %rax, %r15
testl %r15d, %r15d
jg 0x2addb
movups 0x1fd20(%rip), %xmm0    # 0x4aace
leaq -0x460(%rbp), %rdx
movaps %xmm0, 0x10(%rdx)
movups 0x1fcfe(%rip), %xmm0    # 0x4aabe
movaps %xmm0, (%rdx)
movabsq $0x2e30206e616874, %rax # imm = 0x2E30206E616874
movq %rax, 0x20(%rdx)
movq %r14, %rdi
movq %rbx, %rsi
callq *0x58(%r14)
cmpl $0x1, %r15d
sete %al
testb $0x1, %r15b
sete %cl
orb %al, %cl
jne 0x2ae21
movups 0x1fd02(%rip), %xmm0    # 0x4aaf6
leaq -0x460(%rbp), %rdx
movaps %xmm0, 0x10(%rdx)
movups 0x1fce0(%rip), %xmm0    # 0x4aae6
movaps %xmm0, (%rdx)
movabsq $0x2e3220666f2072, %rax # imm = 0x2E3220666F2072
movq %rax, 0x1d(%rdx)
movq %r14, %rdi
movq %rbx, %rsi
callq *0x58(%r14)
movl %r15d, 0x70(%r13)
cmpl $0xc00, (%r13)          # imm = 0xC00
jne 0x2b1d3
movq %r13, %rax
movq %r14, -0x40(%rbp)
movq %r15, -0x58(%rbp)
movq 0x30(%rax), %rax
testq %rax, %rax
je 0x2b157
movl (%rax), %ecx
cmpl $0x100, %ecx            # imm = 0x100
je 0x2ae78
cmpl $0xd00, %ecx            # imm = 0xD00
je 0x2ae90
cmpl $0xa00, %ecx            # imm = 0xA00
jne 0x2ae3e
movq 0x60(%rax), %rax
movq %rax, -0x50(%rbp)
movb $0x2, %al
movl $0x0, -0x34(%rbp)
jmp 0x2ae9f
movb $0x1, %al
movl %eax, -0x30(%rbp)
movq $0x0, -0x50(%rbp)
movl $0x0, -0x34(%rbp)
movb $0x1, %al
jmp 0x2aea6
movb $0x3, %al
movb $0x1, %cl
movl %ecx, -0x34(%rbp)
movq $0x0, -0x50(%rbp)
movl $0x0, -0x30(%rbp)
movb %al, 0x60(%r13)
cmpl $0x0, 0x44(%r13)
jle 0x2b0e8
xorl %r14d, %r14d
movq 0x48(%r13), %rax
movq (%rax,%r14,8), %r12
cmpl $0xc01, (%r12)          # imm = 0xC01
jne 0x2b138
movl 0x44(%r12), %eax
andl $-0x2, %eax
cmpl $0x2, %eax
jne 0x2b119
movq %r13, %r15
movq 0x48(%r12), %rax
movq (%rax), %r13
cmpl $0x200, (%r13)          # imm = 0x200
jne 0x2b0fa
movq 0x8(%rax), %rsi
movb $0x0, -0x29(%rbp)
movq -0x40(%rbp), %rbx
movq %rbx, %rdi
movq %rsi, -0x48(%rbp)
leaq -0x29(%rbp), %rdx
callq 0x2b24f
movb -0x29(%rbp), %al
cmpb $0xf, %al
jne 0x2af46
movl $0x69, %edx
leaq -0x460(%rbp), %rdi
leaq 0x1fbdd(%rip), %rsi     # 0x4ab0b
callq 0x3110
movq %rbx, %rdi
movq %r15, %rsi
leaq -0x460(%rbp), %rdx
callq *0x58(%rbx)
movb -0x29(%rbp), %al
movq 0x10(%r13), %rdx
movzbl %al, %ecx
movq %rbx, %rdi
movq -0x60(%rbp), %rsi
movq -0x48(%rbp), %r8
callq 0x24d44
movq %rax, %r13
movq -0x50(%rbp), %rax
movq %rax, 0x40(%r13)
movq -0x58(%rbp), %rcx
movl %ecx, %eax
testl %ecx, %ecx
jg 0x2af82
movq -0x40(%rbp), %rdi
movq %r15, %rsi
movq -0x48(%rbp), %rdx
callq 0x2b281
movl %eax, 0x60(%r13)
movq %r13, 0x60(%r12)
cmpl $0x3, 0x44(%r12)
movq %r15, %r13
jne 0x2b0d8
cmpb $0x0, -0x34(%rbp)
je 0x2afe9
movups 0x1fbf7(%rip), %xmm0    # 0x4ab9e
movups %xmm0, -0x436(%rbp)
movups 0x1fbdf(%rip), %xmm0    # 0x4ab94
movaps %xmm0, -0x440(%rbp)
movups 0x1fbc1(%rip), %xmm0    # 0x4ab84
movaps %xmm0, -0x450(%rbp)
movups 0x1fba3(%rip), %xmm0    # 0x4ab74
movaps %xmm0, -0x460(%rbp)
movq -0x40(%rbp), %rdi
movq %r13, %rsi
leaq -0x460(%rbp), %rdx
callq *0x58(%rdi)
movq 0x48(%r12), %rax
movq 0x10(%rax), %r13
movq -0x40(%rbp), %rbx
movq %rbx, %rdi
movl $0xec8, %esi            # imm = 0xEC8
leaq 0x1e0fd(%rip), %rdx     # 0x49102
xorl %ecx, %ecx
callq 0x23fc7
movq %rax, %r12
movq %rbx, %rdi
movq %rax, %rsi
movq -0x48(%rbp), %rdx
callq 0x68cf
movq 0x48(%r13), %rsi
movq %rbx, %rdi
movq %r12, %rdx
callq 0x67ee
movq %rbx, %rdi
movq %r13, %rsi
callq 0x2bd91
cmpb $0x0, -0x30(%rbp)
je 0x2b08d
cmpb $0x0, 0x70(%r13)
jne 0x2b08d
movups 0x1fb8b(%rip), %xmm0    # 0x4abd7
movups %xmm0, -0x437(%rbp)
movups 0x1fb74(%rip), %xmm0    # 0x4abce
movaps %xmm0, -0x440(%rbp)
movups 0x1fb56(%rip), %xmm0    # 0x4abbe
movaps %xmm0, -0x450(%rbp)
movups 0x1fb38(%rip), %xmm0    # 0x4abae
movaps %xmm0, -0x460(%rbp)
movq %rbx, %rdi
movq %r15, %rsi
leaq -0x460(%rbp), %rdx
callq *0x58(%rbx)
movq 0x68(%r13), %rdx
movq %rbx, %rdi
movq -0x48(%rbp), %rsi
callq 0x2be1b
testb %al, %al
movq %r15, %r13
jne 0x2b0d8
movups 0x1fb4c(%rip), %xmm0    # 0x4abf7
movaps %xmm0, -0x450(%rbp)
movups 0x1fb2e(%rip), %xmm0    # 0x4abe7
movaps %xmm0, -0x460(%rbp)
movb $0x0, -0x440(%rbp)
movq -0x40(%rbp), %rdi
movq %r13, %rsi
leaq -0x460(%rbp), %rdx
callq *0x58(%rdi)
incq %r14
movslq 0x44(%r13), %rax
cmpq %rax, %r14
jl 0x2aeb8
addq $0x438, %rsp            # imm = 0x438
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq
leaq 0x1665b(%rip), %rdi     # 0x4175c
leaq 0x1f7f2(%rip), %rsi     # 0x4a8fa
leaq 0x1f915(%rip), %rcx     # 0x4aa24
movl $0x469, %edx            # imm = 0x469
callq 0x30a0
leaq 0x1649f(%rip), %rdi     # 0x415bf
leaq 0x1f7d3(%rip), %rsi     # 0x4a8fa
leaq 0x1f8f6(%rip), %rcx     # 0x4aa24
movl $0x466, %edx            # imm = 0x466
callq 0x30a0
leaq 0x16458(%rip), %rdi     # 0x41597
leaq 0x1f7b4(%rip), %rsi     # 0x4a8fa
leaq 0x1f8d7(%rip), %rcx     # 0x4aa24
movl $0x465, %edx            # imm = 0x465
callq 0x30a0
leaq 0x14202(%rip), %rdi     # 0x3f360
leaq 0x1f795(%rip), %rsi     # 0x4a8fa
leaq 0x21573(%rip), %rcx     # 0x4c6df
movl $0x42d, %edx            # imm = 0x42D
callq 0x30a0
leaq 0x17c65(%rip), %rdi     # 0x42de2
leaq 0x1f776(%rip), %rsi     # 0x4a8fa
leaq 0x1f899(%rip), %rcx     # 0x4aa24
movl $0x436, %edx            # imm = 0x436
callq 0x30a0
leaq 0x1fcbb(%rip), %rdi     # 0x4ae57
leaq 0x1f757(%rip), %rsi     # 0x4a8fa
leaq 0x1f87a(%rip), %rcx     # 0x4aa24
movl $0x437, %edx            # imm = 0x437
callq 0x30a0
leaq 0x163ca(%rip), %rdi     # 0x41585
leaq 0x1f738(%rip), %rsi     # 0x4a8fa
leaq 0x1f85b(%rip), %rcx     # 0x4aa24
movl $0x438, %edx            # imm = 0x438
callq 0x30a0
leaq 0x1fc7d(%rip), %rdi     # 0x4ae57
leaq 0x1f719(%rip), %rsi     # 0x4a8fa
leaq 0x214f7(%rip), %rcx     # 0x4c6df
movl $0x414, %edx            # imm = 0x414
callq 0x30a0
leaq 0x1f874(%rip), %rdi     # 0x4aa6d
leaq 0x1f6fa(%rip), %rsi     # 0x4a8fa
leaq 0x1f81d(%rip), %rcx     # 0x4aa24
movl $0x43e, %edx            # imm = 0x43E
callq 0x30a0
leaq 0x14148(%rip), %rdi     # 0x3f360
leaq 0x1f6db(%rip), %rsi     # 0x4a8fa
leaq 0x1f7fe(%rip), %rcx     # 0x4aa24
movl $0x459, %edx            # imm = 0x459
callq 0x30a0
leaq 0x1f84f(%rip), %rdi     # 0x4aa86
leaq 0x1f6bc(%rip), %rsi     # 0x4a8fa
leaq 0x1f7df(%rip), %rcx     # 0x4aa24
movl $0x444, %edx            # imm = 0x444
callq 0x30a0