123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305 |
- /* GCC-StarPU
- Copyright (C) 2011, 2012 Institut National de Recherche en Informatique et Automatique
- GCC-StarPU is free software: you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation, either version 3 of the License, or
- (at your option) any later version.
- GCC-StarPU is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
- You should have received a copy of the GNU General Public License
- along with GCC-StarPU. If not, see <http://www.gnu.org/licenses/>. */
- /* Parser for simple C expressions in pragmas. */
- %define api.pure
- %parse-param { location_t loc }
- %parse-param { const char *pragma }
- %parse-param { tree *seq }
- %debug
- %{
- #include <starpu-gcc/config.h>
- #include <gcc-plugin.h>
- #include <plugin.h>
- #include <tree.h>
- #include <cpplib.h>
- #ifdef HAVE_C_FAMILY_C_COMMON_H
- # include <c-family/c-common.h>
- #elif HAVE_C_COMMON_H
- # include <c-common.h>
- #endif
- #ifdef HAVE_C_FAMILY_C_PRAGMA_H
- # include <c-family/c-pragma.h>
- #elif HAVE_C_PRAGMA_H
- # include <c-pragma.h>
- #endif
- #include <diagnostic.h>
- #if !HAVE_DECL_BUILD_ARRAY_REF
- /* This declaration is missing in GCC 4.6.1. */
- extern tree build_array_ref (location_t loc, tree array, tree index);
- #endif
- #define YYSTYPE tree
- #define YYLTYPE location_t
- static void
- yyerror (location_t loc, const char *pragma, tree *seq,
- char const *message)
- {
- error_at (loc, "parse error in pragma %qs: %s", pragma, message);
- }
- /* Return SOMETHING if it's a VAR_DECL, an identifier bound to a VAR_DECL,
- or another object; raise an error otherwise. */
- static tree
- ensure_bound (location_t loc, tree something)
- {
- gcc_assert (something != NULL_TREE);
- if (DECL_P (something))
- return something;
- else if (TREE_CODE (something) == IDENTIFIER_NODE)
- {
- tree var = lookup_name (something);
- if (var == NULL_TREE)
- {
- error_at (loc, "unbound variable %qE", something);
- return error_mark_node;
- }
- else
- return var;
- }
- return something;
- }
- static tree
- build_component_ref (location_t loc, tree what, tree field)
- {
- sorry ("struct field access not implemented yet"); /* XXX */
- return error_mark_node;
- }
- /* Interpret the string beneath CST, and return a new string constant. */
- static tree
- interpret_string (const_tree cst)
- {
- gcc_assert (TREE_CODE (cst) == STRING_CST);
- cpp_string input, interpreted;
- input.text = (unsigned char *) TREE_STRING_POINTER (cst);
- input.len = TREE_STRING_LENGTH (cst);
- bool success;
- success = cpp_interpret_string (parse_in, &input, 1, &interpreted,
- CPP_STRING);
- gcc_assert (success);
- return build_string (interpreted.len, (char *) interpreted.text);
- }
- %}
- %code {
- /* Mapping of libcpp token names to Bison-generated token names. This is
- not ideal but Bison cannot be told to use the `enum cpp_ttype'
- values. */
- #define STARPU_CPP_TOKENS \
- TK (CPP_NAME) \
- TK (CPP_NUMBER) \
- TK (CPP_AND) \
- TK (CPP_OPEN_SQUARE) \
- TK (CPP_CLOSE_SQUARE) \
- TK (CPP_OPEN_PAREN) \
- TK (CPP_CLOSE_PAREN) \
- TK (CPP_PLUS) \
- TK (CPP_MINUS) \
- TK (CPP_MULT) \
- TK (CPP_DIV) \
- TK (CPP_DOT) \
- TK (CPP_DEREF) \
- TK (CPP_STRING)
- #ifndef __cplusplus
- static const int cpplib_bison_token_map[] =
- {
- # define TK(x) [x] = Y ## x,
- STARPU_CPP_TOKENS
- # undef TK
- };
- #else /* __cplusplus */
- /* No designated initializers in C++. */
- static int cpplib_bison_token_map[CPP_PADDING];
- #endif /* __cplusplus */
- static int
- yylex (YYSTYPE *lvalp)
- {
- int ret;
- enum cpp_ttype type;
- location_t loc;
- #ifdef __cplusplus
- if (cpplib_bison_token_map[CPP_NAME] != YCPP_NAME)
- {
- /* Initialize the table. */
- # define TK(x) cpplib_bison_token_map[x] = Y ## x;
- STARPU_CPP_TOKENS
- # undef TK
- }
- #endif
- /* First check whether EOL is reached, because the EOL token needs to be
- left to the C parser. */
- type = cpp_peek_token (parse_in, 0)->type;
- if (type == CPP_PRAGMA_EOL)
- ret = -1;
- else
- {
- /* Tell the lexer to not concatenate adjacent strings like cpp and
- `pragma_lex' normally do, because we want to be able to
- distinguish adjacent STRING_CST. */
- type = c_lex_with_flags (lvalp, &loc, NULL, C_LEX_STRING_NO_JOIN);
- if (type == CPP_STRING)
- /* XXX: When using `C_LEX_STRING_NO_JOIN', `c_lex_with_flags'
- doesn't call `cpp_interpret_string', leaving us with an
- uninterpreted string (with quotes, etc.) This hack works around
- that. */
- *lvalp = interpret_string (*lvalp);
- if (type < sizeof cpplib_bison_token_map / sizeof cpplib_bison_token_map[0])
- ret = cpplib_bison_token_map[type];
- else
- ret = -1;
- }
- return ret;
- }
- }
- %token YCPP_NAME "identifier"
- %token YCPP_NUMBER "integer"
- %token YCPP_AND "&"
- %token YCPP_OPEN_SQUARE "["
- %token YCPP_CLOSE_SQUARE "]"
- %token YCPP_OPEN_PAREN "("
- %token YCPP_CLOSE_PAREN ")"
- %token YCPP_PLUS "+"
- %token YCPP_MINUS "-"
- %token YCPP_MULT "*"
- %token YCPP_DIV "/"
- %token YCPP_DOT "."
- %token YCPP_DEREF "->"
- %token YCPP_STRING "string"
- %% /* Grammar rules. */
- /* Always return a TREE_LIST rather than a raw chain, because the elements
- of that list may be already chained for other purposes---e.g., PARM_DECLs
- of a function are chained together. */
- sequence: expression {
- gcc_assert (*seq == NULL_TREE);
- *seq = tree_cons (NULL_TREE, $1, NULL_TREE);
- $$ = *seq;
- }
- | expression sequence {
- gcc_assert ($2 == *seq);
- *seq = tree_cons (NULL_TREE, $1, $2);
- $$ = *seq;
- }
- ;
- expression: binary_expression
- ;
- /* XXX: `ensure_bound' below leads to errors raised even for non-significant
- arguments---e.g., junk after pragma. */
- identifier: YCPP_NAME { $$ = ensure_bound (loc, $1); }
- ;
- binary_expression: additive_expression
- ;
- multiplicative_expression: multiplicative_expression YCPP_MULT cast_expression {
- $$ = build_binary_op (UNKNOWN_LOCATION, MULT_EXPR, $1, $3, 0);
- }
- | multiplicative_expression YCPP_DIV cast_expression {
- $$ = build_binary_op (UNKNOWN_LOCATION, TRUNC_DIV_EXPR, $1, $3, 0);
- }
- | cast_expression
- ;
- additive_expression: multiplicative_expression
- | additive_expression YCPP_PLUS multiplicative_expression {
- $$ = build_binary_op (UNKNOWN_LOCATION, PLUS_EXPR, $1, $3, 0);
- }
- | additive_expression YCPP_MINUS multiplicative_expression {
- $$ = build_binary_op (UNKNOWN_LOCATION, MINUS_EXPR, $1, $3, 0);
- }
- ;
- cast_expression: unary_expression
- /* XXX: No support for '(' TYPE-NAME ')' UNARY-EXPRESSION. */
- ;
- unary_expression: postfix_expression
- | YCPP_AND cast_expression {
- $$ = build_addr (ensure_bound (loc, $2), current_function_decl);
- }
- ;
- postfix_expression:
- primary_expression
- | postfix_expression YCPP_OPEN_SQUARE expression YCPP_CLOSE_SQUARE {
- #if 1
- /* Build the array ref with proper error checking. */
- $$ = build_array_ref (loc, ensure_bound (loc, $1),
- ensure_bound (loc, $3));
- #else /* TIMTOWTDI */
- $$ = build_indirect_ref (loc,
- build_binary_op (loc, PLUS_EXPR, ensure_bound (loc, $1), ensure_bound (loc, $3), 0),
- RO_ARRAY_INDEXING);
- #endif
- }
- | postfix_expression YCPP_DOT identifier {
- $$ = build_component_ref (loc, ensure_bound (loc, $1), $2);
- }
- | postfix_expression YCPP_DEREF identifier {
- $$ = build_component_ref (loc,
- build_indirect_ref (loc, ensure_bound (loc, $1), RO_ARRAY_INDEXING),
- $2);
- }
- ;
- primary_expression: identifier
- | constant
- | string_literal
- | YCPP_OPEN_PAREN expression YCPP_CLOSE_PAREN { $$ = $2; }
- ;
- constant: YCPP_NUMBER { $$ = $1; }
- ;
- string_literal: YCPP_STRING { $$ = $1; }
- ;
- %%
|