// File: /workspace/github_c_makefile_star2_O0/hsjoihs[P]c-compiler/typecheck_expression.c
// Function: typecheck_unary_expression
struct Expr typecheck_unary_expression(const struct AnalyzerState *ptr_ps,
                                       const struct Expr *ref_expr,
                                       enum TokenKind kind)
{
	const struct Expr expr = *ref_expr;
	switch (kind) {
	case OP_NOT: {
		expect_scalar(&expr.details.type, "operand of logical not");
		struct Type t = INT_TYPE();
		return unary_op_(&expr, kind, &t);
	}
	case OP_TILDA:
	case OP_PLUS:
	case OP_MINUS: {
		expect_integral(&expr.details.type,
		                "operand of bitnot, unary plus or unary minus");

		/* integral promotion */
		struct Type t = INT_TYPE();
		return unary_op_(&expr, kind, &t);
	}

	case OP_PLUS_PLUS:
	case OP_MINUS_MINUS: {
		struct Expr new_expr = unary_op_(&expr, kind, &expr.details.type);
		if (expr.details.type.type_category == PTR_) {
			const struct Type deref = deref_type(&expr.details.type);
			new_expr.size_info_for_pointer_arith = size_of(ptr_ps, &deref);
		}
		return new_expr;
	}

	case OP_AND: {
		struct Type type = expr.details.type;
		if (type.type_category == PTR_ &&
		    expr.details.true_type.type_category == ARRAY) {
			type = expr.details.true_type;
		}
		const struct Type ptr_to_type_ = ptr_to_type(&type);
		return unary_op_(&expr, OP_AND, &ptr_to_type_);
	}
	case OP_ASTERISK: {

		/* function type, automatically converted to a function pointer,
		 * gets dereferenced to become a function type, which is again
		 * automatically converted to a function pointer
		 */
		if (expr.details.type.type_category == FN) {
			struct Expr e = expr;
			if_function_cast_to_pointer(&e);
			return e;
		}

		const struct Type type = deref_type(&expr.details.type);

		if (type.type_category ==
		    FN) { /* function reverts to function pointer */
			return expr;
		}

		struct Type t2 = type;
		if_array_convert_to_ptr_(&t2);

		struct Expr new_expr = unary_op_(&expr, OP_ASTERISK, &t2);
		new_expr.details.true_type = type;

		return new_expr;
	}
	case RES_SIZEOF: {
		struct Expr new_expr;
		new_expr.details.type = INT_TYPE();
		new_expr.int_value = size_of(ptr_ps, &expr.details.true_type);
		new_expr.category = INT_VALUE;
		return new_expr;
	}
	default: {
		fprintf(stderr, "FAILURE::::::: INVALID TOKEN %d in unary\n", kind);
		exit(EXIT_FAILURE);
	}
	}
}

// Assembly:
pushq %rbp
movq %rsp, %rbp
subq $0x3b0, %rsp            # imm = 0x3B0
movq %rdi, -0x3b0(%rbp)
movq %rdi, -0x3a8(%rbp)
movq %rsi, -0x8(%rbp)
movq %rdx, -0x10(%rbp)
movl %ecx, -0x14(%rbp)
movq -0x10(%rbp), %rsi
leaq -0x118(%rbp), %rdi
movl $0x100, %edx            # imm = 0x100
callq 0x10e0
movl -0x14(%rbp), %eax
movq %rax, -0x3a0(%rbp)
subq $0x3b, %rax
ja 0x6fbf
movq -0x3a0(%rbp), %rax
leaq 0xd855(%rip), %rcx      # 0x14590
movslq (%rcx,%rax,4), %rax
addq %rcx, %rax
jmpq *%rax
leaq -0x118(%rbp), %rdi
leaq 0xd5ce(%rip), %rsi      # 0x14320
callq 0x6960
leaq -0x168(%rbp), %rdi
callq 0xb230
movq -0x3b0(%rbp), %rdi
movl -0x14(%rbp), %edx
leaq -0x118(%rbp), %rsi
leaq -0x168(%rbp), %rcx
callq 0x6c40
jmp 0x6fe4
leaq -0x118(%rbp), %rdi
leaq 0xdbea(%rip), %rsi      # 0x1497d
callq 0x6a10
leaq -0x1b8(%rbp), %rdi
callq 0xb230
movq -0x3b0(%rbp), %rdi
movl -0x14(%rbp), %edx
leaq -0x118(%rbp), %rsi
leaq -0x1b8(%rbp), %rcx
callq 0x6c40
jmp 0x6fe4
movq -0x3b0(%rbp), %rdi
movl -0x14(%rbp), %edx
leaq -0x118(%rbp), %rcx
leaq -0x118(%rbp), %rsi
callq 0x6c40
cmpl $0x1, -0x118(%rbp)
jne 0x6e1e
leaq -0x118(%rbp), %rsi
leaq -0x208(%rbp), %rdi
callq 0xb800
movq -0x8(%rbp), %rdi
leaq -0x208(%rbp), %rsi
callq 0x2570
movl %eax, %ecx
movq -0x3b0(%rbp), %rax
movl %ecx, 0xf4(%rax)
jmp 0x6fe4
leaq -0x118(%rbp), %rsi
leaq -0x258(%rbp), %rdi
movl $0x50, %edx
callq 0x10e0
cmpl $0x1, -0x258(%rbp)
jne 0x6e69
cmpl $0x2, -0xc8(%rbp)
jne 0x6e69
leaq -0x118(%rbp), %rsi
addq $0x50, %rsi
leaq -0x258(%rbp), %rdi
movl $0x50, %edx
callq 0x10e0
leaq -0x2a8(%rbp), %rdi
leaq -0x258(%rbp), %rsi
callq 0xb8a0
movq -0x3b0(%rbp), %rdi
leaq -0x118(%rbp), %rsi
movl $0x11, %edx
leaq -0x2a8(%rbp), %rcx
callq 0x6c40
jmp 0x6fe4
cmpl $0x3, -0x118(%rbp)
jne 0x6ed2
movq -0x3b0(%rbp), %rdi
leaq -0x118(%rbp), %rsi
movl $0x100, %edx            # imm = 0x100
callq 0x10e0
movq -0x3b0(%rbp), %rdi
callq 0x6bc0
jmp 0x6fe4
leaq -0x118(%rbp), %rsi
leaq -0x2f8(%rbp), %rdi
callq 0xb800
cmpl $0x3, -0x2f8(%rbp)
jne 0x6f0b
movq -0x3b0(%rbp), %rdi
leaq -0x118(%rbp), %rsi
movl $0x100, %edx            # imm = 0x100
callq 0x10e0
jmp 0x6fe4
leaq -0x348(%rbp), %rdi
leaq -0x2f8(%rbp), %rsi
movl $0x50, %edx
callq 0x10e0
leaq -0x348(%rbp), %rdi
callq 0xb880
movq -0x3b0(%rbp), %rdi
leaq -0x118(%rbp), %rsi
movl $0x5, %edx
leaq -0x348(%rbp), %rcx
callq 0x6c40
movq -0x3b0(%rbp), %rdi
addq $0x50, %rdi
leaq -0x2f8(%rbp), %rsi
movl $0x50, %edx
callq 0x10e0
jmp 0x6fe4
leaq -0x398(%rbp), %rdi
callq 0xb230
movq -0x3b0(%rbp), %rdi
leaq -0x398(%rbp), %rsi
movl $0x50, %edx
callq 0x10e0
movq -0x8(%rbp), %rdi
leaq -0x118(%rbp), %rsi
addq $0x50, %rsi
callq 0x2570
movl %eax, %ecx
movq -0x3b0(%rbp), %rax
movl %ecx, 0xc8(%rax)
movl $0x9, 0xa0(%rax)
jmp 0x6fe4
movq 0x15032(%rip), %rax     # 0x1bff8
movq (%rax), %rdi
movl -0x14(%rbp), %edx
leaq 0xd9d7(%rip), %rsi      # 0x149aa
movb $0x0, %al
callq 0x10d0
movl $0x1, %edi
callq 0x1150
movq -0x3a8(%rbp), %rax
addq $0x3b0, %rsp            # imm = 0x3B0
popq %rbp
retq
nopw %cs:(%rax,%rax)