// File: /workspace/github_c_makefile_star2_O1/Ihsoh[P]ilang/compiler/frontend/irgen_llvmir.c
// Function: ir_type
static void _ir_type(
	IRGeneratorLlvmirContext *ctx,
	ResizableString *rstr,
	ParserASTNode *node_type
) {
	assert(ctx);
	assert(rstr);
	assert(node_type);

	switch (node_type->type) {
		case FE_NODE_TYPE_CHAR: {
			rstr_append_with_cstr(rstr, "i8");
			break;
		}
		case FE_NODE_TYPE_INT8: {
			rstr_append_with_cstr(rstr, "i8");
			break;
		}
		case FE_NODE_TYPE_UINT8: {
			rstr_append_with_cstr(rstr, "i8");
			break;
		}
		case FE_NODE_TYPE_INT16: {
			rstr_append_with_cstr(rstr, "i16");
			break;
		}
		case FE_NODE_TYPE_UINT16: {
			rstr_append_with_cstr(rstr, "i16");
			break;
		}
		case FE_NODE_TYPE_INT32: {
			rstr_append_with_cstr(rstr, "i32");
			break;
		}
		case FE_NODE_TYPE_UINT32: {
			rstr_append_with_cstr(rstr, "i32");
			break;
		}
		case FE_NODE_TYPE_INT64: {
			rstr_append_with_cstr(rstr, "i64");
			break;
		}
		case FE_NODE_TYPE_UINT64: {
			rstr_append_with_cstr(rstr, "i64");
			break;
		}
		case FE_NODE_TYPE_FLOAT: {
			rstr_append_with_cstr(rstr, "float");
			break;
		}
		case FE_NODE_TYPE_DOUBLE: {
			rstr_append_with_cstr(rstr, "double");
			break;
		}
		case FE_NODE_TYPE_VA_LIST: {
			rstr_append_with_cstr(rstr, "%struct.va_list");
			break;
		}
		case FE_NODE_TYPE_STRUCT: {
			assert(node_type->nchilds == 1);

			ParserASTNode *node_id = node_type->childs[0];
			assert(node_id->type == FE_NODE_IDENTIFIER);

			rstr_append_with_cstr(rstr, "%struct.");
			rstr_append_with_raw(rstr, node_id->token->content, node_id->token->len);
			break;
		}
		case FE_NODE_TYPE_ARRAY: {
			assert(node_type->nchilds == 2);

			ParserASTNode *node_array_dims = node_type->childs[0];
			assert(node_array_dims->type == FE_NODE_TYPE_ARRAY_DIMS);
			assert(node_array_dims->nchilds > 0);

			ParserASTNode *node_t = node_type->childs[1];

			_ir_type(ctx, rstr, node_t);

			for (int i = node_array_dims->nchilds - 1; i >= 0; i--) {
				ParserASTNode *node_array_dim = node_array_dims->childs[i];
				assert(node_array_dim->type == FE_NODE_LITERAL_UINT);

				rstr_prepend_with_cstr(rstr, " x ");
				rstr_prepend_with_raw(rstr, node_array_dim->token->content, node_array_dim->token->len);
				rstr_prepend_with_cstr(rstr, "[");

				rstr_append_with_cstr(rstr, "]");
			}

			break;
		}
		case FE_NODE_TYPE_FUNC: {
			assert(node_type->nchilds == 1 || node_type->nchilds == 2);
			ParserASTNode *node_params = NULL;
			ParserASTNode *node_t = NULL;

			node_params = node_type->childs[0];
			assert(node_params->type == FE_NODE_FUNC_PARAMS);

			if (node_type->nchilds == 2) {
				node_t = node_type->childs[1];
			}

			if (node_t != NULL) {
				_ir_type(ctx, rstr, node_t);
			} else {
				rstr_append_with_cstr(rstr, "void");
			}

			rstr_append_with_cstr(rstr, " (");
			_ir_func_type_params(ctx, rstr, node_params);
			rstr_append_with_cstr(rstr, ")");
			break;
		}
		case FE_NODE_TYPE_POINTER: {
			assert(node_type->nchilds == 1);
			ParserASTNode *node_t = node_type->childs[0];

			_ir_type(ctx, rstr, node_t);

			rstr_append_with_cstr(rstr, "*");
			break;
		}
		case FE_NODE_TYPE_VOID: {
			// LLVM IR不允许有void指针类型，需要把void指针类型转换为i8指针类型。
			// 但是在方法的返回值类型的地方，是允许为void类型。
			if (node_type->parent != NULL
					&& node_type->parent->type == FE_NODE_TYPE_POINTER) {
				rstr_prepend_with_cstr(rstr, "i8");
			} else {
				rstr_prepend_with_cstr(rstr, "void");
			}
			break;
		}
		default: {
			assert(0);
			break;
		}
	}
}

// Assembly:
pushq %rbp
movq %rsp, %rbp
pushq %r15
pushq %r14
pushq %r13
pushq %r12
pushq %rbx
subq $0x18, %rsp
testq %rdi, %rdi
je 0x19cd1
testq %rsi, %rsi
je 0x19cf0
movq %rdi, %rbx
movl (%rsi), %eax
cmpl $0x42f, %eax            # imm = 0x42F
jg 0x19943
addl $0xfffffc00, %eax       # imm = 0xFFFFFC00
cmpl $0x20, %eax
ja 0x19e6d
leaq 0x2bdfa(%rip), %rcx     # 0x45728
movslq (%rcx,%rax,4), %rax
addq %rcx, %rax
jmpq *%rax
leaq 0x2c23b(%rip), %rsi     # 0x45b79
jmp 0x19aec
cmpl $0x430, %eax            # imm = 0x430
je 0x19b02
cmpl $0x440, %eax            # imm = 0x440
je 0x19acc
cmpl $0x4ff, %eax            # imm = 0x4FF
jne 0x19e6d
movq 0x30(%rsi), %rax
testq %rax, %rax
je 0x19b31
cmpl $0x440, (%rax)          # imm = 0x440
jne 0x19b31
leaq 0x2c1f5(%rip), %rsi     # 0x45b79
jmp 0x19b38
leaq 0x2c1ec(%rip), %rsi     # 0x45b7c
jmp 0x19aec
leaq 0x2c1e8(%rip), %rsi     # 0x45b84
jmp 0x19aec
leaq 0x2c1d8(%rip), %rsi     # 0x45b80
jmp 0x19aec
leaq 0x28d2d(%rip), %rsi     # 0x426e1
jmp 0x19aec
leaq 0x2c1c8(%rip), %rsi     # 0x45b88
jmp 0x19aec
leaq 0x28d1b(%rip), %rsi     # 0x426e7
jmp 0x19aec
cmpl $0x2, 0x44(%rsi)
jne 0x19d56
movq 0x48(%rsi), %rax
movq (%rax), %r13
cmpl $0x421, (%r13)          # imm = 0x421
jne 0x19dd2
cmpl $0x0, 0x44(%r13)
jle 0x19e2f
movq 0x8(%rax), %rsi
movq %rbx, %rdi
callq 0x198ea
movslq 0x44(%r13), %r14
testq %r14, %r14
jle 0x19ca3
incq %r14
leaq 0x32cff(%rip), %r12     # 0x4c71d
movq 0x48(%r13), %rax
movq -0x10(%rax,%r14,8), %r15
cmpl $0x300, (%r15)          # imm = 0x300
jne 0x19cb2
movq %rbx, %rdi
leaq 0x2c163(%rip), %rsi     # 0x45ba1
callq 0x7f99
movq 0x10(%r15), %rax
movq 0x8(%rax), %rsi
movl 0x4(%rax), %edx
movq %rbx, %rdi
callq 0x7fc9
movq %rbx, %rdi
leaq 0x28d4f(%rip), %rsi     # 0x427af
callq 0x7f99
movq %rbx, %rdi
movq %r12, %rsi
callq 0x75cf
decq %r14
cmpq $0x1, %r14
jg 0x19a1e
jmp 0x19ca3
cmpl $0x1, 0x44(%rsi)
jne 0x19d75
movq 0x48(%rsi), %rax
movq (%rax), %r14
cmpl $0x200, (%r14)          # imm = 0x200
jne 0x19df1
leaq 0x2c0f5(%rip), %rsi     # 0x45b98
movq %rbx, %rdi
callq 0x75cf
movq 0x10(%r14), %rax
movq 0x8(%rax), %rsi
movl 0x4(%rax), %edx
movq %rbx, %rdi
addq $0x18, %rsp
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
jmp 0x7768
cmpl $0x1, 0x44(%rsi)
jne 0x19d94
movq 0x48(%rsi), %rax
movq (%rax), %rsi
movq %rbx, %rdi
callq 0x198ea
leaq 0x2aeeb(%rip), %rsi     # 0x449d7
movq %rbx, %rdi
addq $0x18, %rsp
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
jmp 0x75cf
movl 0x44(%rsi), %eax
leal -0x1(%rax), %ecx
cmpl $0x2, %ecx
jae 0x19db3
movq 0x48(%rsi), %rcx
movq (%rcx), %r12
cmpl $0xa01, (%r12)          # imm = 0xA01
jne 0x19e10
cmpl $0x2, %eax
jne 0x19b4e
movq 0x8(%rcx), %rsi
jmp 0x19b50
leaq 0x2c06d(%rip), %rsi     # 0x45ba5
movq %rbx, %rdi
addq $0x18, %rsp
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
jmp 0x7f99
xorl %esi, %esi
testq %rsi, %rsi
je 0x19b5f
movq %rbx, %rdi
callq 0x198ea
jmp 0x19b6e
leaq 0x2c03f(%rip), %rsi     # 0x45ba5
movq %rbx, %rdi
callq 0x75cf
leaq 0x2b803(%rip), %rsi     # 0x45378
movq %rbx, %rdi
callq 0x75cf
cmpl $0xa01, (%r12)          # imm = 0xA01
jne 0x19e4e
cmpl $0x0, 0x44(%r12)
jle 0x19c94
movq 0x48(%r12), %rax
movq (%rax), %rax
cmpl $0xa02, (%rax)          # imm = 0xA02
jne 0x19e8c
cmpl $0x2, 0x44(%rax)
jne 0x19eab
movq 0x48(%rax), %rax
movq 0x8(%rax), %r14
leaq -0x38(%rbp), %r15
movq %r15, %rdi
callq 0x7548
movq %r15, %rdi
movq %r14, %rsi
callq 0x198ea
movq %rbx, %rdi
movq %r15, %rsi
callq 0x788c
movq %r15, %rdi
callq 0x7a38
cmpl $0x2, 0x44(%r12)
jl 0x19c94
movl $0x1, %r14d
movq 0x48(%r12), %rax
movq (%rax,%r14,8), %r13
movl (%r13), %eax
andl $-0x2, %eax
cmpl $0xa02, %eax            # imm = 0xA02
jne 0x19d0f
movq %rbx, %rdi
leaq 0x293d8(%rip), %rsi     # 0x42ff6
callq 0x75cf
movl (%r13), %eax
cmpl $0xa02, %eax            # imm = 0xA02
je 0x19c4a
cmpl $0xa03, %eax            # imm = 0xA03
jne 0x19d37
movq %rbx, %rdi
leaq 0x28c9d(%rip), %rsi     # 0x428e0
callq 0x75cf
jmp 0x19c83
cmpl $0x2, 0x44(%r13)
jne 0x19d2e
movq 0x48(%r13), %rax
movq 0x8(%rax), %r13
movq %r15, %rdi
callq 0x7548
movq %r15, %rdi
movq %r13, %rsi
callq 0x198ea
movq %rbx, %rdi
movq %r15, %rsi
callq 0x788c
movq %r15, %rdi
callq 0x7a38
incq %r14
movslq 0x44(%r12), %rax
cmpq %rax, %r14
jl 0x19bf9
leaq 0x2ac9f(%rip), %rsi     # 0x4493a
movq %rbx, %rdi
callq 0x75cf
addq $0x18, %rsp
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq
leaq 0x28ac9(%rip), %rdi     # 0x42782
leaq 0x2bbb4(%rip), %rsi     # 0x45874
leaq 0x2be64(%rip), %rcx     # 0x45b2b
movl $0x2b5, %edx            # imm = 0x2B5
callq 0x30a0
leaq 0x26d78(%rip), %rdi     # 0x40a50
leaq 0x2bb95(%rip), %rsi     # 0x45874
leaq 0x2be45(%rip), %rcx     # 0x45b2b
movl $0x26a, %edx            # imm = 0x26A
callq 0x30a0
leaq 0x289c0(%rip), %rdi     # 0x426b7
leaq 0x2bb76(%rip), %rsi     # 0x45874
leaq 0x2be26(%rip), %rcx     # 0x45b2b
movl $0x26b, %edx            # imm = 0x26B
callq 0x30a0
leaq 0x28be7(%rip), %rdi     # 0x428fd
leaq 0x2bb57(%rip), %rsi     # 0x45874
leaq 0x2be86(%rip), %rcx     # 0x45baa
movl $0x259, %edx            # imm = 0x259
callq 0x30a0
leaq 0x28baf(%rip), %rdi     # 0x428e4
jmp 0x19d3e
leaq 0x26646(%rip), %rdi     # 0x40384
leaq 0x2bb2f(%rip), %rsi     # 0x45874
leaq 0x2be5e(%rip), %rcx     # 0x45baa
movl $0x25d, %edx            # imm = 0x25D
callq 0x30a0
leaq 0x28a6f(%rip), %rdi     # 0x427cc
leaq 0x2bb10(%rip), %rsi     # 0x45874
leaq 0x2bdc0(%rip), %rcx     # 0x45b2b
movl $0x2a9, %edx            # imm = 0x2A9
callq 0x30a0
leaq 0x2897c(%rip), %rdi     # 0x426f8
leaq 0x2baf1(%rip), %rsi     # 0x45874
leaq 0x2bda1(%rip), %rcx     # 0x45b2b
movl $0x29f, %edx            # imm = 0x29F
callq 0x30a0
leaq 0x2895d(%rip), %rdi     # 0x426f8
leaq 0x2bad2(%rip), %rsi     # 0x45874
leaq 0x2bd82(%rip), %rcx     # 0x45b2b
movl $0x2d8, %edx            # imm = 0x2D8
callq 0x30a0
leaq 0x289f7(%rip), %rdi     # 0x427b1
leaq 0x2bab3(%rip), %rsi     # 0x45874
leaq 0x2bd63(%rip), %rcx     # 0x45b2b
movl $0x2c1, %edx            # imm = 0x2C1
callq 0x30a0
leaq 0x2895b(%rip), %rdi     # 0x42734
leaq 0x2ba94(%rip), %rsi     # 0x45874
leaq 0x2bd44(%rip), %rcx     # 0x45b2b
movl $0x2ac, %edx            # imm = 0x2AC
callq 0x30a0
leaq 0x28918(%rip), %rdi     # 0x42710
leaq 0x2ba75(%rip), %rsi     # 0x45874
leaq 0x2bd25(%rip), %rcx     # 0x45b2b
movl $0x2a2, %edx            # imm = 0x2A2
callq 0x30a0
leaq 0x289cd(%rip), %rdi     # 0x427e4
leaq 0x2ba56(%rip), %rsi     # 0x45874
leaq 0x2bd06(%rip), %rcx     # 0x45b2b
movl $0x2c6, %edx            # imm = 0x2C6
callq 0x30a0
leaq 0x2892f(%rip), %rdi     # 0x42765
leaq 0x2ba37(%rip), %rsi     # 0x45874
leaq 0x2bce7(%rip), %rcx     # 0x45b2b
movl $0x2ad, %edx            # imm = 0x2AD
callq 0x30a0
leaq 0x28a2b(%rip), %rdi     # 0x42880
leaq 0x2ba18(%rip), %rsi     # 0x45874
leaq 0x2bd47(%rip), %rcx     # 0x45baa
movl $0x237, %edx            # imm = 0x237
callq 0x30a0
leaq 0x26510(%rip), %rdi     # 0x40384
leaq 0x2b9f9(%rip), %rsi     # 0x45874
leaq 0x2bca9(%rip), %rcx     # 0x45b2b
movl $0x2ec, %edx            # imm = 0x2EC
callq 0x30a0
leaq 0x28a20(%rip), %rdi     # 0x428b3
leaq 0x2b9da(%rip), %rsi     # 0x45874
leaq 0x2bd09(%rip), %rcx     # 0x45baa
movl $0x23b, %edx            # imm = 0x23B
callq 0x30a0
leaq 0x28a32(%rip), %rdi     # 0x428e4
leaq 0x2b9bb(%rip), %rsi     # 0x45874
leaq 0x2bcea(%rip), %rcx     # 0x45baa
movl $0x254, %edx            # imm = 0x254
callq 0x30a0