// File: /workspace/github_c_makefile_star2_O0/Ihsoh[P]ilang/compiler/backend/asmgen_gas64.c
// Function: asm_func
static void _asm_func(
	ASMGeneratorGas64Context *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) {
		// .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 %rbp
		// movq %rsp, %rbp
		rstr_append_with_cstr(ctx->body, "pushq %rbp\nmovq %rsp, %rbp\n\n");

		/*
			Position			Contents				Frame
			------------------------------------------------------
			8n+16(%rbp)			param N
								...						previous
			16(%rbp)			param 0			
			------------------------------------------------------
			8(%rbp)				return address
			0(%rbp)				previous %rbp value
			-8(%rbp)			local variable 0		current
			-16(%rbp)			local variable 1
			-24(%rbp)			local variable 2
								...
		*/
		ctx->local_var_address_counter = 0;
		ctx->local_var_size = 0;
		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(%%rbp)",
				16 + 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,
			"subq $%zu, %%rsp\n\n",
			ctx->local_var_size
		);

		rstr_append_with_rstr(body, ctx->local_var_defs);
		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指令的标签。
		__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\naddq $%zu, %%rsp\n",
			ctx->local_var_size
		);

		// popq	%rbp
		// retq
		rstr_append_with_cstr(ctx->body, "popq %rbp\nretq\n");

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

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

// Assembly:
pushq %rbp
movq %rsp, %rbp
subq $0xb0, %rsp
movq %rdi, -0x8(%rbp)
movq %rsi, -0x10(%rbp)
cmpq $0x0, -0x8(%rbp)
je 0x28dbc
jmp 0x28ddb
leaq 0x5739e(%rip), %rdi     # 0x80161
leaq 0x51d3a(%rip), %rsi     # 0x7ab04
movl $0x1d55, %edx           # imm = 0x1D55
leaq 0x52152(%rip), %rcx     # 0x7af28
callq 0x30a0
cmpq $0x0, -0x10(%rbp)
je 0x28de4
jmp 0x28e03
leaq 0x4d771(%rip), %rdi     # 0x7655c
leaq 0x51d12(%rip), %rsi     # 0x7ab04
movl $0x1d56, %edx           # imm = 0x1D56
leaq 0x5212a(%rip), %rcx     # 0x7af28
callq 0x30a0
movq -0x10(%rbp), %rax
cmpl $0xa00, (%rax)          # imm = 0xA00
jne 0x28e11
jmp 0x28e30
leaq 0x4d26b(%rip), %rdi     # 0x76083
leaq 0x51ce5(%rip), %rsi     # 0x7ab04
movl $0x1d57, %edx           # imm = 0x1D57
leaq 0x520fd(%rip), %rcx     # 0x7af28
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 0x28e4d
jmp 0x28e6c
leaq 0x4d24a(%rip), %rdi     # 0x7609e
leaq 0x51ca9(%rip), %rsi     # 0x7ab04
movl $0x1d5a, %edx           # imm = 0x1D5A
leaq 0x520c1(%rip), %rcx     # 0x7af28
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 0x28ecd
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 0x28f35
cmpl $0x4, -0x34(%rbp)
jne 0x28f14
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 0x28f33
leaq 0x4a53f(%rip), %rdi     # 0x7345a
leaq 0x51be2(%rip), %rsi     # 0x7ab04
movl $0x1d6c, %edx           # imm = 0x1D6C
leaq 0x51ffa(%rip), %rcx     # 0x7af28
callq 0x30a0
jmp 0x28f35
movq -0x18(%rbp), %rax
cmpl $0x200, (%rax)          # imm = 0x200
jne 0x28f43
jmp 0x28f62
leaq 0x4cd07(%rip), %rdi     # 0x75c51
leaq 0x51bb3(%rip), %rsi     # 0x7ab04
movl $0x1d6e, %edx           # imm = 0x1D6E
leaq 0x51fcb(%rip), %rcx     # 0x7af28
callq 0x30a0
movq -0x20(%rbp), %rax
cmpl $0xa01, (%rax)          # imm = 0xA01
jne 0x28f70
jmp 0x28f8f
leaq 0x4d138(%rip), %rdi     # 0x760af
leaq 0x51b86(%rip), %rsi     # 0x7ab04
movl $0x1d6f, %edx           # imm = 0x1D6F
leaq 0x51f9e(%rip), %rcx     # 0x7af28
callq 0x30a0
movq -0x20(%rbp), %rax
cmpl $0x0, 0x44(%rax)
jle 0x28fcf
movq -0x20(%rbp), %rax
movq 0x48(%rax), %rax
movq (%rax), %rax
cmpl $0xa02, (%rax)          # imm = 0xA02
jne 0x28fae
jmp 0x28fcd
leaq 0x4d128(%rip), %rdi     # 0x760dd
leaq 0x51b48(%rip), %rsi     # 0x7ab04
movl $0x1d71, %edx           # imm = 0x1D71
leaq 0x51f60(%rip), %rcx     # 0x7af28
callq 0x30a0
jmp 0x28fcf
movq -0x8(%rbp), %rax
movq 0x20(%rax), %rdi
movl $0xa, %esi
callq 0x8ea0
movq -0x30(%rbp), %rax
cmpl $0xb00, (%rax)          # imm = 0xB00
jne 0x29417
movq -0x8(%rbp), %rax
movq 0x20(%rax), %rdi
leaq 0x4cf1b(%rip), %rsi     # 0x75f1b
callq 0x8d70
movq -0x8(%rbp), %rax
movq 0x20(%rax), %rdi
leaq 0x4cc70(%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 0x51ebe(%rip), %rsi     # 0x7af64
callq 0x8d70
movq -0x8(%rbp), %rax
movq $0x0, 0x38(%rax)
movq -0x8(%rbp), %rax
movq $0x0, 0x40(%rax)
movq -0x8(%rbp), %rax
movq $0x1, 0x48(%rax)
movl $0x0, -0x38(%rbp)
movl -0x38(%rbp), %eax
movq -0x20(%rbp), %rcx
cmpl 0x44(%rcx), %eax
jge 0x292c5
movq -0x20(%rbp), %rax
movq 0x48(%rax), %rax
movslq -0x38(%rbp), %rcx
movq (%rax,%rcx,8), %rax
movq %rax, -0x40(%rbp)
movq -0x40(%rbp), %rax
cmpl $0xa03, (%rax)          # imm = 0xA03
jne 0x2910b
jmp 0x292b7
movq -0x40(%rbp), %rax
movq 0x48(%rax), %rax
movq (%rax), %rax
movq %rax, -0x48(%rbp)
movq -0x40(%rbp), %rax
movq 0x48(%rax), %rax
movq 0x8(%rax), %rax
movq %rax, -0x50(%rbp)
movq -0x40(%rbp), %rax
movq 0x60(%rax), %rax
movq %rax, -0x58(%rbp)
movl $0x8, -0x5c(%rbp)
cmpl $0x0, -0x5c(%rbp)
je 0x29145
jmp 0x29164
leaq 0x4cb94(%rip), %rdi     # 0x75ce0
leaq 0x519b1(%rip), %rsi     # 0x7ab04
movl $0x1daa, %edx           # imm = 0x1DAA
leaq 0x51dc9(%rip), %rcx     # 0x7af28
callq 0x30a0
movq $0x8, -0x68(%rbp)
cmpq $0x0, -0x68(%rbp)
je 0x29175
jmp 0x29194
leaq 0x4cfbc(%rip), %rdi     # 0x76138
leaq 0x51981(%rip), %rsi     # 0x7ab04
movl $0x1dae, %edx           # imm = 0x1DAE
leaq 0x51d99(%rip), %rcx     # 0x7af28
callq 0x30a0
movq -0x58(%rbp), %rax
movb $0x1, 0x48(%rax)
movq -0x58(%rbp), %rax
addq $0x30, %rax
addq $0x20, %rax
movq %rax, -0x70(%rbp)
movq -0x70(%rbp), %rdi
callq 0x8c90
movq -0x70(%rbp), %rdi
movl -0x38(%rbp), %edx
shll $0x3, %edx
addl $0x10, %edx
leaq 0x51ae8(%rip), %rsi     # 0x7acb1
movb $0x0, %al
callq 0x94d0
movq -0x8(%rbp), %rax
movq 0x20(%rax), %rax
movq %rax, -0xa0(%rbp)
movq -0x8(%rbp), %rax
movq 0x48(%rax), %rax
movq %rax, -0x98(%rbp)
movq -0x8(%rbp), %rax
movq 0x38(%rax), %rax
movq %rax, -0x90(%rbp)
movl -0x5c(%rbp), %eax
movl %eax, -0x84(%rbp)
movq -0x68(%rbp), %rax
movq %rax, -0x80(%rbp)
movq -0x70(%rbp), %rax
cmpq $0x0, 0x8(%rax)
jne 0x29229
leaq 0x4cd1f(%rip), %rax     # 0x75f3f
movq %rax, -0xa8(%rbp)
jmp 0x29238
movq -0x70(%rbp), %rax
movq 0x8(%rax), %rax
movq %rax, -0xa8(%rbp)
movq -0x80(%rbp), %r9
movl -0x84(%rbp), %r8d
movq -0x90(%rbp), %rcx
movq -0x98(%rbp), %rdx
movq -0xa0(%rbp), %rdi
movq -0xa8(%rbp), %rax
leaq 0x4ceeb(%rip), %rsi     # 0x76151
movq %rax, (%rsp)
movb $0x0, %al
callq 0x94d0
movq -0x8(%rbp), %rax
movq 0x20(%rax), %rdi
movq -0x48(%rbp), %rax
movq 0x10(%rax), %rax
movq 0x8(%rax), %rsi
movq -0x48(%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 -0x38(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x38(%rbp)
jmp 0x290d6
movq -0x8(%rbp), %rax
movq 0x20(%rax), %rax
movq %rax, -0x78(%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 0x29f00
movq -0x8(%rbp), %rax
movq 0x30(%rax), %rdi
movq -0x8(%rbp), %rax
movq 0x40(%rax), %rdx
leaq 0x4ce91(%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 0x51c4e(%rip), %rsi     # 0x7af81
movb $0x0, %al
callq 0x94d0
movq -0x78(%rbp), %rdi
movq -0x8(%rbp), %rax
movq 0x30(%rax), %rsi
callq 0x9100
movq -0x78(%rbp), %rdi
leaq 0x4cec3(%rip), %rsi     # 0x76219
callq 0x8d70
movq -0x78(%rbp), %rdi
movq -0x8(%rbp), %rax
movq 0x20(%rax), %rsi
callq 0x9100
movq -0x8(%rbp), %rax
movq 0x20(%rax), %rdi
callq 0x9310
movq -0x78(%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), %rdi
movq -0x8(%rbp), %rax
movq 0x20(%rax), %rsi
leaq 0x4ce72(%rip), %rdx     # 0x76223
leaq 0x4ce70(%rip), %rcx     # 0x76228
callq 0x29fe0
movq -0x8(%rbp), %rax
movq 0x20(%rax), %rdi
leaq 0x4ce54(%rip), %rsi     # 0x76220
callq 0x8d70
movq -0x8(%rbp), %rax
movq 0x20(%rax), %rdi
movq -0x8(%rbp), %rax
movq 0x40(%rax), %rdx
leaq 0x51bac(%rip), %rsi     # 0x7af94
movb $0x0, %al
callq 0x94d0
movq -0x8(%rbp), %rax
movq 0x20(%rax), %rdi
leaq 0x51baa(%rip), %rsi     # 0x7afa8
callq 0x8d70
movq -0x8(%rbp), %rax
movq 0x20(%rax), %rdi
movl $0xa, %esi
callq 0x8ea0
jmp 0x29444
movq -0x30(%rbp), %rax
cmpl $0x900, (%rax)          # imm = 0x900
jne 0x29425
jmp 0x29444
leaq 0x4a02e(%rip), %rdi     # 0x7345a
leaq 0x516d1(%rip), %rsi     # 0x7ab04
movl $0x1e0c, %edx           # imm = 0x1E0C
leaq 0x51ae9(%rip), %rcx     # 0x7af28
callq 0x30a0
addq $0xb0, %rsp
popq %rbp
retq
nopl (%rax)