| #ifndef EXPRESSION_H |
| #define EXPRESSION_H |
| /* |
| * sparse/expression.h |
| * |
| * Copyright (C) 2003 Transmeta Corp. |
| * 2003 Linus Torvalds |
| * |
| * Permission is hereby granted, free of charge, to any person obtaining a copy |
| * of this software and associated documentation files (the "Software"), to deal |
| * in the Software without restriction, including without limitation the rights |
| * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell |
| * copies of the Software, and to permit persons to whom the Software is |
| * furnished to do so, subject to the following conditions: |
| * |
| * The above copyright notice and this permission notice shall be included in |
| * all copies or substantial portions of the Software. |
| * |
| * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR |
| * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, |
| * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE |
| * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER |
| * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, |
| * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN |
| * THE SOFTWARE. |
| * |
| * Declarations and helper functions for expression parsing. |
| */ |
| |
| #include "allocate.h" |
| #include "lib.h" |
| #include "symbol.h" |
| |
| struct expression_list; |
| |
| enum expression_type { |
| EXPR_VALUE = 1, |
| EXPR_STRING, |
| EXPR_SYMBOL, |
| EXPR_TYPE, |
| EXPR_BINOP, |
| EXPR_ASSIGNMENT, |
| EXPR_LOGICAL, |
| EXPR_DEREF, |
| EXPR_PREOP, |
| EXPR_POSTOP, |
| EXPR_CAST, |
| EXPR_FORCE_CAST, |
| EXPR_IMPLIED_CAST, |
| EXPR_SIZEOF, |
| EXPR_ALIGNOF, |
| EXPR_PTRSIZEOF, |
| EXPR_CONDITIONAL, |
| EXPR_SELECT, // a "safe" conditional expression |
| EXPR_STATEMENT, |
| EXPR_CALL, |
| EXPR_COMMA, |
| EXPR_COMPARE, |
| EXPR_LABEL, |
| EXPR_INITIALIZER, // initializer list |
| EXPR_IDENTIFIER, // identifier in initializer |
| EXPR_INDEX, // index in initializer |
| EXPR_POS, // position in initializer |
| EXPR_FVALUE, |
| EXPR_SLICE, |
| EXPR_OFFSETOF, |
| EXPR_ASM_OPERAND, |
| }; |
| |
| |
| /* |
| * Flags for tracking the promotion of constness related attributes |
| * from subexpressions to their parents. |
| * |
| * The flags are not independent as one might imply another. |
| * The implications are as follows: |
| * - CEF_INT, CEF_ENUM and |
| * CEF_CHAR imply CEF_ICE. |
| * |
| * Use the CEF_*_SET_MASK and CEF_*_CLEAR_MASK |
| * helper macros defined below to set or clear one of these flags. |
| */ |
| enum constexpr_flag { |
| CEF_NONE = 0, |
| /* |
| * A constant in the sense of [6.4.4]: |
| * - Integer constant [6.4.4.1] |
| * - Floating point constant [6.4.4.2] |
| * - Enumeration constant [6.4.4.3] |
| * - Character constant [6.4.4.4] |
| */ |
| CEF_INT = (1 << 0), |
| CEF_FLOAT = (1 << 1), |
| CEF_ENUM = (1 << 2), |
| CEF_CHAR = (1 << 3), |
| |
| /* |
| * A constant expression in the sense of [6.6]: |
| * - integer constant expression [6.6(6)] |
| * - arithmetic constant expression [6.6(8)] |
| * - address constant [6.6(9)] |
| */ |
| CEF_ICE = (1 << 4), |
| CEF_ACE = (1 << 5), |
| CEF_ADDR = (1 << 6), |
| |
| /* integer constant expression => arithmetic constant expression */ |
| CEF_SET_ICE = (CEF_ICE | CEF_ACE), |
| |
| /* integer constant => integer constant expression */ |
| CEF_SET_INT = (CEF_INT | CEF_SET_ICE), |
| |
| /* floating point constant => arithmetic constant expression */ |
| CEF_SET_FLOAT = (CEF_FLOAT | CEF_ACE), |
| |
| /* enumeration constant => integer constant expression */ |
| CEF_SET_ENUM = (CEF_ENUM | CEF_SET_ICE), |
| |
| /* character constant => integer constant expression */ |
| CEF_SET_CHAR = (CEF_CHAR | CEF_SET_ICE), |
| |
| /* |
| * Remove any "Constant" [6.4.4] flag, but retain the "constant |
| * expression" [6.6] flags. |
| */ |
| CEF_CONST_MASK = (CEF_INT | CEF_FLOAT | CEF_CHAR), |
| |
| /* |
| * not an integer constant expression => neither of integer, |
| * enumeration and character constant |
| */ |
| CEF_CLR_ICE = (CEF_ICE | CEF_INT | CEF_ENUM | CEF_CHAR), |
| }; |
| |
| enum { |
| Taint_comma = 1, |
| }; /* for expr->taint */ |
| |
| struct expression { |
| enum expression_type type:8; |
| unsigned flags:8; |
| int op; |
| struct position pos; |
| struct symbol *ctype; |
| union { |
| // EXPR_VALUE |
| struct { |
| unsigned long long value; |
| unsigned taint; |
| }; |
| |
| // EXPR_FVALUE |
| long double fvalue; |
| |
| // EXPR_STRING |
| struct { |
| int wide; |
| struct string *string; |
| }; |
| |
| // EXPR_UNOP, EXPR_PREOP and EXPR_POSTOP |
| struct /* unop */ { |
| struct expression *unop; |
| unsigned long op_value; |
| }; |
| |
| // EXPR_SYMBOL, EXPR_TYPE |
| struct /* symbol_arg */ { |
| struct symbol *symbol; |
| struct ident *symbol_name; |
| }; |
| |
| // EXPR_STATEMENT |
| struct statement *statement; |
| |
| // EXPR_BINOP, EXPR_COMMA, EXPR_COMPARE, EXPR_LOGICAL and EXPR_ASSIGNMENT |
| struct /* binop_arg */ { |
| struct expression *left, *right; |
| }; |
| // EXPR_DEREF |
| struct /* deref_arg */ { |
| struct expression *deref; |
| struct ident *member; |
| }; |
| // EXPR_SLICE |
| struct /* slice */ { |
| struct expression *base; |
| unsigned r_bitpos, r_nrbits; |
| }; |
| // EXPR_CAST, EXPR_FORCE_CAST, EXPR_IMPLIED_CAST, |
| // EXPR_SIZEOF, EXPR_ALIGNOF and EXPR_PTRSIZEOF |
| struct /* cast_arg */ { |
| struct symbol *cast_type; |
| struct expression *cast_expression; |
| }; |
| // EXPR_CONDITIONAL |
| // EXPR_SELECT |
| struct /* conditional_expr */ { |
| struct expression *conditional, *cond_true, *cond_false; |
| }; |
| // EXPR_CALL |
| struct /* call_expr */ { |
| struct expression *fn; |
| struct expression_list *args; |
| }; |
| // EXPR_LABEL |
| struct /* label_expr */ { |
| struct symbol *label_symbol; |
| }; |
| // EXPR_INITIALIZER |
| struct expression_list *expr_list; |
| // EXPR_IDENTIFIER |
| struct /* ident_expr */ { |
| int offset; |
| struct ident *expr_ident; |
| struct symbol *field; |
| struct expression *ident_expression; |
| }; |
| // EXPR_INDEX |
| struct /* index_expr */ { |
| unsigned int idx_from, idx_to; |
| struct expression *idx_expression; |
| }; |
| // EXPR_POS |
| struct /* initpos_expr */ { |
| unsigned int init_offset, init_nr; |
| struct expression *init_expr; |
| }; |
| // EXPR_OFFSETOF |
| struct { |
| struct symbol *in; |
| struct expression *down; |
| union { |
| struct ident *ident; |
| struct expression *index; |
| }; |
| }; |
| // EXPR_ASM_OPERAND |
| struct { |
| struct ident *name; |
| struct expression *constraint; |
| struct expression *expr; |
| }; |
| }; |
| }; |
| |
| /// |
| // Constant expression values |
| // -------------------------- |
| |
| /// |
| // test if an expression evaluates to the constant ``0``. |
| // @return: ``1`` if @expr evaluate to ``0``, |
| // ``0`` otherwise. |
| int is_zero_constant(struct expression *expr); |
| |
| /// |
| // test the compile time truth value of an expression |
| // @return: |
| // * ``-1`` if @expr is not constant, |
| // * ``0`` or ``1`` depending on the truth value of @expr. |
| int expr_truth_value(struct expression *expr); |
| |
| long long get_expression_value(struct expression *); |
| long long const_expression_value(struct expression *); |
| long long get_expression_value_silent(struct expression *expr); |
| |
| /* Expression parsing */ |
| struct token *parse_expression(struct token *token, struct expression **tree); |
| struct token *conditional_expression(struct token *token, struct expression **tree); |
| struct token *primary_expression(struct token *token, struct expression **tree); |
| struct token *parens_expression(struct token *token, struct expression **expr, const char *where); |
| struct token *assignment_expression(struct token *token, struct expression **tree); |
| |
| extern int expand_symbol(struct symbol *); |
| |
| static inline struct expression *alloc_expression(struct position pos, int type) |
| { |
| struct expression *expr = __alloc_expression(0); |
| expr->type = type; |
| expr->pos = pos; |
| expr->flags = CEF_NONE; |
| return expr; |
| } |
| |
| static inline struct expression *alloc_const_expression(struct position pos, int value) |
| { |
| struct expression *expr = __alloc_expression(0); |
| expr->type = EXPR_VALUE; |
| expr->pos = pos; |
| expr->value = value; |
| expr->ctype = &int_ctype; |
| expr->flags = CEF_SET_INT; |
| return expr; |
| } |
| |
| /* Type name parsing */ |
| struct token *typename(struct token *, struct symbol **, int *); |
| |
| static inline int lookup_type(struct token *token) |
| { |
| if (token->pos.type == TOKEN_IDENT) { |
| struct symbol *sym = lookup_symbol(token->ident, NS_SYMBOL | NS_TYPEDEF); |
| return sym && (sym->namespace & NS_TYPEDEF); |
| } |
| return 0; |
| } |
| |
| /* Statement parsing */ |
| struct statement *alloc_statement(struct position pos, int type); |
| struct token *initializer(struct expression **tree, struct token *token); |
| struct token *compound_statement(struct token *, struct statement *); |
| |
| /* The preprocessor calls this 'constant_expression()' */ |
| #define constant_expression(token,tree) conditional_expression(token, tree) |
| |
| /* Cast folding of constant values.. */ |
| void cast_value(struct expression *expr, struct symbol *newtype, |
| struct expression *old, struct symbol *oldtype); |
| |
| #endif |