Meinersbur created this revision.
Meinersbur added reviewers: hfinkel, kbarton, SjoerdMeijer, aaron.ballman, 
ABataev, fhahn, hsaito, hans, greened, dmgreen, reames, Ayal, asavonic, rtrieu, 
dorit, rsmith, tyler.nowicki.
Herald added a subscriber: mgorny.
Herald added a reviewer: jdoerfert.

Parse the tokens between the annotation tokens and calls ActOn... methods of 
Sema which are empty in this patch.

For a full description, see D69088 <https://reviews.llvm.org/D69088>.


https://reviews.llvm.org/D69089

Files:
  include/clang/AST/StmtTransform.h
  include/clang/AST/Transform.h
  include/clang/AST/TransformKinds.def
  include/clang/Basic/DiagnosticGroups.td
  include/clang/Basic/DiagnosticParseKinds.td
  include/clang/Parse/Parser.h
  include/clang/Sema/Sema.h
  lib/AST/CMakeLists.txt
  lib/AST/StmtTransform.cpp
  lib/AST/Transform.cpp
  lib/Parse/CMakeLists.txt
  lib/Parse/ParseStmt.cpp
  lib/Parse/ParseTransform.cpp
  lib/Sema/CMakeLists.txt
  lib/Sema/SemaTransform.cpp
  test/Parser/pragma-transform.cpp

Index: test/Parser/pragma-transform.cpp
===================================================================
--- /dev/null
+++ test/Parser/pragma-transform.cpp
@@ -0,0 +1,90 @@
+// RUN: %clang_cc1 -std=c++11 -verify %s
+
+void pragma_transform(int *List, int Length) {
+// FIXME: This does not emit an error
+#pragma clang
+
+/* expected-error@+1 {{expected a transformation name}} */
+#pragma clang transform
+  for (int i = 0; i < Length; i+=1)
+      List[i] = i;
+
+/* expected-error@+1 {{unknown transformation}} */
+#pragma clang transform unknown_transformation
+  for (int i = 0; i < Length; i+=1)
+      List[i] = i;
+
+/* expected-error@+2 {{expected loop after transformation pragma}} */
+#pragma clang transform unroll
+  pragma_transform(List, Length);
+
+/* expected-error@+1 {{unknown clause name}} */
+#pragma clang transform unroll unknown_clause
+  for (int i = 0; i < Length; i+=1)
+      List[i] = i;
+
+/* expected-error@+1 {{expected '(' after 'partial'}} */
+#pragma clang transform unroll partial
+  for (int i = 0; i < Length; i+=1)
+      List[i] = i;
+
+/* expected-error@+1 {{expected expression}} */
+#pragma clang transform unroll partial(
+  for (int i = 0; i < Length; i+=1)
+      List[i] = i;
+
+/* expected-error@+1 {{expected '(' after 'partial'}} */
+#pragma clang transform unroll partial)
+  for (int i = 0; i < Length; i+=1)
+      List[i] = i;
+
+/* expected-error@+2 {{expected ')'}} */
+/* expected-note@+1 {{to match this '('}} */
+#pragma clang transform unroll partial(4
+  for (int i = 0; i < Length; i+=1)
+      List[i] = i;
+
+/* expected-error@+1 {{expected expression}} */
+#pragma clang transform unroll partial()
+  for (int i = 0; i < Length; i+=1)
+      List[i] = i;
+
+/* expected-error@+1 {{use of undeclared identifier 'badvalue'}} */
+#pragma clang transform unroll partial(badvalue)
+  for (int i = 0; i < Length; i+=1)
+      List[i] = i;
+
+  {
+/* expected-error@+2 {{expected statement}} */
+#pragma clang transform unroll
+  }
+}
+
+/* expected-error@+1 {{expected unqualified-id}} */
+#pragma clang transform unroll
+int I;
+
+/* expected-error@+1 {{expected unqualified-id}} */
+#pragma clang transform unroll
+void func();
+
+class C1 {
+/* expected-error@+1 {{expected member name or ';' after declaration specifiers}} */
+#pragma clang transform unroll
+};
+
+template<int F>
+void pragma_transform_template_func(int *List, int Length) {
+#pragma clang transform unroll partial(F)
+  for (int i = 0; i < Length; i+=1)
+      List[i] = i;
+}
+
+template<int F>
+class C2 {
+  void pragma_transform_template_class(int *List, int Length) {
+#pragma clang transform unroll partial(F)
+    for (int i = 0; i < Length; i+=1)
+        List[i] = i;
+  }
+};
Index: lib/Sema/SemaTransform.cpp
===================================================================
--- /dev/null
+++ lib/Sema/SemaTransform.cpp
@@ -0,0 +1,62 @@
+//===---- SemaTransform.h ------------------------------------- -*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// Semantic analysis for code transformations.
+//
+//===----------------------------------------------------------------------===//
+
+#include "clang/AST/RecursiveASTVisitor.h"
+#include "clang/AST/StmtTransform.h"
+#include "clang/AST/Transform.h"
+#include "clang/Sema/Sema.h"
+#include "clang/Sema/SemaDiagnostic.h"
+#include "llvm/ADT/DenseMap.h"
+#include "llvm/ADT/StringMap.h"
+
+using namespace clang;
+
+static bool isTemplateDependent(Expr *E) {
+  return E->isValueDependent() || E->isTypeDependent() ||
+         E->isInstantiationDependent() || E->containsUnexpandedParameterPack();
+}
+
+Sema::TransformResult
+Sema::ActOnTransform(Transform::Kind Kind,
+                     llvm::ArrayRef<TransformClause *> Clauses,
+                     SourceRange Loc) {
+  // TOOD: implement
+  return TransformError();
+}
+
+StmtResult
+Sema::ActOnLoopTransformDirective(Transform::Kind Kind, Transform *Trans,
+                                  llvm::ArrayRef<TransformClause *> Clauses,
+                                  Stmt *AStmt, SourceRange Loc) {
+  // TOOD: implement
+  return StmtError();
+}
+
+TransformClause *Sema::ActOnFullClause(SourceRange Loc) {
+  // TOOD: implement
+  return nullptr;
+}
+
+TransformClause *Sema::ActOnPartialClause(SourceRange Loc, Expr *Factor) {
+  // TOOD: implement
+  return nullptr;
+}
+
+TransformClause *Sema::ActOnWidthClause(SourceRange Loc, Expr *Width) {
+  // TOOD: implement
+  return nullptr;
+}
+
+TransformClause *Sema::ActOnFactorClause(SourceRange Loc, Expr *Factor) {
+  // TOOD: implement
+  return nullptr;
+}
Index: lib/Sema/CMakeLists.txt
===================================================================
--- lib/Sema/CMakeLists.txt
+++ lib/Sema/CMakeLists.txt
@@ -62,6 +62,7 @@
   SemaTemplateInstantiate.cpp
   SemaTemplateInstantiateDecl.cpp
   SemaTemplateVariadic.cpp
+  SemaTransform.cpp
   SemaType.cpp
   TypeLocBuilder.cpp
 
Index: lib/Parse/ParseTransform.cpp
===================================================================
--- /dev/null
+++ lib/Parse/ParseTransform.cpp
@@ -0,0 +1,145 @@
+//===---- ParseTransform.h -------------------------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// Parse #pragma clang transform ...
+//
+//===----------------------------------------------------------------------===//
+
+#include "clang/AST/StmtTransform.h"
+#include "clang/Parse/Parser.h"
+#include "clang/Parse/RAIIObjectsForParser.h"
+
+using namespace clang;
+
+Transform::Kind
+Parser::tryParsePragmaTransform(SourceLocation BeginLoc,
+                                ParsedStmtContext StmtCtx,
+                                SmallVectorImpl<TransformClause *> &Clauses) {
+  // ... Tok=<transform> | <...> tok::annot_pragma_transform_end ...
+  if (Tok.isNot(tok::identifier)) {
+    Diag(Tok, diag::err_pragma_transform_expected_directive);
+    return Transform::UnknownKind;
+  }
+  std::string DirectiveStr = PP.getSpelling(Tok);
+  Transform::Kind DirectiveKind =
+      Transform::getTransformDirectiveKind(DirectiveStr);
+  ConsumeToken();
+
+  switch (DirectiveKind) {
+  case Transform::LoopUnrollingKind:
+  case Transform::LoopUnrollAndJamKind:
+  case Transform::LoopDistributionKind:
+  case Transform::LoopVectorizationKind:
+  case Transform::LoopInterleavingKind:
+    break;
+  default:
+    Diag(Tok, diag::err_pragma_transform_unknown_directive);
+    return Transform::UnknownKind;
+  }
+
+  while (true) {
+    TransformClauseResult Clause = ParseTransformClause(DirectiveKind);
+    if (Clause.isInvalid())
+      return Transform::UnknownKind;
+    if (!Clause.isUsable())
+      break;
+
+    Clauses.push_back(Clause.get());
+  }
+
+  assert(Tok.is(tok::annot_pragma_transform_end));
+  return DirectiveKind;
+}
+
+StmtResult Parser::ParsePragmaTransform(ParsedStmtContext StmtCtx) {
+  assert(Tok.is(tok::annot_pragma_transform) && "Not a transform directive!");
+
+  // ... Tok=annot_pragma_transform | <trans> <...> annot_pragma_transform_end
+  // ...
+  SourceLocation BeginLoc = ConsumeAnnotationToken();
+
+  ParenBraceBracketBalancer BalancerRAIIObj(*this);
+
+  SmallVector<TransformClause *, 8> DirectiveClauses;
+  Transform::Kind DirectiveKind =
+      tryParsePragmaTransform(BeginLoc, StmtCtx, DirectiveClauses);
+  if (DirectiveKind == Transform::UnknownKind) {
+    SkipUntil(tok::annot_pragma_transform_end);
+    return StmtError();
+  }
+
+  assert(Tok.is(tok::annot_pragma_transform_end));
+  SourceLocation EndLoc = ConsumeAnnotationToken();
+
+  SourceLocation PreStmtLoc = Tok.getLocation();
+  StmtResult AssociatedStmt = ParseStatement();
+  if (AssociatedStmt.isInvalid())
+    return AssociatedStmt;
+  if (!getAssociatedLoop(AssociatedStmt.get()))
+    return StmtError(
+        Diag(PreStmtLoc, diag::err_pragma_transform_expected_loop));
+
+  return Actions.ActOnLoopTransformDirective(
+      DirectiveKind, nullptr, DirectiveClauses, AssociatedStmt.get(),
+      {BeginLoc, EndLoc});
+}
+
+Parser::TransformClauseResult
+Parser::ParseTransformClause(Transform::Kind TransformKind) {
+  // No more clauses
+  if (Tok.is(tok::annot_pragma_transform_end))
+    return ClauseEmpty();
+
+  SourceLocation StartLoc = Tok.getLocation();
+  if (Tok.isNot(tok::identifier))
+    return ClauseError(Diag(Tok, diag::err_pragma_transform_expected_clause));
+  std::string ClauseKeyword = PP.getSpelling(Tok);
+  ConsumeToken();
+  TransformClause::Kind Kind =
+      TransformClause::getClauseKind(TransformKind, ClauseKeyword);
+
+  switch (Kind) {
+  case TransformClause::UnknownKind:
+    return ClauseError(Diag(Tok, diag::err_pragma_transform_unknown_clause));
+
+    // Clauses without arguments.
+  case TransformClause::FullKind:
+    return Actions.ActOnFullClause(SourceRange{StartLoc, StartLoc});
+
+    // Clauses with integer argument.
+  case TransformClause::PartialKind:
+  case TransformClause::WidthKind:
+  case TransformClause::FactorKind: {
+    BalancedDelimiterTracker T(*this, tok::l_paren,
+                               tok::annot_pragma_transform_end);
+    if (T.expectAndConsume(diag::err_expected_lparen_after,
+                           ClauseKeyword.data()))
+      return ClauseError();
+
+    ExprResult Expr = ParseConstantExpression();
+    if (Expr.isInvalid())
+      return ClauseError();
+
+    if (T.consumeClose())
+      return ClauseError();
+    SourceLocation EndLoc = T.getCloseLocation();
+    SourceRange Range{StartLoc, EndLoc};
+    switch (Kind) {
+    case TransformClause::PartialKind:
+      return Actions.ActOnPartialClause(Range, Expr.get());
+    case TransformClause::WidthKind:
+      return Actions.ActOnWidthClause(Range, Expr.get());
+    case TransformClause::FactorKind:
+      return Actions.ActOnFactorClause(Range, Expr.get());
+    default:
+      llvm_unreachable("Unhandled clause");
+    }
+  }
+  }
+  llvm_unreachable("Unhandled clause");
+}
Index: lib/Parse/ParseStmt.cpp
===================================================================
--- lib/Parse/ParseStmt.cpp
+++ lib/Parse/ParseStmt.cpp
@@ -12,6 +12,7 @@
 //===----------------------------------------------------------------------===//
 
 #include "clang/AST/PrettyDeclStackTrace.h"
+#include "clang/AST/Transform.h"
 #include "clang/Basic/Attributes.h"
 #include "clang/Basic/PrettyStackTrace.h"
 #include "clang/Parse/LoopHint.h"
@@ -398,6 +399,10 @@
     ProhibitAttributes(Attrs);
     return ParsePragmaLoopHint(Stmts, StmtCtx, TrailingElseLoc, Attrs);
 
+  case tok::annot_pragma_transform:
+    ProhibitAttributes(Attrs);
+    return ParsePragmaTransform(StmtCtx);
+
   case tok::annot_pragma_dump:
     HandlePragmaDump();
     return StmtEmpty();
Index: lib/Parse/CMakeLists.txt
===================================================================
--- lib/Parse/CMakeLists.txt
+++ lib/Parse/CMakeLists.txt
@@ -19,6 +19,7 @@
   ParseStmtAsm.cpp
   ParseTemplate.cpp
   ParseTentative.cpp
+  ParseTransform.cpp
   Parser.cpp
 
   LINK_LIBS
Index: lib/AST/Transform.cpp
===================================================================
--- /dev/null
+++ lib/AST/Transform.cpp
@@ -0,0 +1,48 @@
+//===--- Transform.h - Code transformation classes --------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+//  This file defines classes used for code transformations such as
+//  #pragma clang transform ...
+//
+//===----------------------------------------------------------------------===//
+
+#include "clang/AST/Transform.h"
+#include "llvm/ADT/StringSwitch.h"
+#include "llvm/Support/Casting.h"
+
+using namespace clang;
+
+Transform::Kind Transform ::getTransformDirectiveKind(llvm::StringRef Str) {
+  return llvm::StringSwitch<Transform::Kind>(Str)
+#define TRANSFORM_DIRECTIVE(Keyword, Name)                                     \
+  .Case(#Keyword, Transform::Kind::Name##Kind)
+#include "clang/AST/TransformKinds.def"
+      .Default(Transform::UnknownKind);
+}
+
+llvm::StringRef Transform ::getTransformDirectiveKeyword(Kind K) {
+  assert(K >= UnknownKind);
+  assert(K <= LastKind);
+  const char *Keywords[LastKind + 1] = {
+      "<<Unknown>>",
+#define TRANSFORM_DIRECTIVE(Keyword, Name) #Keyword,
+#include "clang/AST/TransformKinds.def"
+  };
+  return Keywords[K];
+}
+
+llvm::StringRef Transform ::getTransformDirectiveName(Kind K) {
+  assert(K >= UnknownKind);
+  assert(K <= LastKind);
+  const char *Keywords[LastKind + 1] = {
+      "<<Unknown>>",
+#define TRANSFORM_DIRECTIVE(Keyword, Name) #Name,
+#include "clang/AST/TransformKinds.def"
+  };
+  return Keywords[K];
+}
Index: lib/AST/StmtTransform.cpp
===================================================================
--- /dev/null
+++ lib/AST/StmtTransform.cpp
@@ -0,0 +1,64 @@
+//===--- StmtTransform.h - Code transformation AST nodes --------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+//  Transformation directive statement and clauses for the AST.
+//
+//===----------------------------------------------------------------------===//
+
+#include "clang/AST/StmtTransform.h"
+#include "clang/AST/ASTContext.h"
+#include "clang/AST/Stmt.h"
+#include "clang/AST/StmtOpenMP.h"
+
+using namespace clang;
+
+bool TransformClause::isValidForTransform(Transform::Kind TransformKind,
+                                          TransformClause::Kind ClauseKind) {
+  switch (TransformKind) {
+  case clang::Transform::LoopUnrollingKind:
+    return ClauseKind == PartialKind || ClauseKind == FullKind;
+  case clang::Transform::LoopUnrollAndJamKind:
+    return ClauseKind == PartialKind;
+  case clang::Transform::LoopVectorizationKind:
+    return ClauseKind == WidthKind;
+  case clang::Transform::LoopInterleavingKind:
+    return ClauseKind == FactorKind;
+  default:
+    return false;
+  }
+}
+
+TransformClause::Kind
+TransformClause ::getClauseKind(Transform::Kind TransformKind,
+                                llvm::StringRef Str) {
+#define TRANSFORM_CLAUSE(Keyword, Name)                                        \
+  if (isValidForTransform(TransformKind, TransformClause::Kind::Name##Kind) && \
+      Str == #Keyword)                                                         \
+    return TransformClause::Kind::Name##Kind;
+#include "clang/AST/TransformKinds.def"
+  return TransformClause::UnknownKind;
+}
+
+const Stmt *clang::getAssociatedLoop(const Stmt *S) {
+  switch (S->getStmtClass()) {
+  case Stmt::ForStmtClass:
+  case Stmt::WhileStmtClass:
+  case Stmt::DoStmtClass:
+  case Stmt::CXXForRangeStmtClass:
+    return S;
+  case Stmt::CapturedStmtClass:
+    return getAssociatedLoop(cast<CapturedStmt>(S)->getCapturedStmt());
+  case Stmt::AttributedStmtClass:
+    return getAssociatedLoop(cast<AttributedStmt>(S)->getSubStmt());
+  default:
+    if (auto LD = dyn_cast<OMPLoopDirective>(S))
+      return getAssociatedLoop(LD->getAssociatedStmt());
+  }
+
+  return nullptr;
+}
Index: lib/AST/CMakeLists.txt
===================================================================
--- lib/AST/CMakeLists.txt
+++ lib/AST/CMakeLists.txt
@@ -98,10 +98,12 @@
   StmtOpenMP.cpp
   StmtPrinter.cpp
   StmtProfile.cpp
+  StmtTransform.cpp
   StmtViz.cpp
   TemplateBase.cpp
   TemplateName.cpp
   TextNodeDumper.cpp
+  Transform.cpp
   Type.cpp
   TypeLoc.cpp
   TypePrinter.cpp
Index: include/clang/Sema/Sema.h
===================================================================
--- include/clang/Sema/Sema.h
+++ include/clang/Sema/Sema.h
@@ -28,6 +28,7 @@
 #include "clang/AST/NSAPI.h"
 #include "clang/AST/PrettyPrinter.h"
 #include "clang/AST/StmtCXX.h"
+#include "clang/AST/StmtTransform.h"
 #include "clang/AST/TypeLoc.h"
 #include "clang/AST/TypeOrdering.h"
 #include "clang/Basic/ExpressionTraits.h"
@@ -11528,6 +11529,26 @@
     ConstructorDestructor,
     BuiltinFunction
   };
+
+  using TransformResult = ActionResult<Transform *>;
+  static TransformResult TransformError() { return TransformResult(true); }
+  static TransformResult TransformError(const DiagnosticBuilder &) {
+    return TransformResult();
+  }
+  static TransformResult TransformEmpty() { return TransformResult(false); }
+
+  TransformResult ActOnTransform(Transform::Kind Kind,
+                                 llvm::ArrayRef<TransformClause *> Clauses,
+                                 SourceRange Loc);
+  StmtResult
+  ActOnLoopTransformDirective(Transform::Kind Kind, Transform *Trans,
+                              llvm::ArrayRef<TransformClause *> Clauses,
+                              Stmt *AStmt, SourceRange Loc);
+
+  TransformClause *ActOnFullClause(SourceRange Loc);
+  TransformClause *ActOnPartialClause(SourceRange Loc, Expr *Factor);
+  TransformClause *ActOnWidthClause(SourceRange Loc, Expr *Width);
+  TransformClause *ActOnFactorClause(SourceRange Loc, Expr *Factor);
 };
 
 /// RAII object that enters a new expression evaluation context.
Index: include/clang/Parse/Parser.h
===================================================================
--- include/clang/Parse/Parser.h
+++ include/clang/Parse/Parser.h
@@ -1642,6 +1642,17 @@
     IsTypeCast
   };
 
+  using TransformClauseResult = ActionResult<TransformClause *>;
+  static TransformClauseResult ClauseError() {
+    return TransformClauseResult(true);
+  }
+  static TransformClauseResult ClauseError(const DiagnosticBuilder &) {
+    return ClauseError();
+  }
+  static TransformClauseResult ClauseEmpty() {
+    return TransformClauseResult(false);
+  }
+
   ExprResult ParseExpression(TypeCastState isTypeCast = NotTypeCast);
   ExprResult ParseConstantExpressionInExprEvalContext(
       TypeCastState isTypeCast = NotTypeCast);
@@ -1978,6 +1989,12 @@
                                  SourceLocation *TrailingElseLoc,
                                  ParsedAttributesWithRange &Attrs);
 
+  Transform::Kind
+  tryParsePragmaTransform(SourceLocation BeginLoc, ParsedStmtContext StmtCtx,
+                          SmallVectorImpl<TransformClause *> &Clauses);
+  StmtResult ParsePragmaTransform(ParsedStmtContext StmtCtx);
+  TransformClauseResult ParseTransformClause(Transform::Kind TransformKind);
+
   /// Describes the behavior that should be taken for an __if_exists
   /// block.
   enum IfExistsBehavior {
Index: include/clang/Basic/DiagnosticParseKinds.td
===================================================================
--- include/clang/Basic/DiagnosticParseKinds.td
+++ include/clang/Basic/DiagnosticParseKinds.td
@@ -1233,6 +1233,18 @@
   "vectorize_width, interleave, interleave_count, unroll, unroll_count, "
   "pipeline, pipeline_initiation_interval, vectorize_predicate, or distribute">;
 
+// Pragma transform support.
+def err_pragma_transform_expected_directive : Error<
+  "expected a transformation name">;
+def err_pragma_transform_unknown_directive : Error<
+  "unknown transformation">;
+def err_pragma_transform_expected_loop : Error<
+  "expected loop after transformation pragma">;
+def err_pragma_transform_expected_clause : Error<
+  "expected a clause name">;
+def err_pragma_transform_unknown_clause : Error<
+  "unknown clause name">;
+
 def err_pragma_fp_invalid_option : Error<
   "%select{invalid|missing}0 option%select{ %1|}0; expected contract">;
 def err_pragma_fp_invalid_argument : Error<
Index: include/clang/Basic/DiagnosticGroups.td
===================================================================
--- include/clang/Basic/DiagnosticGroups.td
+++ include/clang/Basic/DiagnosticGroups.td
@@ -1105,3 +1105,5 @@
 def CTADMaybeUnsupported : DiagGroup<"ctad-maybe-unsupported">;
 
 def FortifySource : DiagGroup<"fortify-source">;
+
+def ClangTransform : DiagGroup<"pragma-transform">;
Index: include/clang/AST/TransformKinds.def
===================================================================
--- /dev/null
+++ include/clang/AST/TransformKinds.def
@@ -0,0 +1,39 @@
+
+#ifndef TRANSFORM_DIRECTIVE
+#  define TRANSFORM_DIRECTIVE(Keyword, Name)
+#endif
+#ifndef TRANSFORM_DIRECTIVE_LAST
+#  define TRANSFORM_DIRECTIVE_LAST(Keyword, Name) TRANSFORM_DIRECTIVE(Keyword, Name)
+#endif
+
+// Loop transformations
+TRANSFORM_DIRECTIVE(distribute,LoopDistribution)
+TRANSFORM_DIRECTIVE(vectorize,LoopVectorization)
+TRANSFORM_DIRECTIVE(interleave,LoopInterleaving)
+TRANSFORM_DIRECTIVE(vectorize_interleave,LoopVectorizationInterleaving)
+TRANSFORM_DIRECTIVE(unrollandjam,LoopUnrollAndJam)
+TRANSFORM_DIRECTIVE(unroll,LoopUnrolling)
+TRANSFORM_DIRECTIVE(pipeline,LoopPipelining)
+
+// Assumptions
+TRANSFORM_DIRECTIVE_LAST(assume_parallel,LoopAssumeParallel)
+
+#undef TRANSFORM_DIRECTIVE
+#undef TRANSFORM_DIRECTIVE_LAST
+
+
+#ifndef TRANSFORM_CLAUSE
+#  define TRANSFORM_CLAUSE(Keyword, Name)
+#endif
+#ifndef TRANSFORM_CLAUSE_LAST
+#  define TRANSFORM_CLAUSE_LAST(Keyword, Name)  TRANSFORM_CLAUSE(Keyword, Name)
+#endif
+
+TRANSFORM_CLAUSE(full,Full)
+TRANSFORM_CLAUSE(partial,Partial)
+
+TRANSFORM_CLAUSE(width,Width)
+TRANSFORM_CLAUSE_LAST(factor,Factor)
+
+#undef TRANSFORM_CLAUSE
+#undef TRANSFORM_CLAUSE_LAST
Index: include/clang/AST/Transform.h
===================================================================
--- /dev/null
+++ include/clang/AST/Transform.h
@@ -0,0 +1,40 @@
+//===--- Transform.h - Code transformation classes --------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+//  This file defines classes used for code transformations such as
+//  #pragma clang transform ...
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_AST_TRANSFORM_H
+#define LLVM_CLANG_AST_TRANSFORM_H
+
+#include "llvm/ADT/StringRef.h"
+
+namespace clang {
+
+class Transform {
+public:
+  enum Kind {
+    UnknownKind,
+#define TRANSFORM_DIRECTIVE(Keyword, Name) Name##Kind,
+#define TRANSFORM_DIRECTIVE_LAST(Keyword, Name)                                \
+  TRANSFORM_DIRECTIVE(Keyword, Name)                                           \
+  LastKind = Name##Kind
+#include "clang/AST/TransformKinds.def"
+  };
+
+  static Kind getTransformDirectiveKind(llvm::StringRef Str);
+  static llvm::StringRef getTransformDirectiveKeyword(Kind K);
+  static llvm::StringRef getTransformDirectiveName(Kind K);
+
+  // TODO: implement
+};
+
+} // namespace clang
+#endif /* LLVM_CLANG_AST_TRANSFORM_H */
Index: include/clang/AST/StmtTransform.h
===================================================================
--- /dev/null
+++ include/clang/AST/StmtTransform.h
@@ -0,0 +1,51 @@
+//===--- StmtTransform.h - Code transformation AST nodes --------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+//  Transformation directive statement and clauses for the AST.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_AST_STMTTRANSFROM_H
+#define LLVM_CLANG_AST_STMTTRANSFROM_H
+
+#include "clang/AST/Stmt.h"
+#include "clang/AST/Transform.h"
+#include "llvm/Support/raw_ostream.h"
+
+namespace clang {
+
+/// Represents a clause of a \p TransformExecutableDirective.
+class TransformClause {
+public:
+  enum Kind {
+    UnknownKind,
+#define TRANSFORM_CLAUSE(Keyword, Name) Name##Kind,
+#define TRANSFORM_CLAUSE_LAST(Keyword, Name) Name##Kind, LastKind = Name##Kind
+#include "clang/AST/TransformKinds.def"
+  };
+
+  static bool isValidForTransform(Transform::Kind TransformKind,
+                                  TransformClause::Kind ClauseKind);
+  static Kind getClauseKind(Transform::Kind TransformKind, llvm::StringRef Str);
+
+  // TODO: implement
+};
+
+/// Represents
+///
+///   #pragma clang transform
+///
+/// in the AST.
+class TransformExecutableDirective final {
+  // TODO: implement
+};
+
+const Stmt *getAssociatedLoop(const Stmt *S);
+} // namespace clang
+
+#endif /* LLVM_CLANG_AST_STMTTRANSFROM_H */
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
  • [PATCH] D69089: [Parser] #pr... Michael Kruse via Phabricator via cfe-commits

Reply via email to