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

	switch (token_type(token)) {
	case TOKEN_CHAR ... TOKEN_WIDE_CHAR_EMBEDDED_3:
		expr = alloc_expression(token->pos, EXPR_VALUE);
		expr->flags = CEF_SET_CHAR;
		get_char_constant(token, &expr->value);

		// TODO: handle 'u8', 'u' & 'U' prefixes.
		if (token_type(token) < TOKEN_WIDE_CHAR) {
			expr->ctype = &char_ctype;
			cast_value(expr, &int_ctype, expr);
		} else {
			expr->ctype = wchar_ctype;
		}
		token = token->next;
		break;

	case TOKEN_NUMBER:
		expr = alloc_expression(token->pos, EXPR_VALUE);
		get_number_value(expr, token); /* will see if it's an integer */
		token = token->next;
		break;

	case TOKEN_ZERO_IDENT: {
		expr = alloc_expression(token->pos, EXPR_SYMBOL);
		expr->flags = CEF_SET_INT;
		expr->ctype = &int_ctype;
		expr->symbol = &zero_int;
		expr->symbol_name = token->ident;
		token = token->next;
		break;
	}

	case TOKEN_IDENT: {
		struct symbol *sym = lookup_symbol(token->ident, NS_SYMBOL | NS_TYPEDEF);
		struct token *next = token->next;

		if (!sym) {
			sym = handle_func(token);
			if (token->ident == &__builtin_types_compatible_p_ident) {
				token = builtin_types_compatible_p_expr(token, &expr);
				break;
			}
			if (token->ident == &__builtin_offsetof_ident) {
				token = builtin_offsetof_expr(token, &expr);
				break;
			}
			if (token->ident == &_Generic_ident) {
				token = generic_selection(token->next, &expr);
				break;
			}
		} else if (sym->enum_member) {
			expr = alloc_expression(token->pos, EXPR_VALUE);
			*expr = *sym->initializer;
			/* we want the right position reported, thus the copy */
			expr->pos = token->pos;
			expr->flags = CEF_SET_ENUM;
			token = next;
			break;
		}

		expr = alloc_expression(token->pos, EXPR_SYMBOL);

		/*
		 * We support types as real first-class citizens, with type
		 * comparisons etc:
		 *
		 *	if (typeof(a) == int) ..
		 */
		if (sym && sym->namespace == NS_TYPEDEF) {
			sparse_error(token->pos, "typename in expression");
			sym = NULL;
		}
		expr->symbol_name = token->ident;
		expr->symbol = sym;

		/*
		 * A pointer to an lvalue designating a static storage
		 * duration object is an address constant [6.6(9)].
		 */
		if (sym && (sym->ctype.modifiers & (MOD_TOPLEVEL | MOD_STATIC)))
			expr->flags = CEF_ADDR;

		token = next;
		break;
	}

	case TOKEN_STRING:
	case TOKEN_WIDE_STRING:
		expr = alloc_expression(token->pos, EXPR_STRING);
		token = get_string_constant(token, expr);
		break;

	case TOKEN_SPECIAL:
		if (token->special == '(') {
			expr = alloc_expression(token->pos, EXPR_PREOP);
			expr->op = '(';
			token = parens_expression(token, &expr->unop, "in expression");
			break;
		}
		if (token->special == '[' && lookup_type(token->next)) {
			expr = alloc_expression(token->pos, EXPR_TYPE);
			token = typename(token->next, &expr->symbol, NULL);
			token = expect(token, ']', "in type expression");
			break;
		}
			
	default:
		;
	}
	*tree = expr;
	return token;
}

// Assembly:
pushq %rbp
movq %rsp, %rbp
subq $0x30, %rsp
movq %rdi, -0x8(%rbp)
movq %rsi, -0x10(%rbp)
movq $0x0, -0x18(%rbp)
movq -0x8(%rbp), %rax
movl (%rax), %eax
andl $0x3f, %eax
addl $-0x3, %eax
movl %eax, %ecx
movq %rcx, -0x30(%rbp)
subl $0xf, %eax
ja 0x56169
movq -0x30(%rbp), %rax
leaq 0x16a72(%rip), %rcx     # 0x6c800
movslq (%rcx,%rax,4), %rax
addq %rcx, %rax
jmpq *%rax
movq -0x8(%rbp), %rax
movq (%rax), %rdi
movl $0x1, %esi
callq 0x55c50
movq %rax, -0x18(%rbp)
movq -0x18(%rbp), %rax
movl (%rax), %ecx
andl $0xffff00ff, %ecx       # imm = 0xFFFF00FF
orl $0x3800, %ecx           # imm = 0x3800
movl %ecx, (%rax)
movq -0x8(%rbp), %rdi
movq -0x18(%rbp), %rsi
addq $0x20, %rsi
callq 0x60ad0
movq -0x8(%rbp), %rax
movq (%rax), %rax
andq $0x3f, %rax
cmpl $0xb, %eax
jge 0x55e06
movq -0x18(%rbp), %rax
leaq 0x3b00c(%rip), %rcx     # 0x90df8
movq %rcx, 0x10(%rax)
movq -0x18(%rbp), %rdi
movq -0x18(%rbp), %rdx
leaq 0x3bd19(%rip), %rsi     # 0x91b18
callq 0x11640
jmp 0x55e18
leaq 0x34823(%rip), %rax     # 0x8a630
movq (%rax), %rcx
movq -0x18(%rbp), %rax
movq %rcx, 0x10(%rax)
movq -0x8(%rbp), %rax
movq 0x8(%rax), %rax
movq %rax, -0x8(%rbp)
jmp 0x5616b
movq -0x8(%rbp), %rax
movq (%rax), %rdi
movl $0x1, %esi
callq 0x55c50
movq %rax, -0x18(%rbp)
movq -0x18(%rbp), %rdi
movq -0x8(%rbp), %rsi
callq 0x56180
movq -0x8(%rbp), %rax
movq 0x8(%rax), %rax
movq %rax, -0x8(%rbp)
jmp 0x5616b
movq -0x8(%rbp), %rax
movq (%rax), %rdi
movl $0x3, %esi
callq 0x55c50
movq %rax, -0x18(%rbp)
movq -0x18(%rbp), %rax
movl (%rax), %ecx
andl $0xffff00ff, %ecx       # imm = 0xFFFF00FF
orl $0x3100, %ecx           # imm = 0x3100
movl %ecx, (%rax)
movq -0x18(%rbp), %rax
leaq 0x3bc88(%rip), %rcx     # 0x91b18
movq %rcx, 0x10(%rax)
movq -0x18(%rbp), %rax
leaq 0x3e3d9(%rip), %rcx     # 0x94278
movq %rcx, 0x20(%rax)
movq -0x8(%rbp), %rax
movq 0x10(%rax), %rcx
movq -0x18(%rbp), %rax
movq %rcx, 0x28(%rax)
movq -0x8(%rbp), %rax
movq 0x8(%rax), %rax
movq %rax, -0x8(%rbp)
jmp 0x5616b
movq -0x8(%rbp), %rax
movq 0x10(%rax), %rdi
movl $0x12, %esi
callq 0x3f450
movq %rax, -0x20(%rbp)
movq -0x8(%rbp), %rax
movq 0x8(%rax), %rax
movq %rax, -0x28(%rbp)
cmpq $0x0, -0x20(%rbp)
jne 0x55f79
movq -0x8(%rbp), %rdi
callq 0x566a0
movq %rax, -0x20(%rbp)
movq -0x8(%rbp), %rax
leaq 0x3438f(%rip), %rcx     # 0x8a298
cmpq %rcx, 0x10(%rax)
jne 0x55f25
movq -0x8(%rbp), %rdi
leaq -0x18(%rbp), %rsi
callq 0x568d0
movq %rax, -0x8(%rbp)
jmp 0x5616b
movq -0x8(%rbp), %rax
leaq 0x34398(%rip), %rcx     # 0x8a2c8
cmpq %rcx, 0x10(%rax)
jne 0x55f4c
movq -0x8(%rbp), %rdi
leaq -0x18(%rbp), %rsi
callq 0x56a10
movq %rax, -0x8(%rbp)
jmp 0x5616b
movq -0x8(%rbp), %rax
leaq 0x341c9(%rip), %rcx     # 0x8a120
cmpq %rcx, 0x10(%rax)
jne 0x55f77
movq -0x8(%rbp), %rax
movq 0x8(%rax), %rdi
leaq -0x18(%rbp), %rsi
callq 0x56ce0
movq %rax, -0x8(%rbp)
jmp 0x5616b
jmp 0x55fe9
movq -0x20(%rbp), %rax
movl (%rax), %eax
shrl $0x14, %eax
andl $0x1, %eax
cmpb $0x0, %al
je 0x55fe7
movq -0x8(%rbp), %rax
movq (%rax), %rdi
movl $0x1, %esi
callq 0x55c50
movq %rax, -0x18(%rbp)
movq -0x18(%rbp), %rdi
movq -0x20(%rbp), %rax
movq 0xb0(%rax), %rsi
movl $0x40, %edx
callq 0x111d0
movq -0x18(%rbp), %rax
movq -0x8(%rbp), %rcx
movq (%rcx), %rcx
movq %rcx, 0x8(%rax)
movq -0x18(%rbp), %rax
movl (%rax), %ecx
andl $0xffff00ff, %ecx       # imm = 0xFFFF00FF
orl $0x3400, %ecx           # imm = 0x3400
movl %ecx, (%rax)
movq -0x28(%rbp), %rax
movq %rax, -0x8(%rbp)
jmp 0x5616b
jmp 0x55fe9
movq -0x8(%rbp), %rax
movq (%rax), %rdi
movl $0x3, %esi
callq 0x55c50
movq %rax, -0x18(%rbp)
cmpq $0x0, -0x20(%rbp)
je 0x56035
movq -0x20(%rbp), %rax
movl (%rax), %eax
shrl $0x8, %eax
andl $0x1ff, %eax            # imm = 0x1FF
cmpl $0x2, %eax
jne 0x56035
movq -0x8(%rbp), %rax
movq (%rax), %rdi
leaq 0x168a9(%rip), %rsi     # 0x6c8cf
movb $0x0, %al
callq 0x16f90
movq $0x0, -0x20(%rbp)
movq -0x8(%rbp), %rax
movq 0x10(%rax), %rcx
movq -0x18(%rbp), %rax
movq %rcx, 0x28(%rax)
movq -0x20(%rbp), %rcx
movq -0x18(%rbp), %rax
movq %rcx, 0x20(%rax)
cmpq $0x0, -0x20(%rbp)
je 0x5607e
movq -0x20(%rbp), %rax
movq 0x68(%rax), %rax
andq $0x14, %rax
cmpq $0x0, %rax
je 0x5607e
movq -0x18(%rbp), %rax
movl (%rax), %ecx
andl $0xffff00ff, %ecx       # imm = 0xFFFF00FF
orl $0x4000, %ecx           # imm = 0x4000
movl %ecx, (%rax)
movq -0x28(%rbp), %rax
movq %rax, -0x8(%rbp)
jmp 0x5616b
movq -0x8(%rbp), %rax
movq (%rax), %rdi
movl $0x2, %esi
callq 0x55c50
movq %rax, -0x18(%rbp)
movq -0x8(%rbp), %rdi
movq -0x18(%rbp), %rsi
callq 0x60e80
movq %rax, -0x8(%rbp)
jmp 0x5616b
movq -0x8(%rbp), %rax
cmpl $0x28, 0x10(%rax)
jne 0x560fe
movq -0x8(%rbp), %rax
movq (%rax), %rdi
movl $0x9, %esi
callq 0x55c50
movq %rax, -0x18(%rbp)
movq -0x18(%rbp), %rax
movl $0x28, 0x4(%rax)
movq -0x8(%rbp), %rdi
movq -0x18(%rbp), %rsi
addq $0x20, %rsi
leaq 0x167e5(%rip), %rdx     # 0x6c8d8
callq 0x55b00
movq %rax, -0x8(%rbp)
jmp 0x5616b
movq -0x8(%rbp), %rax
cmpl $0x5b, 0x10(%rax)
jne 0x56167
movq -0x8(%rbp), %rax
movq 0x8(%rax), %rdi
callq 0x56ec0
cmpl $0x0, %eax
je 0x56167
movq -0x8(%rbp), %rax
movq (%rax), %rdi
movl $0x4, %esi
callq 0x55c50
movq %rax, -0x18(%rbp)
movq -0x8(%rbp), %rax
movq 0x8(%rax), %rdi
movq -0x18(%rbp), %rsi
addq $0x20, %rsi
xorl %eax, %eax
movl %eax, %edx
callq 0x23160
movq %rax, -0x8(%rbp)
movq -0x8(%rbp), %rdi
movl $0x5d, %esi
leaq 0x1678a(%rip), %rdx     # 0x6c8e6
callq 0x22eb0
movq %rax, -0x8(%rbp)
jmp 0x5616b
jmp 0x56169
jmp 0x5616b
movq -0x18(%rbp), %rcx
movq -0x10(%rbp), %rax
movq %rcx, (%rax)
movq -0x8(%rbp), %rax
addq $0x30, %rsp
popq %rbp
retq