diff options
author | Mahesha S <mahesha.llvm@gmail.com> | 2012-10-27 09:05:45 +0000 |
---|---|---|
committer | Mahesha S <mahesha.llvm@gmail.com> | 2012-10-27 09:05:45 +0000 |
commit | 68de140b5d1df4c21cbf5ef1be2abcbfbc835cb5 (patch) | |
tree | 9cfe9f75dc0595f69ea1c8f4c723bc94f7383f67 /lib/Parse/Parser.cpp | |
parent | f3b52315e2ee52bdff9cba31b037c7e6b3adfadc (diff) |
Feature:
OpenMP support.
Sub-Feature:
Support for "#pragma omp ..." registration with
Preprocessor.
Files Changed/Added:
* include/clang/Basic/DiagnosticGroups.td (C)
* include/clang/Basic/DiagnosticParseKinds.td (C)
* include/clang/Basic/TokenKinds.def (C)
* include/clang/Parse/Parser.h (C)
* lib/Parse/Parser.cpp (C)
Test Cases Changed/Added:
* test/Preprocessor/pragma_omp.c (A)
* test/Preprocessor/pragma_omp_ignored_warning.c (A)
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@166869 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/Parse/Parser.cpp')
-rw-r--r-- | lib/Parse/Parser.cpp | 235 |
1 files changed, 235 insertions, 0 deletions
diff --git a/lib/Parse/Parser.cpp b/lib/Parse/Parser.cpp index 99c36365c3..5a235733a5 100644 --- a/lib/Parse/Parser.cpp +++ b/lib/Parse/Parser.cpp @@ -23,6 +23,237 @@ #include "clang/AST/ASTConsumer.h" using namespace clang; + +namespace clang { + +/// \brief An instance of this interface is defined to initiate OpenMP parsing, +/// and to help Parser during subsequent parsing of OpenMP constrcuts. +class OpenMP { + // Private Member Objects. +private: + // \brief The member object reference to the Preprocessor. + Preprocessor &PP; + + // \brief Handler objects which handle different OpenMP pragma directive + // statements. + OwningPtr<PragmaHandler> ParallelHandler; + OwningPtr<PragmaHandler> ForHandler; + OwningPtr<PragmaHandler> SectionsHandler; + OwningPtr<PragmaHandler> SectionHandler; + OwningPtr<PragmaHandler> SingleHandler; + OwningPtr<PragmaHandler> TaskHandler; + OwningPtr<PragmaHandler> MasterHandler; + OwningPtr<PragmaHandler> CriticalHandler; + OwningPtr<PragmaHandler> BarrierHandler; + OwningPtr<PragmaHandler> TaskwaitHandler; + OwningPtr<PragmaHandler> TaskyieldHandler; + OwningPtr<PragmaHandler> AtomicHandler; + OwningPtr<PragmaHandler> FlushHandler; + OwningPtr<PragmaHandler> OrderedHandler; + OwningPtr<PragmaHandler> ThreadPrivateHandler; + + // \brief When an OpenMP pragma is ignored, we emit a warning message + // saying so, but only once per translation unit irrespective of the + // number of OpenMP pragmas appeared in the translation unit. This flag + // keeps track of whether the unkown pragma warning message is emitted + // or not for the current translation unit. + bool OmpUnknownWarned; + + // Private Member Methods. +private: + // \brief When source contains omp pragmas, but user does not pass the + // '-fopenmp' flag, we emit a warning message saying so, but only once per + // source file. + void SetPragmaOmpUnknownWarned() { OmpUnknownWarned = true; } + void ResetPragmaOmpUnknownWarned() { OmpUnknownWarned = false; } + bool PragmaOmpUnknownWarned() { return OmpUnknownWarned; } + + // \brief Handles "\#pragma omp ...". + // It Checks if the user has passed the flag, '-fopenmp', if so, + // it enters the *token* which is *representing* the current OpenMP + // pragma *directive* into the TokenStream, so that the Parser can + // recognizes it and can parse the respective OpenMP pragma directive + // statement. Otherwise, it reports a warning that the current OpenMP + // directive statement will be ignored. However, note that only + // *one* warning message per translation unit is reported + // irrespective of the number of OpenMP directive statments which + // appear in the translation unit. + void HandlePragma(Token &OmpTok, tok::TokenKind TKind) { + if (!PP.getLangOpts().OpenMP) { + if (!PragmaOmpUnknownWarned()) { + PP.Diag(OmpTok, diag::warn_pragma_omp_ignored); + SetPragmaOmpUnknownWarned(); + } + } else { + Token *Toks = new Token[1]; + Toks[0].startToken(); + Toks[0].setKind(TKind); + Toks[0].setLocation(OmpTok.getLocation()); + PP.EnterTokenStream(Toks, 1, /*DisableMacroExpansion=*/true, + /*OwnsTokens=*/false); + } + } + + // Constructors and Destructors. +public: + OpenMP(Preprocessor &pp); + ~OpenMP(); + +private: + // \brief An OpenMP pragma handler interface. It acts as an intermediate + // between the Preprocessor class and the OpenMP (this) class. It by passes + // the omp pragma handling call to OpenMP class upon requested by the + // Preprocessor. + struct PragmaOmpHandler : public PragmaHandler { + friend class OpenMP; + tok::TokenKind TKind; + OpenMP *Omp; + PragmaOmpHandler(tok::TokenKind Kind, StringRef Name, OpenMP *omp) + : PragmaHandler(Name), TKind(Kind), Omp(omp) {} + virtual ~PragmaOmpHandler() { Omp = 0; } + virtual void HandlePragma(Preprocessor &PP, PragmaIntroducerKind Introducer, + Token &OmpTok) { + Omp->HandlePragma(OmpTok, TKind); + } + }; +}; + +} // end of namespace clang + +OpenMP::OpenMP(Preprocessor &pp) + : PP(pp) { + + // Add "#pragma omp ..." handlers. These are removed and destroyed + // in the destructor. + // + // Note that OpenMP pragma annotations below are listed in the same order + // as listed in the OpenMP 3.1 standard specification document. Please + // do *adhere* to the same order. + + // OpenMP parallel constructs. + ParallelHandler.reset(new PragmaOmpHandler( + tok::annot_pragma_omp_parallel, "parallel", this)); + PP.AddPragmaHandler("omp", ParallelHandler.get()); + + // OpenMP work sharing constructs. + ForHandler.reset(new PragmaOmpHandler( + tok::annot_pragma_omp_for, "for", this)); + PP.AddPragmaHandler("omp", ForHandler.get()); + + SectionsHandler.reset(new PragmaOmpHandler( + tok::annot_pragma_omp_sections, "sections", this)); + PP.AddPragmaHandler("omp", SectionsHandler.get()); + + SingleHandler.reset(new PragmaOmpHandler( + tok::annot_pragma_omp_single, "single", this)); + PP.AddPragmaHandler("omp", SingleHandler.get()); + + SectionHandler.reset(new PragmaOmpHandler( + tok::annot_pragma_omp_section, "section", this)); + PP.AddPragmaHandler("omp", SectionHandler.get()); + + // OpenMP combined parallel work sharing constructs. + // FIXME: not supported yet. + + // OpenMP tasking constructs. + TaskHandler.reset(new PragmaOmpHandler( + tok::annot_pragma_omp_task, "task", this)); + PP.AddPragmaHandler("omp", TaskHandler.get()); + + TaskyieldHandler.reset(new PragmaOmpHandler( + tok::annot_pragma_omp_taskyield, "taskyield", this)); + PP.AddPragmaHandler("omp", TaskyieldHandler.get()); + + // OpenMP master and synchronization constructs. + MasterHandler.reset(new PragmaOmpHandler( + tok::annot_pragma_omp_master, "master", this)); + PP.AddPragmaHandler("omp", MasterHandler.get()); + + CriticalHandler.reset(new PragmaOmpHandler( + tok::annot_pragma_omp_critical, "critical", this)); + PP.AddPragmaHandler("omp", CriticalHandler.get()); + + BarrierHandler.reset(new PragmaOmpHandler( + tok::annot_pragma_omp_barrier, "barrier", this)); + PP.AddPragmaHandler("omp", BarrierHandler.get()); + + TaskwaitHandler.reset(new PragmaOmpHandler( + tok::annot_pragma_omp_taskwait, "taskwait", this)); + PP.AddPragmaHandler("omp", TaskwaitHandler.get()); + + AtomicHandler.reset(new PragmaOmpHandler( + tok::annot_pragma_omp_atomic, "atomic", this)); + PP.AddPragmaHandler("omp", AtomicHandler.get()); + + FlushHandler.reset(new PragmaOmpHandler( + tok::annot_pragma_omp_flush, "flush", this)); + PP.AddPragmaHandler("omp", FlushHandler.get()); + + OrderedHandler.reset(new PragmaOmpHandler( + tok::annot_pragma_omp_ordered, "ordered", this)); + PP.AddPragmaHandler("omp", OrderedHandler.get()); + + // OpenMP data environment related constructs. + ThreadPrivateHandler.reset(new PragmaOmpHandler( + tok::annot_pragma_omp_threadprivate, "threadprivate", this)); + PP.AddPragmaHandler("omp", ThreadPrivateHandler.get()); + + // We have not yet reported the unknown OpenMP pragma *warning* message + // as we have not yet started the processing of translation unit. + ResetPragmaOmpUnknownWarned(); +} + +OpenMP::~OpenMP() { + // Remove the "#pragma omp ..." handlers we installed. + // + // Note that OpenMP pragma annotations below are listed in the same order + // as listed in the OpenMP 3.1 standard specification document. Please + // do *adhere* to the same order. + + // OpenMP parallel constructs. + PP.RemovePragmaHandler("omp", ParallelHandler.get()); + ParallelHandler.reset(); + + // OpenMP work sharing constructs. + PP.RemovePragmaHandler("omp", ForHandler.get()); + ForHandler.reset(); + PP.RemovePragmaHandler("omp", SectionsHandler.get()); + SectionsHandler.reset(); + PP.RemovePragmaHandler("omp", SingleHandler.get()); + SingleHandler.reset(); + PP.RemovePragmaHandler("omp", SectionHandler.get()); + SectionHandler.reset(); + + // OpenMP combined parallel work sharing constructs. + // FIXME: Yet to support. + + // OpenMP tasking constructs. + PP.RemovePragmaHandler("omp", TaskHandler.get()); + TaskHandler.reset(); + PP.RemovePragmaHandler("omp", TaskyieldHandler.get()); + TaskyieldHandler.reset(); + + // OpenMP master and synchronization constructs. + PP.RemovePragmaHandler("omp", MasterHandler.get()); + MasterHandler.reset(); + PP.RemovePragmaHandler("omp", CriticalHandler.get()); + CriticalHandler.reset(); + PP.RemovePragmaHandler("omp", BarrierHandler.get()); + BarrierHandler.reset(); + PP.RemovePragmaHandler("omp", TaskwaitHandler.get()); + TaskwaitHandler.reset(); + PP.RemovePragmaHandler("omp", AtomicHandler.get()); + AtomicHandler.reset(); + PP.RemovePragmaHandler("omp", FlushHandler.get()); + FlushHandler.reset(); + PP.RemovePragmaHandler("omp", OrderedHandler.get()); + OrderedHandler.reset(); + + // OpenMP data environment related constructs. + PP.RemovePragmaHandler("omp", ThreadPrivateHandler.get()); + ThreadPrivateHandler.reset(); +} + namespace { /// \brief A comment handler that passes comments found by the preprocessor /// to the parser action. @@ -98,6 +329,8 @@ Parser::Parser(Preprocessor &pp, Sema &actions, bool SkipFunctionBodies) PP.addCommentHandler(CommentSemaHandler.get()); PP.setCodeCompletionHandler(*this); + + OpenMPHandler.reset(new OpenMP(pp)); } /// If a crash happens while the parser is active, print out a line indicating @@ -456,6 +689,8 @@ Parser::~Parser() { PP.clearCodeCompletionHandler(); + OpenMPHandler.reset(); + assert(TemplateIds.empty() && "Still alive TemplateIdAnnotations around?"); } |