Index: include/clang/Basic/Attr.td =================================================================== --- include/clang/Basic/Attr.td +++ include/clang/Basic/Attr.td @@ -1757,53 +1757,53 @@ let Documentation = [Undocumented]; } -def Unaligned : IgnoredAttr { - let Spellings = [Keyword<"__unaligned">]; -} - -def LoopHint : Attr { - /// vectorize: vectorizes loop operations if 'value != 0'. - /// vectorize_width: vectorize loop operations with width 'value'. - /// interleave: interleave multiple loop iterations if 'value != 0'. - /// interleave_count: interleaves 'value' loop interations. - - /// FIXME: Add Pragma spelling to tablegen and - /// use it here. - let Spellings = [Keyword<"loop">]; - - /// State of the loop optimization specified by the spelling. - let Args = [EnumArgument<"Option", "OptionType", - ["vectorize", "vectorize_width", "interleave", "interleave_count"], - ["Vectorize", "VectorizeWidth", "Interleave", "InterleaveCount"]>, - DefaultIntArgument<"Value", 1>]; - - let AdditionalMembers = [{ - static StringRef getOptionName(int Option) { - switch(Option) { - case Vectorize: return "vectorize"; - case VectorizeWidth: return "vectorize_width"; - case Interleave: return "interleave"; - case InterleaveCount: return "interleave_count"; - } - llvm_unreachable("Unhandled LoopHint option."); - } - - static StringRef getValueName(int Value) { - if (Value) - return "enable"; - return "disable"; - } - - // FIXME: Modify pretty printer to print this pragma. - void print(raw_ostream &OS, const PrintingPolicy &Policy) const { - OS << "#pragma clang loop " << getOptionName(option) << "("; - if (option == VectorizeWidth || option == InterleaveCount) - OS << value; - else - OS << getValueName(value); - OS << ")\n"; - } - }]; - - let Documentation = [Undocumented]; -} +def Unaligned : IgnoredAttr { + let Spellings = [Keyword<"__unaligned">]; +} + +def LoopHint : Attr { + /// vectorize: vectorizes loop operations if 'value != 0'. + /// vectorize_width: vectorize loop operations with width 'value'. + /// interleave: interleave multiple loop iterations if 'value != 0'. + /// interleave_count: interleaves 'value' loop interations. + + /// FIXME: Add Pragma spelling to tablegen and + /// use it here. + let Spellings = [Keyword<"loop">]; + + /// State of the loop optimization specified by the spelling. + let Args = [EnumArgument<"Option", "OptionType", + ["vectorize", "vectorize_width", "interleave", "interleave_count"], + ["Vectorize", "VectorizeWidth", "Interleave", "InterleaveCount"]>, + DefaultIntArgument<"Value", 1>]; + + let AdditionalMembers = [{ + static StringRef getOptionName(int Option) { + switch(Option) { + case Vectorize: return "vectorize"; + case VectorizeWidth: return "vectorize_width"; + case Interleave: return "interleave"; + case InterleaveCount: return "interleave_count"; + } + llvm_unreachable("Unhandled LoopHint option."); + } + + static StringRef getValueName(int Value) { + if (Value) + return "enable"; + return "disable"; + } + + // FIXME: Modify pretty printer to print this pragma. + void print(raw_ostream &OS, const PrintingPolicy &Policy) const { + OS << "#pragma clang loop " << getOptionName(option) << "("; + if (option == VectorizeWidth || option == InterleaveCount) + OS << value; + else + OS << getValueName(value); + OS << ")\n"; + } + }]; + + let Documentation = [Undocumented]; +} Index: include/clang/Basic/DiagnosticParseKinds.td =================================================================== --- include/clang/Basic/DiagnosticParseKinds.td +++ include/clang/Basic/DiagnosticParseKinds.td @@ -889,16 +889,16 @@ def err_omp_expected_punc : Error< "expected ',' or ')' in '%0' clause">; def err_omp_unexpected_clause : Error< - "unexpected OpenMP clause '%0' in directive '#pragma omp %1'">; -def err_omp_more_one_clause : Error< - "directive '#pragma omp %0' cannot contain more than one '%1' clause">; - -// Pragma loop support. -def err_pragma_loop_invalid_option : Error< - "%select{invalid|missing}0 option%select{ %1|}0; expected vectorize, vectorize_width, interleave, or interleave_count">; -} // end of Parse Issue category. - -let CategoryName = "Modules Issue" in { + "unexpected OpenMP clause '%0' in directive '#pragma omp %1'">; +def err_omp_more_one_clause : Error< + "directive '#pragma omp %0' cannot contain more than one '%1' clause">; + +// Pragma loop support. +def err_pragma_loop_invalid_option : Error< + "%select{invalid|missing}0 option%select{ %1|}0; expected vectorize, vectorize_width, interleave, or interleave_count">; +} // end of Parse Issue category. + +let CategoryName = "Modules Issue" in { def err_module_expected_ident : Error< "expected a module name after module import">; def err_module_expected_semi : Error< Index: include/clang/Basic/DiagnosticSemaKinds.td =================================================================== --- include/clang/Basic/DiagnosticSemaKinds.td +++ include/clang/Basic/DiagnosticSemaKinds.td @@ -539,21 +539,21 @@ def note_surrounding_namespace_ends_here : Note< "surrounding namespace with visibility attribute ends here">; def err_pragma_pop_visibility_mismatch : Error< - "#pragma visibility pop with no matching #pragma visibility push">; -def note_surrounding_namespace_starts_here : Note< - "surrounding namespace with visibility attribute starts here">; -def err_pragma_loop_invalid_value : Error< - "%select{invalid|missing}0 value%select{ %1|}0; expected a positive integer value">; -def err_pragma_loop_invalid_keyword : Error< - "%select{invalid|missing}0 keyword%select{ %1|}0; expected 'enable' or 'disable'">; -def err_pragma_loop_compatibility : Error< - "%select{incompatible|duplicate}0 directives '%1(%2)' and '%3(%4)'">; -def err_pragma_loop_precedes_nonloop : Error< - "expected a for, while, or do-while loop to follow the '#pragma clang loop' " - "directive">; - -/// Objective-C parser diagnostics -def err_duplicate_class_def : Error< + "#pragma visibility pop with no matching #pragma visibility push">; +def note_surrounding_namespace_starts_here : Note< + "surrounding namespace with visibility attribute starts here">; +def err_pragma_loop_invalid_value : Error< + "%select{invalid|missing}0 value%select{ %1|}0; expected a positive integer value">; +def err_pragma_loop_invalid_keyword : Error< + "%select{invalid|missing}0 keyword%select{ %1|}0; expected 'enable' or 'disable'">; +def err_pragma_loop_compatibility : Error< + "%select{incompatible|duplicate}0 directives '%1(%2)' and '%3(%4)'">; +def err_pragma_loop_precedes_nonloop : Error< + "expected a for, while, or do-while loop to follow the '#pragma clang loop' " + "directive">; + +/// Objective-C parser diagnostics +def err_duplicate_class_def : Error< "duplicate interface definition for class %0">; def err_undef_superclass : Error< "cannot find interface declaration for %0, superclass of %1">; Index: lib/Parse/ParsePragma.cpp =================================================================== --- lib/Parse/ParsePragma.cpp +++ lib/Parse/ParsePragma.cpp @@ -12,13 +12,13 @@ //===----------------------------------------------------------------------===// #include "RAIIObjectsForParser.h" -#include "clang/Lex/Preprocessor.h" -#include "clang/Parse/ParseDiagnostic.h" -#include "clang/Parse/Parser.h" -#include "clang/Sema/LoopHint.h" -#include "clang/Sema/Scope.h" -#include "llvm/ADT/StringSwitch.h" -using namespace clang; +#include "clang/Lex/Preprocessor.h" +#include "clang/Parse/ParseDiagnostic.h" +#include "clang/Parse/Parser.h" +#include "clang/Sema/LoopHint.h" +#include "clang/Sema/Scope.h" +#include "llvm/ADT/StringSwitch.h" +using namespace clang; namespace { @@ -139,18 +139,18 @@ void HandlePragma(Preprocessor &PP, PragmaIntroducerKind Introducer, Token &FirstToken) override; private: - Sema &Actions; -}; - -struct PragmaLoopHintHandler : public PragmaHandler { - PragmaLoopHintHandler() : PragmaHandler("loop") {} - void HandlePragma(Preprocessor &PP, PragmaIntroducerKind Introducer, - Token &FirstToken) override; -}; - -} // end namespace - -void Parser::initializePragmaHandlers() { + Sema &Actions; +}; + +struct PragmaLoopHintHandler : public PragmaHandler { + PragmaLoopHintHandler() : PragmaHandler("loop") {} + void HandlePragma(Preprocessor &PP, PragmaIntroducerKind Introducer, + Token &FirstToken) override; +}; + +} // end namespace + +void Parser::initializePragmaHandlers() { AlignHandler.reset(new PragmaAlignHandler()); PP.AddPragmaHandler(AlignHandler.get()); @@ -212,15 +212,15 @@ MSSection.reset(new PragmaMSPragma("section")); PP.AddPragmaHandler(MSSection.get()); } - - OptimizeHandler.reset(new PragmaOptimizeHandler(Actions)); - PP.AddPragmaHandler("clang", OptimizeHandler.get()); - - LoopHintHandler.reset(new PragmaLoopHintHandler()); - PP.AddPragmaHandler("clang", LoopHintHandler.get()); -} - -void Parser::resetPragmaHandlers() { + + OptimizeHandler.reset(new PragmaOptimizeHandler(Actions)); + PP.AddPragmaHandler("clang", OptimizeHandler.get()); + + LoopHintHandler.reset(new PragmaLoopHintHandler()); + PP.AddPragmaHandler("clang", LoopHintHandler.get()); +} + +void Parser::resetPragmaHandlers() { // Remove the pragma handlers we installed. PP.RemovePragmaHandler(AlignHandler.get()); AlignHandler.reset(); @@ -272,15 +272,15 @@ PP.RemovePragmaHandler("STDC", FPContractHandler.get()); FPContractHandler.reset(); - - PP.RemovePragmaHandler("clang", OptimizeHandler.get()); - OptimizeHandler.reset(); - - PP.RemovePragmaHandler("clang", LoopHintHandler.get()); - LoopHintHandler.reset(); -} - -/// \brief Handle the annotation token produced for #pragma unused(...) + + PP.RemovePragmaHandler("clang", OptimizeHandler.get()); + OptimizeHandler.reset(); + + PP.RemovePragmaHandler("clang", LoopHintHandler.get()); + LoopHintHandler.reset(); +} + +/// \brief Handle the annotation token produced for #pragma unused(...) /// /// Each annot_pragma_unused is followed by the argument token so e.g. /// "#pragma unused(x,y)" becomes: @@ -596,46 +596,46 @@ unsigned Parser::HandlePragmaMSInitSeg(llvm::StringRef PragmaName, SourceLocation PragmaLocation) { return PP.getDiagnostics().getCustomDiagID( - DiagnosticsEngine::Error, "'#pragma %0' not implemented."); -} - -struct PragmaLoopHintInfo { - Token Loop; - Token Value; - Token Option; -}; - -LoopHint Parser::HandlePragmaLoopHint() { - assert(Tok.is(tok::annot_pragma_loop_hint)); - PragmaLoopHintInfo *Info = - static_cast(Tok.getAnnotationValue()); - - LoopHint Hint; - Hint.LoopLoc = - IdentifierLoc::create(Actions.Context, Info->Loop.getLocation(), - Info->Loop.getIdentifierInfo()); - Hint.OptionLoc = - IdentifierLoc::create(Actions.Context, Info->Option.getLocation(), - Info->Option.getIdentifierInfo()); - Hint.ValueLoc = - IdentifierLoc::create(Actions.Context, Info->Value.getLocation(), - Info->Value.getIdentifierInfo()); - Hint.Range = - SourceRange(Info->Option.getLocation(), Info->Value.getLocation()); - - // FIXME: We should support template parameters for the loop hint value. - // See bug report #19610 - if (Info->Value.is(tok::numeric_constant)) - Hint.ValueExpr = Actions.ActOnNumericConstant(Info->Value).get(); - else - Hint.ValueExpr = nullptr; - - return Hint; -} - -// #pragma GCC visibility comes in two variants: -// 'push' '(' [visibility] ')' -// 'pop' + DiagnosticsEngine::Error, "'#pragma %0' not implemented."); +} + +struct PragmaLoopHintInfo { + Token Loop; + Token Value; + Token Option; +}; + +LoopHint Parser::HandlePragmaLoopHint() { + assert(Tok.is(tok::annot_pragma_loop_hint)); + PragmaLoopHintInfo *Info = + static_cast(Tok.getAnnotationValue()); + + LoopHint Hint; + Hint.LoopLoc = + IdentifierLoc::create(Actions.Context, Info->Loop.getLocation(), + Info->Loop.getIdentifierInfo()); + Hint.OptionLoc = + IdentifierLoc::create(Actions.Context, Info->Option.getLocation(), + Info->Option.getIdentifierInfo()); + Hint.ValueLoc = + IdentifierLoc::create(Actions.Context, Info->Value.getLocation(), + Info->Value.getIdentifierInfo()); + Hint.Range = + SourceRange(Info->Option.getLocation(), Info->Value.getLocation()); + + // FIXME: We should support template parameters for the loop hint value. + // See bug report #19610 + if (Info->Value.is(tok::numeric_constant)) + Hint.ValueExpr = Actions.ActOnNumericConstant(Info->Value).get(); + else + Hint.ValueExpr = nullptr; + + return Hint; +} + +// #pragma GCC visibility comes in two variants: +// 'push' '(' [visibility] ')' +// 'pop' void PragmaGCCVisibilityHandler::HandlePragma(Preprocessor &PP, PragmaIntroducerKind Introducer, Token &VisTok) { @@ -1628,113 +1628,113 @@ << PP.getSpelling(Tok); return; } - - Actions.ActOnPragmaOptimize(IsOn, FirstToken.getLocation()); -} - -/// \brief Handle the \#pragma clang loop directive. -/// #pragma clang 'loop' loop-hints -/// -/// loop-hints: -/// loop-hint loop-hints[opt] -/// -/// loop-hint: -/// 'vectorize' '(' loop-hint-keyword ')' -/// 'interleave' '(' loop-hint-keyword ')' -/// 'vectorize_width' '(' loop-hint-value ')' -/// 'interleave_count' '(' loop-hint-value ')' -/// -/// loop-hint-keyword: -/// 'enable' -/// 'disable' -/// -/// loop-hint-value: -/// constant-expression -/// -/// Specifying vectorize(enable) or vectorize_width(_value_) instructs llvm to -/// try vectorizing the instructions of the loop it precedes. Specifying -/// interleave(enable) or interleave_count(_value_) instructs llvm to try -/// interleaving multiple iterations of the loop it precedes. The width of the -/// vector instructions is specified by vectorize_width() and the number of -/// interleaved loop iterations is specified by interleave_count(). Specifying a -/// value of 1 effectively disables vectorization/interleaving, even if it is -/// possible and profitable, and 0 is invalid. The loop vectorizer currently -/// only works on inner loops. -/// -void PragmaLoopHintHandler::HandlePragma(Preprocessor &PP, - PragmaIntroducerKind Introducer, - Token &Tok) { - Token Loop = Tok; - SmallVector TokenList; - - // Lex the optimization option and verify it is an identifier. - PP.Lex(Tok); - if (Tok.isNot(tok::identifier)) { - PP.Diag(Tok.getLocation(), diag::err_pragma_loop_invalid_option) - << /*MissingOption=*/true << ""; - return; - } - - while (Tok.is(tok::identifier)) { - Token Option = Tok; - IdentifierInfo *OptionInfo = Tok.getIdentifierInfo(); - - if (!OptionInfo->isStr("vectorize") && !OptionInfo->isStr("interleave") && - !OptionInfo->isStr("vectorize_width") && - !OptionInfo->isStr("interleave_count")) { - PP.Diag(Tok.getLocation(), diag::err_pragma_loop_invalid_option) - << /*MissingOption=*/false << OptionInfo; - return; - } - - // Read '(' - PP.Lex(Tok); - if (Tok.isNot(tok::l_paren)) { - PP.Diag(Tok.getLocation(), diag::err_expected) << tok::l_paren; - return; - } - - // FIXME: All tokens between '(' and ')' should be stored and parsed as a - // constant expression. - PP.Lex(Tok); - Token Value; - if (Tok.is(tok::identifier) || Tok.is(tok::numeric_constant)) - Value = Tok; - - // Read ')' - PP.Lex(Tok); - if (Tok.isNot(tok::r_paren)) { - PP.Diag(Tok.getLocation(), diag::err_expected) << tok::r_paren; - return; - } - - // Get next optimization option. - PP.Lex(Tok); - - auto *Info = new (PP.getPreprocessorAllocator()) PragmaLoopHintInfo; - Info->Loop = Loop; - Info->Option = Option; - Info->Value = Value; - - // Generate the vectorization hint token. - Token LoopHintTok; - LoopHintTok.startToken(); - LoopHintTok.setKind(tok::annot_pragma_loop_hint); - LoopHintTok.setLocation(Loop.getLocation()); - LoopHintTok.setAnnotationValue(static_cast(Info)); - TokenList.push_back(LoopHintTok); - } - - if (Tok.isNot(tok::eod)) { - PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol) - << "clang loop"; - return; - } - - Token *TokenArray = new Token[TokenList.size()]; - std::copy(TokenList.begin(), TokenList.end(), TokenArray); - - PP.EnterTokenStream(TokenArray, TokenList.size(), - /*DisableMacroExpansion=*/false, - /*OwnsTokens=*/true); -} + + Actions.ActOnPragmaOptimize(IsOn, FirstToken.getLocation()); +} + +/// \brief Handle the \#pragma clang loop directive. +/// #pragma clang 'loop' loop-hints +/// +/// loop-hints: +/// loop-hint loop-hints[opt] +/// +/// loop-hint: +/// 'vectorize' '(' loop-hint-keyword ')' +/// 'interleave' '(' loop-hint-keyword ')' +/// 'vectorize_width' '(' loop-hint-value ')' +/// 'interleave_count' '(' loop-hint-value ')' +/// +/// loop-hint-keyword: +/// 'enable' +/// 'disable' +/// +/// loop-hint-value: +/// constant-expression +/// +/// Specifying vectorize(enable) or vectorize_width(_value_) instructs llvm to +/// try vectorizing the instructions of the loop it precedes. Specifying +/// interleave(enable) or interleave_count(_value_) instructs llvm to try +/// interleaving multiple iterations of the loop it precedes. The width of the +/// vector instructions is specified by vectorize_width() and the number of +/// interleaved loop iterations is specified by interleave_count(). Specifying a +/// value of 1 effectively disables vectorization/interleaving, even if it is +/// possible and profitable, and 0 is invalid. The loop vectorizer currently +/// only works on inner loops. +/// +void PragmaLoopHintHandler::HandlePragma(Preprocessor &PP, + PragmaIntroducerKind Introducer, + Token &Tok) { + Token Loop = Tok; + SmallVector TokenList; + + // Lex the optimization option and verify it is an identifier. + PP.Lex(Tok); + if (Tok.isNot(tok::identifier)) { + PP.Diag(Tok.getLocation(), diag::err_pragma_loop_invalid_option) + << /*MissingOption=*/true << ""; + return; + } + + while (Tok.is(tok::identifier)) { + Token Option = Tok; + IdentifierInfo *OptionInfo = Tok.getIdentifierInfo(); + + if (!OptionInfo->isStr("vectorize") && !OptionInfo->isStr("interleave") && + !OptionInfo->isStr("vectorize_width") && + !OptionInfo->isStr("interleave_count")) { + PP.Diag(Tok.getLocation(), diag::err_pragma_loop_invalid_option) + << /*MissingOption=*/false << OptionInfo; + return; + } + + // Read '(' + PP.Lex(Tok); + if (Tok.isNot(tok::l_paren)) { + PP.Diag(Tok.getLocation(), diag::err_expected) << tok::l_paren; + return; + } + + // FIXME: All tokens between '(' and ')' should be stored and parsed as a + // constant expression. + PP.Lex(Tok); + Token Value; + if (Tok.is(tok::identifier) || Tok.is(tok::numeric_constant)) + Value = Tok; + + // Read ')' + PP.Lex(Tok); + if (Tok.isNot(tok::r_paren)) { + PP.Diag(Tok.getLocation(), diag::err_expected) << tok::r_paren; + return; + } + + // Get next optimization option. + PP.Lex(Tok); + + auto *Info = new (PP.getPreprocessorAllocator()) PragmaLoopHintInfo; + Info->Loop = Loop; + Info->Option = Option; + Info->Value = Value; + + // Generate the vectorization hint token. + Token LoopHintTok; + LoopHintTok.startToken(); + LoopHintTok.setKind(tok::annot_pragma_loop_hint); + LoopHintTok.setLocation(Loop.getLocation()); + LoopHintTok.setAnnotationValue(static_cast(Info)); + TokenList.push_back(LoopHintTok); + } + + if (Tok.isNot(tok::eod)) { + PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol) + << "clang loop"; + return; + } + + Token *TokenArray = new Token[TokenList.size()]; + std::copy(TokenList.begin(), TokenList.end(), TokenArray); + + PP.EnterTokenStream(TokenArray, TokenList.size(), + /*DisableMacroExpansion=*/false, + /*OwnsTokens=*/true); +}