// File: /workspace/github_c_makefile_star2_O0/lucvoo[P]sparse-dev/expression.c
// Function: postfix_expression
static struct token *postfix_expression(struct token *token, struct expression **tree, struct expression *cast_init_expr)
{
	struct expression *expr = cast_init_expr;

	if (!expr)
		token = primary_expression(token, &expr);

	while (expr && token_type(token) == TOKEN_SPECIAL) {
		switch (token->special) {
		case '[': {			/* Array dereference */
			struct expression *deref = alloc_expression(token->pos, EXPR_PREOP);
			struct expression *add = alloc_expression(token->pos, EXPR_BINOP);

			deref->op = '*';
			deref->unop = add;

			add->op = '+';
			add->left = expr;
			token = parse_expression(token->next, &add->right);
			token = expect(token, ']', "at end of array dereference");
			expr = deref;
			continue;
		}
		case SPECIAL_INCREMENT:		/* Post-increment */
		case SPECIAL_DECREMENT:	{	/* Post-decrement */
			struct expression *post = alloc_expression(token->pos, EXPR_POSTOP);
			post->op = token->special;
			post->unop = expr;
			expr = post;
			token = token->next;
			continue;
		}
		case SPECIAL_DEREFERENCE: {	/* Structure pointer member dereference */
			/* "x->y" is just shorthand for "(*x).y" */
			struct expression *inner = alloc_expression(token->pos, EXPR_PREOP);
			inner->op = '*';
			inner->unop = expr;
			expr = inner;
		}
		/* Fall through!! */
		case '.': {			/* Structure member dereference */
			struct expression *deref = alloc_expression(token->pos, EXPR_DEREF);
			deref->op = '.';
			deref->deref = expr;
			token = token->next;
			if (token_type(token) != TOKEN_IDENT) {
				sparse_error(token->pos, "Expected member name");
				break;
			}
			deref->member = token->ident;
			token = token->next;
			expr = deref;
			continue;
		}

		case '(': {			/* Function call */
			struct expression *call = alloc_expression(token->pos, EXPR_CALL);
			call->op = '(';
			call->fn = expr;
			token = expression_list(token->next, &call->args);
			token = expect(token, ')', "in function call");
			expr = call;
			continue;
		}

		default:
			break;
		}
		break;
	}
	*tree = expr;
	return token;
}

// Assembly:
pushq %rbp
movq %rsp, %rbp
subq $0x60, %rsp
movq %rdi, -0x8(%rbp)
movq %rsi, -0x10(%rbp)
movq %rdx, -0x18(%rbp)
movq -0x18(%rbp), %rax
movq %rax, -0x20(%rbp)
cmpq $0x0, -0x20(%rbp)
jne 0x58134
movq -0x8(%rbp), %rdi
leaq -0x20(%rbp), %rsi
callq 0x55d50
movq %rax, -0x8(%rbp)
jmp 0x58136
xorl %eax, %eax
cmpq $0x0, -0x20(%rbp)
movb %al, -0x51(%rbp)
je 0x58156
movq -0x8(%rbp), %rax
movq (%rax), %rax
andq $0x3f, %rax
cmpl $0x12, %eax
sete %al
movb %al, -0x51(%rbp)
movb -0x51(%rbp), %al
testb $0x1, %al
jne 0x58162
jmp 0x583d7
movq -0x8(%rbp), %rax
movl 0x10(%rax), %eax
movl %eax, -0x58(%rbp)
subl $0x28, %eax
je 0x58364
jmp 0x58177
movl -0x58(%rbp), %eax
subl $0x2e, %eax
je 0x582d9
jmp 0x58185
movl -0x58(%rbp), %eax
subl $0x5b, %eax
je 0x581c2
jmp 0x5818f
movl -0x58(%rbp), %eax
subl $0x101, %eax            # imm = 0x101
je 0x5825d
jmp 0x5819f
movl -0x58(%rbp), %eax
subl $0x103, %eax            # imm = 0x103
je 0x5825d
jmp 0x581af
movl -0x58(%rbp), %eax
subl $0x104, %eax            # imm = 0x104
je 0x582a5
jmp 0x583d3
movq -0x8(%rbp), %rax
movq (%rax), %rdi
movl $0x9, %esi
callq 0x55c50
movq %rax, -0x28(%rbp)
movq -0x8(%rbp), %rax
movq (%rax), %rdi
movl $0x5, %esi
callq 0x55c50
movq %rax, -0x30(%rbp)
movq -0x28(%rbp), %rax
movl $0x2a, 0x4(%rax)
movq -0x30(%rbp), %rcx
movq -0x28(%rbp), %rax
movq %rcx, 0x20(%rax)
movq -0x30(%rbp), %rax
movl $0x2b, 0x4(%rax)
movq -0x20(%rbp), %rcx
movq -0x30(%rbp), %rax
movq %rcx, 0x20(%rax)
movq -0x8(%rbp), %rax
movq 0x8(%rax), %rdi
movq -0x30(%rbp), %rsi
addq $0x20, %rsi
addq $0x8, %rsi
callq 0x55cb0
movq %rax, -0x8(%rbp)
movq -0x8(%rbp), %rdi
movl $0x5d, %esi
leaq 0x14922(%rip), %rdx     # 0x6cb69
callq 0x22eb0
movq %rax, -0x8(%rbp)
movq -0x28(%rbp), %rax
movq %rax, -0x20(%rbp)
jmp 0x58136
movq -0x8(%rbp), %rax
movq (%rax), %rdi
movl $0xa, %esi
callq 0x55c50
movq %rax, -0x38(%rbp)
movq -0x8(%rbp), %rax
movl 0x10(%rax), %ecx
movq -0x38(%rbp), %rax
movl %ecx, 0x4(%rax)
movq -0x20(%rbp), %rcx
movq -0x38(%rbp), %rax
movq %rcx, 0x20(%rax)
movq -0x38(%rbp), %rax
movq %rax, -0x20(%rbp)
movq -0x8(%rbp), %rax
movq 0x8(%rax), %rax
movq %rax, -0x8(%rbp)
jmp 0x58136
movq -0x8(%rbp), %rax
movq (%rax), %rdi
movl $0x9, %esi
callq 0x55c50
movq %rax, -0x40(%rbp)
movq -0x40(%rbp), %rax
movl $0x2a, 0x4(%rax)
movq -0x20(%rbp), %rcx
movq -0x40(%rbp), %rax
movq %rcx, 0x20(%rax)
movq -0x40(%rbp), %rax
movq %rax, -0x20(%rbp)
movq -0x8(%rbp), %rax
movq (%rax), %rdi
movl $0x8, %esi
callq 0x55c50
movq %rax, -0x48(%rbp)
movq -0x48(%rbp), %rax
movl $0x2e, 0x4(%rax)
movq -0x20(%rbp), %rcx
movq -0x48(%rbp), %rax
movq %rcx, 0x20(%rax)
movq -0x8(%rbp), %rax
movq 0x8(%rax), %rax
movq %rax, -0x8(%rbp)
movq -0x8(%rbp), %rax
movq (%rax), %rax
andq $0x3f, %rax
cmpl $0x3, %eax
je 0x5833b
movq -0x8(%rbp), %rax
movq (%rax), %rdi
leaq 0x14825(%rip), %rsi     # 0x6cb54
movb $0x0, %al
callq 0x16f90
jmp 0x583d5
movq -0x8(%rbp), %rax
movq 0x10(%rax), %rcx
movq -0x48(%rbp), %rax
movq %rcx, 0x28(%rax)
movq -0x8(%rbp), %rax
movq 0x8(%rax), %rax
movq %rax, -0x8(%rbp)
movq -0x48(%rbp), %rax
movq %rax, -0x20(%rbp)
jmp 0x58136
movq -0x8(%rbp), %rax
movq (%rax), %rdi
movl $0x14, %esi
callq 0x55c50
movq %rax, -0x50(%rbp)
movq -0x50(%rbp), %rax
movl $0x28, 0x4(%rax)
movq -0x20(%rbp), %rcx
movq -0x50(%rbp), %rax
movq %rcx, 0x20(%rax)
movq -0x8(%rbp), %rax
movq 0x8(%rax), %rdi
movq -0x50(%rbp), %rsi
addq $0x20, %rsi
addq $0x8, %rsi
callq 0x58730
movq %rax, -0x8(%rbp)
movq -0x8(%rbp), %rdi
movl $0x29, %esi
leaq 0x14892(%rip), %rdx     # 0x6cc4f
callq 0x22eb0
movq %rax, -0x8(%rbp)
movq -0x50(%rbp), %rax
movq %rax, -0x20(%rbp)
jmp 0x58136
jmp 0x583d5
jmp 0x583d7
movq -0x20(%rbp), %rcx
movq -0x10(%rbp), %rax
movq %rcx, (%rax)
movq -0x8(%rbp), %rax
addq $0x60, %rsp
popq %rbp
retq
nopl (%rax)