11f5207b7SJohn Levon #ifndef EXPRESSION_H
21f5207b7SJohn Levon #define EXPRESSION_H
31f5207b7SJohn Levon /*
41f5207b7SJohn Levon  * sparse/expression.h
51f5207b7SJohn Levon  *
61f5207b7SJohn Levon  * Copyright (C) 2003 Transmeta Corp.
71f5207b7SJohn Levon  *               2003 Linus Torvalds
81f5207b7SJohn Levon  *
91f5207b7SJohn Levon  * Permission is hereby granted, free of charge, to any person obtaining a copy
101f5207b7SJohn Levon  * of this software and associated documentation files (the "Software"), to deal
111f5207b7SJohn Levon  * in the Software without restriction, including without limitation the rights
121f5207b7SJohn Levon  * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
131f5207b7SJohn Levon  * copies of the Software, and to permit persons to whom the Software is
141f5207b7SJohn Levon  * furnished to do so, subject to the following conditions:
151f5207b7SJohn Levon  *
161f5207b7SJohn Levon  * The above copyright notice and this permission notice shall be included in
171f5207b7SJohn Levon  * all copies or substantial portions of the Software.
181f5207b7SJohn Levon  *
191f5207b7SJohn Levon  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
201f5207b7SJohn Levon  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
211f5207b7SJohn Levon  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
221f5207b7SJohn Levon  * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
231f5207b7SJohn Levon  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
241f5207b7SJohn Levon  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
251f5207b7SJohn Levon  * THE SOFTWARE.
261f5207b7SJohn Levon  *
271f5207b7SJohn Levon  * Declarations and helper functions for expression parsing.
281f5207b7SJohn Levon  */
291f5207b7SJohn Levon 
301f5207b7SJohn Levon #include "allocate.h"
311f5207b7SJohn Levon #include "lib.h"
321f5207b7SJohn Levon #include "symbol.h"
331f5207b7SJohn Levon 
341f5207b7SJohn Levon struct expression_list;
351f5207b7SJohn Levon 
361f5207b7SJohn Levon enum expression_type {
371f5207b7SJohn Levon 	EXPR_VALUE = 1,
381f5207b7SJohn Levon 	EXPR_STRING,
391f5207b7SJohn Levon 	EXPR_SYMBOL,
401f5207b7SJohn Levon 	EXPR_TYPE,
411f5207b7SJohn Levon 	EXPR_BINOP,
421f5207b7SJohn Levon 	EXPR_ASSIGNMENT,
431f5207b7SJohn Levon 	EXPR_LOGICAL,
441f5207b7SJohn Levon 	EXPR_DEREF,
451f5207b7SJohn Levon 	EXPR_PREOP,
461f5207b7SJohn Levon 	EXPR_POSTOP,
471f5207b7SJohn Levon 	EXPR_CAST,
481f5207b7SJohn Levon 	EXPR_FORCE_CAST,
491f5207b7SJohn Levon 	EXPR_IMPLIED_CAST,
501f5207b7SJohn Levon 	EXPR_SIZEOF,
511f5207b7SJohn Levon 	EXPR_ALIGNOF,
521f5207b7SJohn Levon 	EXPR_PTRSIZEOF,
531f5207b7SJohn Levon 	EXPR_CONDITIONAL,
541f5207b7SJohn Levon 	EXPR_SELECT,		// a "safe" conditional expression
551f5207b7SJohn Levon 	EXPR_STATEMENT,
561f5207b7SJohn Levon 	EXPR_CALL,
571f5207b7SJohn Levon 	EXPR_COMMA,
581f5207b7SJohn Levon 	EXPR_COMPARE,
591f5207b7SJohn Levon 	EXPR_LABEL,
601f5207b7SJohn Levon 	EXPR_INITIALIZER,	// initializer list
611f5207b7SJohn Levon 	EXPR_IDENTIFIER,	// identifier in initializer
621f5207b7SJohn Levon 	EXPR_INDEX,		// index in initializer
631f5207b7SJohn Levon 	EXPR_POS,		// position in initializer
641f5207b7SJohn Levon 	EXPR_FVALUE,
651f5207b7SJohn Levon 	EXPR_SLICE,
661f5207b7SJohn Levon 	EXPR_OFFSETOF,
67c85f09ccSJohn Levon 	EXPR_ASM_OPERAND,
681f5207b7SJohn Levon };
691f5207b7SJohn Levon 
701f5207b7SJohn Levon 
711f5207b7SJohn Levon /*
721f5207b7SJohn Levon  * Flags for tracking the promotion of constness related attributes
731f5207b7SJohn Levon  * from subexpressions to their parents.
741f5207b7SJohn Levon  *
751f5207b7SJohn Levon  * The flags are not independent as one might imply another.
761f5207b7SJohn Levon  * The implications are as follows:
771f5207b7SJohn Levon  * - CEF_INT, CEF_ENUM and
781f5207b7SJohn Levon  *   CEF_CHAR imply CEF_ICE.
791f5207b7SJohn Levon  *
801f5207b7SJohn Levon  * Use the CEF_*_SET_MASK and CEF_*_CLEAR_MASK
811f5207b7SJohn Levon  * helper macros defined below to set or clear one of these flags.
821f5207b7SJohn Levon  */
831f5207b7SJohn Levon enum constexpr_flag {
841f5207b7SJohn Levon 	CEF_NONE = 0,
851f5207b7SJohn Levon 	/*
861f5207b7SJohn Levon 	 * A constant in the sense of [6.4.4]:
871f5207b7SJohn Levon 	 * - Integer constant [6.4.4.1]
881f5207b7SJohn Levon 	 * - Floating point constant [6.4.4.2]
891f5207b7SJohn Levon 	 * - Enumeration constant [6.4.4.3]
901f5207b7SJohn Levon 	 * - Character constant [6.4.4.4]
911f5207b7SJohn Levon 	 */
921f5207b7SJohn Levon 	CEF_INT = (1 << 0),
931f5207b7SJohn Levon 	CEF_FLOAT = (1 << 1),
941f5207b7SJohn Levon 	CEF_ENUM = (1 << 2),
951f5207b7SJohn Levon 	CEF_CHAR = (1 << 3),
961f5207b7SJohn Levon 
971f5207b7SJohn Levon 	/*
981f5207b7SJohn Levon 	 * A constant expression in the sense of [6.6]:
991f5207b7SJohn Levon 	 * - integer constant expression [6.6(6)]
1001f5207b7SJohn Levon 	 * - arithmetic constant expression [6.6(8)]
1011f5207b7SJohn Levon 	 * - address constant [6.6(9)]
1021f5207b7SJohn Levon 	 */
1031f5207b7SJohn Levon 	CEF_ICE = (1 << 4),
1041f5207b7SJohn Levon 	CEF_ACE = (1 << 5),
1051f5207b7SJohn Levon 	CEF_ADDR = (1 << 6),
1061f5207b7SJohn Levon 
1071f5207b7SJohn Levon 	/* integer constant expression => arithmetic constant expression */
1081f5207b7SJohn Levon 	CEF_SET_ICE = (CEF_ICE | CEF_ACE),
1091f5207b7SJohn Levon 
1101f5207b7SJohn Levon 	/* integer constant => integer constant expression */
1111f5207b7SJohn Levon 	CEF_SET_INT = (CEF_INT | CEF_SET_ICE),
1121f5207b7SJohn Levon 
1131f5207b7SJohn Levon 	/* floating point constant => arithmetic constant expression */
1141f5207b7SJohn Levon 	CEF_SET_FLOAT = (CEF_FLOAT | CEF_ACE),
1151f5207b7SJohn Levon 
1161f5207b7SJohn Levon 	/* enumeration constant => integer constant expression */
1171f5207b7SJohn Levon 	CEF_SET_ENUM = (CEF_ENUM | CEF_SET_ICE),
1181f5207b7SJohn Levon 
1191f5207b7SJohn Levon 	/* character constant => integer constant expression */
1201f5207b7SJohn Levon 	CEF_SET_CHAR = (CEF_CHAR | CEF_SET_ICE),
1211f5207b7SJohn Levon 
1221f5207b7SJohn Levon 	/*
1231f5207b7SJohn Levon 	 * Remove any "Constant" [6.4.4] flag, but retain the "constant
1241f5207b7SJohn Levon 	 * expression" [6.6] flags.
1251f5207b7SJohn Levon 	 */
1261f5207b7SJohn Levon 	CEF_CONST_MASK = (CEF_INT | CEF_FLOAT | CEF_CHAR),
1271f5207b7SJohn Levon 
1281f5207b7SJohn Levon 	/*
1291f5207b7SJohn Levon 	 * not an integer constant expression => neither of integer,
1301f5207b7SJohn Levon 	 * enumeration and character constant
1311f5207b7SJohn Levon 	 */
1321f5207b7SJohn Levon 	CEF_CLR_ICE = (CEF_ICE | CEF_INT | CEF_ENUM | CEF_CHAR),
1331f5207b7SJohn Levon };
1341f5207b7SJohn Levon 
1351f5207b7SJohn Levon enum {
1361f5207b7SJohn Levon 	Handled = 1 << 0,
137*6523a3aaSJohn Levon 	Tmp	= 1 << 1,
138*6523a3aaSJohn Levon 	Fake	= 1 << 2,
139*6523a3aaSJohn Levon }; /* for expr->smatch_flags */
1401f5207b7SJohn Levon 
1411f5207b7SJohn Levon enum {
1421f5207b7SJohn Levon 	Taint_comma = 1,
1431f5207b7SJohn Levon }; /* for expr->taint */
1441f5207b7SJohn Levon 
1451f5207b7SJohn Levon struct expression {
1461f5207b7SJohn Levon 	enum expression_type type:8;
1471f5207b7SJohn Levon 	unsigned flags:8;
1481f5207b7SJohn Levon 	unsigned smatch_flags:16;
1491f5207b7SJohn Levon 	int op;
1501f5207b7SJohn Levon 	struct position pos;
1511f5207b7SJohn Levon 	struct symbol *ctype;
1521f5207b7SJohn Levon 	unsigned long parent;
1531f5207b7SJohn Levon 	union {
1541f5207b7SJohn Levon 		// EXPR_VALUE
1551f5207b7SJohn Levon 		struct {
1561f5207b7SJohn Levon 			unsigned long long value;
1571f5207b7SJohn Levon 			unsigned taint;
1581f5207b7SJohn Levon 		};
1591f5207b7SJohn Levon 
1601f5207b7SJohn Levon 		// EXPR_FVALUE
1611f5207b7SJohn Levon 		long double fvalue;
1621f5207b7SJohn Levon 
1631f5207b7SJohn Levon 		// EXPR_STRING
1641f5207b7SJohn Levon 		struct {
1651f5207b7SJohn Levon 			int wide;
1661f5207b7SJohn Levon 			struct string *string;
1671f5207b7SJohn Levon 		};
1681f5207b7SJohn Levon 
1691f5207b7SJohn Levon 		// EXPR_UNOP, EXPR_PREOP and EXPR_POSTOP
1701f5207b7SJohn Levon 		struct /* unop */ {
1711f5207b7SJohn Levon 			struct expression *unop;
1721f5207b7SJohn Levon 			unsigned long op_value;
1731f5207b7SJohn Levon 		};
1741f5207b7SJohn Levon 
1751f5207b7SJohn Levon 		// EXPR_SYMBOL, EXPR_TYPE
1761f5207b7SJohn Levon 		struct /* symbol_arg */ {
1771f5207b7SJohn Levon 			struct symbol *symbol;
1781f5207b7SJohn Levon 			struct ident *symbol_name;
1791f5207b7SJohn Levon 		};
1801f5207b7SJohn Levon 
1811f5207b7SJohn Levon 		// EXPR_STATEMENT
1821f5207b7SJohn Levon 		struct statement *statement;
1831f5207b7SJohn Levon 
1841f5207b7SJohn Levon 		// EXPR_BINOP, EXPR_COMMA, EXPR_COMPARE, EXPR_LOGICAL and EXPR_ASSIGNMENT
1851f5207b7SJohn Levon 		struct /* binop_arg */ {
1861f5207b7SJohn Levon 			struct expression *left, *right;
1871f5207b7SJohn Levon 		};
1881f5207b7SJohn Levon 		// EXPR_DEREF
1891f5207b7SJohn Levon 		struct /* deref_arg */ {
1901f5207b7SJohn Levon 			struct expression *deref;
1911f5207b7SJohn Levon 			struct ident *member;
1921f5207b7SJohn Levon 			int member_offset;
1931f5207b7SJohn Levon 		};
1941f5207b7SJohn Levon 		// EXPR_SLICE
1951f5207b7SJohn Levon 		struct /* slice */ {
1961f5207b7SJohn Levon 			struct expression *base;
1971f5207b7SJohn Levon 			unsigned r_bitpos, r_nrbits;
1981f5207b7SJohn Levon 		};
199c85f09ccSJohn Levon 		// EXPR_CAST, EXPR_FORCE_CAST, EXPR_IMPLIED_CAST,
200c85f09ccSJohn Levon 		// EXPR_SIZEOF, EXPR_ALIGNOF and EXPR_PTRSIZEOF
2011f5207b7SJohn Levon 		struct /* cast_arg */ {
2021f5207b7SJohn Levon 			struct symbol *cast_type;
2031f5207b7SJohn Levon 			struct expression *cast_expression;
2041f5207b7SJohn Levon 		};
2051f5207b7SJohn Levon 		// EXPR_CONDITIONAL
2061f5207b7SJohn Levon 		// EXPR_SELECT
2071f5207b7SJohn Levon 		struct /* conditional_expr */ {
2081f5207b7SJohn Levon 			struct expression *conditional, *cond_true, *cond_false;
2091f5207b7SJohn Levon 		};
2101f5207b7SJohn Levon 		// EXPR_CALL
2111f5207b7SJohn Levon 		struct /* call_expr */ {
2121f5207b7SJohn Levon 			struct expression *fn;
2131f5207b7SJohn Levon 			struct expression_list *args;
2141f5207b7SJohn Levon 		};
2151f5207b7SJohn Levon 		// EXPR_LABEL
2161f5207b7SJohn Levon 		struct /* label_expr */ {
2171f5207b7SJohn Levon 			struct symbol *label_symbol;
2181f5207b7SJohn Levon 		};
2191f5207b7SJohn Levon 		// EXPR_INITIALIZER
2201f5207b7SJohn Levon 		struct expression_list *expr_list;
2211f5207b7SJohn Levon 		// EXPR_IDENTIFIER
2221f5207b7SJohn Levon 		struct /* ident_expr */ {
2231f5207b7SJohn Levon 			int offset;
2241f5207b7SJohn Levon 			struct ident *expr_ident;
2251f5207b7SJohn Levon 			struct symbol *field;
2261f5207b7SJohn Levon 			struct expression *ident_expression;
2271f5207b7SJohn Levon 		};
2281f5207b7SJohn Levon 		// EXPR_INDEX
2291f5207b7SJohn Levon 		struct /* index_expr */ {
2301f5207b7SJohn Levon 			unsigned int idx_from, idx_to;
2311f5207b7SJohn Levon 			struct expression *idx_expression;
2321f5207b7SJohn Levon 		};
2331f5207b7SJohn Levon 		// EXPR_POS
2341f5207b7SJohn Levon 		struct /* initpos_expr */ {
2351f5207b7SJohn Levon 			unsigned int init_offset, init_nr;
2361f5207b7SJohn Levon 			struct expression *init_expr;
2371f5207b7SJohn Levon 		};
2381f5207b7SJohn Levon 		// EXPR_OFFSETOF
2391f5207b7SJohn Levon 		struct {
2401f5207b7SJohn Levon 			struct symbol *in;
2411f5207b7SJohn Levon 			struct expression *down;
2421f5207b7SJohn Levon 			union {
2431f5207b7SJohn Levon 				struct ident *ident;
2441f5207b7SJohn Levon 				struct expression *index;
2451f5207b7SJohn Levon 			};
2461f5207b7SJohn Levon 		};
247c85f09ccSJohn Levon 		// EXPR_ASM_OPERAND
248c85f09ccSJohn Levon 		struct {
249c85f09ccSJohn Levon 			struct ident *name;
250c85f09ccSJohn Levon 			struct expression *constraint;
251c85f09ccSJohn Levon 			struct expression *expr;
252c85f09ccSJohn Levon 		};
2531f5207b7SJohn Levon 	};
2541f5207b7SJohn Levon };
2551f5207b7SJohn Levon 
256c85f09ccSJohn Levon ///
257c85f09ccSJohn Levon // Constant expression values
258c85f09ccSJohn Levon // --------------------------
259c85f09ccSJohn Levon 
260c85f09ccSJohn Levon ///
261c85f09ccSJohn Levon // test if an expression evaluates to the constant ``0``.
262c85f09ccSJohn Levon // @return: ``1`` if @expr evaluate to ``0``,
263c85f09ccSJohn Levon //	``0`` otherwise.
264c85f09ccSJohn Levon int is_zero_constant(struct expression *expr);
265c85f09ccSJohn Levon 
266c85f09ccSJohn Levon ///
267c85f09ccSJohn Levon // test the compile time truth value of an expression
268c85f09ccSJohn Levon // @return:
269c85f09ccSJohn Levon //	* ``-1`` if @expr is not constant,
270c85f09ccSJohn Levon //	* ``0`` or ``1`` depending on the truth value of @expr.
2711f5207b7SJohn Levon int expr_truth_value(struct expression *expr);
272c85f09ccSJohn Levon 
2731f5207b7SJohn Levon long long get_expression_value(struct expression *);
2741f5207b7SJohn Levon long long const_expression_value(struct expression *);
2751f5207b7SJohn Levon long long get_expression_value_silent(struct expression *expr);
2761f5207b7SJohn Levon 
2771f5207b7SJohn Levon /* Expression parsing */
2781f5207b7SJohn Levon struct token *parse_expression(struct token *token, struct expression **tree);
2791f5207b7SJohn Levon struct token *conditional_expression(struct token *token, struct expression **tree);
2801f5207b7SJohn Levon struct token *primary_expression(struct token *token, struct expression **tree);
2811f5207b7SJohn Levon struct token *parens_expression(struct token *token, struct expression **expr, const char *where);
2821f5207b7SJohn Levon struct token *assignment_expression(struct token *token, struct expression **tree);
2831f5207b7SJohn Levon 
2841f5207b7SJohn Levon extern void evaluate_symbol_list(struct symbol_list *list);
2851f5207b7SJohn Levon extern struct symbol *evaluate_statement(struct statement *stmt);
2861f5207b7SJohn Levon extern struct symbol *evaluate_expression(struct expression *);
287efe51d0cSJohn Levon struct symbol *find_identifier(struct ident *ident, struct symbol_list *_list, int *offset);
2881f5207b7SJohn Levon 
2891f5207b7SJohn Levon extern int expand_symbol(struct symbol *);
2901f5207b7SJohn Levon 
alloc_expression(struct position pos,int type)2911f5207b7SJohn Levon static inline struct expression *alloc_expression(struct position pos, int type)
2921f5207b7SJohn Levon {
2931f5207b7SJohn Levon 	struct expression *expr = __alloc_expression(0);
2941f5207b7SJohn Levon 	expr->type = type;
2951f5207b7SJohn Levon 	expr->pos = pos;
2961f5207b7SJohn Levon 	expr->flags = CEF_NONE;
2971f5207b7SJohn Levon 	return expr;
2981f5207b7SJohn Levon }
2991f5207b7SJohn Levon 
alloc_const_expression(struct position pos,int value)3001f5207b7SJohn Levon static inline struct expression *alloc_const_expression(struct position pos, int value)
3011f5207b7SJohn Levon {
3021f5207b7SJohn Levon 	struct expression *expr = __alloc_expression(0);
3031f5207b7SJohn Levon 	expr->type = EXPR_VALUE;
3041f5207b7SJohn Levon 	expr->pos = pos;
3051f5207b7SJohn Levon 	expr->value = value;
3061f5207b7SJohn Levon 	expr->ctype = &int_ctype;
3071f5207b7SJohn Levon 	expr->flags = CEF_SET_INT;
3081f5207b7SJohn Levon 	return expr;
3091f5207b7SJohn Levon }
3101f5207b7SJohn Levon 
3111f5207b7SJohn Levon /* Type name parsing */
3121f5207b7SJohn Levon struct token *typename(struct token *, struct symbol **, int *);
3131f5207b7SJohn Levon 
lookup_type(struct token * token)3141f5207b7SJohn Levon static inline int lookup_type(struct token *token)
3151f5207b7SJohn Levon {
3161f5207b7SJohn Levon 	if (token->pos.type == TOKEN_IDENT) {
3171f5207b7SJohn Levon 		struct symbol *sym = lookup_symbol(token->ident, NS_SYMBOL | NS_TYPEDEF);
3181f5207b7SJohn Levon 		return sym && (sym->namespace & NS_TYPEDEF);
3191f5207b7SJohn Levon 	}
3201f5207b7SJohn Levon 	return 0;
3211f5207b7SJohn Levon }
3221f5207b7SJohn Levon 
3231f5207b7SJohn Levon /* Statement parsing */
3241f5207b7SJohn Levon struct statement *alloc_statement(struct position pos, int type);
3251f5207b7SJohn Levon struct token *initializer(struct expression **tree, struct token *token);
3261f5207b7SJohn Levon struct token *compound_statement(struct token *, struct statement *);
3271f5207b7SJohn Levon 
3281f5207b7SJohn Levon /* The preprocessor calls this 'constant_expression()' */
3291f5207b7SJohn Levon #define constant_expression(token,tree) conditional_expression(token, tree)
3301f5207b7SJohn Levon 
3311f5207b7SJohn Levon /* Cast folding of constant values.. */
3321f5207b7SJohn Levon void cast_value(struct expression *expr, struct symbol *newtype,
3331f5207b7SJohn Levon 	struct expression *old, struct symbol *oldtype);
3341f5207b7SJohn Levon 
3351f5207b7SJohn Levon #endif
336