// File: /workspace/github_c_makefile_star2_O2/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, -0x58(%rbp)
testq %rsi, %rsi
je 0x29011
movq %rsi, %r13
cmpl $0xc00, (%rsi)          # imm = 0xC00
jne 0x29030
cmpl $0x0, 0x44(%r13)
jle 0x2904f
movq %rdi, %r14
movq 0x68(%r13), %rax
testq %rax, %rax
je 0x28be4
cmpl $0x1, 0x44(%rax)
jne 0x2908d
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
pushq $0x1
popq %rax
cmovnel %ecx, %eax
cmpl $0x2, %eax
je 0x28beb
cmpl $0x1, %eax
jne 0x290ac
movq %r14, %rdi
movq %rbx, %rsi
xorl %edx, %edx
callq 0x290cb
movq %r14, %rdi
movq %r13, %rsi
movq %rbx, %rdx
callq 0x290fb
testq %rax, %rax
jne 0x28cc0
leaq 0x1eefa(%rip), %rdi     # 0x47ac6
leaq 0x1ed67(%rip), %rsi     # 0x4793a
leaq 0x1ee8a(%rip), %rcx     # 0x47a64
movl $0x444, %edx            # imm = 0x444
callq 0x30a0
xorl %eax, %eax
jmp 0x28cc4
movq %r14, %rdi
movq %rbx, %rsi
callq 0x294d8
cmpb $0x0, 0x70(%rbx)
jne 0x28c2d
movups 0x1eeeb(%rip), %xmm0    # 0x47aee
leaq -0x460(%rbp), %rdx
movups %xmm0, 0x1d(%rdx)
movups 0x1eecc(%rip), %xmm0    # 0x47ae1
movaps %xmm0, 0x10(%rdx)
movups 0x1eeb1(%rip), %xmm0    # 0x47ad1
movaps %xmm0, (%rdx)
movq %r14, %rdi
movq %rbx, %rsi
callq *0x58(%r14)
movq %rbx, %rdi
callq 0x2fac4
testl %eax, %eax
jg 0x28c73
movups 0x1eece(%rip), %xmm0    # 0x47b0e
leaq -0x460(%rbp), %rdx
movaps %xmm0, 0x10(%rdx)
movups 0x1eeac(%rip), %xmm0    # 0x47afe
movaps %xmm0, (%rdx)
movq %rax, %r15
movabsq $0x2e30206e616874, %rax # imm = 0x2E30206E616874
movq %rax, 0x20(%rdx)
movq %r14, %rdi
movq %rbx, %rsi
callq *0x58(%r14)
movq %r15, %rax
cmpl $0x1, %eax
movq %rax, %rcx
sete %al
movq %rcx, %r15
testb $0x1, %cl
sete %cl
orb %al, %cl
jne 0x28cbd
movups 0x1eea6(%rip), %xmm0    # 0x47b36
leaq -0x460(%rbp), %rdx
movaps %xmm0, 0x10(%rdx)
movups 0x1ee84(%rip), %xmm0    # 0x47b26
movaps %xmm0, (%rdx)
movabsq $0x2e3220666f2072, %rax # imm = 0x2E3220666F2072
movq %rax, 0x1d(%rdx)
movq %r14, %rdi
movq %rbx, %rsi
callq *0x58(%r14)
movq %r15, %rax
movl %eax, 0x70(%r13)
movq %rax, -0x50(%rbp)
cmpl $0xc00, (%r13)          # imm = 0xC00
jne 0x2906e
movq %r13, %rax
movq %r14, -0x40(%rbp)
movq 0x30(%rax), %rax
testq %rax, %rax
je 0x28ff2
movl (%rax), %ecx
cmpl $0x100, %ecx            # imm = 0x100
je 0x28d17
cmpl $0xd00, %ecx            # imm = 0xD00
je 0x28d2f
cmpl $0xa00, %ecx            # imm = 0xA00
jne 0x28cdd
movq 0x60(%rax), %rax
movq %rax, -0x48(%rbp)
movb $0x2, %al
movl $0x0, -0x34(%rbp)
jmp 0x28d3e
movb $0x1, %al
movl %eax, -0x30(%rbp)
movq $0x0, -0x48(%rbp)
movl $0x0, -0x34(%rbp)
movb $0x1, %al
jmp 0x28d45
movb $0x3, %al
movb $0x1, %cl
movl %ecx, -0x34(%rbp)
movq $0x0, -0x48(%rbp)
movl $0x0, -0x30(%rbp)
movb %al, 0x60(%r13)
xorl %ecx, %ecx
movslq 0x44(%r13), %rax
cmpq %rax, %rcx
jge 0x28f83
movq 0x48(%r13), %rax
movq (%rax,%rcx,8), %r12
cmpl $0xc01, (%r12)          # imm = 0xC01
jne 0x28f95
movl 0x44(%r12), %eax
andl $-0x2, %eax
cmpl $0x2, %eax
jne 0x28fb4
movq %r13, %r15
movq %rcx, -0x60(%rbp)
movq 0x48(%r12), %rax
movq (%rax), %r13
cmpl $0x200, (%r13)          # imm = 0x200
jne 0x28fd3
movq 0x8(%rax), %rbx
movb $0x0, -0x29(%rbp)
movq -0x40(%rbp), %r14
movq %r14, %rdi
movq %rbx, %rsi
leaq -0x29(%rbp), %rdx
callq 0x290cb
movb -0x29(%rbp), %al
cmpb $0xf, %al
jne 0x28de8
leaq -0x460(%rbp), %rdi
leaq 0x1ed7f(%rip), %rsi     # 0x47b4b
pushq $0x69
popq %rdx
callq 0x3100
movq %r14, %rdi
movq %r15, %rsi
leaq -0x460(%rbp), %rdx
callq *0x58(%r14)
movb -0x29(%rbp), %al
movq 0x10(%r13), %rdx
movzbl %al, %ecx
movq %r14, %rdi
movq -0x58(%rbp), %rsi
movq %rbx, %r8
callq 0x236f9
movq %rax, %r13
movq -0x48(%rbp), %rax
movq %rax, 0x40(%r13)
movq -0x50(%rbp), %rcx
movl %ecx, %eax
testl %ecx, %ecx
jg 0x28e22
movq -0x40(%rbp), %rdi
movq %r15, %rsi
movq %rbx, %rdx
callq 0x290fb
movl %eax, 0x60(%r13)
movq %r13, 0x60(%r12)
cmpl $0x3, 0x44(%r12)
movq %r15, %r13
jne 0x28f77
cmpb $0x0, -0x34(%rbp)
je 0x28e89
movups 0x1ed97(%rip), %xmm0    # 0x47bde
movups %xmm0, -0x436(%rbp)
movups 0x1ed7f(%rip), %xmm0    # 0x47bd4
movaps %xmm0, -0x440(%rbp)
movups 0x1ed61(%rip), %xmm0    # 0x47bc4
movaps %xmm0, -0x450(%rbp)
movups 0x1ed43(%rip), %xmm0    # 0x47bb4
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), %r14
movq %r14, %rdi
movl $0xec8, %esi            # imm = 0xEC8
leaq 0x1d2a1(%rip), %rdx     # 0x46146
xorl %ecx, %ecx
callq 0x229fb
movq %rax, %r12
movq %r14, %rdi
movq %rax, %rsi
movq %rbx, %rdx
callq 0x63c4
movq 0x48(%r13), %rsi
movq %r14, %rdi
movq %r12, %rdx
callq 0x62e3
movq %r14, %rdi
movq %r13, %rsi
callq 0x29bc2
cmpb $0x0, -0x30(%rbp)
je 0x28f2d
cmpb $0x0, 0x70(%r13)
jne 0x28f2d
movups 0x1ed2c(%rip), %xmm0    # 0x47c17
movups %xmm0, -0x437(%rbp)
movups 0x1ed15(%rip), %xmm0    # 0x47c0e
movaps %xmm0, -0x440(%rbp)
movups 0x1ecf7(%rip), %xmm0    # 0x47bfe
movaps %xmm0, -0x450(%rbp)
movups 0x1ecd9(%rip), %xmm0    # 0x47bee
movaps %xmm0, -0x460(%rbp)
movq %r14, %rdi
movq %r15, %rsi
leaq -0x460(%rbp), %rdx
callq *0x58(%r14)
movq 0x68(%r13), %rdx
movq %r14, %rdi
movq %rbx, %rsi
callq 0x29c4c
testb %al, %al
movq %r15, %r13
jne 0x28f77
movups 0x1eced(%rip), %xmm0    # 0x47c37
movaps %xmm0, -0x450(%rbp)
movups 0x1eccf(%rip), %xmm0    # 0x47c27
movaps %xmm0, -0x460(%rbp)
movb $0x0, -0x440(%rbp)
movq -0x40(%rbp), %rdi
movq %r13, %rsi
leaq -0x460(%rbp), %rdx
callq *0x58(%rdi)
movq -0x60(%rbp), %rcx
incq %rcx
jmp 0x28d4b
addq $0x438, %rsp            # imm = 0x438
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq
leaq 0x1560b(%rip), %rdi     # 0x3e5a7
leaq 0x1e997(%rip), %rsi     # 0x4793a
leaq 0x1eaba(%rip), %rcx     # 0x47a64
movl $0x465, %edx            # imm = 0x465
callq 0x30a0
leaq 0x15614(%rip), %rdi     # 0x3e5cf
leaq 0x1e978(%rip), %rsi     # 0x4793a
leaq 0x1ea9b(%rip), %rcx     # 0x47a64
movl $0x466, %edx            # imm = 0x466
callq 0x30a0
leaq 0x15792(%rip), %rdi     # 0x3e76c
leaq 0x1e959(%rip), %rsi     # 0x4793a
leaq 0x1ea7c(%rip), %rcx     # 0x47a64
movl $0x469, %edx            # imm = 0x469
callq 0x30a0
leaq 0x13367(%rip), %rdi     # 0x3c360
leaq 0x1e93a(%rip), %rsi     # 0x4793a
leaq 0x20718(%rip), %rcx     # 0x4971f
movl $0x42d, %edx            # imm = 0x42D
callq 0x30a0
leaq 0x16dda(%rip), %rdi     # 0x3fdf2
leaq 0x1e91b(%rip), %rsi     # 0x4793a
leaq 0x1ea3e(%rip), %rcx     # 0x47a64
movl $0x436, %edx            # imm = 0x436
callq 0x30a0
leaq 0x1ee60(%rip), %rdi     # 0x47e97
leaq 0x1e8fc(%rip), %rsi     # 0x4793a
leaq 0x1ea1f(%rip), %rcx     # 0x47a64
movl $0x437, %edx            # imm = 0x437
callq 0x30a0
leaq 0x1553f(%rip), %rdi     # 0x3e595
leaq 0x1e8dd(%rip), %rsi     # 0x4793a
leaq 0x1ea00(%rip), %rcx     # 0x47a64
movl $0x438, %edx            # imm = 0x438
callq 0x30a0
leaq 0x1ee22(%rip), %rdi     # 0x47e97
leaq 0x1e8be(%rip), %rsi     # 0x4793a
leaq 0x2069c(%rip), %rcx     # 0x4971f
movl $0x414, %edx            # imm = 0x414
callq 0x30a0
leaq 0x1ea19(%rip), %rdi     # 0x47aad
leaq 0x1e89f(%rip), %rsi     # 0x4793a
leaq 0x1e9c2(%rip), %rcx     # 0x47a64
movl $0x43e, %edx            # imm = 0x43E
callq 0x30a0
leaq 0x132ad(%rip), %rdi     # 0x3c360
leaq 0x1e880(%rip), %rsi     # 0x4793a
leaq 0x1e9a3(%rip), %rcx     # 0x47a64
movl $0x459, %edx            # imm = 0x459
callq 0x30a0