// File: /workspace/github_c_makefile_star2_O0/markdryan[P]subtilis/frontend/string_type.c
// Function: subtilis_string_type_mid_exp
subtilis_exp_t *subtilis_string_type_mid_exp(subtilis_parser_t *p,
					     subtilis_exp_t *str,
					     subtilis_exp_t *start,
					     subtilis_exp_t *len,
					     subtilis_error_t *err)
{
	size_t const_str_len;
	subtilis_exp_t *ret = NULL;
	size_t len_reg;

	start = subtilis_type_if_to_int(p, start, err);
	if (err->type != SUBTILIS_ERROR_OK)
		goto cleanup;

	if (len) {
		len = subtilis_type_if_to_int(p, len, err);
		if (err->type != SUBTILIS_ERROR_OK)
			goto cleanup;
	}

	switch (str->type.type) {
	case SUBTILIS_TYPE_CONST_STRING:
		const_str_len = subtilis_buffer_get_size(&str->exp.str) - 1;
		if (const_str_len == 0) {
			ret = str;
			str = NULL;
			goto cleanup;
		}
		if (len && len->type.type == SUBTILIS_TYPE_CONST_INTEGER) {
			if (len->exp.ir_op.integer == 0) {
				subtilis_buffer_reset(&str->exp.str);
				if (err->type != SUBTILIS_ERROR_OK)
					goto cleanup;
				subtilis_buffer_zero_terminate(&str->exp.str,
							       err);
				ret = str;
				str = NULL;
				goto cleanup;
			}
			if (len->exp.ir_op.integer < 0)
				len->exp.ir_op.integer = const_str_len;
		}

		if (start->type.type == SUBTILIS_TYPE_CONST_INTEGER)
			return prv_mid_str_cc(p, str, start, len, err);
		if (len) {
			len = subtilis_type_if_exp_to_var(p, len, err);
			if (err->type != SUBTILIS_ERROR_OK)
				goto cleanup;
			len_reg = len->exp.ir_op.reg;
		} else {
			len_reg = SIZE_MAX;
		}
		ret =
		    prv_mid_str_cv(p, str, start->exp.ir_op.reg, len_reg, err);
		break;
	case SUBTILIS_TYPE_STRING:
		start = subtilis_type_if_exp_to_var(p, start, err);
		if (err->type != SUBTILIS_ERROR_OK)
			goto cleanup;
		if (len) {
			len = subtilis_type_if_exp_to_var(p, len, err);
			if (err->type != SUBTILIS_ERROR_OK)
				goto cleanup;
			len_reg = len->exp.ir_op.reg;
		} else {
			len_reg = SIZE_MAX;
		}
		ret =
		    prv_mid_str_vvv(p, str, start->exp.ir_op.reg, len_reg, err);
		break;
	default:
		subtilis_error_set_string_expected(err, p->l->stream->name,
						   p->l->line);
		break;
	}

cleanup:

	subtilis_exp_delete(str);
	subtilis_exp_delete(start);
	subtilis_exp_delete(len);

	return ret;
}

// Assembly:
pushq %rbp
movq %rsp, %rbp
subq $0x50, %rsp
movq %rdi, -0x10(%rbp)
movq %rsi, -0x18(%rbp)
movq %rdx, -0x20(%rbp)
movq %rcx, -0x28(%rbp)
movq %r8, -0x30(%rbp)
movq $0x0, -0x40(%rbp)
movq -0x10(%rbp), %rdi
movq -0x20(%rbp), %rsi
movq -0x30(%rbp), %rdx
callq 0x488b0
movq %rax, -0x20(%rbp)
movq -0x30(%rbp), %rax
cmpl $0x0, (%rax)
je 0x68d47
jmp 0x68f9d
cmpq $0x0, -0x28(%rbp)
je 0x68d73
movq -0x10(%rbp), %rdi
movq -0x28(%rbp), %rsi
movq -0x30(%rbp), %rdx
callq 0x488b0
movq %rax, -0x28(%rbp)
movq -0x30(%rbp), %rax
cmpl $0x0, (%rax)
je 0x68d71
jmp 0x68f9d
jmp 0x68d73
movq -0x18(%rbp), %rax
movl (%rax), %eax
movl %eax, -0x4c(%rbp)
subl $0x3, %eax
je 0x68d94
jmp 0x68d83
movl -0x4c(%rbp), %eax
subl $0x7, %eax
je 0x68ee2
jmp 0x68f6b
movq -0x18(%rbp), %rdi
addq $0x148, %rdi            # imm = 0x148
callq 0x16270
subq $0x1, %rax
movq %rax, -0x38(%rbp)
cmpq $0x0, -0x38(%rbp)
jne 0x68dc8
movq -0x18(%rbp), %rax
movq %rax, -0x40(%rbp)
movq $0x0, -0x18(%rbp)
jmp 0x68f9d
cmpq $0x0, -0x28(%rbp)
je 0x68e4b
movq -0x28(%rbp), %rax
cmpl $0x1, (%rax)
jne 0x68e4b
movq -0x28(%rbp), %rax
cmpl $0x0, 0x148(%rax)
jne 0x68e2c
movq -0x18(%rbp), %rdi
addq $0x148, %rdi            # imm = 0x148
callq 0x16690
movq -0x30(%rbp), %rax
cmpl $0x0, (%rax)
je 0x68e03
jmp 0x68f9d
movq -0x18(%rbp), %rdi
addq $0x148, %rdi            # imm = 0x148
movq -0x30(%rbp), %rsi
callq 0x16560
movq -0x18(%rbp), %rax
movq %rax, -0x40(%rbp)
movq $0x0, -0x18(%rbp)
jmp 0x68f9d
movq -0x28(%rbp), %rax
cmpl $0x0, 0x148(%rax)
jge 0x68e49
movq -0x38(%rbp), %rax
movl %eax, %ecx
movq -0x28(%rbp), %rax
movl %ecx, 0x148(%rax)
jmp 0x68e4b
movq -0x20(%rbp), %rax
cmpl $0x1, (%rax)
jne 0x68e76
movq -0x10(%rbp), %rdi
movq -0x18(%rbp), %rsi
movq -0x20(%rbp), %rdx
movq -0x28(%rbp), %rcx
movq -0x30(%rbp), %r8
callq 0x68fd0
movq %rax, -0x8(%rbp)
jmp 0x68fc0
cmpq $0x0, -0x28(%rbp)
je 0x68eb1
movq -0x10(%rbp), %rdi
movq -0x28(%rbp), %rsi
movq -0x30(%rbp), %rdx
callq 0x47c10
movq %rax, -0x28(%rbp)
movq -0x30(%rbp), %rax
cmpl $0x0, (%rax)
je 0x68ea0
jmp 0x68f9d
movq -0x28(%rbp), %rax
movq 0x148(%rax), %rax
movq %rax, -0x48(%rbp)
jmp 0x68eb9
movq $-0x1, -0x48(%rbp)
movq -0x10(%rbp), %rdi
movq -0x18(%rbp), %rsi
movq -0x20(%rbp), %rax
movq 0x148(%rax), %rdx
movq -0x48(%rbp), %rcx
movq -0x30(%rbp), %r8
callq 0x69190
movq %rax, -0x40(%rbp)
jmp 0x68f9b
movq -0x10(%rbp), %rdi
movq -0x20(%rbp), %rsi
movq -0x30(%rbp), %rdx
callq 0x47c10
movq %rax, -0x20(%rbp)
movq -0x30(%rbp), %rax
cmpl $0x0, (%rax)
je 0x68f05
jmp 0x68f9d
cmpq $0x0, -0x28(%rbp)
je 0x68f3d
movq -0x10(%rbp), %rdi
movq -0x28(%rbp), %rsi
movq -0x30(%rbp), %rdx
callq 0x47c10
movq %rax, -0x28(%rbp)
movq -0x30(%rbp), %rax
cmpl $0x0, (%rax)
je 0x68f2c
jmp 0x68f9d
movq -0x28(%rbp), %rax
movq 0x148(%rax), %rax
movq %rax, -0x48(%rbp)
jmp 0x68f45
movq $-0x1, -0x48(%rbp)
movq -0x10(%rbp), %rdi
movq -0x18(%rbp), %rsi
movq -0x20(%rbp), %rax
movq 0x148(%rax), %rdx
movq -0x48(%rbp), %rcx
movq -0x30(%rbp), %r8
callq 0x69400
movq %rax, -0x40(%rbp)
jmp 0x68f9b
movq -0x30(%rbp), %rdi
movq -0x10(%rbp), %rax
movq (%rax), %rax
movq 0x30(%rax), %rdx
movq -0x10(%rbp), %rax
movq (%rax), %rax
movl 0x38(%rax), %ecx
movl $0x49, %esi
leaq 0x43ac7(%rip), %r8      # 0xaca57
movl $0x93c, %r9d            # imm = 0x93C
callq 0x15930
jmp 0x68f9d
movq -0x18(%rbp), %rdi
callq 0x36ee0
movq -0x20(%rbp), %rdi
callq 0x36ee0
movq -0x28(%rbp), %rdi
callq 0x36ee0
movq -0x40(%rbp), %rax
movq %rax, -0x8(%rbp)
movq -0x8(%rbp), %rax
addq $0x50, %rsp
popq %rbp
retq
nopw (%rax,%rax)