diff options
Diffstat (limited to 'gcc/c/c-parser.c')
-rw-r--r-- | gcc/c/c-parser.c | 144 |
1 files changed, 120 insertions, 24 deletions
diff --git a/gcc/c/c-parser.c b/gcc/c/c-parser.c index f1bae8a..05d1e0f 100644 --- a/gcc/c/c-parser.c +++ b/gcc/c/c-parser.c @@ -1406,9 +1406,9 @@ static tree c_parser_c99_block_statement (c_parser *, bool *, location_t * = NULL); static void c_parser_if_statement (c_parser *, bool *, vec<tree> *); static void c_parser_switch_statement (c_parser *, bool *); -static void c_parser_while_statement (c_parser *, bool, bool *); -static void c_parser_do_statement (c_parser *, bool); -static void c_parser_for_statement (c_parser *, bool, bool *); +static void c_parser_while_statement (c_parser *, bool, unsigned short, bool *); +static void c_parser_do_statement (c_parser *, bool, unsigned short); +static void c_parser_for_statement (c_parser *, bool, unsigned short, bool *); static tree c_parser_asm_statement (c_parser *); static tree c_parser_asm_operands (c_parser *); static tree c_parser_asm_goto_operands (c_parser *); @@ -5400,13 +5400,13 @@ c_parser_statement_after_labels (c_parser *parser, bool *if_p, c_parser_switch_statement (parser, if_p); break; case RID_WHILE: - c_parser_while_statement (parser, false, if_p); + c_parser_while_statement (parser, false, 0, if_p); break; case RID_DO: - c_parser_do_statement (parser, false); + c_parser_do_statement (parser, 0, false); break; case RID_FOR: - c_parser_for_statement (parser, false, if_p); + c_parser_for_statement (parser, false, 0, if_p); break; case RID_GOTO: c_parser_consume_token (parser); @@ -5896,7 +5896,8 @@ c_parser_switch_statement (c_parser *parser, bool *if_p) implement -Wparentheses. */ static void -c_parser_while_statement (c_parser *parser, bool ivdep, bool *if_p) +c_parser_while_statement (c_parser *parser, bool ivdep, unsigned short unroll, + bool *if_p) { tree block, cond, body, save_break, save_cont; location_t loc; @@ -5912,6 +5913,11 @@ c_parser_while_statement (c_parser *parser, bool ivdep, bool *if_p) build_int_cst (integer_type_node, annot_expr_ivdep_kind), integer_zero_node); + if (unroll && cond != error_mark_node) + cond = build3 (ANNOTATE_EXPR, TREE_TYPE (cond), cond, + build_int_cst (integer_type_node, + annot_expr_unroll_kind), + build_int_cst (integer_type_node, unroll)); save_break = c_break_label; c_break_label = NULL_TREE; save_cont = c_cont_label; @@ -5946,7 +5952,7 @@ c_parser_while_statement (c_parser *parser, bool ivdep, bool *if_p) */ static void -c_parser_do_statement (c_parser *parser, bool ivdep) +c_parser_do_statement (c_parser *parser, bool ivdep, unsigned short unroll) { tree block, cond, body, save_break, save_cont, new_break, new_cont; location_t loc; @@ -5974,6 +5980,11 @@ c_parser_do_statement (c_parser *parser, bool ivdep) build_int_cst (integer_type_node, annot_expr_ivdep_kind), integer_zero_node); + if (unroll && cond != error_mark_node) + cond = build3 (ANNOTATE_EXPR, TREE_TYPE (cond), cond, + build_int_cst (integer_type_node, + annot_expr_unroll_kind), + build_int_cst (integer_type_node, unroll)); if (!c_parser_require (parser, CPP_SEMICOLON, "expected %<;%>")) c_parser_skip_to_end_of_block_or_statement (parser); c_finish_loop (loc, cond, NULL, body, new_break, new_cont, false); @@ -6040,7 +6051,8 @@ c_parser_do_statement (c_parser *parser, bool ivdep) implement -Wparentheses. */ static void -c_parser_for_statement (c_parser *parser, bool ivdep, bool *if_p) +c_parser_for_statement (c_parser *parser, bool ivdep, unsigned short unroll, + bool *if_p) { tree block, cond, incr, save_break, save_cont, body; /* The following are only used when parsing an ObjC foreach statement. */ @@ -6159,6 +6171,12 @@ c_parser_for_statement (c_parser *parser, bool ivdep, bool *if_p) "%<GCC ivdep%> pragma"); cond = error_mark_node; } + else if (unroll) + { + c_parser_error (parser, "missing loop condition in loop with " + "%<GCC unroll%> pragma"); + cond = error_mark_node; + } else { c_parser_consume_token (parser); @@ -6176,6 +6194,11 @@ c_parser_for_statement (c_parser *parser, bool ivdep, bool *if_p) build_int_cst (integer_type_node, annot_expr_ivdep_kind), integer_zero_node); + if (unroll && cond != error_mark_node) + cond = build3 (ANNOTATE_EXPR, TREE_TYPE (cond), cond, + build_int_cst (integer_type_node, + annot_expr_unroll_kind), + build_int_cst (integer_type_node, unroll)); } /* Parse the increment expression (the third expression in a for-statement). In the case of a foreach-statement, this is @@ -10833,6 +10856,49 @@ c_parser_objc_at_dynamic_declaration (c_parser *parser) } +/* Parse a pragma GCC ivdep. */ + +static bool +c_parse_pragma_ivdep (c_parser *parser) +{ + c_parser_consume_pragma (parser); + c_parser_skip_to_pragma_eol (parser); + return true; +} + +/* Parse a pragma GCC unroll. */ + +static unsigned short +c_parser_pragma_unroll (c_parser *parser) +{ + unsigned short unroll; + c_parser_consume_pragma (parser); + location_t location = c_parser_peek_token (parser)->location; + tree expr = c_parser_expr_no_commas (parser, NULL).value; + mark_exp_read (expr); + expr = c_fully_fold (expr, false, NULL); + HOST_WIDE_INT lunroll = 0; + if (!INTEGRAL_TYPE_P (TREE_TYPE (expr)) + || TREE_CODE (expr) != INTEGER_CST + || (lunroll = tree_to_shwi (expr)) < 0 + || lunroll >= USHRT_MAX) + { + error_at (location, "%<#pragma GCC unroll%> requires an" + " assignment-expression that evaluates to a non-negative" + " integral constant less than %u", USHRT_MAX); + unroll = 0; + } + else + { + unroll = (unsigned short)lunroll; + if (unroll == 0) + unroll = 1; + } + + c_parser_skip_to_pragma_eol (parser); + return unroll; +} + /* Handle pragmas. Some OpenMP pragmas are associated with, and therefore should be considered, statements. ALLOW_STMT is true if we're within the context of a function and such pragmas are to be allowed. Returns @@ -10975,21 +11041,51 @@ c_parser_pragma (c_parser *parser, enum pragma_context context, bool *if_p) return c_parser_omp_ordered (parser, context, if_p); case PRAGMA_IVDEP: - c_parser_consume_pragma (parser); - c_parser_skip_to_pragma_eol (parser); - if (!c_parser_next_token_is_keyword (parser, RID_FOR) - && !c_parser_next_token_is_keyword (parser, RID_WHILE) - && !c_parser_next_token_is_keyword (parser, RID_DO)) - { - c_parser_error (parser, "for, while or do statement expected"); - return false; - } - if (c_parser_next_token_is_keyword (parser, RID_FOR)) - c_parser_for_statement (parser, true, if_p); - else if (c_parser_next_token_is_keyword (parser, RID_WHILE)) - c_parser_while_statement (parser, true, if_p); - else - c_parser_do_statement (parser, true); + { + const bool ivdep = c_parse_pragma_ivdep (parser); + unsigned short unroll; + if (c_parser_peek_token (parser)->pragma_kind == PRAGMA_UNROLL) + unroll = c_parser_pragma_unroll (parser); + else + unroll = 0; + if (!c_parser_next_token_is_keyword (parser, RID_FOR) + && !c_parser_next_token_is_keyword (parser, RID_WHILE) + && !c_parser_next_token_is_keyword (parser, RID_DO)) + { + c_parser_error (parser, "for, while or do statement expected"); + return false; + } + if (c_parser_next_token_is_keyword (parser, RID_FOR)) + c_parser_for_statement (parser, ivdep, unroll, if_p); + else if (c_parser_next_token_is_keyword (parser, RID_WHILE)) + c_parser_while_statement (parser, ivdep, unroll, if_p); + else + c_parser_do_statement (parser, ivdep, unroll); + } + return false; + + case PRAGMA_UNROLL: + { + unsigned short unroll = c_parser_pragma_unroll (parser); + bool ivdep; + if (c_parser_peek_token (parser)->pragma_kind == PRAGMA_IVDEP) + ivdep = c_parse_pragma_ivdep (parser); + else + ivdep = false; + if (!c_parser_next_token_is_keyword (parser, RID_FOR) + && !c_parser_next_token_is_keyword (parser, RID_WHILE) + && !c_parser_next_token_is_keyword (parser, RID_DO)) + { + c_parser_error (parser, "for, while or do statement expected"); + return false; + } + if (c_parser_next_token_is_keyword (parser, RID_FOR)) + c_parser_for_statement (parser, ivdep, unroll, if_p); + else if (c_parser_next_token_is_keyword (parser, RID_WHILE)) + c_parser_while_statement (parser, ivdep, unroll, if_p); + else + c_parser_do_statement (parser, ivdep, unroll); + } return false; case PRAGMA_GCC_PCH_PREPROCESS: |