// File: /workspace/github_c_makefile_star2_O0/Ihsoh[P]ilang/compiler/backend/asmgen_gas32.c
// Function: asm_func
static void _asm_func(
	ASMGeneratorGas32Context *ctx,
	ParserASTNode *node
) {
	assert(ctx);
	assert(node);
	assert(node->type == BE_NODE_FUNC);

	ctx->func_symbol = BE_FUNC_AST_NODE_GET_SYMBOL(node);
	assert(ctx->func_symbol);

	ParserASTNode *node_identifier = NULL;
	ParserASTNode *node_func_params = NULL;
	ParserASTNode *node_return_type = NULL;
	ParserASTNode *node_body = NULL;

	int nchilds = node->nchilds;
	if (nchilds == 3) {
		node_identifier = node->childs[0];
		node_func_params = node->childs[1];
		node_body = node->childs[2];
	} else if (nchilds == 4) {
		node_identifier = node->childs[0];
		node_func_params = node->childs[1];
		node_return_type = node->childs[2];
		node_body = node->childs[3];
	} else {
		assert(0);
	}
	assert(node_identifier->type == BE_NODE_IDENTIFIER);
	assert(node_func_params->type == BE_NODE_FUNC_PARAMS);
	if (node_func_params->nchilds > 0) {
		assert(node_func_params->childs[0]->type == BE_NODE_FUNC_PARAMS_ITEM);
	}

	rstr_append_with_char(ctx->body, '\n');

	if (node_body->type == BE_NODE_STATS_BLOCK) {
		ResizableString rstr_func_name;
		rstr_init_with_raw(&rstr_func_name, node_identifier->token->content, node_identifier->token->len);

		// .section	__TEXT,__text,regular,pure_instructions
		// rstr_append_with_cstr(ctx->body, ".section	__TEXT,__text,regular,pure_instructions\n");
		rstr_append_with_cstr(ctx->body, ".text\n");

		// .globl _FUNCTION_NAME
		rstr_append_with_cstr(ctx->body, ".globl ");
		rstr_append_with_raw(ctx->body, node_identifier->token->content, node_identifier->token->len);
		rstr_append_with_char(ctx->body, '\n');

		// .p2align	4, 0x90
		// TODO: ...
		// rstr_append_with_cstr(ctx->body, ".p2align	4, 0x90\n");

		// _FUNCTION_NAME:
		rstr_append_with_raw(ctx->body, node_identifier->token->content, node_identifier->token->len);
		rstr_append_with_char(ctx->body, ':');
		rstr_append_with_char(ctx->body, '\n');

		// pushq %ebp
		// movq %esp, %ebp
		rstr_append_with_cstr(ctx->body, "pushl %ebp\nmovl %esp, %ebp\n\n");

		/*
			Position			Contents				Frame
			------------------------------------------------------
			8n+8(%ebp)			param N
								...						previous
			8(%ebp)			param 0			
			------------------------------------------------------
			4(%ebp)				return address
			0(%ebp)				previous %ebp value

			-4(%ebp)			FUNC IP

			-12(%ebp)			local variable 0		current
			-20(%ebp)			local variable 1
			-28(%ebp)			local variable 2
								...
		*/
		ctx->local_var_address_counter = _FUNC_STACK_RESERVE_SIZE;
		ctx->local_var_size = _FUNC_STACK_RESERVE_SIZE;
		ctx->local_var_index_counter = 1;
		for (int i = 0; i < node_func_params->nchilds; i++) {
			ParserASTNode *node_param = node_func_params->childs[i];
			if (node_param->type == BE_NODE_FUNC_PARAMS_ELLIPSIS_ITEM) {
				continue;
			}

			ParserASTNode *node_param_id = node_param->childs[0];
			ParserASTNode *node_param_type = node_param->childs[1];
			ParserSymbol *symbol = BE_FUNC_PARAM_AST_NODE_GET_SYMBOL(node_param);

			// int align = BE_VAR_SYMBOL_GET_ALIGN(symbol);
			int align = 8;
			assert(align);

			// size_t type_size = BE_VAR_SYMBOL_GET_TYPE_SIZE(symbol);
			size_t type_size = 8;
			assert(type_size != 0);

			// if (ctx->local_var_address_counter % align > 0) {
			// 	size_t align_padding = align - ctx->local_var_address_counter % align;
			// 	ctx->local_var_address_counter += align_padding;
			// }

			// BE_VAR_SYMBOL_SET_ADDRESS(symbol, ctx->local_var_address_counter);

			BE_VAR_SYMBOL_SET_HAS_CODE_GEN_NAME(symbol, true);	
			ResizableString *code_gen_name = BE_VAR_SYMBOL_GET_CODE_GEN_NAME(symbol);
			rstr_init(code_gen_name);
			rstr_appendf(
				code_gen_name,
				"%d(%%ebp)",
				8 + 8 * i
			);

			rstr_appendf(
				ctx->body,
				"# local-var: type=param, index=%zu, address=%zu, align=%d, size=%zu, value=%s, name=",
				ctx->local_var_index_counter,
				ctx->local_var_address_counter,
				align,
				type_size,
				RSTR_CSTR(code_gen_name)
			);
			rstr_append_with_raw(
				ctx->body,
				node_param_id->token->content,
				node_param_id->token->len
			);
			rstr_append_with_char(
				ctx->body,
				'\n'
			);

			// ctx->local_var_address_counter += type_size;
			ctx->local_var_index_counter++;
		}

		ResizableString *body = ctx->body;
		ctx->body = rstr_new();
		ctx->local_var_defs = rstr_new();

		_asm_stats_block(ctx, node_body);

		rstr_appendf(
			ctx->local_var_defs,
			"# local-var-space: total-size=%zu\n",
			ctx->local_var_size
		);

		rstr_appendf(
			ctx->local_var_defs,
			"subl $%zu, %%esp\n\n",
			ctx->local_var_size
		);

		rstr_append_with_rstr(body, ctx->local_var_defs);

		// 生成为了获取EIP的代码。
		rstr_appendf(
			body,
			"calll %s%s\n"
				"%s%s:\n"
				"popl %s\n"
				"movl %s, %d(%%ebp)\n\n",
			_ASM_IP_LABEL_PREFIX,
			RSTR_CSTR(&rstr_func_name),
			_ASM_IP_LABEL_PREFIX,
			RSTR_CSTR(&rstr_func_name),
			_ASM_IP_REG,
			_ASM_IP_REG,
			_FUNC_IP_STACK_OFFSET
		);

		rstr_append_with_cstr(body, "\n# code:\n");
		rstr_append_with_rstr(body, ctx->body);
	
		rstr_free(ctx->body);
		ctx->body = body;
		rstr_free(ctx->local_var_defs);
		ctx->local_var_defs = NULL;



		// 用于return指令的标签。
		rstr_append_with_cstr(ctx->body, "\n");
		__out_label(
			ctx,
			ctx->body,
			_ASM_FUNC_RETURN_LABEL_PREFIX,
			_ASM_FUNC_RETURN_LABEL
		);
		rstr_append_with_cstr(ctx->body, ":\n");

		rstr_appendf(
			ctx->body,
			"\n\naddl $%zu, %%esp\n",
			ctx->local_var_size
		);

		// popl	%ebp
		// retl
		rstr_append_with_cstr(ctx->body, "popl %ebp\nretl\n");

		rstr_append_with_char(ctx->body, '\n');

		rstr_free(&rstr_func_name);
	} else if (node_body->type == BE_NODE_DUMMY) {
		return;
	} else {
		assert(0);
	}
}

// Assembly:
pushq %rbp
movq %rsp, %rbp
subq $0x100, %rsp            # imm = 0x100
movq %rdi, -0x8(%rbp)
movq %rsi, -0x10(%rbp)
cmpq $0x0, -0x8(%rbp)
je 0x1058c
jmp 0x105ab
leaq 0x6fbce(%rip), %rdi     # 0x80161
leaq 0x6535e(%rip), %rsi     # 0x758f8
movl $0x2baf, %edx           # imm = 0x2BAF
leaq 0x65aa1(%rip), %rcx     # 0x76047
callq 0x30a0
cmpq $0x0, -0x10(%rbp)
je 0x105b4
jmp 0x105d3
leaq 0x65fa1(%rip), %rdi     # 0x7655c
leaq 0x65336(%rip), %rsi     # 0x758f8
movl $0x2bb0, %edx           # imm = 0x2BB0
leaq 0x65a79(%rip), %rcx     # 0x76047
callq 0x30a0
movq -0x10(%rbp), %rax
cmpl $0xa00, (%rax)          # imm = 0xA00
jne 0x105e1
jmp 0x10600
leaq 0x65a9b(%rip), %rdi     # 0x76083
leaq 0x65309(%rip), %rsi     # 0x758f8
movl $0x2bb1, %edx           # imm = 0x2BB1
leaq 0x65a4c(%rip), %rcx     # 0x76047
callq 0x30a0
movq -0x10(%rbp), %rax
movq 0x60(%rax), %rcx
movq -0x8(%rbp), %rax
movq %rcx, 0x58(%rax)
movq -0x8(%rbp), %rax
cmpq $0x0, 0x58(%rax)
je 0x1061d
jmp 0x1063c
leaq 0x65a7a(%rip), %rdi     # 0x7609e
leaq 0x652cd(%rip), %rsi     # 0x758f8
movl $0x2bb4, %edx           # imm = 0x2BB4
leaq 0x65a10(%rip), %rcx     # 0x76047
callq 0x30a0
movq $0x0, -0x18(%rbp)
movq $0x0, -0x20(%rbp)
movq $0x0, -0x28(%rbp)
movq $0x0, -0x30(%rbp)
movq -0x10(%rbp), %rax
movl 0x44(%rax), %eax
movl %eax, -0x34(%rbp)
cmpl $0x3, -0x34(%rbp)
jne 0x1069d
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 0x10705
cmpl $0x4, -0x34(%rbp)
jne 0x106e4
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 0x10703
leaq 0x62d6f(%rip), %rdi     # 0x7345a
leaq 0x65206(%rip), %rsi     # 0x758f8
movl $0x2bc6, %edx           # imm = 0x2BC6
leaq 0x65949(%rip), %rcx     # 0x76047
callq 0x30a0
jmp 0x10705
movq -0x18(%rbp), %rax
cmpl $0x200, (%rax)          # imm = 0x200
jne 0x10713
jmp 0x10732
leaq 0x65537(%rip), %rdi     # 0x75c51
leaq 0x651d7(%rip), %rsi     # 0x758f8
movl $0x2bc8, %edx           # imm = 0x2BC8
leaq 0x6591a(%rip), %rcx     # 0x76047
callq 0x30a0
movq -0x20(%rbp), %rax
cmpl $0xa01, (%rax)          # imm = 0xA01
jne 0x10740
jmp 0x1075f
leaq 0x65968(%rip), %rdi     # 0x760af
leaq 0x651aa(%rip), %rsi     # 0x758f8
movl $0x2bc9, %edx           # imm = 0x2BC9
leaq 0x658ed(%rip), %rcx     # 0x76047
callq 0x30a0
movq -0x20(%rbp), %rax
cmpl $0x0, 0x44(%rax)
jle 0x1079f
movq -0x20(%rbp), %rax
movq 0x48(%rax), %rax
movq (%rax), %rax
cmpl $0xa02, (%rax)          # imm = 0xA02
jne 0x1077e
jmp 0x1079d
leaq 0x65958(%rip), %rdi     # 0x760dd
leaq 0x6516c(%rip), %rsi     # 0x758f8
movl $0x2bcb, %edx           # imm = 0x2BCB
leaq 0x658af(%rip), %rcx     # 0x76047
callq 0x30a0
jmp 0x1079f
movq -0x8(%rbp), %rax
movq 0x20(%rax), %rdi
movl $0xa, %esi
callq 0x8ea0
movq -0x30(%rbp), %rax
cmpl $0xb00, (%rax)          # imm = 0xB00
jne 0x10ced
movq -0x18(%rbp), %rax
movq 0x10(%rax), %rax
movq 0x8(%rax), %rsi
movq -0x18(%rbp), %rax
movq 0x10(%rax), %rax
movl 0x4(%rax), %edx
leaq -0x48(%rbp), %rdi
callq 0x8ee0
movq -0x8(%rbp), %rax
movq 0x20(%rax), %rdi
leaq 0x6572b(%rip), %rsi     # 0x75f1b
callq 0x8d70
movq -0x8(%rbp), %rax
movq 0x20(%rax), %rdi
leaq 0x65480(%rip), %rsi     # 0x75c84
callq 0x8d70
movq -0x8(%rbp), %rax
movq 0x20(%rax), %rdi
movq -0x18(%rbp), %rax
movq 0x10(%rax), %rax
movq 0x8(%rax), %rsi
movq -0x18(%rbp), %rax
movq 0x10(%rax), %rax
movl 0x4(%rax), %edx
callq 0x8f90
movq -0x8(%rbp), %rax
movq 0x20(%rax), %rdi
movl $0xa, %esi
callq 0x8ea0
movq -0x8(%rbp), %rax
movq 0x20(%rax), %rdi
movq -0x18(%rbp), %rax
movq 0x10(%rax), %rax
movq 0x8(%rax), %rsi
movq -0x18(%rbp), %rax
movq 0x10(%rax), %rax
movl 0x4(%rax), %edx
callq 0x8f90
movq -0x8(%rbp), %rax
movq 0x20(%rax), %rdi
movl $0x3a, %esi
callq 0x8ea0
movq -0x8(%rbp), %rax
movq 0x20(%rax), %rdi
movl $0xa, %esi
callq 0x8ea0
movq -0x8(%rbp), %rax
movq 0x20(%rax), %rdi
leaq 0x65885(%rip), %rsi     # 0x7611b
callq 0x8d70
movq -0x8(%rbp), %rax
movq $0x4, 0x38(%rax)
movq -0x8(%rbp), %rax
movq $0x4, 0x40(%rax)
movq -0x8(%rbp), %rax
movq $0x1, 0x48(%rax)
movl $0x0, -0x4c(%rbp)
movl -0x4c(%rbp), %eax
movq -0x20(%rbp), %rcx
cmpl 0x44(%rcx), %eax
jge 0x10aca
movq -0x20(%rbp), %rax
movq 0x48(%rax), %rax
movslq -0x4c(%rbp), %rcx
movq (%rax,%rcx,8), %rax
movq %rax, -0x58(%rbp)
movq -0x58(%rbp), %rax
cmpl $0xa03, (%rax)          # imm = 0xA03
jne 0x108fb
jmp 0x10abc
movq -0x58(%rbp), %rax
movq 0x48(%rax), %rax
movq (%rax), %rax
movq %rax, -0x60(%rbp)
movq -0x58(%rbp), %rax
movq 0x48(%rax), %rax
movq 0x8(%rax), %rax
movq %rax, -0x68(%rbp)
movq -0x58(%rbp), %rax
movq 0x60(%rax), %rax
movq %rax, -0x70(%rbp)
movl $0x8, -0x74(%rbp)
cmpl $0x0, -0x74(%rbp)
je 0x10935
jmp 0x10954
leaq 0x653a4(%rip), %rdi     # 0x75ce0
leaq 0x64fb5(%rip), %rsi     # 0x758f8
movl $0x2c0a, %edx           # imm = 0x2C0A
leaq 0x656f8(%rip), %rcx     # 0x76047
callq 0x30a0
movq $0x8, -0x80(%rbp)
cmpq $0x0, -0x80(%rbp)
je 0x10965
jmp 0x10984
leaq 0x657cc(%rip), %rdi     # 0x76138
leaq 0x64f85(%rip), %rsi     # 0x758f8
movl $0x2c0e, %edx           # imm = 0x2C0E
leaq 0x656c8(%rip), %rcx     # 0x76047
callq 0x30a0
movq -0x70(%rbp), %rax
movb $0x1, 0x48(%rax)
movq -0x70(%rbp), %rax
addq $0x30, %rax
addq $0x20, %rax
movq %rax, -0x88(%rbp)
movq -0x88(%rbp), %rdi
callq 0x8c90
movq -0x88(%rbp), %rdi
movl -0x4c(%rbp), %edx
shll $0x3, %edx
addl $0x8, %edx
leaq 0x65785(%rip), %rsi     # 0x76147
movb $0x0, %al
callq 0x94d0
movq -0x8(%rbp), %rax
movq 0x20(%rax), %rax
movq %rax, -0xb8(%rbp)
movq -0x8(%rbp), %rax
movq 0x48(%rax), %rax
movq %rax, -0xb0(%rbp)
movq -0x8(%rbp), %rax
movq 0x38(%rax), %rax
movq %rax, -0xa8(%rbp)
movl -0x74(%rbp), %eax
movl %eax, -0x9c(%rbp)
movq -0x80(%rbp), %rax
movq %rax, -0x98(%rbp)
movq -0x88(%rbp), %rax
cmpq $0x0, 0x8(%rax)
jne 0x10a28
leaq 0x65520(%rip), %rax     # 0x75f3f
movq %rax, -0xc0(%rbp)
jmp 0x10a3a
movq -0x88(%rbp), %rax
movq 0x8(%rax), %rax
movq %rax, -0xc0(%rbp)
movq -0x98(%rbp), %r9
movl -0x9c(%rbp), %r8d
movq -0xa8(%rbp), %rcx
movq -0xb0(%rbp), %rdx
movq -0xb8(%rbp), %rdi
movq -0xc0(%rbp), %rax
leaq 0x656e6(%rip), %rsi     # 0x76151
movq %rax, (%rsp)
movb $0x0, %al
callq 0x94d0
movq -0x8(%rbp), %rax
movq 0x20(%rax), %rdi
movq -0x60(%rbp), %rax
movq 0x10(%rax), %rax
movq 0x8(%rax), %rsi
movq -0x60(%rbp), %rax
movq 0x10(%rax), %rax
movl 0x4(%rax), %edx
callq 0x8f90
movq -0x8(%rbp), %rax
movq 0x20(%rax), %rdi
movl $0xa, %esi
callq 0x8ea0
movq -0x8(%rbp), %rax
movq 0x48(%rax), %rcx
addq $0x1, %rcx
movq %rcx, 0x48(%rax)
movl -0x4c(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x4c(%rbp)
jmp 0x108c6
movq -0x8(%rbp), %rax
movq 0x20(%rax), %rax
movq %rax, -0x90(%rbp)
callq 0x91e0
movq %rax, %rcx
movq -0x8(%rbp), %rax
movq %rcx, 0x20(%rax)
callq 0x91e0
movq %rax, %rcx
movq -0x8(%rbp), %rax
movq %rcx, 0x30(%rax)
movq -0x8(%rbp), %rdi
movq -0x30(%rbp), %rsi
callq 0x117e0
movq -0x8(%rbp), %rax
movq 0x30(%rax), %rdi
movq -0x8(%rbp), %rax
movq 0x40(%rax), %rdx
leaq 0x65689(%rip), %rsi     # 0x761a6
movb $0x0, %al
callq 0x94d0
movq -0x8(%rbp), %rax
movq 0x30(%rax), %rdi
movq -0x8(%rbp), %rax
movq 0x40(%rax), %rdx
leaq 0x6568e(%rip), %rsi     # 0x761c9
movb $0x0, %al
callq 0x94d0
movq -0x90(%rbp), %rdi
movq -0x8(%rbp), %rax
movq 0x30(%rax), %rsi
callq 0x9100
movq -0x90(%rbp), %rax
movq %rax, -0xc8(%rbp)
cmpq $0x0, -0x40(%rbp)
jne 0x10b7b
leaq 0x653cd(%rip), %rax     # 0x75f3f
movq %rax, -0xd0(%rbp)
jmp 0x10b86
movq -0x40(%rbp), %rax
movq %rax, -0xd0(%rbp)
movq -0xd0(%rbp), %rax
movq %rax, -0xd8(%rbp)
cmpq $0x0, -0x40(%rbp)
jne 0x10bab
leaq 0x6539d(%rip), %rax     # 0x75f3f
movq %rax, -0xe0(%rbp)
jmp 0x10bb6
movq -0x40(%rbp), %rax
movq %rax, -0xe0(%rbp)
movq -0xd8(%rbp), %rcx
movq -0xc8(%rbp), %rdi
movq -0xe0(%rbp), %r9
leaq 0x6560a(%rip), %rsi     # 0x761dc
leaq 0x65631(%rip), %r8      # 0x7620a
leaq 0x65634(%rip), %rax     # 0x76214
movq %r8, %rdx
movq %rax, (%rsp)
movq %rax, 0x8(%rsp)
movl $0xfffffffc, 0x10(%rsp) # imm = 0xFFFFFFFC
movb $0x0, %al
callq 0x94d0
movq -0x90(%rbp), %rdi
leaq 0x65610(%rip), %rsi     # 0x76219
callq 0x8d70
movq -0x90(%rbp), %rdi
movq -0x8(%rbp), %rax
movq 0x20(%rax), %rsi
callq 0x9100
movq -0x8(%rbp), %rax
movq 0x20(%rax), %rdi
callq 0x9310
movq -0x90(%rbp), %rcx
movq -0x8(%rbp), %rax
movq %rcx, 0x20(%rax)
movq -0x8(%rbp), %rax
movq 0x30(%rax), %rdi
callq 0x9310
movq -0x8(%rbp), %rax
movq $0x0, 0x30(%rax)
movq -0x8(%rbp), %rax
movq 0x20(%rax), %rdi
leaq 0x652d8(%rip), %rsi     # 0x75f3e
callq 0x8d70
movq -0x8(%rbp), %rdi
movq -0x8(%rbp), %rax
movq 0x20(%rax), %rsi
leaq 0x655a5(%rip), %rdx     # 0x76223
leaq 0x655a3(%rip), %rcx     # 0x76228
callq 0x118c0
movq -0x8(%rbp), %rax
movq 0x20(%rax), %rdi
leaq 0x65587(%rip), %rsi     # 0x76220
callq 0x8d70
movq -0x8(%rbp), %rax
movq 0x20(%rax), %rdi
movq -0x8(%rbp), %rax
movq 0x40(%rax), %rdx
leaq 0x65577(%rip), %rsi     # 0x7622c
movb $0x0, %al
callq 0x94d0
movq -0x8(%rbp), %rax
movq 0x20(%rax), %rdi
leaq 0x65575(%rip), %rsi     # 0x76240
callq 0x8d70
movq -0x8(%rbp), %rax
movq 0x20(%rax), %rdi
movl $0xa, %esi
callq 0x8ea0
leaq -0x48(%rbp), %rdi
callq 0x9310
jmp 0x10d1a
movq -0x30(%rbp), %rax
cmpl $0x900, (%rax)          # imm = 0x900
jne 0x10cfb
jmp 0x10d1a
leaq 0x62758(%rip), %rdi     # 0x7345a
leaq 0x64bef(%rip), %rsi     # 0x758f8
movl $0x2c7f, %edx           # imm = 0x2C7F
leaq 0x65332(%rip), %rcx     # 0x76047
callq 0x30a0
addq $0x100, %rsp            # imm = 0x100
popq %rbp
retq
nopw %cs:(%rax,%rax)