// File: /workspace/github_c_makefile_star2_O3/Ihsoh[P]ilang/compiler/frontend/irgen_llvmir.c
// Function: ir_constexpr
static void _ir_constexpr(
	IRGeneratorLlvmirContext *ctx,
	ResizableString *rstr_type,
	ResizableString *rstr_val,
	ParserASTNode *node_constexpr
) {
	assert(ctx);
	assert(rstr_val);
	assert(node_constexpr);
	assert(FE_EXPR_AST_NODE_GET_CONSTANT(node_constexpr));

	if (rstr_type != NULL) {
		_ir_type(ctx, rstr_type, FE_EXPR_AST_NODE_GET_TYPE_NODE(node_constexpr));
	}

	switch (FE_EXPR_AST_NODE_GET_CONSTANT_TYPE(node_constexpr)) {
		case FE_TYPE_CHAR: {
			char str[128];
			snprintf(
				str, sizeof(str), "%d",
				FE_EXPR_AST_NODE_GET_CONSTEXPR_RESULT_CHAR_VAL(node_constexpr)
			);
			rstr_append_with_cstr(rstr_val, str);
			break;
		}
		case FE_TYPE_INT8: {
			char str[128];
			snprintf(
				str, sizeof(str), "%d",
				FE_EXPR_AST_NODE_GET_CONSTEXPR_RESULT_INT8_VAL(node_constexpr)
			);
			rstr_append_with_cstr(rstr_val, str);
			break;
		}
		case FE_TYPE_INT16: {
			char str[128];
			snprintf(
				str, sizeof(str), "%d",
				FE_EXPR_AST_NODE_GET_CONSTEXPR_RESULT_INT16_VAL(node_constexpr)
			);
			rstr_append_with_cstr(rstr_val, str);
			break;
		}
		case FE_TYPE_INT32: {
			char str[128];
			snprintf(
				str, sizeof(str), "%d",
				FE_EXPR_AST_NODE_GET_CONSTEXPR_RESULT_INT32_VAL(node_constexpr)
			);
			rstr_append_with_cstr(rstr_val, str);
			break;
		}
		case FE_TYPE_INT64: {
			char str[128];
			snprintf(
				str, sizeof(str), "%lld",
				FE_EXPR_AST_NODE_GET_CONSTEXPR_RESULT_INT64_VAL(node_constexpr)
			);
			rstr_append_with_cstr(rstr_val, str);
			break;
		}
		case FE_TYPE_UINT8: {
			char str[128];
			snprintf(
				str, sizeof(str), "%u",
				FE_EXPR_AST_NODE_GET_CONSTEXPR_RESULT_UINT8_VAL(node_constexpr)
			);
			rstr_append_with_cstr(rstr_val, str);
			break;
		}
		case FE_TYPE_UINT16: {
			char str[128];
			snprintf(
				str, sizeof(str), "%u",
				FE_EXPR_AST_NODE_GET_CONSTEXPR_RESULT_UINT16_VAL(node_constexpr)
			);
			rstr_append_with_cstr(rstr_val, str);
			break;
		}
		case FE_TYPE_UINT32: {
			char str[128];
			snprintf(
				str, sizeof(str), "%u",
				FE_EXPR_AST_NODE_GET_CONSTEXPR_RESULT_UINT32_VAL(node_constexpr)
			);
			rstr_append_with_cstr(rstr_val, str);
			break;
		}
		case FE_TYPE_UINT64: {
			char str[128];
			snprintf(
				str, sizeof(str), "%llu",
				FE_EXPR_AST_NODE_GET_CONSTEXPR_RESULT_UINT64_VAL(node_constexpr)
			);
			rstr_append_with_cstr(rstr_val, str);
			break;
		}
		case FE_TYPE_FLOAT: {
			char str[128];
			double val = FE_EXPR_AST_NODE_GET_CONSTEXPR_RESULT_FLOAT_VAL(node_constexpr);
			snprintf(
				str, sizeof(str), "0x%llX",
				*(uint64_t *)&val
			);
			rstr_append_with_cstr(rstr_val, str);
			break;
		}
		case FE_TYPE_DOUBLE: {
			char str[128];
			double val = FE_EXPR_AST_NODE_GET_CONSTEXPR_RESULT_DOUBLE_VAL(node_constexpr);
			snprintf(
				str, sizeof(str), "0x%llX",
				*(uint64_t *)&val
			);
			rstr_append_with_cstr(rstr_val, str);
			break;
		}
		case FE_TYPE_POINTER: {
			if (FE_EXPR_AST_NODE_GET_HAS_CONSTSTR(node_constexpr)) {
				FeParserConstexprString *conststr = FE_EXPR_AST_NODE_GET_CONSTSTR(node_constexpr);
				uint64_t ptr_val = FE_EXPR_AST_NODE_GET_CONSTEXPR_RESULT_POINTER_VAL(node_constexpr);

				ResizableString conststr_name;
				rstr_init(&conststr_name);

				int len = _new_string(ctx, &conststr_name, conststr->str, conststr->len);

				ResizableString target_type;
				rstr_init(&target_type);

				_ir_type(ctx, &target_type, FE_EXPR_AST_NODE_GET_TYPE_NODE(node_constexpr));

				char *offset_type = "";
				if (ctx->psrctx->arch == FE_ARCH_32) {
					offset_type = "i32";
				} else if (ctx->psrctx->arch == FE_ARCH_64) {
					offset_type = "i64";
				} else {
					assert(0);
				}

				if (ptr_val == 0) {
					rstr_appendf(
						rstr_val,
						"bitcast (i8* getelementptr inbounds ([%zu x i8], [%zu x i8]* %s, i32 0, %s 0) to %s)",
						len,
						len,
						RSTR_CSTR(&conststr_name),
						offset_type,
						RSTR_CSTR(&target_type)
					);
				} else {
					rstr_appendf(
						rstr_val,
						"bitcast (i8* getelementptr inbounds ([%zu x i8], [%zu x i8]* %s, i32 0, %s %u) to %s)",
						len,
						len,
						RSTR_CSTR(&conststr_name),
						offset_type,
						ptr_val,
						RSTR_CSTR(&target_type)
					);
				}

				rstr_free(&conststr_name);
				rstr_free(&target_type);
			} else {
				char *source_type = "";
				if (ctx->psrctx->arch == FE_ARCH_32) {
					source_type = "i32";
				} else if (ctx->psrctx->arch == FE_ARCH_64) {
					source_type = "i64";
				} else {
					assert(0);
				}

				ResizableString target_type;
				rstr_init(&target_type);
				_ir_type(ctx, &target_type, FE_EXPR_AST_NODE_GET_TYPE_NODE(node_constexpr));

				char str[128];
				snprintf(
					str, sizeof(str), "inttoptr (%s %llu to %s)",
					source_type,
					FE_EXPR_AST_NODE_GET_CONSTEXPR_RESULT_POINTER_VAL(node_constexpr),
					RSTR_CSTR(&target_type)
				);
				rstr_append_with_cstr(rstr_val, str);

				rstr_free(&target_type);
			}
			break;
		}
		default: {
			assert(0);
		}
	}
}

// Assembly:
pushq %rbp
movq %rsp, %rbp
pushq %r15
pushq %r14
pushq %r13
pushq %r12
pushq %rbx
subq $0xa8, %rsp
testq %rdx, %rdx
je 0x1a821
movq %rcx, %r14
cmpb $0x0, 0x70(%rcx)
je 0x1a840
movq %rdx, %rbx
movq %rdi, %r15
testq %rsi, %rsi
je 0x1a4bb
movq 0x68(%r14), %rax
movq %rsi, %rdi
movq %rax, %rsi
callq 0x19540
movzbl 0x71(%r14), %eax
decl %eax
cmpl $0xf, %eax
ja 0x1a85f
leaq 0x2a3aa(%rip), %rcx     # 0x4487c
movslq (%rcx,%rax,4), %rax
addq %rcx, %rax
jmpq *%rax
movsbl 0x88(%r14), %ecx
jmp 0x1a6d5
cmpb $0x1, 0x72(%r14)
jne 0x1a720
movq %rbx, -0x40(%rbp)
movq 0x88(%r14), %rax
movq %rax, -0x38(%rbp)
leaq -0x50(%rbp), %rdi
callq 0x7354
movq 0x78(%r14), %r12
testq %r12, %r12
je 0x1a87e
movq 0x80(%r14), %rax
movq %rax, -0x30(%rbp)
movq 0x38(%r15), %r13
leaq 0x1(%r13), %rax
movq %rax, 0x38(%r15)
leaq 0x2a9f6(%rip), %rsi     # 0x44f2c
leaq -0x50(%rbp), %rdi
movq %r13, %rdx
xorl %eax, %eax
callq 0x7945
leaq -0xd0(%rbp), %rbx
movq %rbx, %rdi
callq 0x7354
movq (%r15), %rax
movq (%rax), %rdi
movq %rbx, %rsi
movq %r12, %rdx
movq -0x30(%rbp), %rcx
callq 0x21732
movslq 0x4(%rbx), %r12
movq 0x18(%r15), %rdi
leal 0x1(%r12), %ecx
leaq 0x2a9ba(%rip), %rsi     # 0x44f36
movq %r13, %rdx
movl %ecx, -0x30(%rbp)
xorl %eax, %eax
callq 0x7945
testq %r12, %r12
jle 0x1a5f8
callq 0x3190
movq %rax, %r13
xorl %ebx, %ebx
movslq -0xcc(%rbp), %rcx
movb $-0x1, %al
cmpq %rcx, %rbx
jge 0x1a5be
movq -0xc8(%rbp), %rax
testq %rax, %rax
leaq 0x2894f(%rip), %rcx     # 0x42f06
cmoveq %rcx, %rax
movb (%rax,%rbx), %al
movq (%r13), %rcx
movsbq %al, %rdx
testb $0x40, 0x1(%rcx,%rdx,2)
jne 0x1a5e4
movsbl %al, %edx
movq 0x18(%r15), %rdi
leaq 0x2a992(%rip), %rsi     # 0x44f6d
xorl %eax, %eax
callq 0x7945
jmp 0x1a5f0
movq 0x18(%r15), %rdi
movsbl %al, %esi
callq 0x74da
incq %rbx
cmpq %rbx, %r12
jne 0x1a598
movq 0x18(%r15), %rdi
leaq 0x2a970(%rip), %rsi     # 0x44f73
callq 0x73db
leaq -0xd0(%rbp), %rdi
callq 0x7852
leaq -0xd0(%rbp), %r12
movq %r12, %rdi
callq 0x7354
movq 0x68(%r14), %rsi
movq %r12, %rdi
callq 0x19540
movq (%r15), %rax
movl 0x30(%rax), %eax
cmpl $0x1, %eax
je 0x1a7a5
cmpl $0x2, %eax
movq -0x40(%rbp), %rdi
movq -0x38(%rbp), %r11
jne 0x1a8bc
leaq 0x2a5fe(%rip), %r9      # 0x44c54
jmp 0x1a7b4
cvtss2sd 0x88(%r14), %xmm0
movq %xmm0, %rcx
jmp 0x1a672
movq 0x88(%r14), %rcx
leaq 0x2a793(%rip), %rdx     # 0x44e0c
jmp 0x1a699
movq 0x88(%r14), %rcx
leaq 0x29559(%rip), %rdx     # 0x43be2
jmp 0x1a699
movq 0x88(%r14), %rcx
leaq 0x29541(%rip), %rdx     # 0x43bda
leaq -0xd0(%rbp), %r14
movl $0x80, %esi
movq %r14, %rdi
xorl %eax, %eax
callq 0x3090
jmp 0x1a703
movzbl 0x88(%r14), %ecx
jmp 0x1a6e6
movswl 0x88(%r14), %ecx
jmp 0x1a6d5
movl 0x88(%r14), %ecx
jmp 0x1a6e6
movl 0x88(%r14), %ecx
leaq 0x2a4e7(%rip), %rdx     # 0x44bc3
jmp 0x1a6ed
movzwl 0x88(%r14), %ecx
leaq 0x294f2(%rip), %rdx     # 0x43bdf
leaq -0xd0(%rbp), %r14
movl $0x80, %esi
movq %r14, %rdi
xorl %eax, %eax
callq 0x3090
movq %rbx, %rdi
movq %r14, %rsi
callq 0x73db
addq $0xa8, %rsp
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq
movq (%r15), %rax
movl 0x30(%rax), %eax
cmpl $0x1, %eax
je 0x1a73d
cmpl $0x2, %eax
jne 0x1a89d
leaq 0x2a519(%rip), %r12     # 0x44c54
jmp 0x1a744
leaq 0x2a50c(%rip), %r12     # 0x44c50
leaq -0x50(%rbp), %r15
movq %r15, %rdi
callq 0x7354
movq 0x68(%r14), %rsi
movq %r15, %rdi
callq 0x19540
movq 0x88(%r14), %r8
movq 0x8(%r15), %rax
testq %rax, %rax
leaq 0x28795(%rip), %r9      # 0x42f06
cmovneq %rax, %r9
leaq 0x2a742(%rip), %rdx     # 0x44ebe
leaq -0xd0(%rbp), %r14
movl $0x80, %esi
movq %r14, %rdi
movq %r12, %rcx
xorl %eax, %eax
callq 0x3090
movq %rbx, %rdi
movq %r14, %rsi
callq 0x73db
movq %r15, %rdi
jmp 0x1a817
leaq 0x2a4a4(%rip), %r9      # 0x44c50
movq -0x40(%rbp), %rdi
movq -0x38(%rbp), %r11
movl -0x30(%rbp), %ecx
movq -0x48(%rbp), %r8
testq %r8, %r8
leaq 0x28741(%rip), %rax     # 0x42f06
cmoveq %rax, %r8
movq -0xc8(%rbp), %r10
testq %r10, %r10
cmoveq %rax, %r10
testq %r11, %r11
je 0x1a7ed
leaq 0x2a685(%rip), %rsi     # 0x44e68
movl %ecx, %edx
xorl %eax, %eax
pushq %r10
pushq %r11
jmp 0x1a7fe
subq $0x8, %rsp
leaq 0x2a61b(%rip), %rsi     # 0x44e13
movl %ecx, %edx
xorl %eax, %eax
pushq %r10
callq 0x7945
addq $0x10, %rsp
leaq -0x50(%rbp), %rdi
callq 0x7852
leaq -0xd0(%rbp), %rdi
callq 0x7852
jmp 0x1a70e
leaq 0x272bc(%rip), %rdi     # 0x41ae4
leaq 0x2a115(%rip), %rsi     # 0x44944
leaq 0x2a570(%rip), %rcx     # 0x44da6
movl $0x327, %edx            # imm = 0x327
callq 0x30a0
leaq 0x27222(%rip), %rdi     # 0x41a69
leaq 0x2a0f6(%rip), %rsi     # 0x44944
leaq 0x2a551(%rip), %rcx     # 0x44da6
movl $0x329, %edx            # imm = 0x329
callq 0x30a0
leaq 0x24afa(%rip), %rdi     # 0x3f360
leaq 0x2a0d7(%rip), %rsi     # 0x44944
leaq 0x2a532(%rip), %rcx     # 0x44da6
movl $0x3e2, %edx            # imm = 0x3E2
callq 0x30a0
leaq 0x25216(%rip), %rdi     # 0x3fa9b
leaq 0x2a0b8(%rip), %rsi     # 0x44944
leaq 0x2a644(%rip), %rcx     # 0x44ed7
movl $0x11d, %edx            # imm = 0x11D
callq 0x30a0
leaq 0x24abc(%rip), %rdi     # 0x3f360
leaq 0x2a099(%rip), %rsi     # 0x44944
leaq 0x2a4f4(%rip), %rcx     # 0x44da6
movl $0x3cd, %edx            # imm = 0x3CD
callq 0x30a0
leaq 0x24a9d(%rip), %rdi     # 0x3f360
leaq 0x2a07a(%rip), %rsi     # 0x44944
leaq 0x2a4d5(%rip), %rcx     # 0x44da6
movl $0x3aa, %edx            # imm = 0x3AA
callq 0x30a0