1 | /* Parser for GIMPLE. |
2 | Copyright (C) 2016-2017 Free Software Foundation, Inc. |
3 | |
4 | This file is part of GCC. |
5 | |
6 | GCC is free software; you can redistribute it and/or modify it under |
7 | the terms of the GNU General Public License as published by the Free |
8 | Software Foundation; either version 3, or (at your option) any later |
9 | version. |
10 | |
11 | GCC is distributed in the hope that it will be useful, but WITHOUT ANY |
12 | WARRANTY; without even the implied warranty of MERCHANTABILITY or |
13 | FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License |
14 | for more details. |
15 | |
16 | You should have received a copy of the GNU General Public License |
17 | along with GCC; see the file COPYING3. If not see |
18 | <http://www.gnu.org/licenses/>. */ |
19 | |
20 | #include "config.h" |
21 | #include "system.h" |
22 | #include "coretypes.h" |
23 | #include "target.h" |
24 | #include "function.h" |
25 | #include "c-tree.h" |
26 | #include "timevar.h" |
27 | #include "stringpool.h" |
28 | #include "cgraph.h" |
29 | #include "attribs.h" |
30 | #include "stor-layout.h" |
31 | #include "varasm.h" |
32 | #include "trans-mem.h" |
33 | #include "c-family/c-pragma.h" |
34 | #include "c-lang.h" |
35 | #include "c-family/c-objc.h" |
36 | #include "plugin.h" |
37 | #include "builtins.h" |
38 | #include "gomp-constants.h" |
39 | #include "c-family/c-indentation.h" |
40 | #include "gimple-expr.h" |
41 | #include "context.h" |
42 | #include "gcc-rich-location.h" |
43 | #include "c-parser.h" |
44 | #include "tree-vrp.h" |
45 | #include "tree-pass.h" |
46 | #include "tree-pretty-print.h" |
47 | #include "tree.h" |
48 | #include "basic-block.h" |
49 | #include "gimple.h" |
50 | #include "gimple-pretty-print.h" |
51 | #include "tree-ssa.h" |
52 | #include "pass_manager.h" |
53 | #include "tree-ssanames.h" |
54 | #include "gimple-ssa.h" |
55 | #include "tree-dfa.h" |
56 | |
57 | |
58 | /* Gimple parsing functions. */ |
59 | static bool c_parser_gimple_compound_statement (c_parser *, gimple_seq *); |
60 | static void c_parser_gimple_label (c_parser *, gimple_seq *); |
61 | static void c_parser_gimple_statement (c_parser *, gimple_seq *); |
62 | static struct c_expr c_parser_gimple_binary_expression (c_parser *); |
63 | static struct c_expr c_parser_gimple_unary_expression (c_parser *); |
64 | static struct c_expr c_parser_gimple_postfix_expression (c_parser *); |
65 | static struct c_expr c_parser_gimple_postfix_expression_after_primary (c_parser *, |
66 | location_t, |
67 | struct c_expr); |
68 | static void c_parser_gimple_declaration (c_parser *); |
69 | static void c_parser_gimple_goto_stmt (location_t, tree, gimple_seq *); |
70 | static void c_parser_gimple_if_stmt (c_parser *, gimple_seq *); |
71 | static void c_parser_gimple_switch_stmt (c_parser *, gimple_seq *); |
72 | static void c_parser_gimple_return_stmt (c_parser *, gimple_seq *); |
73 | static void c_finish_gimple_return (location_t, tree); |
74 | static tree c_parser_gimple_paren_condition (c_parser *); |
75 | static void c_parser_gimple_expr_list (c_parser *, vec<tree> *); |
76 | |
77 | |
78 | /* Parse the body of a function declaration marked with "__GIMPLE". */ |
79 | |
80 | void |
81 | c_parser_parse_gimple_body (c_parser *parser) |
82 | { |
83 | gimple_seq seq = NULL; |
84 | gimple_seq body = NULL; |
85 | tree stmt = push_stmt_list (); |
86 | push_scope (); |
87 | location_t loc1 = c_parser_peek_token (parser)->location; |
88 | |
89 | init_tree_ssa (cfun); |
90 | |
91 | if (! c_parser_gimple_compound_statement (parser, &seq)) |
92 | { |
93 | gimple *ret = gimple_build_return (NULL); |
94 | gimple_seq_add_stmt (&seq, ret); |
95 | } |
96 | |
97 | tree block = pop_scope (); |
98 | stmt = pop_stmt_list (stmt); |
99 | stmt = c_build_bind_expr (loc1, block, stmt); |
100 | |
101 | block = DECL_INITIAL (current_function_decl); |
102 | BLOCK_SUBBLOCKS (block) = NULL_TREE; |
103 | BLOCK_CHAIN (block) = NULL_TREE; |
104 | TREE_ASM_WRITTEN (block) = 1; |
105 | |
106 | gbind *bind_stmt = gimple_build_bind (BIND_EXPR_VARS (stmt), NULL, |
107 | BIND_EXPR_BLOCK (stmt)); |
108 | gimple_bind_set_body (bind_stmt, seq); |
109 | gimple_seq_add_stmt (&body, bind_stmt); |
110 | gimple_set_body (current_function_decl, body); |
111 | |
112 | /* While we have SSA names in the IL we do not have a CFG built yet |
113 | and PHIs are represented using a PHI internal function. We do |
114 | have lowered control flow and exception handling (well, we do not |
115 | have parser support for EH yet). But as we still have BINDs |
116 | we have to go through lowering again. */ |
117 | cfun->curr_properties = PROP_gimple_any; |
118 | |
119 | dump_function (TDI_gimple, current_function_decl); |
120 | } |
121 | |
122 | /* Parse a compound statement in gimple function body. |
123 | |
124 | gimple-statement: |
125 | gimple-statement |
126 | gimple-declaration-statement |
127 | gimple-if-statement |
128 | gimple-switch-statement |
129 | gimple-labeled-statement |
130 | gimple-expression-statement |
131 | gimple-goto-statement |
132 | gimple-phi-statement |
133 | gimple-return-statement |
134 | */ |
135 | |
136 | static bool |
137 | c_parser_gimple_compound_statement (c_parser *parser, gimple_seq *seq) |
138 | { |
139 | bool return_p = false; |
140 | |
141 | if (! c_parser_require (parser, CPP_OPEN_BRACE, "expected %<{%>" )) |
142 | return false; |
143 | |
144 | /* A compund statement starts with optional declarations. */ |
145 | while (c_parser_next_tokens_start_declaration (parser)) |
146 | { |
147 | c_parser_gimple_declaration (parser); |
148 | if (! c_parser_require (parser, CPP_SEMICOLON, "expected %<;%>" )) |
149 | return false; |
150 | } |
151 | |
152 | while (c_parser_next_token_is_not (parser, CPP_CLOSE_BRACE)) |
153 | { |
154 | if (c_parser_error (parser)) |
155 | { |
156 | c_parser_skip_until_found (parser, CPP_CLOSE_BRACE, NULL); |
157 | return return_p; |
158 | } |
159 | else if (c_parser_next_token_is (parser, CPP_EOF)) |
160 | { |
161 | c_parser_error (parser, "expected declaration or statement" ); |
162 | return return_p; |
163 | } |
164 | |
165 | switch (c_parser_peek_token (parser)->type) |
166 | { |
167 | case CPP_KEYWORD: |
168 | switch (c_parser_peek_token (parser)->keyword) |
169 | { |
170 | case RID_IF: |
171 | c_parser_gimple_if_stmt (parser, seq); |
172 | break; |
173 | case RID_SWITCH: |
174 | c_parser_gimple_switch_stmt (parser, seq); |
175 | break; |
176 | case RID_GOTO: |
177 | { |
178 | location_t loc = c_parser_peek_token (parser)->location; |
179 | c_parser_consume_token (parser); |
180 | if (c_parser_next_token_is (parser, CPP_NAME)) |
181 | { |
182 | c_parser_gimple_goto_stmt (loc, |
183 | c_parser_peek_token |
184 | (parser)->value, |
185 | seq); |
186 | c_parser_consume_token (parser); |
187 | if (! c_parser_require (parser, CPP_SEMICOLON, |
188 | "expected %<;%>" )) |
189 | return return_p; |
190 | } |
191 | } |
192 | break; |
193 | case RID_RETURN: |
194 | return_p = true; |
195 | c_parser_gimple_return_stmt (parser, seq); |
196 | if (! c_parser_require (parser, CPP_SEMICOLON, |
197 | "expected %<;%>" )) |
198 | return return_p; |
199 | break; |
200 | default: |
201 | goto expr_stmt; |
202 | } |
203 | break; |
204 | case CPP_NAME: |
205 | if (c_parser_peek_2nd_token (parser)->type == CPP_COLON) |
206 | { |
207 | c_parser_gimple_label (parser, seq); |
208 | break; |
209 | } |
210 | goto expr_stmt; |
211 | |
212 | case CPP_SEMICOLON: |
213 | { |
214 | /* Empty stmt. */ |
215 | location_t loc = c_parser_peek_token (parser)->location; |
216 | c_parser_consume_token (parser); |
217 | gimple *nop = gimple_build_nop (); |
218 | gimple_set_location (nop, loc); |
219 | gimple_seq_add_stmt (seq, nop); |
220 | break; |
221 | } |
222 | |
223 | default: |
224 | expr_stmt: |
225 | c_parser_gimple_statement (parser, seq); |
226 | if (! c_parser_require (parser, CPP_SEMICOLON, "expected %<;%>" )) |
227 | c_parser_skip_until_found (parser, CPP_SEMICOLON, NULL); |
228 | } |
229 | } |
230 | c_parser_consume_token (parser); |
231 | return return_p; |
232 | } |
233 | |
234 | /* Parse a gimple statement. |
235 | |
236 | gimple-statement: |
237 | gimple-call-expression |
238 | gimple-assign-statement |
239 | gimple-phi-statement |
240 | |
241 | gimple-assign-statement: |
242 | gimple-unary-expression = gimple-assign-rhs |
243 | |
244 | gimple-assign-rhs: |
245 | gimple-cast-expression |
246 | gimple-unary-expression |
247 | gimple-binary-expression |
248 | gimple-call-expression |
249 | |
250 | gimple-phi-statement: |
251 | identifier = __PHI ( label : gimple_primary-expression, ... ) |
252 | |
253 | gimple-call-expr: |
254 | gimple-primary-expression ( argument-list ) |
255 | |
256 | gimple-cast-expression: |
257 | ( type-name ) gimple-primary-expression |
258 | |
259 | */ |
260 | |
261 | static void |
262 | c_parser_gimple_statement (c_parser *parser, gimple_seq *seq) |
263 | { |
264 | struct c_expr lhs, rhs; |
265 | gimple *assign = NULL; |
266 | location_t loc; |
267 | tree arg = NULL_TREE; |
268 | auto_vec<tree> vargs; |
269 | |
270 | lhs = c_parser_gimple_unary_expression (parser); |
271 | loc = EXPR_LOCATION (lhs.value); |
272 | rhs.set_error (); |
273 | |
274 | /* GIMPLE call statement without LHS. */ |
275 | if (c_parser_next_token_is (parser, CPP_SEMICOLON) |
276 | && TREE_CODE (lhs.value) == CALL_EXPR) |
277 | { |
278 | gimple *call; |
279 | call = gimple_build_call_from_tree (lhs.value, NULL); |
280 | gimple_seq_add_stmt (seq, call); |
281 | gimple_set_location (call, loc); |
282 | return; |
283 | } |
284 | |
285 | /* All following cases are statements with LHS. */ |
286 | if (! c_parser_require (parser, CPP_EQ, "expected %<=%>" )) |
287 | return; |
288 | |
289 | /* Cast expression. */ |
290 | if (c_parser_next_token_is (parser, CPP_OPEN_PAREN) |
291 | && c_token_starts_typename (c_parser_peek_2nd_token (parser))) |
292 | { |
293 | c_parser_consume_token (parser); |
294 | struct c_type_name *type_name = c_parser_type_name (parser); |
295 | c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, "expected %<)%>" ); |
296 | if (type_name == NULL) |
297 | return; |
298 | /* ??? The actual type used in the cast expression is ignored as |
299 | in GIMPLE it is encoded by the type of the LHS. */ |
300 | rhs = c_parser_gimple_postfix_expression (parser); |
301 | if (lhs.value != error_mark_node |
302 | && rhs.value != error_mark_node) |
303 | { |
304 | enum tree_code code = NOP_EXPR; |
305 | if (VECTOR_TYPE_P (TREE_TYPE (lhs.value))) |
306 | { |
307 | code = VIEW_CONVERT_EXPR; |
308 | rhs.value = build1 (VIEW_CONVERT_EXPR, |
309 | TREE_TYPE (lhs.value), rhs.value); |
310 | } |
311 | else if (FLOAT_TYPE_P (TREE_TYPE (lhs.value)) |
312 | && ! FLOAT_TYPE_P (TREE_TYPE (rhs.value))) |
313 | code = FLOAT_EXPR; |
314 | else if (! FLOAT_TYPE_P (TREE_TYPE (lhs.value)) |
315 | && FLOAT_TYPE_P (TREE_TYPE (rhs.value))) |
316 | code = FIX_TRUNC_EXPR; |
317 | assign = gimple_build_assign (lhs.value, code, rhs.value); |
318 | gimple_seq_add_stmt (seq, assign); |
319 | gimple_set_location (assign, loc); |
320 | return; |
321 | } |
322 | } |
323 | |
324 | /* Unary expression. */ |
325 | switch (c_parser_peek_token (parser)->type) |
326 | { |
327 | case CPP_NAME: |
328 | { |
329 | tree id = c_parser_peek_token (parser)->value; |
330 | if (strcmp (IDENTIFIER_POINTER (id), "__ABS" ) == 0) |
331 | goto build_unary_expr; |
332 | break; |
333 | } |
334 | case CPP_KEYWORD: |
335 | if (c_parser_peek_token (parser)->keyword != RID_REALPART |
336 | && c_parser_peek_token (parser)->keyword != RID_IMAGPART) |
337 | break; |
338 | /* Fallthru. */ |
339 | case CPP_AND: |
340 | case CPP_PLUS: |
341 | case CPP_MINUS: |
342 | case CPP_COMPL: |
343 | case CPP_NOT: |
344 | case CPP_MULT: /* pointer deref */ |
345 | build_unary_expr: |
346 | rhs = c_parser_gimple_unary_expression (parser); |
347 | if (rhs.value != error_mark_node) |
348 | { |
349 | assign = gimple_build_assign (lhs.value, rhs.value); |
350 | gimple_set_location (assign, loc); |
351 | gimple_seq_add_stmt (seq, assign); |
352 | } |
353 | return; |
354 | |
355 | default:; |
356 | } |
357 | |
358 | /* GIMPLE PHI statement. */ |
359 | if (c_parser_next_token_is_keyword (parser, RID_PHI)) |
360 | { |
361 | c_parser_consume_token (parser); |
362 | |
363 | if (! c_parser_require (parser, CPP_OPEN_PAREN, "expected %<(%>" )) |
364 | return; |
365 | |
366 | if (c_parser_next_token_is (parser, CPP_OPEN_PAREN)) |
367 | c_parser_consume_token (parser); |
368 | |
369 | while (c_parser_next_token_is_not (parser, CPP_CLOSE_PAREN)) |
370 | { |
371 | if (c_parser_next_token_is (parser, CPP_NAME) |
372 | && c_parser_peek_2nd_token (parser)->type == CPP_COLON) |
373 | { |
374 | arg = lookup_label_for_goto (loc, |
375 | c_parser_peek_token (parser)->value); |
376 | c_parser_consume_token (parser); |
377 | |
378 | if (c_parser_next_token_is (parser, CPP_COLON)) |
379 | c_parser_consume_token (parser); |
380 | vargs.safe_push (arg); |
381 | } |
382 | else if (c_parser_next_token_is (parser, CPP_COMMA)) |
383 | c_parser_consume_token (parser); |
384 | else |
385 | { |
386 | arg = c_parser_gimple_unary_expression (parser).value; |
387 | vargs.safe_push (arg); |
388 | } |
389 | } |
390 | |
391 | c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, |
392 | "expected %<)%>" ); |
393 | |
394 | /* Build internal function for PHI. */ |
395 | gcall *call_stmt = gimple_build_call_internal_vec (IFN_PHI, vargs); |
396 | gimple_call_set_lhs (call_stmt, lhs.value); |
397 | gimple_set_location (call_stmt, UNKNOWN_LOCATION); |
398 | gimple_seq_add_stmt (seq, call_stmt); |
399 | return; |
400 | } |
401 | |
402 | /* GIMPLE call with lhs. */ |
403 | if (c_parser_next_token_is (parser, CPP_NAME) |
404 | && c_parser_peek_2nd_token (parser)->type == CPP_OPEN_PAREN |
405 | && lookup_name (c_parser_peek_token (parser)->value)) |
406 | { |
407 | rhs = c_parser_gimple_unary_expression (parser); |
408 | if (rhs.value != error_mark_node) |
409 | { |
410 | gimple *call = gimple_build_call_from_tree (rhs.value, NULL); |
411 | gimple_call_set_lhs (call, lhs.value); |
412 | gimple_seq_add_stmt (seq, call); |
413 | gimple_set_location (call, loc); |
414 | } |
415 | return; |
416 | } |
417 | |
418 | rhs = c_parser_gimple_binary_expression (parser); |
419 | if (lhs.value != error_mark_node |
420 | && rhs.value != error_mark_node) |
421 | { |
422 | /* If we parsed a comparison and the next token is a '?' then |
423 | parse a conditional expression. */ |
424 | if (COMPARISON_CLASS_P (rhs.value) |
425 | && c_parser_next_token_is (parser, CPP_QUERY)) |
426 | { |
427 | struct c_expr trueval, falseval; |
428 | c_parser_consume_token (parser); |
429 | trueval = c_parser_gimple_postfix_expression (parser); |
430 | falseval.set_error (); |
431 | if (c_parser_require (parser, CPP_COLON, "expected %<:%>" )) |
432 | falseval = c_parser_gimple_postfix_expression (parser); |
433 | if (trueval.value == error_mark_node |
434 | || falseval.value == error_mark_node) |
435 | return; |
436 | rhs.value = build3_loc (loc, COND_EXPR, TREE_TYPE (trueval.value), |
437 | rhs.value, trueval.value, falseval.value); |
438 | } |
439 | assign = gimple_build_assign (lhs.value, rhs.value); |
440 | gimple_seq_add_stmt (seq, assign); |
441 | gimple_set_location (assign, loc); |
442 | } |
443 | return; |
444 | } |
445 | |
446 | /* Parse gimple binary expr. |
447 | |
448 | gimple-binary-expression: |
449 | gimple-unary-expression * gimple-unary-expression |
450 | gimple-unary-expression / gimple-unary-expression |
451 | gimple-unary-expression % gimple-unary-expression |
452 | gimple-unary-expression + gimple-unary-expression |
453 | gimple-unary-expression - gimple-unary-expression |
454 | gimple-unary-expression << gimple-unary-expression |
455 | gimple-unary-expression >> gimple-unary-expression |
456 | gimple-unary-expression < gimple-unary-expression |
457 | gimple-unary-expression > gimple-unary-expression |
458 | gimple-unary-expression <= gimple-unary-expression |
459 | gimple-unary-expression >= gimple-unary-expression |
460 | gimple-unary-expression == gimple-unary-expression |
461 | gimple-unary-expression != gimple-unary-expression |
462 | gimple-unary-expression & gimple-unary-expression |
463 | gimple-unary-expression ^ gimple-unary-expression |
464 | gimple-unary-expression | gimple-unary-expression |
465 | |
466 | */ |
467 | |
468 | static c_expr |
469 | c_parser_gimple_binary_expression (c_parser *parser) |
470 | { |
471 | /* Location of the binary operator. */ |
472 | struct c_expr ret, lhs, rhs; |
473 | enum tree_code code = ERROR_MARK; |
474 | ret.set_error (); |
475 | lhs = c_parser_gimple_postfix_expression (parser); |
476 | if (c_parser_error (parser)) |
477 | return ret; |
478 | tree ret_type = TREE_TYPE (lhs.value); |
479 | switch (c_parser_peek_token (parser)->type) |
480 | { |
481 | case CPP_MULT: |
482 | code = MULT_EXPR; |
483 | break; |
484 | case CPP_DIV: |
485 | code = TRUNC_DIV_EXPR; |
486 | break; |
487 | case CPP_MOD: |
488 | code = TRUNC_MOD_EXPR; |
489 | break; |
490 | case CPP_PLUS: |
491 | if (POINTER_TYPE_P (TREE_TYPE (lhs.value))) |
492 | code = POINTER_PLUS_EXPR; |
493 | else |
494 | code = PLUS_EXPR; |
495 | break; |
496 | case CPP_MINUS: |
497 | code = MINUS_EXPR; |
498 | break; |
499 | case CPP_LSHIFT: |
500 | code = LSHIFT_EXPR; |
501 | break; |
502 | case CPP_RSHIFT: |
503 | code = RSHIFT_EXPR; |
504 | break; |
505 | case CPP_LESS: |
506 | code = LT_EXPR; |
507 | ret_type = boolean_type_node; |
508 | break; |
509 | case CPP_GREATER: |
510 | code = GT_EXPR; |
511 | ret_type = boolean_type_node; |
512 | break; |
513 | case CPP_LESS_EQ: |
514 | code = LE_EXPR; |
515 | ret_type = boolean_type_node; |
516 | break; |
517 | case CPP_GREATER_EQ: |
518 | code = GE_EXPR; |
519 | ret_type = boolean_type_node; |
520 | break; |
521 | case CPP_EQ_EQ: |
522 | code = EQ_EXPR; |
523 | ret_type = boolean_type_node; |
524 | break; |
525 | case CPP_NOT_EQ: |
526 | code = NE_EXPR; |
527 | ret_type = boolean_type_node; |
528 | break; |
529 | case CPP_AND: |
530 | code = BIT_AND_EXPR; |
531 | break; |
532 | case CPP_XOR: |
533 | code = BIT_XOR_EXPR; |
534 | break; |
535 | case CPP_OR: |
536 | code = BIT_IOR_EXPR; |
537 | break; |
538 | case CPP_AND_AND: |
539 | c_parser_error (parser, "%<&&%> not valid in GIMPLE" ); |
540 | return ret; |
541 | case CPP_OR_OR: |
542 | c_parser_error (parser, "%<||%> not valid in GIMPLE" ); |
543 | return ret; |
544 | default: |
545 | /* Not a binary expression. */ |
546 | return lhs; |
547 | } |
548 | location_t ret_loc = c_parser_peek_token (parser)->location; |
549 | c_parser_consume_token (parser); |
550 | rhs = c_parser_gimple_postfix_expression (parser); |
551 | if (lhs.value != error_mark_node && rhs.value != error_mark_node) |
552 | ret.value = build2_loc (ret_loc, code, ret_type, lhs.value, rhs.value); |
553 | return ret; |
554 | } |
555 | |
556 | /* Parse gimple unary expression. |
557 | |
558 | gimple-unary-expression: |
559 | gimple-postfix-expression |
560 | unary-operator gimple-postfix-expression |
561 | |
562 | unary-operator: one of |
563 | & * + - ~ abs_expr |
564 | */ |
565 | |
566 | static c_expr |
567 | c_parser_gimple_unary_expression (c_parser *parser) |
568 | { |
569 | struct c_expr ret, op; |
570 | location_t op_loc = c_parser_peek_token (parser)->location; |
571 | location_t finish; |
572 | ret.set_error (); |
573 | switch (c_parser_peek_token (parser)->type) |
574 | { |
575 | case CPP_AND: |
576 | c_parser_consume_token (parser); |
577 | op = c_parser_gimple_postfix_expression (parser); |
578 | mark_exp_read (op.value); |
579 | return parser_build_unary_op (op_loc, ADDR_EXPR, op); |
580 | case CPP_MULT: |
581 | { |
582 | c_parser_consume_token (parser); |
583 | op = c_parser_gimple_postfix_expression (parser); |
584 | if (op.value == error_mark_node) |
585 | return ret; |
586 | if (! POINTER_TYPE_P (TREE_TYPE (op.value))) |
587 | { |
588 | error_at (op_loc, "expected pointer as argument of unary %<*%>" ); |
589 | return ret; |
590 | } |
591 | finish = op.get_finish (); |
592 | location_t combined_loc = make_location (op_loc, op_loc, finish); |
593 | ret.value = build_simple_mem_ref_loc (combined_loc, op.value); |
594 | TREE_SIDE_EFFECTS (ret.value) |
595 | = TREE_THIS_VOLATILE (ret.value) |
596 | = TYPE_VOLATILE (TREE_TYPE (TREE_TYPE (op.value))); |
597 | ret.src_range.m_start = op_loc; |
598 | ret.src_range.m_finish = finish; |
599 | return ret; |
600 | } |
601 | case CPP_PLUS: |
602 | c_parser_consume_token (parser); |
603 | op = c_parser_gimple_postfix_expression (parser); |
604 | return parser_build_unary_op (op_loc, CONVERT_EXPR, op); |
605 | case CPP_MINUS: |
606 | c_parser_consume_token (parser); |
607 | op = c_parser_gimple_postfix_expression (parser); |
608 | return parser_build_unary_op (op_loc, NEGATE_EXPR, op); |
609 | case CPP_COMPL: |
610 | c_parser_consume_token (parser); |
611 | op = c_parser_gimple_postfix_expression (parser); |
612 | return parser_build_unary_op (op_loc, BIT_NOT_EXPR, op); |
613 | case CPP_NOT: |
614 | c_parser_error (parser, "%<!%> not valid in GIMPLE" ); |
615 | return ret; |
616 | case CPP_KEYWORD: |
617 | switch (c_parser_peek_token (parser)->keyword) |
618 | { |
619 | case RID_REALPART: |
620 | c_parser_consume_token (parser); |
621 | op = c_parser_gimple_postfix_expression (parser); |
622 | return parser_build_unary_op (op_loc, REALPART_EXPR, op); |
623 | case RID_IMAGPART: |
624 | c_parser_consume_token (parser); |
625 | op = c_parser_gimple_postfix_expression (parser); |
626 | return parser_build_unary_op (op_loc, IMAGPART_EXPR, op); |
627 | default: |
628 | return c_parser_gimple_postfix_expression (parser); |
629 | } |
630 | case CPP_NAME: |
631 | { |
632 | tree id = c_parser_peek_token (parser)->value; |
633 | if (strcmp (IDENTIFIER_POINTER (id), "__ABS" ) == 0) |
634 | { |
635 | c_parser_consume_token (parser); |
636 | op = c_parser_gimple_postfix_expression (parser); |
637 | return parser_build_unary_op (op_loc, ABS_EXPR, op); |
638 | } |
639 | else |
640 | return c_parser_gimple_postfix_expression (parser); |
641 | } |
642 | default: |
643 | return c_parser_gimple_postfix_expression (parser); |
644 | } |
645 | } |
646 | |
647 | /* Decompose ID into base name (ID until ver_offset) and VERSION. Return |
648 | true if ID matches a SSA name. */ |
649 | |
650 | static bool |
651 | c_parser_parse_ssa_name_id (tree id, unsigned *version, unsigned *ver_offset) |
652 | { |
653 | const char *token = IDENTIFIER_POINTER (id); |
654 | const char *var_version = strrchr (token, '_'); |
655 | if (! var_version) |
656 | return false; |
657 | |
658 | *ver_offset = var_version - token; |
659 | for (const char *p = var_version + 1; *p; ++p) |
660 | if (! ISDIGIT (*p)) |
661 | return false; |
662 | *version = atoi (var_version + 1); |
663 | return *version > 0; |
664 | } |
665 | |
666 | /* Get at the actual SSA name ID with VERSION starting at VER_OFFSET. |
667 | TYPE is the type if the SSA name is being declared. */ |
668 | |
669 | static tree |
670 | c_parser_parse_ssa_name (c_parser *parser, |
671 | tree id, tree type, unsigned version, |
672 | unsigned ver_offset) |
673 | { |
674 | tree name = NULL_TREE; |
675 | const char *token = IDENTIFIER_POINTER (id); |
676 | |
677 | if (ver_offset == 0) |
678 | { |
679 | /* Anonymous unnamed SSA name. */ |
680 | if (version < num_ssa_names) |
681 | name = ssa_name (version); |
682 | if (! name) |
683 | { |
684 | if (! type) |
685 | { |
686 | c_parser_error (parser, "SSA name undeclared" ); |
687 | return error_mark_node; |
688 | } |
689 | name = make_ssa_name_fn (cfun, type, NULL, version); |
690 | } |
691 | } |
692 | else |
693 | { |
694 | if (version < num_ssa_names) |
695 | name = ssa_name (version); |
696 | if (! name) |
697 | { |
698 | /* Separate var name from version. */ |
699 | char *var_name = XNEWVEC (char, ver_offset + 1); |
700 | memcpy (var_name, token, ver_offset); |
701 | var_name[ver_offset] = '\0'; |
702 | /* lookup for parent decl. */ |
703 | id = get_identifier (var_name); |
704 | tree parent = lookup_name (id); |
705 | XDELETEVEC (var_name); |
706 | if (! parent || parent == error_mark_node) |
707 | { |
708 | c_parser_error (parser, "base variable or SSA name undeclared" ); |
709 | return error_mark_node; |
710 | } |
711 | if (!(VAR_P (parent) |
712 | || TREE_CODE (parent) == PARM_DECL |
713 | || TREE_CODE (parent) == RESULT_DECL)) |
714 | { |
715 | error ("invalid base %qE for SSA name" , parent); |
716 | return error_mark_node; |
717 | } |
718 | if (VECTOR_TYPE_P (TREE_TYPE (parent)) |
719 | || TREE_CODE (TREE_TYPE (parent)) == COMPLEX_TYPE) |
720 | DECL_GIMPLE_REG_P (parent) = 1; |
721 | name = make_ssa_name_fn (cfun, parent, |
722 | gimple_build_nop (), version); |
723 | } |
724 | } |
725 | |
726 | return name; |
727 | } |
728 | |
729 | /* Parse gimple postfix expression. |
730 | |
731 | gimple-postfix-expression: |
732 | gimple-primary-expression |
733 | gimple-primary-xpression [ gimple-primary-expression ] |
734 | gimple-primary-expression ( gimple-argument-expression-list[opt] ) |
735 | postfix-expression . identifier |
736 | postfix-expression -> identifier |
737 | |
738 | gimple-argument-expression-list: |
739 | gimple-unary-expression |
740 | gimple-argument-expression-list , gimple-unary-expression |
741 | |
742 | gimple-primary-expression: |
743 | identifier |
744 | constant |
745 | string-literal |
746 | |
747 | */ |
748 | |
749 | static struct c_expr |
750 | c_parser_gimple_postfix_expression (c_parser *parser) |
751 | { |
752 | location_t loc = c_parser_peek_token (parser)->location; |
753 | source_range tok_range = c_parser_peek_token (parser)->get_range (); |
754 | struct c_expr expr; |
755 | expr.set_error (); |
756 | switch (c_parser_peek_token (parser)->type) |
757 | { |
758 | case CPP_NUMBER: |
759 | expr.value = c_parser_peek_token (parser)->value; |
760 | set_c_expr_source_range (&expr, tok_range); |
761 | loc = c_parser_peek_token (parser)->location; |
762 | c_parser_consume_token (parser); |
763 | break; |
764 | case CPP_CHAR: |
765 | case CPP_CHAR16: |
766 | case CPP_CHAR32: |
767 | case CPP_WCHAR: |
768 | expr.value = c_parser_peek_token (parser)->value; |
769 | set_c_expr_source_range (&expr, tok_range); |
770 | c_parser_consume_token (parser); |
771 | break; |
772 | case CPP_STRING: |
773 | case CPP_STRING16: |
774 | case CPP_STRING32: |
775 | case CPP_WSTRING: |
776 | case CPP_UTF8STRING: |
777 | expr.value = c_parser_peek_token (parser)->value; |
778 | set_c_expr_source_range (&expr, tok_range); |
779 | expr.original_code = STRING_CST; |
780 | c_parser_consume_token (parser); |
781 | break; |
782 | case CPP_NAME: |
783 | if (c_parser_peek_token (parser)->id_kind == C_ID_ID) |
784 | { |
785 | tree id = c_parser_peek_token (parser)->value; |
786 | if (strcmp (IDENTIFIER_POINTER (id), "__MEM" ) == 0) |
787 | { |
788 | /* __MEM '<' type-name [ ',' number ] '>' |
789 | '(' [ '(' type-name ')' ] unary-expression |
790 | [ '+' number ] ')' */ |
791 | location_t loc = c_parser_peek_token (parser)->location; |
792 | c_parser_consume_token (parser); |
793 | struct c_type_name *type_name = NULL; |
794 | tree alignment = NULL_TREE; |
795 | if (c_parser_require (parser, CPP_LESS, "expected %<<%>" )) |
796 | { |
797 | type_name = c_parser_type_name (parser); |
798 | /* Optional alignment. */ |
799 | if (c_parser_next_token_is (parser, CPP_COMMA)) |
800 | { |
801 | c_parser_consume_token (parser); |
802 | alignment |
803 | = c_parser_gimple_postfix_expression (parser).value; |
804 | } |
805 | c_parser_skip_until_found (parser, |
806 | CPP_GREATER, "expected %<>%>" ); |
807 | } |
808 | struct c_expr ptr; |
809 | ptr.value = error_mark_node; |
810 | tree alias_off = NULL_TREE; |
811 | if (c_parser_require (parser, CPP_OPEN_PAREN, "expected %<(%>" )) |
812 | { |
813 | tree alias_type = NULL_TREE; |
814 | /* Optional alias-type cast. */ |
815 | if (c_parser_next_token_is (parser, CPP_OPEN_PAREN)) |
816 | { |
817 | c_parser_consume_token (parser); |
818 | struct c_type_name *alias_type_name |
819 | = c_parser_type_name (parser); |
820 | c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, |
821 | "expected %<)%>" ); |
822 | if (alias_type_name) |
823 | { |
824 | tree tem; |
825 | alias_type = groktypename (alias_type_name, |
826 | &tem, NULL); |
827 | } |
828 | } |
829 | ptr = c_parser_gimple_unary_expression (parser); |
830 | if (ptr.value == error_mark_node |
831 | || ! POINTER_TYPE_P (TREE_TYPE (ptr.value))) |
832 | { |
833 | if (ptr.value != error_mark_node) |
834 | error_at (ptr.get_start (), |
835 | "invalid type of %<__MEM%> operand" ); |
836 | c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, |
837 | "expected %<)%>" ); |
838 | return expr; |
839 | } |
840 | if (! alias_type) |
841 | alias_type = TREE_TYPE (ptr.value); |
842 | /* Optional constant offset. */ |
843 | if (c_parser_next_token_is (parser, CPP_PLUS)) |
844 | { |
845 | c_parser_consume_token (parser); |
846 | alias_off |
847 | = c_parser_gimple_postfix_expression (parser).value; |
848 | alias_off = fold_convert (alias_type, alias_off); |
849 | } |
850 | if (! alias_off) |
851 | alias_off = build_int_cst (alias_type, 0); |
852 | c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, |
853 | "expected %<)%>" ); |
854 | } |
855 | if (! type_name || c_parser_error (parser)) |
856 | { |
857 | c_parser_set_error (parser, false); |
858 | return expr; |
859 | } |
860 | tree tem = NULL_TREE; |
861 | tree type = groktypename (type_name, &tem, NULL); |
862 | if (alignment) |
863 | type = build_aligned_type (type, tree_to_uhwi (alignment)); |
864 | expr.value = build2_loc (loc, MEM_REF, |
865 | type, ptr.value, alias_off); |
866 | break; |
867 | } |
868 | else if (strcmp (IDENTIFIER_POINTER (id), "_Literal" ) == 0) |
869 | { |
870 | /* _Literal '(' type-name ')' [ '-' ] constant */ |
871 | c_parser_consume_token (parser); |
872 | tree type = NULL_TREE; |
873 | if (c_parser_require (parser, CPP_OPEN_PAREN, "expected %<(%>" )) |
874 | { |
875 | struct c_type_name *type_name = c_parser_type_name (parser); |
876 | tree tem; |
877 | if (type_name) |
878 | type = groktypename (type_name, &tem, NULL); |
879 | c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, |
880 | "expected %<)%>" ); |
881 | } |
882 | bool neg_p; |
883 | if ((neg_p = c_parser_next_token_is (parser, CPP_MINUS))) |
884 | c_parser_consume_token (parser); |
885 | tree val = c_parser_gimple_postfix_expression (parser).value; |
886 | if (! type |
887 | || ! val |
888 | || val == error_mark_node |
889 | || ! CONSTANT_CLASS_P (val)) |
890 | { |
891 | c_parser_error (parser, "invalid _Literal" ); |
892 | return expr; |
893 | } |
894 | if (neg_p) |
895 | { |
896 | val = const_unop (NEGATE_EXPR, TREE_TYPE (val), val); |
897 | if (! val) |
898 | { |
899 | c_parser_error (parser, "invalid _Literal" ); |
900 | return expr; |
901 | } |
902 | } |
903 | expr.value = fold_convert (type, val); |
904 | return expr; |
905 | } |
906 | else if (strcmp (IDENTIFIER_POINTER (id), "__FMA" ) == 0) |
907 | { |
908 | c_parser_consume_token (parser); |
909 | auto_vec<tree> args; |
910 | |
911 | if (c_parser_require (parser, CPP_OPEN_PAREN, "expected %<(%>" )) |
912 | { |
913 | c_parser_gimple_expr_list (parser, &args); |
914 | c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, |
915 | "expected %<)%>" ); |
916 | } |
917 | if (args.length () != 3) |
918 | { |
919 | error_at (loc, "invalid number of operands to __FMA" ); |
920 | expr.value = error_mark_node; |
921 | return expr; |
922 | } |
923 | expr.value = build3_loc (loc, FMA_EXPR, TREE_TYPE (args[0]), |
924 | args[0], args[1], args[2]); |
925 | return expr; |
926 | } |
927 | |
928 | /* SSA name. */ |
929 | unsigned version, ver_offset; |
930 | if (! lookup_name (id) |
931 | && c_parser_parse_ssa_name_id (id, &version, &ver_offset)) |
932 | { |
933 | c_parser_consume_token (parser); |
934 | expr.value = c_parser_parse_ssa_name (parser, id, NULL_TREE, |
935 | version, ver_offset); |
936 | if (expr.value == error_mark_node) |
937 | return expr; |
938 | set_c_expr_source_range (&expr, tok_range); |
939 | /* For default definition SSA names. */ |
940 | if (c_parser_next_token_is (parser, CPP_OPEN_PAREN) |
941 | && c_parser_peek_2nd_token (parser)->type == CPP_NAME |
942 | && strcmp ("D" , |
943 | IDENTIFIER_POINTER |
944 | (c_parser_peek_2nd_token (parser)->value)) == 0 |
945 | && c_parser_peek_nth_token (parser, 3)->type == CPP_CLOSE_PAREN) |
946 | { |
947 | c_parser_consume_token (parser); |
948 | c_parser_consume_token (parser); |
949 | c_parser_consume_token (parser); |
950 | if (! SSA_NAME_IS_DEFAULT_DEF (expr.value)) |
951 | { |
952 | if (!SSA_NAME_VAR (expr.value)) |
953 | { |
954 | error_at (loc, "anonymous SSA name cannot have" |
955 | " default definition" ); |
956 | expr.value = error_mark_node; |
957 | return expr; |
958 | } |
959 | set_ssa_default_def (cfun, SSA_NAME_VAR (expr.value), |
960 | expr.value); |
961 | SSA_NAME_DEF_STMT (expr.value) = gimple_build_nop (); |
962 | } |
963 | } |
964 | } |
965 | else |
966 | { |
967 | c_parser_consume_token (parser); |
968 | expr.value |
969 | = build_external_ref (loc, id, |
970 | (c_parser_peek_token (parser)->type |
971 | == CPP_OPEN_PAREN), &expr.original_type); |
972 | set_c_expr_source_range (&expr, tok_range); |
973 | } |
974 | break; |
975 | } |
976 | else |
977 | { |
978 | c_parser_error (parser, "expected expression" ); |
979 | expr.set_error (); |
980 | break; |
981 | } |
982 | break; |
983 | default: |
984 | c_parser_error (parser, "expected expression" ); |
985 | expr.set_error (); |
986 | break; |
987 | } |
988 | return c_parser_gimple_postfix_expression_after_primary |
989 | (parser, EXPR_LOC_OR_LOC (expr.value, loc), expr); |
990 | } |
991 | |
992 | /* Parse a gimple postfix expression after the initial primary or compound |
993 | literal. */ |
994 | |
995 | static struct c_expr |
996 | c_parser_gimple_postfix_expression_after_primary (c_parser *parser, |
997 | location_t expr_loc, |
998 | struct c_expr expr) |
999 | { |
1000 | location_t start; |
1001 | location_t finish; |
1002 | tree ident; |
1003 | location_t comp_loc; |
1004 | |
1005 | while (true) |
1006 | { |
1007 | location_t op_loc = c_parser_peek_token (parser)->location; |
1008 | switch (c_parser_peek_token (parser)->type) |
1009 | { |
1010 | case CPP_OPEN_SQUARE: |
1011 | { |
1012 | c_parser_consume_token (parser); |
1013 | tree idx = c_parser_gimple_unary_expression (parser).value; |
1014 | |
1015 | if (! c_parser_require (parser, CPP_CLOSE_SQUARE, "expected %<]%>" )) |
1016 | { |
1017 | c_parser_skip_until_found (parser, CPP_CLOSE_SQUARE, NULL); |
1018 | break; |
1019 | } |
1020 | |
1021 | start = expr.get_start (); |
1022 | finish = c_parser_tokens_buf (parser, 0)->location; |
1023 | expr.value = build_array_ref (op_loc, expr.value, idx); |
1024 | set_c_expr_source_range (&expr, start, finish); |
1025 | |
1026 | expr.original_code = ERROR_MARK; |
1027 | expr.original_type = NULL; |
1028 | break; |
1029 | } |
1030 | case CPP_OPEN_PAREN: |
1031 | { |
1032 | /* Function call. */ |
1033 | c_parser_consume_token (parser); |
1034 | auto_vec<tree> exprlist; |
1035 | if (! c_parser_next_token_is (parser, CPP_CLOSE_PAREN)) |
1036 | c_parser_gimple_expr_list (parser, &exprlist); |
1037 | c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, |
1038 | "expected %<)%>" ); |
1039 | expr.value = build_call_array_loc |
1040 | (expr_loc, TREE_TYPE (TREE_TYPE (expr.value)), |
1041 | expr.value, exprlist.length (), exprlist.address ()); |
1042 | expr.original_code = ERROR_MARK; |
1043 | expr.original_type = NULL; |
1044 | break; |
1045 | } |
1046 | case CPP_DOT: |
1047 | { |
1048 | /* Structure element reference. */ |
1049 | c_parser_consume_token (parser); |
1050 | if (c_parser_next_token_is (parser, CPP_NAME)) |
1051 | { |
1052 | c_token *comp_tok = c_parser_peek_token (parser); |
1053 | ident = comp_tok->value; |
1054 | comp_loc = comp_tok->location; |
1055 | } |
1056 | else |
1057 | { |
1058 | c_parser_error (parser, "expected identifier" ); |
1059 | expr.set_error (); |
1060 | expr.original_code = ERROR_MARK; |
1061 | expr.original_type = NULL; |
1062 | return expr; |
1063 | } |
1064 | start = expr.get_start (); |
1065 | finish = c_parser_peek_token (parser)->get_finish (); |
1066 | c_parser_consume_token (parser); |
1067 | expr.value = build_component_ref (op_loc, expr.value, ident, |
1068 | comp_loc); |
1069 | set_c_expr_source_range (&expr, start, finish); |
1070 | expr.original_code = ERROR_MARK; |
1071 | if (TREE_CODE (expr.value) != COMPONENT_REF) |
1072 | expr.original_type = NULL; |
1073 | else |
1074 | { |
1075 | /* Remember the original type of a bitfield. */ |
1076 | tree field = TREE_OPERAND (expr.value, 1); |
1077 | if (TREE_CODE (field) != FIELD_DECL) |
1078 | expr.original_type = NULL; |
1079 | else |
1080 | expr.original_type = DECL_BIT_FIELD_TYPE (field); |
1081 | } |
1082 | break; |
1083 | } |
1084 | case CPP_DEREF: |
1085 | { |
1086 | /* Structure element reference. */ |
1087 | c_parser_consume_token (parser); |
1088 | if (c_parser_next_token_is (parser, CPP_NAME)) |
1089 | { |
1090 | c_token *comp_tok = c_parser_peek_token (parser); |
1091 | ident = comp_tok->value; |
1092 | comp_loc = comp_tok->location; |
1093 | } |
1094 | else |
1095 | { |
1096 | c_parser_error (parser, "expected identifier" ); |
1097 | expr.set_error (); |
1098 | expr.original_code = ERROR_MARK; |
1099 | expr.original_type = NULL; |
1100 | return expr; |
1101 | } |
1102 | start = expr.get_start (); |
1103 | finish = c_parser_peek_token (parser)->get_finish (); |
1104 | c_parser_consume_token (parser); |
1105 | expr.value = build_component_ref (op_loc, |
1106 | build_simple_mem_ref_loc |
1107 | (op_loc, expr.value), |
1108 | ident, comp_loc); |
1109 | set_c_expr_source_range (&expr, start, finish); |
1110 | expr.original_code = ERROR_MARK; |
1111 | if (TREE_CODE (expr.value) != COMPONENT_REF) |
1112 | expr.original_type = NULL; |
1113 | else |
1114 | { |
1115 | /* Remember the original type of a bitfield. */ |
1116 | tree field = TREE_OPERAND (expr.value, 1); |
1117 | if (TREE_CODE (field) != FIELD_DECL) |
1118 | expr.original_type = NULL; |
1119 | else |
1120 | expr.original_type = DECL_BIT_FIELD_TYPE (field); |
1121 | } |
1122 | break; |
1123 | } |
1124 | default: |
1125 | return expr; |
1126 | } |
1127 | } |
1128 | } |
1129 | |
1130 | /* Parse expression list. |
1131 | |
1132 | gimple-expr-list: |
1133 | gimple-unary-expression |
1134 | gimple-expr-list , gimple-unary-expression |
1135 | |
1136 | */ |
1137 | |
1138 | static void |
1139 | c_parser_gimple_expr_list (c_parser *parser, vec<tree> *ret) |
1140 | { |
1141 | struct c_expr expr; |
1142 | |
1143 | expr = c_parser_gimple_unary_expression (parser); |
1144 | ret->safe_push (expr.value); |
1145 | while (c_parser_next_token_is (parser, CPP_COMMA)) |
1146 | { |
1147 | c_parser_consume_token (parser); |
1148 | expr = c_parser_gimple_unary_expression (parser); |
1149 | ret->safe_push (expr.value); |
1150 | } |
1151 | } |
1152 | |
1153 | /* Parse gimple label. |
1154 | |
1155 | gimple-label: |
1156 | identifier : |
1157 | case constant-expression : |
1158 | default : |
1159 | |
1160 | */ |
1161 | |
1162 | static void |
1163 | c_parser_gimple_label (c_parser *parser, gimple_seq *seq) |
1164 | { |
1165 | tree name = c_parser_peek_token (parser)->value; |
1166 | location_t loc1 = c_parser_peek_token (parser)->location; |
1167 | gcc_assert (c_parser_next_token_is (parser, CPP_NAME)); |
1168 | c_parser_consume_token (parser); |
1169 | gcc_assert (c_parser_next_token_is (parser, CPP_COLON)); |
1170 | c_parser_consume_token (parser); |
1171 | tree label = define_label (loc1, name); |
1172 | gimple_seq_add_stmt (seq, gimple_build_label (label)); |
1173 | return; |
1174 | } |
1175 | |
1176 | /* Parse gimple/RTL pass list. |
1177 | |
1178 | gimple-or-rtl-pass-list: |
1179 | startwith("pass-name") |
1180 | */ |
1181 | |
1182 | char * |
1183 | c_parser_gimple_or_rtl_pass_list (c_parser *parser) |
1184 | { |
1185 | char *pass = NULL; |
1186 | |
1187 | /* Accept __GIMPLE/__RTL. */ |
1188 | if (c_parser_next_token_is_not (parser, CPP_OPEN_PAREN)) |
1189 | return NULL; |
1190 | c_parser_consume_token (parser); |
1191 | |
1192 | if (c_parser_next_token_is (parser, CPP_NAME)) |
1193 | { |
1194 | const char *op = IDENTIFIER_POINTER (c_parser_peek_token (parser)->value); |
1195 | c_parser_consume_token (parser); |
1196 | if (! strcmp (op, "startwith" )) |
1197 | { |
1198 | if (! c_parser_require (parser, CPP_OPEN_PAREN, "expected %<(%>" )) |
1199 | return NULL; |
1200 | if (c_parser_next_token_is_not (parser, CPP_STRING)) |
1201 | { |
1202 | error_at (c_parser_peek_token (parser)->location, |
1203 | "expected pass name" ); |
1204 | return NULL; |
1205 | } |
1206 | pass = xstrdup (TREE_STRING_POINTER |
1207 | (c_parser_peek_token (parser)->value)); |
1208 | c_parser_consume_token (parser); |
1209 | if (! c_parser_require (parser, CPP_CLOSE_PAREN, "expected %<)%>" )) |
1210 | return NULL; |
1211 | } |
1212 | else |
1213 | { |
1214 | error_at (c_parser_peek_token (parser)->location, |
1215 | "invalid operation" ); |
1216 | return NULL; |
1217 | } |
1218 | } |
1219 | |
1220 | if (! c_parser_require (parser, CPP_CLOSE_PAREN, "expected %<)%>" )) |
1221 | return NULL; |
1222 | |
1223 | return pass; |
1224 | } |
1225 | |
1226 | /* Parse gimple local declaration. |
1227 | |
1228 | declaration-specifiers: |
1229 | storage-class-specifier declaration-specifiers[opt] |
1230 | type-specifier declaration-specifiers[opt] |
1231 | type-qualifier declaration-specifiers[opt] |
1232 | function-specifier declaration-specifiers[opt] |
1233 | alignment-specifier declaration-specifiers[opt] |
1234 | |
1235 | storage-class-specifier: |
1236 | typedef |
1237 | extern |
1238 | static |
1239 | auto |
1240 | register |
1241 | |
1242 | type-specifier: |
1243 | void |
1244 | char |
1245 | short |
1246 | int |
1247 | long |
1248 | float |
1249 | double |
1250 | signed |
1251 | unsigned |
1252 | _Bool |
1253 | _Complex |
1254 | |
1255 | type-qualifier: |
1256 | const |
1257 | restrict |
1258 | volatile |
1259 | address-space-qualifier |
1260 | _Atomic |
1261 | |
1262 | */ |
1263 | |
1264 | static void |
1265 | c_parser_gimple_declaration (c_parser *parser) |
1266 | { |
1267 | struct c_declarator *declarator; |
1268 | struct c_declspecs *specs = build_null_declspecs (); |
1269 | c_parser_declspecs (parser, specs, true, true, true, |
1270 | true, true, cla_nonabstract_decl); |
1271 | finish_declspecs (specs); |
1272 | |
1273 | /* Provide better error recovery. Note that a type name here is usually |
1274 | better diagnosed as a redeclaration. */ |
1275 | if (c_parser_next_token_starts_declspecs (parser) |
1276 | && ! c_parser_next_token_is (parser, CPP_NAME)) |
1277 | { |
1278 | c_parser_error (parser, "expected %<;%>" ); |
1279 | c_parser_set_error (parser, false); |
1280 | return; |
1281 | } |
1282 | |
1283 | bool dummy = false; |
1284 | declarator = c_parser_declarator (parser, |
1285 | specs->typespec_kind != ctsk_none, |
1286 | C_DTR_NORMAL, &dummy); |
1287 | |
1288 | if (c_parser_next_token_is (parser, CPP_SEMICOLON)) |
1289 | { |
1290 | /* Handle SSA name decls specially, they do not go into the identifier |
1291 | table but we simply build the SSA name for later lookup. */ |
1292 | unsigned version, ver_offset; |
1293 | if (declarator->kind == cdk_id |
1294 | && is_gimple_reg_type (specs->type) |
1295 | && c_parser_parse_ssa_name_id (declarator->u.id, |
1296 | &version, &ver_offset) |
1297 | /* The following restricts it to unnamed anonymous SSA names |
1298 | which fails parsing of named ones in dumps (we could |
1299 | decide to not dump their name for -gimple). */ |
1300 | && ver_offset == 0) |
1301 | c_parser_parse_ssa_name (parser, declarator->u.id, specs->type, |
1302 | version, ver_offset); |
1303 | else |
1304 | { |
1305 | tree postfix_attrs = NULL_TREE; |
1306 | tree all_prefix_attrs = specs->attrs; |
1307 | specs->attrs = NULL; |
1308 | tree decl = start_decl (declarator, specs, false, |
1309 | chainon (postfix_attrs, all_prefix_attrs)); |
1310 | if (decl) |
1311 | finish_decl (decl, UNKNOWN_LOCATION, NULL_TREE, NULL_TREE, |
1312 | NULL_TREE); |
1313 | } |
1314 | } |
1315 | else |
1316 | { |
1317 | c_parser_error (parser, "expected %<;%>" ); |
1318 | return; |
1319 | } |
1320 | } |
1321 | |
1322 | /* Parse gimple goto statement. */ |
1323 | |
1324 | static void |
1325 | c_parser_gimple_goto_stmt (location_t loc, tree label, gimple_seq *seq) |
1326 | { |
1327 | tree decl = lookup_label_for_goto (loc, label); |
1328 | gimple_seq_add_stmt (seq, gimple_build_goto (decl)); |
1329 | return; |
1330 | } |
1331 | |
1332 | /* Parse a parenthesized condition. |
1333 | gimple-condition: |
1334 | ( gimple-binary-expression ) */ |
1335 | |
1336 | static tree |
1337 | c_parser_gimple_paren_condition (c_parser *parser) |
1338 | { |
1339 | if (! c_parser_require (parser, CPP_OPEN_PAREN, "expected %<(%>" )) |
1340 | return error_mark_node; |
1341 | tree cond = c_parser_gimple_binary_expression (parser).value; |
1342 | if (! c_parser_require (parser, CPP_CLOSE_PAREN, "expected %<)%>" )) |
1343 | return error_mark_node; |
1344 | return cond; |
1345 | } |
1346 | |
1347 | /* Parse gimple if-else statement. |
1348 | |
1349 | if-statement: |
1350 | if ( gimple-binary-expression ) gimple-goto-statement |
1351 | if ( gimple-binary-expression ) gimple-goto-statement \ |
1352 | else gimple-goto-statement |
1353 | */ |
1354 | |
1355 | static void |
1356 | c_parser_gimple_if_stmt (c_parser *parser, gimple_seq *seq) |
1357 | { |
1358 | tree t_label, f_label, label; |
1359 | location_t loc; |
1360 | c_parser_consume_token (parser); |
1361 | tree cond = c_parser_gimple_paren_condition (parser); |
1362 | |
1363 | if (c_parser_next_token_is_keyword (parser, RID_GOTO)) |
1364 | { |
1365 | loc = c_parser_peek_token (parser)->location; |
1366 | c_parser_consume_token (parser); |
1367 | if (! c_parser_next_token_is (parser, CPP_NAME)) |
1368 | { |
1369 | c_parser_error (parser, "expected label" ); |
1370 | return; |
1371 | } |
1372 | label = c_parser_peek_token (parser)->value; |
1373 | c_parser_consume_token (parser); |
1374 | t_label = lookup_label_for_goto (loc, label); |
1375 | if (! c_parser_require (parser, CPP_SEMICOLON, "expected %<;%>" )) |
1376 | return; |
1377 | } |
1378 | else |
1379 | { |
1380 | c_parser_error (parser, "expected goto expression" ); |
1381 | return; |
1382 | } |
1383 | |
1384 | if (c_parser_next_token_is_keyword (parser, RID_ELSE)) |
1385 | c_parser_consume_token (parser); |
1386 | else |
1387 | { |
1388 | c_parser_error (parser, "expected else statement" ); |
1389 | return; |
1390 | } |
1391 | |
1392 | if (c_parser_next_token_is_keyword (parser, RID_GOTO)) |
1393 | { |
1394 | loc = c_parser_peek_token (parser)->location; |
1395 | c_parser_consume_token (parser); |
1396 | if (! c_parser_next_token_is (parser, CPP_NAME)) |
1397 | { |
1398 | c_parser_error (parser, "expected label" ); |
1399 | return; |
1400 | } |
1401 | label = c_parser_peek_token (parser)->value; |
1402 | f_label = lookup_label_for_goto (loc, label); |
1403 | c_parser_consume_token (parser); |
1404 | if (! c_parser_require (parser, CPP_SEMICOLON, "expected %<;%>" )) |
1405 | return; |
1406 | } |
1407 | else |
1408 | { |
1409 | c_parser_error (parser, "expected goto expression" ); |
1410 | return; |
1411 | } |
1412 | |
1413 | if (cond != error_mark_node) |
1414 | gimple_seq_add_stmt (seq, gimple_build_cond_from_tree (cond, t_label, |
1415 | f_label)); |
1416 | } |
1417 | |
1418 | /* Parse gimple switch-statement. |
1419 | |
1420 | gimple-switch-statement: |
1421 | switch (gimple-postfix-expression) gimple-case-statement |
1422 | |
1423 | gimple-case-statement: |
1424 | gimple-case-statement |
1425 | gimple-label-statement : gimple-goto-statment |
1426 | */ |
1427 | |
1428 | static void |
1429 | c_parser_gimple_switch_stmt (c_parser *parser, gimple_seq *seq) |
1430 | { |
1431 | c_expr cond_expr; |
1432 | tree case_label, label; |
1433 | auto_vec<tree> labels; |
1434 | tree default_label = NULL_TREE; |
1435 | gimple_seq switch_body = NULL; |
1436 | c_parser_consume_token (parser); |
1437 | |
1438 | if (! c_parser_require (parser, CPP_OPEN_PAREN, "expected %<(%>" )) |
1439 | return; |
1440 | cond_expr = c_parser_gimple_postfix_expression (parser); |
1441 | if (! c_parser_require (parser, CPP_CLOSE_PAREN, "expected %<)%>" )) |
1442 | return; |
1443 | |
1444 | if (! c_parser_require (parser, CPP_OPEN_BRACE, "expected %<{%>" )) |
1445 | return; |
1446 | |
1447 | while (c_parser_next_token_is_not (parser, CPP_CLOSE_BRACE)) |
1448 | { |
1449 | if (c_parser_next_token_is (parser, CPP_EOF)) |
1450 | { |
1451 | c_parser_error (parser, "expected statement" ); |
1452 | return; |
1453 | } |
1454 | |
1455 | switch (c_parser_peek_token (parser)->keyword) |
1456 | { |
1457 | case RID_CASE: |
1458 | { |
1459 | c_expr exp1; |
1460 | location_t loc = c_parser_peek_token (parser)->location; |
1461 | c_parser_consume_token (parser); |
1462 | |
1463 | if (c_parser_next_token_is (parser, CPP_NAME) |
1464 | || c_parser_peek_token (parser)->type == CPP_NUMBER) |
1465 | exp1 = c_parser_gimple_postfix_expression (parser); |
1466 | else |
1467 | { |
1468 | c_parser_error (parser, "expected expression" ); |
1469 | return; |
1470 | } |
1471 | |
1472 | if (c_parser_next_token_is (parser, CPP_COLON)) |
1473 | { |
1474 | c_parser_consume_token (parser); |
1475 | if (c_parser_next_token_is (parser, CPP_NAME)) |
1476 | { |
1477 | label = c_parser_peek_token (parser)->value; |
1478 | c_parser_consume_token (parser); |
1479 | tree decl = lookup_label_for_goto (loc, label); |
1480 | case_label = build_case_label (exp1.value, NULL_TREE, |
1481 | decl); |
1482 | labels.safe_push (case_label); |
1483 | if (! c_parser_require (parser, CPP_SEMICOLON, |
1484 | "expected %<;%>" )) |
1485 | return; |
1486 | } |
1487 | else if (! c_parser_require (parser, CPP_NAME, |
1488 | "expected label" )) |
1489 | return; |
1490 | } |
1491 | else if (! c_parser_require (parser, CPP_SEMICOLON, |
1492 | "expected %<:%>" )) |
1493 | return; |
1494 | break; |
1495 | } |
1496 | case RID_DEFAULT: |
1497 | { |
1498 | location_t loc = c_parser_peek_token (parser)->location; |
1499 | c_parser_consume_token (parser); |
1500 | if (c_parser_next_token_is (parser, CPP_COLON)) |
1501 | { |
1502 | c_parser_consume_token (parser); |
1503 | if (c_parser_next_token_is (parser, CPP_NAME)) |
1504 | { |
1505 | label = c_parser_peek_token (parser)->value; |
1506 | c_parser_consume_token (parser); |
1507 | tree decl = lookup_label_for_goto (loc, label); |
1508 | default_label = build_case_label (NULL_TREE, NULL_TREE, |
1509 | decl); |
1510 | if (! c_parser_require (parser, CPP_SEMICOLON, |
1511 | "expected %<;%>" )) |
1512 | return; |
1513 | } |
1514 | else if (! c_parser_require (parser, CPP_NAME, |
1515 | "expected label" )) |
1516 | return; |
1517 | } |
1518 | else if (! c_parser_require (parser, CPP_SEMICOLON, |
1519 | "expected %<:%>" )) |
1520 | return; |
1521 | break; |
1522 | } |
1523 | case RID_GOTO: |
1524 | { |
1525 | location_t loc = c_parser_peek_token (parser)->location; |
1526 | c_parser_consume_token (parser); |
1527 | if (c_parser_next_token_is (parser, CPP_NAME)) |
1528 | { |
1529 | c_parser_gimple_goto_stmt (loc, |
1530 | c_parser_peek_token |
1531 | (parser)->value, |
1532 | &switch_body); |
1533 | c_parser_consume_token (parser); |
1534 | if (c_parser_next_token_is (parser, CPP_SEMICOLON)) |
1535 | c_parser_consume_token (parser); |
1536 | else |
1537 | { |
1538 | c_parser_error (parser, "expected semicolon" ); |
1539 | return; |
1540 | } |
1541 | } |
1542 | else if (! c_parser_require (parser, CPP_NAME, |
1543 | "expected label" )) |
1544 | return; |
1545 | break; |
1546 | } |
1547 | default: |
1548 | c_parser_error (parser, "expected case label or goto statement" ); |
1549 | return; |
1550 | } |
1551 | |
1552 | } |
1553 | if (! c_parser_require (parser, CPP_CLOSE_BRACE, "expected %<}%>" )) |
1554 | return; |
1555 | |
1556 | if (cond_expr.value != error_mark_node) |
1557 | { |
1558 | gimple_seq_add_stmt (seq, gimple_build_switch (cond_expr.value, |
1559 | default_label, labels)); |
1560 | gimple_seq_add_seq (seq, switch_body); |
1561 | } |
1562 | } |
1563 | |
1564 | /* Parse gimple return statement. */ |
1565 | |
1566 | static void |
1567 | c_parser_gimple_return_stmt (c_parser *parser, gimple_seq *seq) |
1568 | { |
1569 | location_t loc = c_parser_peek_token (parser)->location; |
1570 | gimple *ret = NULL; |
1571 | c_parser_consume_token (parser); |
1572 | if (c_parser_next_token_is (parser, CPP_SEMICOLON)) |
1573 | { |
1574 | c_finish_gimple_return (loc, NULL_TREE); |
1575 | ret = gimple_build_return (NULL); |
1576 | gimple_seq_add_stmt (seq, ret); |
1577 | } |
1578 | else |
1579 | { |
1580 | location_t xloc = c_parser_peek_token (parser)->location; |
1581 | c_expr expr = c_parser_gimple_unary_expression (parser); |
1582 | if (expr.value != error_mark_node) |
1583 | { |
1584 | c_finish_gimple_return (xloc, expr.value); |
1585 | ret = gimple_build_return (expr.value); |
1586 | gimple_seq_add_stmt (seq, ret); |
1587 | } |
1588 | } |
1589 | } |
1590 | |
1591 | /* Support function for c_parser_gimple_return_stmt. */ |
1592 | |
1593 | static void |
1594 | c_finish_gimple_return (location_t loc, tree retval) |
1595 | { |
1596 | tree valtype = TREE_TYPE (TREE_TYPE (current_function_decl)); |
1597 | |
1598 | /* Use the expansion point to handle cases such as returning NULL |
1599 | in a function returning void. */ |
1600 | source_location xloc = expansion_point_location_if_in_system_header (loc); |
1601 | |
1602 | if (TREE_THIS_VOLATILE (current_function_decl)) |
1603 | warning_at (xloc, 0, |
1604 | "function declared %<noreturn%> has a %<return%> statement" ); |
1605 | |
1606 | if (! retval) |
1607 | current_function_returns_null = 1; |
1608 | else if (valtype == 0 || TREE_CODE (valtype) == VOID_TYPE) |
1609 | { |
1610 | current_function_returns_null = 1; |
1611 | if (TREE_CODE (TREE_TYPE (retval)) != VOID_TYPE) |
1612 | { |
1613 | error_at |
1614 | (xloc, "%<return%> with a value, in function returning void" ); |
1615 | inform (DECL_SOURCE_LOCATION (current_function_decl), |
1616 | "declared here" ); |
1617 | } |
1618 | } |
1619 | else if (TREE_CODE (valtype) != TREE_CODE (TREE_TYPE (retval))) |
1620 | { |
1621 | error_at |
1622 | (xloc, "invalid conversion in return statement" ); |
1623 | inform (DECL_SOURCE_LOCATION (current_function_decl), |
1624 | "declared here" ); |
1625 | } |
1626 | return; |
1627 | } |
1628 | |