c-expr.y 7.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305
  1. /* GCC-StarPU
  2. Copyright (C) 2011, 2012 Institut National de Recherche en Informatique et Automatique
  3. GCC-StarPU is free software: you can redistribute it and/or modify
  4. it under the terms of the GNU General Public License as published by
  5. the Free Software Foundation, either version 3 of the License, or
  6. (at your option) any later version.
  7. GCC-StarPU is distributed in the hope that it will be useful,
  8. but WITHOUT ANY WARRANTY; without even the implied warranty of
  9. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  10. GNU General Public License for more details.
  11. You should have received a copy of the GNU General Public License
  12. along with GCC-StarPU. If not, see <http://www.gnu.org/licenses/>. */
  13. /* Parser for simple C expressions in pragmas. */
  14. %define api.pure
  15. %parse-param { location_t loc }
  16. %parse-param { const char *pragma }
  17. %parse-param { tree *seq }
  18. %debug
  19. %{
  20. #include <starpu-gcc/config.h>
  21. #include <gcc-plugin.h>
  22. #include <plugin.h>
  23. #include <tree.h>
  24. #include <cpplib.h>
  25. #ifdef HAVE_C_FAMILY_C_COMMON_H
  26. # include <c-family/c-common.h>
  27. #elif HAVE_C_COMMON_H
  28. # include <c-common.h>
  29. #endif
  30. #ifdef HAVE_C_FAMILY_C_PRAGMA_H
  31. # include <c-family/c-pragma.h>
  32. #elif HAVE_C_PRAGMA_H
  33. # include <c-pragma.h>
  34. #endif
  35. #include <diagnostic.h>
  36. #if !HAVE_DECL_BUILD_ARRAY_REF
  37. /* This declaration is missing in GCC 4.6.1. */
  38. extern tree build_array_ref (location_t loc, tree array, tree index);
  39. #endif
  40. #define YYSTYPE tree
  41. #define YYLTYPE location_t
  42. static void
  43. yyerror (location_t loc, const char *pragma, tree *seq,
  44. char const *message)
  45. {
  46. error_at (loc, "parse error in pragma %qs: %s", pragma, message);
  47. }
  48. /* Return SOMETHING if it's a VAR_DECL, an identifier bound to a VAR_DECL,
  49. or another object; raise an error otherwise. */
  50. static tree
  51. ensure_bound (location_t loc, tree something)
  52. {
  53. gcc_assert (something != NULL_TREE);
  54. if (DECL_P (something))
  55. return something;
  56. else if (TREE_CODE (something) == IDENTIFIER_NODE)
  57. {
  58. tree var = lookup_name (something);
  59. if (var == NULL_TREE)
  60. {
  61. error_at (loc, "unbound variable %qE", something);
  62. return error_mark_node;
  63. }
  64. else
  65. return var;
  66. }
  67. return something;
  68. }
  69. static tree
  70. build_component_ref (location_t loc, tree what, tree field)
  71. {
  72. sorry ("struct field access not implemented yet"); /* XXX */
  73. return error_mark_node;
  74. }
  75. /* Interpret the string beneath CST, and return a new string constant. */
  76. static tree
  77. interpret_string (const_tree cst)
  78. {
  79. gcc_assert (TREE_CODE (cst) == STRING_CST);
  80. cpp_string input, interpreted;
  81. input.text = (unsigned char *) TREE_STRING_POINTER (cst);
  82. input.len = TREE_STRING_LENGTH (cst);
  83. bool success;
  84. success = cpp_interpret_string (parse_in, &input, 1, &interpreted,
  85. CPP_STRING);
  86. gcc_assert (success);
  87. return build_string (interpreted.len, (char *) interpreted.text);
  88. }
  89. %}
  90. %code {
  91. /* Mapping of libcpp token names to Bison-generated token names. This is
  92. not ideal but Bison cannot be told to use the `enum cpp_ttype'
  93. values. */
  94. #define STARPU_CPP_TOKENS \
  95. TK (CPP_NAME) \
  96. TK (CPP_NUMBER) \
  97. TK (CPP_AND) \
  98. TK (CPP_OPEN_SQUARE) \
  99. TK (CPP_CLOSE_SQUARE) \
  100. TK (CPP_OPEN_PAREN) \
  101. TK (CPP_CLOSE_PAREN) \
  102. TK (CPP_PLUS) \
  103. TK (CPP_MINUS) \
  104. TK (CPP_MULT) \
  105. TK (CPP_DIV) \
  106. TK (CPP_DOT) \
  107. TK (CPP_DEREF) \
  108. TK (CPP_STRING)
  109. #ifndef __cplusplus
  110. static const int cpplib_bison_token_map[] =
  111. {
  112. # define TK(x) [x] = Y ## x,
  113. STARPU_CPP_TOKENS
  114. # undef TK
  115. };
  116. #else /* __cplusplus */
  117. /* No designated initializers in C++. */
  118. static int cpplib_bison_token_map[CPP_PADDING];
  119. #endif /* __cplusplus */
  120. static int
  121. yylex (YYSTYPE *lvalp)
  122. {
  123. int ret;
  124. enum cpp_ttype type;
  125. location_t loc;
  126. #ifdef __cplusplus
  127. if (cpplib_bison_token_map[CPP_NAME] != YCPP_NAME)
  128. {
  129. /* Initialize the table. */
  130. # define TK(x) cpplib_bison_token_map[x] = Y ## x;
  131. STARPU_CPP_TOKENS
  132. # undef TK
  133. }
  134. #endif
  135. /* First check whether EOL is reached, because the EOL token needs to be
  136. left to the C parser. */
  137. type = cpp_peek_token (parse_in, 0)->type;
  138. if (type == CPP_PRAGMA_EOL)
  139. ret = -1;
  140. else
  141. {
  142. /* Tell the lexer to not concatenate adjacent strings like cpp and
  143. `pragma_lex' normally do, because we want to be able to
  144. distinguish adjacent STRING_CST. */
  145. type = c_lex_with_flags (lvalp, &loc, NULL, C_LEX_STRING_NO_JOIN);
  146. if (type == CPP_STRING)
  147. /* XXX: When using `C_LEX_STRING_NO_JOIN', `c_lex_with_flags'
  148. doesn't call `cpp_interpret_string', leaving us with an
  149. uninterpreted string (with quotes, etc.) This hack works around
  150. that. */
  151. *lvalp = interpret_string (*lvalp);
  152. if (type < sizeof cpplib_bison_token_map / sizeof cpplib_bison_token_map[0])
  153. ret = cpplib_bison_token_map[type];
  154. else
  155. ret = -1;
  156. }
  157. return ret;
  158. }
  159. }
  160. %token YCPP_NAME "identifier"
  161. %token YCPP_NUMBER "integer"
  162. %token YCPP_AND "&"
  163. %token YCPP_OPEN_SQUARE "["
  164. %token YCPP_CLOSE_SQUARE "]"
  165. %token YCPP_OPEN_PAREN "("
  166. %token YCPP_CLOSE_PAREN ")"
  167. %token YCPP_PLUS "+"
  168. %token YCPP_MINUS "-"
  169. %token YCPP_MULT "*"
  170. %token YCPP_DIV "/"
  171. %token YCPP_DOT "."
  172. %token YCPP_DEREF "->"
  173. %token YCPP_STRING "string"
  174. %% /* Grammar rules. */
  175. /* Always return a TREE_LIST rather than a raw chain, because the elements
  176. of that list may be already chained for other purposes---e.g., PARM_DECLs
  177. of a function are chained together. */
  178. sequence: expression {
  179. gcc_assert (*seq == NULL_TREE);
  180. *seq = tree_cons (NULL_TREE, $1, NULL_TREE);
  181. $$ = *seq;
  182. }
  183. | expression sequence {
  184. gcc_assert ($2 == *seq);
  185. *seq = tree_cons (NULL_TREE, $1, $2);
  186. $$ = *seq;
  187. }
  188. ;
  189. expression: binary_expression
  190. ;
  191. /* XXX: `ensure_bound' below leads to errors raised even for non-significant
  192. arguments---e.g., junk after pragma. */
  193. identifier: YCPP_NAME { $$ = ensure_bound (loc, $1); }
  194. ;
  195. binary_expression: additive_expression
  196. ;
  197. multiplicative_expression: multiplicative_expression YCPP_MULT cast_expression {
  198. $$ = build_binary_op (UNKNOWN_LOCATION, MULT_EXPR, $1, $3, 0);
  199. }
  200. | multiplicative_expression YCPP_DIV cast_expression {
  201. $$ = build_binary_op (UNKNOWN_LOCATION, TRUNC_DIV_EXPR, $1, $3, 0);
  202. }
  203. | cast_expression
  204. ;
  205. additive_expression: multiplicative_expression
  206. | additive_expression YCPP_PLUS multiplicative_expression {
  207. $$ = build_binary_op (UNKNOWN_LOCATION, PLUS_EXPR, $1, $3, 0);
  208. }
  209. | additive_expression YCPP_MINUS multiplicative_expression {
  210. $$ = build_binary_op (UNKNOWN_LOCATION, MINUS_EXPR, $1, $3, 0);
  211. }
  212. ;
  213. cast_expression: unary_expression
  214. /* XXX: No support for '(' TYPE-NAME ')' UNARY-EXPRESSION. */
  215. ;
  216. unary_expression: postfix_expression
  217. | YCPP_AND cast_expression {
  218. $$ = build_addr (ensure_bound (loc, $2), current_function_decl);
  219. }
  220. ;
  221. postfix_expression:
  222. primary_expression
  223. | postfix_expression YCPP_OPEN_SQUARE expression YCPP_CLOSE_SQUARE {
  224. #if 1
  225. /* Build the array ref with proper error checking. */
  226. $$ = build_array_ref (loc, ensure_bound (loc, $1),
  227. ensure_bound (loc, $3));
  228. #else /* TIMTOWTDI */
  229. $$ = build_indirect_ref (loc,
  230. build_binary_op (loc, PLUS_EXPR, ensure_bound (loc, $1), ensure_bound (loc, $3), 0),
  231. RO_ARRAY_INDEXING);
  232. #endif
  233. }
  234. | postfix_expression YCPP_DOT identifier {
  235. $$ = build_component_ref (loc, ensure_bound (loc, $1), $2);
  236. }
  237. | postfix_expression YCPP_DEREF identifier {
  238. $$ = build_component_ref (loc,
  239. build_indirect_ref (loc, ensure_bound (loc, $1), RO_ARRAY_INDEXING),
  240. $2);
  241. }
  242. ;
  243. primary_expression: identifier
  244. | constant
  245. | string_literal
  246. | YCPP_OPEN_PAREN expression YCPP_CLOSE_PAREN { $$ = $2; }
  247. ;
  248. constant: YCPP_NUMBER { $$ = $1; }
  249. ;
  250. string_literal: YCPP_STRING { $$ = $1; }
  251. ;
  252. %%