--- orig/gcc/c-parser.c +++ mod/gcc/c-parser.c @@ -54,6 +54,8 @@ #include "ggc.h" #include "c-common.h" +#include + /* Miscellaneous data and functions needed for the parser. */ @@ -254,6 +256,28 @@ C_ID_NONE } c_id_kind; +/* Stack for OpenMP sections pragma */ +struct obstack *omp_stack; + +typedef enum pragma_omp_kind { + PRAGMA_OMP_NONE = 0, + + PRAGMA_OMP_ATOMIC, + PRAGMA_OMP_BARRIER, + PRAGMA_OMP_CRITICAL, + PRAGMA_OMP_FLUSH, + PRAGMA_OMP_FOR, + PRAGMA_OMP_MASTER, + PRAGMA_OMP_ORDERED, + PRAGMA_OMP_PARALLEL, + PRAGMA_OMP_PARALLEL_FOR, + PRAGMA_OMP_PARALLEL_SECTIONS, + PRAGMA_OMP_SECTION, + PRAGMA_OMP_SECTIONS, + PRAGMA_OMP_SINGLE, + PRAGMA_OMP_THREADPRIVATE +} pragma_omp_kind; + /* A single C token after string literal concatenation and conversion of preprocessing tokens to tokens. */ typedef struct c_token GTY (()) @@ -266,6 +290,7 @@ /* If this token is a keyword, this value indicates which keyword. Otherwise, this value is RID_MAX. */ ENUM_BITFIELD (rid) keyword : 8; + ENUM_BITFIELD (pragma_omp_kind) omp_kind : 8; /* True if this token is from a system header. */ BOOL_BITFIELD in_system_header : 1; /* The value associated with this token, if any. */ @@ -287,6 +312,8 @@ c_parser_error sets this flag. It should clear this flag when enough tokens have been consumed to recover from the error. */ BOOL_BITFIELD error : 1; + /* True if expect statement after #pragma omp section. False otherwise. */ + BOOL_BITFIELD omp_need_statement : 1; } c_parser; /* Read in and lex a single token, storing it in *TOKEN. */ @@ -298,6 +325,8 @@ token->type = c_lex (&token->value); token->location = input_location; token->in_system_header = in_system_header; + token->omp_kind = PRAGMA_OMP_NONE; + switch (token->type) { case CPP_NAME: @@ -378,6 +407,65 @@ token->id_kind = C_ID_NONE; token->keyword = RID_MAX; break; + case CPP_PRAGMA: + token->id_kind = C_ID_NONE; + token->keyword = RID_MAX; + + if (flag_openmp) + { + const char *p = TREE_STRING_POINTER (token->value); + + /* parsing "omp" */ + while (*p != '\n' && isspace (*p)) + ++p; + + if (strncmp ("omp", p, 3)) + break; + + p += 3; + if (!isspace (*p) || *p == '\n') + break; + + /* parsing first word */ + while (*p != '\n' && isspace (*p)) + ++p; + + if (!strncmp ("atomic", p, 6) && isspace (*(p + 6))) + token->omp_kind = PRAGMA_OMP_ATOMIC; + else if (!strncmp ("barrier", p, 7) && isspace (*(p + 7))) + token->omp_kind = PRAGMA_OMP_BARRIER; + else if (!strncmp ("critical", p, 8) && isspace (*(p + 8))) + token->omp_kind = PRAGMA_OMP_CRITICAL; + else if (!strncmp ("flush", p, 5) && isspace (*(p + 5))) + token->omp_kind = PRAGMA_OMP_FLUSH; + else if (!strncmp ("for", p, 3) && isspace (*(p + 3))) + token->omp_kind = PRAGMA_OMP_FOR; + else if (!strncmp ("master", p, 6) && isspace (*(p + 6))) + token->omp_kind = PRAGMA_OMP_MASTER; + else if (!strncmp ("ordered", p, 7) && isspace (*(p + 7))) + token->omp_kind = PRAGMA_OMP_ORDERED; + else if (!strncmp ("parallel", p, 8) && isspace (*(p += 8))) + { + /* parsing second word */ + while (*p != '\n' && isspace (*p)) + ++p; + if (!strncmp ("for", p, 3) && isspace (*(p + 3))) + token->omp_kind = PRAGMA_OMP_PARALLEL_FOR; + else if (!strncmp ("sections", p, 8) && isspace (*(p + 8))) + token->omp_kind = PRAGMA_OMP_PARALLEL_SECTIONS; + else + token->omp_kind = PRAGMA_OMP_PARALLEL; + } + else if (!strncmp ("section", p, 7) && isspace (*(p + 7))) + token->omp_kind = PRAGMA_OMP_SECTION; + else if (!strncmp ("sections", p, 8) && isspace (*(p + 8))) + token->omp_kind = PRAGMA_OMP_SECTIONS; + else if (!strncmp ("single", p, 6) && isspace (*(p + 6))) + token->omp_kind = PRAGMA_OMP_SINGLE; + else if (!strncmp ("threadprivate", p, 13) && isspace (*(p + 13))) + token->omp_kind = PRAGMA_OMP_THREADPRIVATE; + } + break; default: token->id_kind = C_ID_NONE; token->keyword = RID_MAX; @@ -592,7 +680,10 @@ else { gcc_assert (parser->tokens_avail == 1); + /* Need to consume CPP_EOF when handle deferred pragmas */ + /* gcc_assert (parser->tokens[0].type != CPP_EOF); + */ } parser->tokens_avail--; } @@ -947,6 +1038,7 @@ static tree c_parser_objc_receiver (c_parser *); static tree c_parser_objc_message_args (c_parser *); static tree c_parser_objc_keywordexpr (c_parser *); +static void c_parser_pragma (c_parser *); /* Parse a translation unit (C90 6.7, C99 6.9). @@ -1126,7 +1218,12 @@ absence is diagnosed through the diagnosis of implicit int. In GNU C we also allow but diagnose declarations without declaration specifiers, but only at top level (elsewhere they conflict with - other syntax). */ + other syntax). + + OpenMP: + + declaration: + threadprivate-directive */ static void c_parser_declaration_or_fndef (c_parser *parser, bool fndef_ok, bool empty_ok, @@ -1135,6 +1232,14 @@ struct c_declspecs *specs; tree prefix_attrs; tree all_prefix_attrs; + + if (c_parser_next_token_is (parser, CPP_PRAGMA) + && c_parser_peek_token (parser)->omp_kind == PRAGMA_OMP_THREADPRIVATE) + { + c_parser_pragma (parser); + return; + } + bool diagnosed_no_specs = false; specs = build_null_declspecs (); c_parser_declspecs (parser, specs, true, true, start_attr_ok); @@ -3163,7 +3268,12 @@ prefix attributes on the declaration. ??? The syntax follows the old parser in requiring something after label declarations. Although they are erroneous if the labels declared aren't defined, - is it useful for the syntax to be this way? */ + is it useful for the syntax to be this way? + + OpenMP: + + block-item: + openmp-directive */ static tree c_parser_compound_statement (c_parser *parser) @@ -3171,8 +3281,35 @@ tree stmt; if (!c_parser_require (parser, CPP_OPEN_BRACE, "expected %<{%>")) return NULL_TREE; + + if (flag_openmp) + { + int *const omp_p = (int *)obstack_base (omp_stack) - 1; + gcc_assert (*omp_p > -2); + if (*omp_p > -1) + { + ++(*omp_p); + } + } + stmt = c_begin_compound_stmt (true); c_parser_compound_statement_nostart (parser); + + if (flag_openmp) + { + int *const omp_p = (int *)obstack_base (omp_stack) - 1; + gcc_assert (*omp_p != 0); + if (*omp_p > 1) + { + --(*omp_p); + } + else if (*omp_p == 1) + { + obstack_free (omp_stack, omp_p); + printf ("section scope closed\n"); + } + } + return c_end_compound_stmt (stmt, true); } @@ -3292,6 +3429,18 @@ else goto statement; } + else if (c_parser_next_token_is (parser, CPP_PRAGMA)) + { + switch (c_parser_peek_token (parser)->omp_kind) + { + case PRAGMA_OMP_BARRIER: + case PRAGMA_OMP_FLUSH: + c_parser_pragma (parser); + break; + default: + goto statement; + } + } else { statement: @@ -3424,7 +3573,11 @@ objc-throw-statement: @throw expression ; @throw ; -*/ + + OpenMP: + + statement: + openmp-construct */ static void c_parser_statement (c_parser *parser) @@ -3545,6 +3698,60 @@ c_parser_error (parser, "expected statement"); c_parser_consume_token (parser); break; + case CPP_PRAGMA: + switch (c_parser_peek_token (parser)->omp_kind) + { + case PRAGMA_OMP_ATOMIC: + c_parser_pragma (parser); + goto expr_stmt; + case PRAGMA_OMP_CRITICAL: + case PRAGMA_OMP_MASTER: + case PRAGMA_OMP_ORDERED: + case PRAGMA_OMP_PARALLEL: + case PRAGMA_OMP_SINGLE: + c_parser_pragma (parser); + c_parser_statement (parser); + break; + case PRAGMA_OMP_FOR: + case PRAGMA_OMP_PARALLEL_FOR: + c_parser_pragma (parser); + if (!c_parser_next_token_is_keyword (parser, RID_FOR)) + { + c_parser_error (parser, "for statement expected"); + } + break; + case PRAGMA_OMP_PARALLEL_SECTIONS: + case PRAGMA_OMP_SECTIONS: + c_parser_pragma (parser); + if (c_parser_next_token_is (parser, CPP_OPEN_BRACE)) + { + int *const omp_p = XOBNEW (omp_stack, int); + *omp_p = 0; + } + else + { + c_parser_error (parser, "section scope expected"); + } + break; + case PRAGMA_OMP_SECTION: + if (!parser->omp_need_statement + && *((int *)obstack_base (omp_stack) - 1) == 1) + { + c_parser_pragma (parser); + parser->omp_need_statement = true; + c_parser_statement (parser); + gcc_assert (parser->omp_need_statement == false); + } + else + { + c_parser_consume_token (parser); + c_parser_error (parser, "OpenMP pragma 'section' not allowed"); + } + break; + default: + goto expr_stmt; + } + break; default: expr_stmt: stmt = c_finish_expr_stmt (c_parser_expression (parser).value); @@ -3564,6 +3771,11 @@ earlier? */ if (stmt && EXPR_P (stmt)) SET_EXPR_LOCATION (stmt, loc); + + if (parser->omp_need_statement) + { + parser->omp_need_statement = false; + } } /* Parse a parenthesized condition from an if, do or while statement. @@ -6200,19 +6412,1049 @@ } } - -/* The actual parser and external interface. ??? Does this need to be - garbage-collected? */ +/* ====== */ -static GTY (()) c_parser *the_parser; +typedef enum pragma_omp_clause { + PRAGMA_OMP_CLAUSE_NONE = 0, -/* Parse a single source file. */ + PRAGMA_OMP_CLAUSE_COPYIN, + PRAGMA_OMP_CLAUSE_DEFAULT, + PRAGMA_OMP_CLAUSE_FIRSTPRIVATE, + PRAGMA_OMP_CLAUSE_IF, + PRAGMA_OMP_CLAUSE_LASTPRIVATE, + PRAGMA_OMP_CLAUSE_NOWAIT, + PRAGMA_OMP_CLAUSE_NUM_THREADS, + PRAGMA_OMP_CLAUSE_ORDERED, + PRAGMA_OMP_CLAUSE_PRIVATE, + PRAGMA_OMP_CLAUSE_REDUCTION, + PRAGMA_OMP_CLAUSE_SCHEDULE, + PRAGMA_OMP_CLAUSE_SHARED +} pragma_omp_clause; -void -c_parse_file (void) +/* Returns name of the next clause. + If the clause is not recognized PRAGMA_OMP_CLAUSE_NONE is returned and + the token is not consumed. Otherwise appropriate pragma_omp_clause is + returned and the token is consumed. */ + +static pragma_omp_clause c_parser_pragma_omp_clause (c_parser *); + +static pragma_omp_clause +c_parser_pragma_omp_clause (c_parser *parser) { - the_parser = c_parser_new (); - c_parser_translation_unit (the_parser); + pragma_omp_clause result; + + if (c_parser_next_token_is_keyword (parser, RID_IF)) + { + result = PRAGMA_OMP_CLAUSE_IF; + } + else if (c_parser_next_token_is_not (parser, CPP_NAME)) + { + result = PRAGMA_OMP_CLAUSE_NONE; + } + else + { + const char *p = IDENTIFIER_POINTER (c_parser_peek_token (parser)->value); + if (!strcmp ("copyin", p)) + { + result = PRAGMA_OMP_CLAUSE_COPYIN; + } + else if (!strcmp ("default", p)) + { + result = PRAGMA_OMP_CLAUSE_DEFAULT; + } + else if (!strcmp ("firstprivate", p)) + { + result = PRAGMA_OMP_CLAUSE_FIRSTPRIVATE; + } + else if (!strcmp ("lastprivate", p)) + { + result = PRAGMA_OMP_CLAUSE_LASTPRIVATE; + } + else if (!strcmp ("nowait", p)) + { + result = PRAGMA_OMP_CLAUSE_NOWAIT; + } + else if (!strcmp ("num_threads", p)) + { + result = PRAGMA_OMP_CLAUSE_NUM_THREADS; + } + else if (!strcmp ("ordered", p)) + { + result = PRAGMA_OMP_CLAUSE_ORDERED; + } + else if (!strcmp ("private", p)) + { + result = PRAGMA_OMP_CLAUSE_PRIVATE; + } + else if (!strcmp ("reduction", p)) + { + result = PRAGMA_OMP_CLAUSE_REDUCTION; + } + else if (!strcmp ("schedule", p)) + { + result = PRAGMA_OMP_CLAUSE_SCHEDULE; + } + else if (!strcmp ("shared", p)) + { + result = PRAGMA_OMP_CLAUSE_SHARED; + } + else + { + result = PRAGMA_OMP_CLAUSE_NONE; + } + } + + if (result != PRAGMA_OMP_CLAUSE_NONE) + { + c_parser_consume_token (parser); + } + return result; +} + +/* Skip till the CPP_EOF, CPP_EOF is not consumed like + in c_parser_skip_until_found () */ + +static void c_parser_skip_until_eof (c_parser *); + +static void +c_parser_skip_until_eof (c_parser *parser) +{ + while (c_parser_next_token_is_not (parser, CPP_EOF)) + { + c_parser_consume_token (parser); + } +} + +/* Parse variable list in form: + [ CPP_NAME [ CPP_COMMA CPP_NAME [ ... ] ] ] + Return when meets unexpected token, doesn't consume it. + Variables must be defined, otherwise returns and doesn't + consume the variable. */ + +static void c_parser_pragma_omp_variable_list (c_parser *); + +static void +c_parser_pragma_omp_variable_list (c_parser *parser) +{ + printf ("Variable list: "); + + while (c_parser_next_token_is (parser, CPP_NAME)) + { + tree t = lookup_name (c_parser_peek_token (parser)->value); + if (!t || TREE_CODE (t) != VAR_DECL) + { + break; + } + printf ("%s ", IDENTIFIER_POINTER (c_parser_peek_token (parser)->value)); + c_parser_consume_token (parser); + + if (c_parser_next_token_is_not (parser, CPP_COMMA)) + { + break; + } + c_parser_consume_token (parser); + } + printf ("\n"); +} + +/* OpenMP pragma clauses handlers. Each CLAUSE has a handler + static void c_parser_pragma_omp_clause_CLAUSE (c_parser *). + Each handler consumes all tokens the clause consists of. + If unexpected token found - skips untill CPP_EOF is found, + CPP_EOF is not consumed. */ + +static void c_parser_pragma_omp_clause_copyin (c_parser *); + +static void +c_parser_pragma_omp_clause_copyin (c_parser *parser) +{ + printf ("copyin\n"); + + if (c_parser_require (parser, CPP_OPEN_PAREN, "'(' expected")) + { + c_parser_pragma_omp_variable_list (parser); + if (!c_parser_require (parser, CPP_CLOSE_PAREN, "')' expected")) + { + c_parser_skip_until_eof (parser); + } + } + else + { + c_parser_skip_until_eof (parser); + } +} + +static void c_parser_pragma_omp_clause_default (c_parser *); + +static void +c_parser_pragma_omp_clause_default (c_parser *parser) +{ + printf ("default: "); + + if (c_parser_require (parser, CPP_OPEN_PAREN, "'(' expected")) + { + if (c_parser_next_token_is (parser, CPP_NAME)) + { + const char *p = IDENTIFIER_POINTER (c_parser_peek_token (parser)->value); + if (!strcmp ("none", p)) + { + printf ("none\n"); + } + else if (!strcmp ("shared", p)) + { + printf ("shared\n"); + } + else + { + goto error; + } + c_parser_consume_token (parser); + if (!c_parser_require (parser, CPP_CLOSE_PAREN, "')' expected")) + { + c_parser_skip_until_eof (parser); + } + } + else + { + error: + c_parser_error (parser, "'none' or 'shared' expected"); + c_parser_skip_until_eof (parser); + } + } + else + { + c_parser_skip_until_eof (parser); + } +} + +static void c_parser_pragma_omp_clause_firstprivate (c_parser *); + +static void +c_parser_pragma_omp_clause_firstprivate (c_parser *parser) +{ + printf ("firstprivate\n"); + + if (c_parser_require (parser, CPP_OPEN_PAREN, "'(' expected")) + { + c_parser_pragma_omp_variable_list (parser); + if (!c_parser_require (parser, CPP_CLOSE_PAREN, "')' expected")) + { + c_parser_skip_until_eof (parser); + } + } + else + { + c_parser_skip_until_eof (parser); + } +} + +static void c_parser_pragma_omp_clause_if (c_parser *); + +static void +c_parser_pragma_omp_clause_if (c_parser *parser) +{ + printf ("if: "); + + if (c_parser_next_token_is (parser, CPP_OPEN_PAREN)) + { + tree t = c_parser_paren_condition (parser); + print_generic_expr (stdout, t, 0); + printf ("\n"); + } + else + { + c_parser_error (parser, "'(' expected"); + c_parser_skip_until_eof (parser); + } +} + +static void c_parser_pragma_omp_clause_lastprivate (c_parser *); + +static void +c_parser_pragma_omp_clause_lastprivate (c_parser *parser) +{ + printf ("lastprivate\n"); + + if (c_parser_require (parser, CPP_OPEN_PAREN, "'(' expected")) + { + c_parser_pragma_omp_variable_list (parser); + if (!c_parser_require (parser, CPP_CLOSE_PAREN, "')' expected")) + { + c_parser_skip_until_eof (parser); + } + } + else + { + c_parser_skip_until_eof (parser); + } +} + +static inline void c_parser_pragma_omp_clause_nowait (c_parser *); + +static inline void +c_parser_pragma_omp_clause_nowait (c_parser *parser ATTRIBUTE_UNUSED) +{ + printf ("nowait\n"); +} + +static inline void c_parser_pragma_omp_clause_num_threads (c_parser *); + +static inline void +c_parser_pragma_omp_clause_num_threads (c_parser *parser) +{ + printf ("num_threads: "); + + if (c_parser_require (parser, CPP_OPEN_PAREN, "'(' expected")) + { + tree t = c_parser_expression (parser).value; + + if (TREE_CODE (TREE_TYPE (t)) == INTEGER_TYPE) + { + print_generic_expr (stdout, t, 0); + if (!c_parser_require (parser, CPP_CLOSE_PAREN, "')' expected")) + { + c_parser_skip_until_eof (parser); + } + } + else + { + c_parser_error (parser, "integer expression expected"); + c_parser_skip_until_eof (parser); + } + } + else + { + c_parser_skip_until_eof (parser); + } + printf ("\n"); +} + +static inline void c_parser_pragma_omp_clause_ordered (c_parser *); + +static inline void +c_parser_pragma_omp_clause_ordered (c_parser *parser ATTRIBUTE_UNUSED) +{ + printf ("ordered\n"); +} + +static void c_parser_pragma_omp_clause_private (c_parser *); + +static void +c_parser_pragma_omp_clause_private (c_parser *parser) +{ + printf ("private\n"); + + if (c_parser_require (parser, CPP_OPEN_PAREN, "'(' expected")) + { + c_parser_pragma_omp_variable_list (parser); + if (!c_parser_require (parser, CPP_CLOSE_PAREN, "')' expected")) + { + c_parser_skip_until_eof (parser); + } + } + else + { + c_parser_skip_until_eof (parser); + } +} + +static void c_parser_pragma_omp_clause_reduction (c_parser *); + +static void +c_parser_pragma_omp_clause_reduction (c_parser *parser) + { + printf ("reduction\n"); + + if (c_parser_require (parser, CPP_OPEN_PAREN, "'(' expected")) + { + switch (c_parser_peek_token (parser)->type) + { + case CPP_PLUS: + printf ("\treduction-operator: '+'\n"); + break; + case CPP_MULT: + printf ("\treduction-operator: '*'\n"); + break; + case CPP_MINUS: + printf ("\treduction-operator: '-'\n"); + break; + case CPP_AND: + printf ("\treduction-operator: '&'\n"); + break; + case CPP_XOR: + printf ("\treduction-operator: '^'\n"); + break; + case CPP_OR: + printf ("\treduction-operator: '|'\n"); + break; + case CPP_AND_AND: + printf ("\treduction-operator: '&&'\n"); + break; + case CPP_OR_OR: + printf ("\treduction-operator: '||'\n"); + break; + default: + c_parser_error (parser, "reduction-operator expected"); + goto error; + } + c_parser_consume_token (parser); + if (c_parser_require (parser, CPP_COLON, "':' expected")) + { + c_parser_pragma_omp_variable_list (parser); + c_parser_require (parser, CPP_CLOSE_PAREN, "')' expected"); + } + else + { + c_parser_skip_until_eof (parser); + } + } + else + { + error: + c_parser_skip_until_eof (parser); + } +} + +static void c_parser_pragma_omp_clause_schedule (c_parser *); + +static void +c_parser_pragma_omp_clause_schedule (c_parser *parser) +{ + printf ("schedule: "); + + if (c_parser_require (parser, CPP_OPEN_PAREN, "'(' expected")) + { + if (c_parser_next_token_is (parser, CPP_NAME)) + { + const char *p = IDENTIFIER_POINTER (c_parser_peek_token (parser)->value); + if (!strcmp ("dynamic", p)) + { + printf ("dynamic"); + } + else if (!strcmp ("guided", p)) + { + printf ("guided"); + } + else if (!strcmp ("runtime", p)) + { + printf ("runtime"); + c_parser_consume_token (parser); + goto skip_chunk; + } + else if (!strcmp ("static", p)) + { + printf ("static"); + } + else + { + goto error; + } + c_parser_consume_token (parser); + if (c_parser_next_token_is (parser, CPP_COMMA)) + { + tree t; + c_parser_consume_token (parser); + + t = c_parser_expression (parser).value; + + if (TREE_CODE (TREE_TYPE (t)) == INTEGER_TYPE) + { + printf (", "); + + print_generic_expr (stdout, t, 0); + + skip_chunk: + if (!c_parser_require (parser, CPP_CLOSE_PAREN, "')' expected")) + { + c_parser_skip_until_eof (parser); + } + } + else + { + c_parser_error (parser, "integer expression expected"); + c_parser_skip_until_eof (parser); + } + } + } + else + { + error: + c_parser_error (parser, "unknown schedule kind"); + c_parser_skip_until_eof (parser); + } + } + else + { + c_parser_skip_until_eof (parser); + } + printf ("\n"); +} + +static void c_parser_pragma_omp_clause_shared (c_parser *); + +static void +c_parser_pragma_omp_clause_shared (c_parser *parser) +{ + printf ("shared\n"); + + if (c_parser_require (parser, CPP_OPEN_PAREN, "'(' expected")) + { + c_parser_pragma_omp_variable_list (parser); + if (!c_parser_require (parser, CPP_CLOSE_PAREN, "')' expected")) + { + c_parser_skip_until_eof (parser); + } + } + else + { + c_parser_skip_until_eof (parser); + } +} + +/* OpenMP pragma handlers. Each PRAGMA has a handler + static inline void c_parser_pragma_omp_PRAGMA (c_parser *). + Parses untill CPP_EOF is found. CPP_EOF is consumed. */ + +static inline void c_parser_pragma_omp_atomic (c_parser *); + +static inline void +c_parser_pragma_omp_atomic (c_parser *parser) +{ + printf ("#pragma omp atomic\n"); + + if (!c_parser_require (parser, CPP_EOF, "EOF expected")) + { + c_parser_skip_until_eof (parser); + c_parser_consume_token (parser); + } +} + +static inline void c_parser_pragma_omp_barrier (c_parser *); + +static inline void +c_parser_pragma_omp_barrier (c_parser *parser) +{ + printf ("#pragma omp barrier\n"); + + if (!c_parser_require (parser, CPP_EOF, "EOF expected")) + { + c_parser_skip_until_eof (parser); + c_parser_consume_token (parser); + } +} + +static inline void c_parser_pragma_omp_critical (c_parser *); + +static inline void +c_parser_pragma_omp_critical (c_parser *parser) +{ + printf ("#pragma omp critical\n"); + + if (c_parser_next_token_is (parser, CPP_OPEN_PAREN)) + { + c_parser_consume_token (parser); + if (c_parser_next_token_is_not (parser, CPP_NAME)) + { + c_parser_error (parser, "identifier expected"); + goto error; + } + printf ("region-phrase: %s\n", + IDENTIFIER_POINTER (c_parser_peek_token (parser)->value)); + c_parser_consume_token (parser); + c_parser_require (parser, CPP_CLOSE_PAREN, "')' expected"); + } + + if (!c_parser_require (parser, CPP_EOF, "EOF expected")) + { + error: + c_parser_skip_until_eof (parser); + c_parser_consume_token (parser); + } +} + +static inline void c_parser_pragma_omp_flush (c_parser *); + +static inline void +c_parser_pragma_omp_flush (c_parser *parser) +{ + printf ("#pragma omp flush\n"); + + if (c_parser_next_token_is (parser, CPP_OPEN_PAREN)) + { + c_parser_consume_token (parser); + c_parser_pragma_omp_variable_list (parser); + c_parser_require (parser, CPP_CLOSE_PAREN, "')' expected"); + } + + if (!c_parser_require (parser, CPP_EOF, "EOF expected")) + { + c_parser_skip_until_eof (parser); + c_parser_consume_token (parser); + } +} + +static inline void c_parser_pragma_omp_for (c_parser *); + +static inline void +c_parser_pragma_omp_for (c_parser *parser) +{ + printf ("#pragma omp for\n"); + while (c_parser_next_token_is_not (parser, CPP_EOF)) + { + const pragma_omp_clause c = c_parser_pragma_omp_clause (parser); + + switch (c) + { + case PRAGMA_OMP_CLAUSE_FIRSTPRIVATE: + c_parser_pragma_omp_clause_firstprivate (parser); + break; + case PRAGMA_OMP_CLAUSE_LASTPRIVATE: + c_parser_pragma_omp_clause_lastprivate (parser); + break; + case PRAGMA_OMP_CLAUSE_NOWAIT: + c_parser_pragma_omp_clause_nowait (parser); + break; + case PRAGMA_OMP_CLAUSE_ORDERED: + c_parser_pragma_omp_clause_ordered (parser); + break; + case PRAGMA_OMP_CLAUSE_PRIVATE: + c_parser_pragma_omp_clause_private (parser); + break; + case PRAGMA_OMP_CLAUSE_REDUCTION: + c_parser_pragma_omp_clause_reduction (parser); + break; + case PRAGMA_OMP_CLAUSE_SCHEDULE: + c_parser_pragma_omp_clause_schedule (parser); + break; + default: + c_parser_error (parser, "unknown clause"); + c_parser_skip_until_eof (parser); + break; + } + } + c_parser_consume_token (parser); +} + +static inline void c_parser_pragma_omp_master (c_parser *); + +static inline void +c_parser_pragma_omp_master (c_parser *parser) +{ + printf ("#pragma omp master\n"); + + if (!c_parser_require (parser, CPP_EOF, "EOF expected")) + { + c_parser_skip_until_eof (parser); + c_parser_consume_token (parser); + } +} + +static inline void c_parser_pragma_omp_ordered (c_parser *); + +static inline void +c_parser_pragma_omp_ordered (c_parser *parser) +{ + printf ("#pragma omp ordered\n"); + + if (!c_parser_require (parser, CPP_EOF, "EOF expected")) + { + c_parser_skip_until_eof (parser); + c_parser_consume_token (parser); + } +} + +static inline void c_parser_pragma_omp_parallel (c_parser *); + +static inline void +c_parser_pragma_omp_parallel (c_parser *parser) +{ + printf ("#pragma omp parallel\n"); + while (c_parser_next_token_is_not (parser, CPP_EOF)) + { + const pragma_omp_clause c = c_parser_pragma_omp_clause (parser); + + switch (c) + { + case PRAGMA_OMP_CLAUSE_COPYIN: + c_parser_pragma_omp_clause_copyin (parser); + break; + case PRAGMA_OMP_CLAUSE_DEFAULT: + c_parser_pragma_omp_clause_default (parser); + break; + case PRAGMA_OMP_CLAUSE_FIRSTPRIVATE: + c_parser_pragma_omp_clause_firstprivate (parser); + break; + case PRAGMA_OMP_CLAUSE_IF: + c_parser_pragma_omp_clause_if (parser); + break; + case PRAGMA_OMP_CLAUSE_NUM_THREADS: + c_parser_pragma_omp_clause_num_threads (parser); + break; + case PRAGMA_OMP_CLAUSE_PRIVATE: + c_parser_pragma_omp_clause_private (parser); + break; + case PRAGMA_OMP_CLAUSE_REDUCTION: + c_parser_pragma_omp_clause_reduction (parser); + break; + case PRAGMA_OMP_CLAUSE_SHARED: + c_parser_pragma_omp_clause_shared (parser); + break; + default: + c_parser_error (parser, "unknown clause"); + c_parser_skip_until_eof (parser); + break; + } + } + c_parser_consume_token (parser); +} + +static inline void c_parser_pragma_omp_parallel_for (c_parser *); + +static inline void +c_parser_pragma_omp_parallel_for (c_parser *parser) +{ + printf ("#pragma omp parallel for\n"); + while (c_parser_next_token_is_not (parser, CPP_EOF)) + { + const pragma_omp_clause c = c_parser_pragma_omp_clause (parser); + + switch (c) + { + case PRAGMA_OMP_CLAUSE_COPYIN: + c_parser_pragma_omp_clause_copyin (parser); + break; + case PRAGMA_OMP_CLAUSE_DEFAULT: + c_parser_pragma_omp_clause_default (parser); + break; + case PRAGMA_OMP_CLAUSE_FIRSTPRIVATE: + c_parser_pragma_omp_clause_firstprivate (parser); + break; + case PRAGMA_OMP_CLAUSE_IF: + c_parser_pragma_omp_clause_if (parser); + break; + case PRAGMA_OMP_CLAUSE_LASTPRIVATE: + c_parser_pragma_omp_clause_lastprivate (parser); + break; + case PRAGMA_OMP_CLAUSE_NUM_THREADS: + c_parser_pragma_omp_clause_num_threads (parser); + break; + case PRAGMA_OMP_CLAUSE_ORDERED: + c_parser_pragma_omp_clause_ordered (parser); + break; + case PRAGMA_OMP_CLAUSE_PRIVATE: + c_parser_pragma_omp_clause_private (parser); + break; + case PRAGMA_OMP_CLAUSE_REDUCTION: + c_parser_pragma_omp_clause_reduction (parser); + break; + case PRAGMA_OMP_CLAUSE_SCHEDULE: + c_parser_pragma_omp_clause_schedule (parser); + break; + case PRAGMA_OMP_CLAUSE_SHARED: + c_parser_pragma_omp_clause_shared (parser); + break; + default: + c_parser_error (parser, "unknown clause"); + c_parser_skip_until_eof (parser); + break; + } + } + c_parser_consume_token (parser); +} + +static inline void c_parser_pragma_omp_parallel_sections (c_parser *); + +static inline void +c_parser_pragma_omp_parallel_sections (c_parser *parser) +{ + printf ("#pragma omp parallel sections\n"); + while (c_parser_next_token_is_not (parser, CPP_EOF)) + { + const pragma_omp_clause c = c_parser_pragma_omp_clause (parser); + + switch (c) + { + case PRAGMA_OMP_CLAUSE_COPYIN: + c_parser_pragma_omp_clause_copyin (parser); + break; + case PRAGMA_OMP_CLAUSE_DEFAULT: + c_parser_pragma_omp_clause_default (parser); + break; + case PRAGMA_OMP_CLAUSE_FIRSTPRIVATE: + c_parser_pragma_omp_clause_firstprivate (parser); + break; + case PRAGMA_OMP_CLAUSE_IF: + c_parser_pragma_omp_clause_if (parser); + break; + case PRAGMA_OMP_CLAUSE_LASTPRIVATE: + c_parser_pragma_omp_clause_lastprivate (parser); + break; + case PRAGMA_OMP_CLAUSE_PRIVATE: + c_parser_pragma_omp_clause_private (parser); + break; + case PRAGMA_OMP_CLAUSE_REDUCTION: + c_parser_pragma_omp_clause_reduction (parser); + break; + case PRAGMA_OMP_CLAUSE_SHARED: + c_parser_pragma_omp_clause_shared (parser); + break; + default: + c_parser_error (parser, "unknown clause"); + c_parser_skip_until_eof (parser); + break; + } + } + c_parser_consume_token (parser); +} + +static inline void c_parser_pragma_omp_section (c_parser *); + +static inline void +c_parser_pragma_omp_section (c_parser *parser) +{ + printf ("#pragma omp section\n"); + + if (!c_parser_require (parser, CPP_EOF, "EOF expected")) + { + c_parser_skip_until_eof (parser); + c_parser_consume_token (parser); + } +} + +static inline void c_parser_pragma_omp_sections (c_parser *); + +static inline void +c_parser_pragma_omp_sections (c_parser *parser) +{ + printf ("#pragma omp sections\n"); + while (c_parser_next_token_is_not (parser, CPP_EOF)) + { + const pragma_omp_clause c = c_parser_pragma_omp_clause (parser); + + switch (c) + { + case PRAGMA_OMP_CLAUSE_FIRSTPRIVATE: + c_parser_pragma_omp_clause_firstprivate (parser); + break; + case PRAGMA_OMP_CLAUSE_LASTPRIVATE: + c_parser_pragma_omp_clause_lastprivate (parser); + break; + case PRAGMA_OMP_CLAUSE_NOWAIT: + c_parser_pragma_omp_clause_nowait (parser); + break; + case PRAGMA_OMP_CLAUSE_PRIVATE: + c_parser_pragma_omp_clause_private (parser); + break; + case PRAGMA_OMP_CLAUSE_REDUCTION: + c_parser_pragma_omp_clause_reduction (parser); + break; + default: + c_parser_error (parser, "unknown clause"); + c_parser_skip_until_eof (parser); + break; + } + } + c_parser_consume_token (parser); +} + +static inline void c_parser_pragma_omp_single (c_parser *); + +static inline void +c_parser_pragma_omp_single (c_parser *parser) +{ + printf ("#pragma omp single\n"); + while (c_parser_next_token_is_not (parser, CPP_EOF)) + { + const pragma_omp_clause c = c_parser_pragma_omp_clause (parser); + + switch (c) + { + case PRAGMA_OMP_CLAUSE_FIRSTPRIVATE: + c_parser_pragma_omp_clause_firstprivate (parser); + break; + case PRAGMA_OMP_CLAUSE_NOWAIT: + c_parser_pragma_omp_clause_nowait (parser); + break; + case PRAGMA_OMP_CLAUSE_PRIVATE: + c_parser_pragma_omp_clause_private (parser); + break; + default: + c_parser_error (parser, "unknown clause"); + c_parser_skip_until_eof (parser); + break; + } + } + c_parser_consume_token (parser); +} + +static inline void c_parser_pragma_omp_threadprivate (c_parser *); + +static inline void +c_parser_pragma_omp_threadprivate (c_parser *parser) +{ + printf ("#pragma omp threadprivate\n"); + + if (c_parser_require (parser, CPP_OPEN_PAREN, "'(' expected")) + { + c_parser_pragma_omp_variable_list (parser); + c_parser_require (parser, CPP_CLOSE_PAREN, "')' expected"); + } + + if (!c_parser_require (parser, CPP_EOF, "EOF expected")) + { + c_parser_skip_until_eof (parser); + c_parser_consume_token (parser); + } +} + +/* Consume and handle a CPP_PRAGMA token. + Taken from gcc/cp/parser.c: cp_lexer_handle_pragma (). */ + +static void +c_parser_pragma (c_parser *parser) +{ + cpp_string s; + c_token *token = c_parser_peek_token (parser); + c_parser_consume_token (parser); + gcc_assert (token->type == CPP_PRAGMA); + gcc_assert (token->value); + + s.len = TREE_STRING_LENGTH (token->value); + s.text = TREE_STRING_POINTER (token->value); + + cpp_handle_deferred_pragma (parse_in, &s); + + /* Clearing token->value here means that we will get an ICE if we + try to process this #pragma again (which should be impossible). */ + token->value = NULL; // ??? +} + + + +/* The actual parser and external interface. ??? Does this need to be + garbage-collected? */ + +static GTY (()) c_parser *the_parser; + +/* Handle OpenMP pragmas. + Calls appropriate handlers. The pragma must be valid. */ + +static void c_parser_handle_pragma_omp (cpp_reader *); + +static void +c_parser_handle_pragma_omp (cpp_reader *pfile ATTRIBUTE_UNUSED) +{ + gcc_assert (c_parser_next_token_is (the_parser, CPP_NAME) + || c_parser_next_token_is_keyword (the_parser, RID_FOR)); + + if (c_parser_next_token_is (the_parser, CPP_NAME)) + { + const c_token *token = c_parser_peek_token (the_parser); + const char *p = IDENTIFIER_POINTER (token->value); + switch (*p) + { + case 'a': + c_parser_consume_token (the_parser); + c_parser_pragma_omp_atomic (the_parser); + break; + case 'b': + c_parser_consume_token (the_parser); + c_parser_pragma_omp_barrier (the_parser); + break; + case 'c': + c_parser_consume_token (the_parser); + c_parser_pragma_omp_critical (the_parser); + break; + case 'f': + c_parser_consume_token (the_parser); + c_parser_pragma_omp_flush (the_parser); + break; + case 'm': + c_parser_consume_token (the_parser); + c_parser_pragma_omp_master (the_parser); + break; + case 'p': + c_parser_consume_token (the_parser); + if (c_parser_next_token_is_keyword (the_parser, RID_FOR)) + { + c_parser_consume_token (the_parser); + c_parser_pragma_omp_parallel_for (the_parser); + } + else if (c_parser_next_token_is (the_parser, CPP_NAME) + && !strcmp ("sections", IDENTIFIER_POINTER + (c_parser_peek_token (the_parser)->value))) + { + c_parser_consume_token (the_parser); + c_parser_pragma_omp_parallel_sections (the_parser); + } + else + { + c_parser_pragma_omp_parallel (the_parser); + } + break; + case 's': + if (*(p + 1) == 'e') + { + if (IDENTIFIER_LENGTH (token->value) == 7) + { + c_parser_consume_token (the_parser); + c_parser_pragma_omp_section (the_parser); + } + else + { + c_parser_consume_token (the_parser); + c_parser_pragma_omp_sections (the_parser); + } + } + else + { + c_parser_consume_token (the_parser); + c_parser_pragma_omp_single (the_parser); + } + break; + case 't': + c_parser_consume_token (the_parser); + c_parser_pragma_omp_threadprivate (the_parser); + break; + } + } + else + { + c_parser_consume_token (the_parser); + c_parser_pragma_omp_for (the_parser); + } +} + +/* Parse a single source file. */ + +void +c_parse_file (void) +{ + if (flag_openmp) + { + /* we want to handle deferred pragmas */ + cpp_get_options (parse_in)->defer_pragmas = true; + /* register OpenMP pragmas handler */ + c_register_pragma (0, "omp", c_parser_handle_pragma_omp); + + omp_stack = XNEW (struct obstack); + gcc_obstack_init (omp_stack); + { + int *const omp_p = XOBNEW (omp_stack, int); + *omp_p = -1; + } + } + + the_parser = c_parser_new (); + + c_parser_translation_unit (the_parser); + + if (flag_openmp) + { + obstack_free (omp_stack, 0); + XDELETE (omp_stack); + } + the_parser = NULL; } --- orig/gcc/c.opt +++ mod/gcc/c.opt @@ -600,6 +600,10 @@ ObjC ObjC++ Enable Objective-C setjmp exception handling runtime +fopenmp +C Var(flag_openmp) +Enable OpenMP + foperator-names C++ ObjC++ Recognize C++ kewords like \"compl\" and \"xor\" --- orig/libcpp/lex.c +++ mod/libcpp/lex.c @@ -742,7 +742,10 @@ else { result = &pfile->directive_result; + /* Want to change line when handling deferred pragmas */ + /* break; + */ } }