[flang-commits] [flang] 3060894 - [flang][directives] Use TableGen to generate clause unparsing
via flang-commits
flang-commits at lists.llvm.org
Mon Aug 17 11:22:35 PDT 2020
Author: Valentin Clement
Date: 2020-08-17T14:22:25-04:00
New Revision: 3060894bbb34937707d7db4d30485ecc98e62497
URL: https://github.com/llvm/llvm-project/commit/3060894bbb34937707d7db4d30485ecc98e62497
DIFF: https://github.com/llvm/llvm-project/commit/3060894bbb34937707d7db4d30485ecc98e62497.diff
LOG: [flang][directives] Use TableGen to generate clause unparsing
Use the TableGen directive back-end to generate code for the clauses unparsing.
Reviewed By: sscalpone, kiranchandramohan
Differential Revision: https://reviews.llvm.org/D85851
Added:
Modified:
flang/include/flang/Parser/dump-parse-tree.h
flang/include/flang/Parser/parse-tree.h
flang/lib/Parser/openmp-parsers.cpp
flang/lib/Parser/unparse.cpp
flang/lib/Semantics/check-omp-structure.cpp
flang/lib/Semantics/check-omp-structure.h
llvm/include/llvm/Frontend/Directive/DirectiveBase.td
llvm/include/llvm/Frontend/OpenACC/ACC.td
llvm/include/llvm/Frontend/OpenMP/OMP.td
llvm/include/llvm/TableGen/DirectiveEmitter.h
llvm/test/TableGen/directive1.td
llvm/test/TableGen/directive2.td
llvm/utils/TableGen/DirectiveEmitter.cpp
Removed:
################################################################################
diff --git a/flang/include/flang/Parser/dump-parse-tree.h b/flang/include/flang/Parser/dump-parse-tree.h
index 185a514e648f..e8c6244d7474 100644
--- a/flang/include/flang/Parser/dump-parse-tree.h
+++ b/flang/include/flang/Parser/dump-parse-tree.h
@@ -457,9 +457,9 @@ class ParseTreeDumper {
NODE(parser, OmpCancelType)
NODE_ENUM(OmpCancelType, Type)
NODE(parser, OmpClause)
- NODE(parser, OmpClauseList)
#define GEN_FLANG_DUMP_PARSE_TREE_CLAUSES
#include "llvm/Frontend/OpenMP/OMP.cpp.inc"
+ NODE(parser, OmpClauseList)
NODE(parser, OmpCriticalDirective)
NODE(OmpCriticalDirective, Hint)
NODE(parser, OmpDeclareTargetSpecifier)
@@ -478,6 +478,7 @@ class ParseTreeDumper {
NODE_ENUM(OmpDependenceType, Type)
NODE(parser, OmpDependSinkVec)
NODE(parser, OmpDependSinkVecLength)
+ NODE(parser, OmpDistScheduleClause)
NODE(parser, OmpEndAtomic)
NODE(parser, OmpEndBlockDirective)
NODE(parser, OmpEndCriticalDirective)
diff --git a/flang/include/flang/Parser/parse-tree.h b/flang/include/flang/Parser/parse-tree.h
index 695121f83959..49e91789fdce 100644
--- a/flang/include/flang/Parser/parse-tree.h
+++ b/flang/include/flang/Parser/parse-tree.h
@@ -3460,6 +3460,10 @@ struct OmpDependClause {
// 2.7.1 nowait-clause -> NOWAIT
EMPTY_CLASS(OmpNowait);
+// dist_schedule clause does not fit in generic clause class for tablegen.
+// Therefore it is declared separatly here.
+WRAPPER_CLASS(OmpDistScheduleClause, std::optional<ScalarIntExpr>);
+
// OpenMP Clauses
struct OmpClause {
UNION_CLASS_BOILERPLATE(OmpClause);
diff --git a/flang/lib/Parser/openmp-parsers.cpp b/flang/lib/Parser/openmp-parsers.cpp
index 2f0765617077..cd5ee0de556d 100644
--- a/flang/lib/Parser/openmp-parsers.cpp
+++ b/flang/lib/Parser/openmp-parsers.cpp
@@ -169,7 +169,7 @@ TYPE_PARSER("ALIGNED" >>
"DEVICE" >> construct<OmpClause>(construct<OmpClause::Device>(
parenthesized(scalarIntExpr))) ||
"DIST_SCHEDULE" >>
- construct<OmpClause>(construct<OmpClause::DistSchedule>(
+ construct<OmpClause>(construct<OmpDistScheduleClause>(
parenthesized("STATIC" >> maybe("," >> scalarIntExpr)))) ||
"FINAL" >> construct<OmpClause>(construct<OmpClause::Final>(
parenthesized(scalarLogicalExpr))) ||
diff --git a/flang/lib/Parser/unparse.cpp b/flang/lib/Parser/unparse.cpp
index 85ed1a2bd60b..3dbf8fb8d961 100644
--- a/flang/lib/Parser/unparse.cpp
+++ b/flang/lib/Parser/unparse.cpp
@@ -1830,211 +1830,8 @@ class UnparseVisitor {
void Unparse(const llvm::acc::Directive &x) {
Word(llvm::acc::getOpenACCDirectiveName(x).str());
}
- void Before(const AccClause::Auto &) { Word("AUTO"); }
- void Before(const AccClause::Capture &) { Word("CAPTURE"); }
- void Before(const AccClause::Finalize &) { Word("FINALIZE"); }
- void Before(const AccClause::IfPresent &) { Word("IF_PRESENT"); }
- void Before(const AccClause::Independent &) { Word("INDEPENDENT"); }
- void Before(const AccClause::Nohost &) { Word("NOHOST"); }
- void Before(const AccClause::Read &) { Word("READ"); }
- void Before(const AccClause::Seq &) { Word("SEQ"); }
- void Before(const AccClause::Write &) { Word("WRITE"); }
- void Before(const AccClause::Unknown &) { Word("UNKNOWN"); }
- void Unparse(const AccClause::Attach &x) {
- Word("ATTACH");
- Put("(");
- Walk(x.v);
- Put(")");
- }
- void Unparse(const AccClause::Bind &x) {
- Word("BIND");
- Put("(");
- Walk(x.v);
- Put(")");
- }
- void Unparse(const AccClause::Collapse &x) {
- Word("COLLAPSE");
- Put("(");
- Walk(x.v);
- Put(")");
- }
- void Unparse(const AccClause::Copy &x) {
- Word("COPY");
- Put("(");
- Walk(x.v);
- Put(")");
- }
- void Unparse(const AccClause::Copyin &x) {
- Word("COPYIN");
- Put("(");
- Walk(x.v);
- Put(")");
- }
- void Unparse(const AccClause::Copyout &x) {
- Word("COPYOUT");
- Put("(");
- Walk(x.v);
- Put(")");
- }
- void Unparse(const AccClause::Create &x) {
- Word("CREATE");
- Put("(");
- Walk(x.v);
- Put(")");
- }
- void Unparse(const AccClause::Default &x) {
- Word("DEFAULT");
- Put("(");
- Walk(x.v);
- Put(")");
- }
- void Unparse(const AccClause::Delete &x) {
- Word("DELETE");
- Put("(");
- Walk(x.v);
- Put(")");
- }
- void Unparse(const AccClause::Detach &x) {
- Word("DETACH");
- Put("(");
- Walk(x.v);
- Put(")");
- }
- void Unparse(const AccClause::Device &x) {
- Word("DEVICE");
- Put("(");
- Walk(x.v);
- Put(")");
- }
- void Unparse(const AccClause::Deviceptr &x) {
- Word("DEVICEPTR");
- Put("(");
- Walk(x.v);
- Put(")");
- }
- void Unparse(const AccClause::DeviceResident &x) {
- Word("DEVICE_RESIDENT");
- Put("(");
- Walk(x.v);
- Put(")");
- }
- void Unparse(const AccClause::Firstprivate &x) {
- Word("FIRSTPRIVATE");
- Put("(");
- Walk(x.v);
- Put(")");
- }
- void Unparse(const AccClause::Host &x) {
- Word("HOST");
- Put("(");
- Walk(x.v);
- Put(")");
- }
- void Unparse(const AccClause::If &x) {
- Word("IF");
- Put("(");
- Walk(x.v);
- Put(")");
- }
- void Unparse(const AccClause::Link &x) {
- Word("LINK");
- Put("(");
- Walk(x.v);
- Put(")");
- }
- void Unparse(const AccClause::NumGangs &x) {
- Word("NUM_GANGS");
- Put("(");
- Walk(x.v);
- Put(")");
- }
- void Unparse(const AccClause::NumWorkers &x) {
- Word("NUM_WORKERS");
- Put("(");
- Walk(x.v);
- Put(")");
- }
- void Unparse(const AccClause::Present &x) {
- Word("PRESENT");
- Put("(");
- Walk(x.v);
- Put(")");
- }
- void Unparse(const AccClause::Private &x) {
- Word("PRIVATE");
- Put("(");
- Walk(x.v);
- Put(")");
- }
- void Unparse(const AccClause::Reduction &x) {
- Word("REDUCTION");
- Put("(");
- Walk(x.v);
- Put(")");
- }
- void Unparse(const AccClause::VectorLength &x) {
- Word("VECTOR_LENGTH");
- Put("(");
- Walk(x.v);
- Put(")");
- }
- void Unparse(const AccClause::Async &x) {
- Word("ASYNC");
- Walk("(", x.v, ")");
- }
- void Unparse(const AccClause::DefaultAsync &x) {
- Word("DEFAULT_ASYNC");
- Put("(");
- Walk(x.v);
- Put(")");
- }
- void Unparse(const AccClause::DeviceNum &x) {
- Word("DEVICE_NUM");
- Put("(");
- Walk(x.v);
- Put(")");
- }
- void Unparse(const AccClause::Gang &x) {
- Word("GANG");
- Walk("(", x.v, ")");
- }
- void Unparse(const AccClause::NoCreate &x) {
- Word("NO_CREATE");
- Put("(");
- Walk(x.v);
- Put(")");
- }
- void Unparse(const AccClause::UseDevice &x) {
- Word("USE_DEVICE");
- Put("(");
- Walk(x.v);
- Put(")");
- }
- void Unparse(const AccClause::Self &x) {
- Word("SELF");
- Walk("(", x.v, ")");
- }
- void Unparse(const AccClause::Vector &x) {
- Word("VECTOR");
- Walk("(", x.v, ")");
- }
- void Unparse(const AccClause::Wait &x) {
- Word("WAIT");
- Walk("(", x.v, ")");
- }
- void Unparse(const AccClause::Worker &x) {
- Word("WORKER");
- Walk("(", x.v, ")");
- }
- void Unparse(const AccClause::DeviceType &x) {
- Word("DEVICE_TYPE");
- Put("(");
- if (x.v.has_value())
- Walk(x.v);
- else
- Put("*");
- Put(")");
- }
+#define GEN_FLANG_CLAUSE_UNPARSE
+#include "llvm/Frontend/OpenACC/ACC.cpp.inc"
void Unparse(const AccObjectListWithModifier &x) {
Walk(std::get<std::optional<AccDataModifier>>(x.t), ":");
Walk(std::get<AccObjectList>(x.t));
@@ -2263,138 +2060,14 @@ class UnparseVisitor {
std::get<std::optional<OmpDefaultmapClause::VariableCategory>>(x.t));
Word(")");
}
- void Before(const OmpClause::Inbranch &) { Word("INBRANCH"); }
- void Before(const OmpClause::Mergeable &) { Word("MERGEABLE"); }
- void Before(const OmpClause::Nogroup &) { Word("NOGROUP"); }
- void Before(const OmpClause::Notinbranch &) { Word("NOTINBRANCH"); }
- void Before(const OmpClause::Untied &) { Word("UNTIED"); }
- void Before(const OmpClause::Threads &) { Word("THREADS"); }
- void Before(const OmpClause::Simd &) { Word("SIMD"); }
void Unparse(const OmpNowait &) { Word("NOWAIT"); }
- void Unparse(const OmpClause::Collapse &x) {
- Word("COLLAPSE(");
- Walk(x.v);
- Put(")");
- }
- void Unparse(const OmpClause::Copyin &x) {
- Word("COPYIN(");
- Walk(x.v);
- Put(")");
- }
- void Unparse(const OmpClause::Copyprivate &x) {
- Word("COPYPRIVATE(");
- Walk(x.v);
- Put(")");
- }
- void Unparse(const OmpClause::Device &x) {
- Word("DEVICE(");
- Walk(x.v);
- Put(")");
- }
- void Unparse(const OmpClause::DistSchedule &x) {
+ void Unparse(const OmpDistScheduleClause &x) {
Word("DIST_SCHEDULE(STATIC");
Walk(", ", x.v);
Put(")");
}
- void Unparse(const OmpClause::Final &x) {
- Word("FINAL(");
- Walk(x.v);
- Put(")");
- }
- void Unparse(const OmpClause::Firstprivate &x) {
- Word("FIRSTPRIVATE(");
- Walk(x.v);
- Put(")");
- }
- void Unparse(const OmpClause::From &x) {
- Word("FROM(");
- Walk(x.v);
- Put(")");
- }
- void Unparse(const OmpClause::Grainsize &x) {
- Word("GRAINSIZE(");
- Walk(x.v);
- Put(")");
- }
- void Unparse(const OmpClause::Lastprivate &x) {
- Word("LASTPRIVATE(");
- Walk(x.v);
- Put(")");
- }
- void Unparse(const OmpClause::NumTasks &x) {
- Word("NUM_TASKS(");
- Walk(x.v);
- Put(")");
- }
- void Unparse(const OmpClause::NumTeams &x) {
- Word("NUM_TEAMS(");
- Walk(x.v);
- Put(")");
- }
- void Unparse(const OmpClause::NumThreads &x) {
- Word("NUM_THREADS(");
- Walk(x.v);
- Put(")");
- }
- void Unparse(const OmpClause::Ordered &x) {
- Word("ORDERED");
- Walk("(", x.v, ")");
- }
- void Unparse(const OmpClause::Priority &x) {
- Word("PRIORITY(");
- Walk(x.v);
- Put(")");
- }
- void Unparse(const OmpClause::Private &x) {
- Word("PRIVATE(");
- Walk(x.v);
- Put(")");
- }
- void Unparse(const OmpClause::Safelen &x) {
- Word("SAFELEN(");
- Walk(x.v);
- Put(")");
- }
- void Unparse(const OmpClause::Simdlen &x) {
- Word("SIMDLEN(");
- Walk(x.v);
- Put(")");
- }
- void Unparse(const OmpClause::ThreadLimit &x) {
- Word("THREAD_LIMIT(");
- Walk(x.v);
- Put(")");
- }
- void Unparse(const OmpClause::Shared &x) {
- Word("SHARED(");
- Walk(x.v);
- Put(")");
- }
- void Unparse(const OmpClause::To &x) {
- Word("TO(");
- Walk(x.v);
- Put(")");
- }
- void Unparse(const OmpClause::Link &x) {
- Word("LINK(");
- Walk(x.v);
- Put(")");
- }
- void Unparse(const OmpClause::Uniform &x) {
- Word("UNIFORM(");
- Walk(x.v, ",");
- Put(")");
- }
- void Unparse(const OmpClause::UseDevicePtr &x) {
- Word("USE_DEVICE_PTR(");
- Walk(x.v, ",");
- Put(")");
- }
- void Unparse(const OmpClause::IsDevicePtr &x) {
- Word("IS_DEVICE_PTR(");
- Walk(x.v, ",");
- Put(")");
- }
+#define GEN_FLANG_CLAUSE_UNPARSE
+#include "llvm/Frontend/OpenMP/OMP.cpp.inc"
void Unparse(const OmpLoopDirective &x) {
switch (x.v) {
case llvm::omp::Directive::OMPD_distribute:
diff --git a/flang/lib/Semantics/check-omp-structure.cpp b/flang/lib/Semantics/check-omp-structure.cpp
index b4e4ad46ef95..6a4980ebcd54 100644
--- a/flang/lib/Semantics/check-omp-structure.cpp
+++ b/flang/lib/Semantics/check-omp-structure.cpp
@@ -355,7 +355,7 @@ void OmpStructureChecker::Enter(const parser::OmpClause::Copyprivate &) {
void OmpStructureChecker::Enter(const parser::OmpClause::Device &) {
CheckAllowed(llvm::omp::Clause::OMPC_device);
}
-void OmpStructureChecker::Enter(const parser::OmpClause::DistSchedule &) {
+void OmpStructureChecker::Enter(const parser::OmpDistScheduleClause &) {
CheckAllowed(llvm::omp::Clause::OMPC_dist_schedule);
}
void OmpStructureChecker::Enter(const parser::OmpClause::Final &) {
diff --git a/flang/lib/Semantics/check-omp-structure.h b/flang/lib/Semantics/check-omp-structure.h
index 4dc318429890..9a0c1e2c0a2d 100644
--- a/flang/lib/Semantics/check-omp-structure.h
+++ b/flang/lib/Semantics/check-omp-structure.h
@@ -128,7 +128,6 @@ class OmpStructureChecker
void Enter(const parser::OmpClause::Copyin &);
void Enter(const parser::OmpClause::Copyprivate &);
void Enter(const parser::OmpClause::Device &);
- void Enter(const parser::OmpClause::DistSchedule &);
void Enter(const parser::OmpClause::Final &);
void Enter(const parser::OmpClause::Firstprivate &);
void Enter(const parser::OmpClause::From &);
@@ -154,6 +153,7 @@ class OmpStructureChecker
void Enter(const parser::OmpDefaultClause &);
void Enter(const parser::OmpDefaultmapClause &);
void Enter(const parser::OmpDependClause &);
+ void Enter(const parser::OmpDistScheduleClause &);
void Enter(const parser::OmpIfClause &);
void Enter(const parser::OmpLinearClause &);
void Enter(const parser::OmpMapClause &);
diff --git a/llvm/include/llvm/Frontend/Directive/DirectiveBase.td b/llvm/include/llvm/Frontend/Directive/DirectiveBase.td
index b691bf8c3a7b..aa415b3f0abc 100644
--- a/llvm/include/llvm/Frontend/Directive/DirectiveBase.td
+++ b/llvm/include/llvm/Frontend/Directive/DirectiveBase.td
@@ -95,6 +95,11 @@ class Clause<string c> {
// List of allowed clause values
list<ClauseVal> allowedClauseValues = [];
+ // If set to 1, value class is part of a list. Single class by default.
+ bit isValueList = 0;
+
+ // Define a default value such as "*".
+ string defaultValue = "";
// Is clause implicit? If clause is set as implicit, the default kind will
// be return in get<LanguageName>ClauseKind instead of their own kind.
diff --git a/llvm/include/llvm/Frontend/OpenACC/ACC.td b/llvm/include/llvm/Frontend/OpenACC/ACC.td
index 4c686aad050b..d6ed93374013 100644
--- a/llvm/include/llvm/Frontend/OpenACC/ACC.td
+++ b/llvm/include/llvm/Frontend/OpenACC/ACC.td
@@ -121,9 +121,10 @@ def ACCC_DeviceResident : Clause<"device_resident"> {
// 2.4
def ACCC_DeviceType : Clause<"device_type"> {
- // (DeviceType, "*"
- let flangClassValue = "std::list<Name>";
+ let flangClassValue = "Name";
+ let defaultValue = "*";
let isValueOptional = 1;
+ let isValueList = 1;
}
// 2.6.6
diff --git a/llvm/include/llvm/Frontend/OpenMP/OMP.td b/llvm/include/llvm/Frontend/OpenMP/OMP.td
index 2e392156766c..de1651369ebc 100644
--- a/llvm/include/llvm/Frontend/OpenMP/OMP.td
+++ b/llvm/include/llvm/Frontend/OpenMP/OMP.td
@@ -184,6 +184,7 @@ def OMPC_Hint : Clause<"hint"> {
}
def OMPC_DistSchedule : Clause<"dist_schedule"> {
let clangClass = "OMPDistScheduleClause";
+ let flangClass = "OmpDistScheduleClause";
let flangClassValue = "ScalarIntExpr";
let isValueOptional = 1;
}
@@ -201,11 +202,13 @@ def OMPC_From : Clause<"from"> {
}
def OMPC_UseDevicePtr : Clause<"use_device_ptr"> {
let clangClass = "OMPUseDevicePtrClause";
- let flangClassValue = "std::list<Name>";
+ let flangClassValue = "Name";
+ let isValueList = 1;
}
def OMPC_IsDevicePtr : Clause<"is_device_ptr"> {
let clangClass = "OMPIsDevicePtrClause";
- let flangClassValue = "std::list<Name>";
+ let flangClassValue = "Name";
+ let isValueList = 1;
}
def OMPC_TaskReduction : Clause<"task_reduction"> {
let clangClass = "OMPTaskReductionClause";
@@ -260,7 +263,8 @@ def OMPC_UseDeviceAddr : Clause<"use_device_addr"> {
let clangClass = "OMPUseDeviceAddrClause";
}
def OMPC_Uniform : Clause<"uniform"> {
- let flangClassValue = "std::list<Name>";
+ let flangClassValue = "Name";
+ let isValueList = 1;
}
def OMPC_DeviceType : Clause<"device_type"> {}
def OMPC_Match : Clause<"match"> {}
diff --git a/llvm/include/llvm/TableGen/DirectiveEmitter.h b/llvm/include/llvm/TableGen/DirectiveEmitter.h
index 8a7664afa98b..0964e7b144c8 100644
--- a/llvm/include/llvm/TableGen/DirectiveEmitter.h
+++ b/llvm/include/llvm/TableGen/DirectiveEmitter.h
@@ -154,6 +154,12 @@ class Clause : public BaseRecord {
bool isValueOptional() const { return Def->getValueAsBit("isValueOptional"); }
+ bool isValueList() const { return Def->getValueAsBit("isValueList"); }
+
+ StringRef getDefaultValue() const {
+ return Def->getValueAsString("defaultValue");
+ }
+
bool isImplict() const { return Def->getValueAsBit("isImplicit"); }
};
diff --git a/llvm/test/TableGen/directive1.td b/llvm/test/TableGen/directive1.td
index 268999e3f0ce..5d9be74e9fce 100644
--- a/llvm/test/TableGen/directive1.td
+++ b/llvm/test/TableGen/directive1.td
@@ -231,5 +231,13 @@ def TDL_DirA : Directive<"dira"> {
// GEN-NEXT: NODE(TdlClause, Clauseb)
// GEN-EMPTY:
// GEN-NEXT: #endif // GEN_FLANG_DUMP_PARSE_TREE_CLAUSES
-
-
+// GEN-EMPTY:
+// GEN-NEXT: #ifdef GEN_FLANG_CLAUSE_UNPARSE
+// GEN-NEXT: #undef GEN_FLANG_CLAUSE_UNPARSE
+// GEN-EMPTY:
+// GEN-NEXT: void Unparse(const TdlClause::Clauseb &x) {
+// GEN-NEXT: Word("CLAUSEB");
+// GEN-NEXT: Walk("(", x.v, ")");
+// GEN-NEXT: }
+// GEN-EMPTY:
+// GEN-NEXT: #endif // GEN_FLANG_CLAUSE_UNPARSE
diff --git a/llvm/test/TableGen/directive2.td b/llvm/test/TableGen/directive2.td
index 685fa6a351bf..bf5ec02d5f0c 100644
--- a/llvm/test/TableGen/directive2.td
+++ b/llvm/test/TableGen/directive2.td
@@ -20,6 +20,12 @@ def TDLC_ClauseA : Clause<"clausea"> {
def TDLC_ClauseB : Clause<"clauseb"> {
let isDefault = 1;
let flangClassValue = "IntExpr";
+ let isValueList = 1;
+}
+def TDLC_ClauseC : Clause<"clausec"> {
+ let flangClassValue = "Name";
+ let defaultValue = "*";
+ let isValueOptional = 1;
}
def TDL_DirA : Directive<"dira"> {
@@ -46,9 +52,10 @@ def TDL_DirA : Directive<"dira"> {
// CHECK-NEXT: enum class Clause {
// CHECK-NEXT: TDLC_clausea,
// CHECK-NEXT: TDLC_clauseb,
+// CHECK-NEXT: TDLC_clausec,
// CHECK-NEXT: };
// CHECK-EMPTY:
-// CHECK-NEXT: static constexpr std::size_t Clause_enumSize = 2;
+// CHECK-NEXT: static constexpr std::size_t Clause_enumSize = 3;
// CHECK-EMPTY:
// CHECK-NEXT: // Enumeration helper functions
// CHECK-NEXT: Directive getTdlDirectiveKind(llvm::StringRef Str);
@@ -93,6 +100,7 @@ def TDL_DirA : Directive<"dira"> {
// IMPL-NEXT: return llvm::StringSwitch<Clause>(Str)
// IMPL-NEXT: .Case("clausea",TDLC_clauseb)
// IMPL-NEXT: .Case("clauseb",TDLC_clauseb)
+// IMPL-NEXT: .Case("clausec",TDLC_clausec)
// IMPL-NEXT: .Default(TDLC_clauseb);
// IMPL-NEXT: }
// IMPL-EMPTY:
@@ -102,6 +110,8 @@ def TDL_DirA : Directive<"dira"> {
// IMPL-NEXT: return "clausea";
// IMPL-NEXT: case TDLC_clauseb:
// IMPL-NEXT: return "clauseb";
+// IMPL-NEXT: case TDLC_clausec:
+// IMPL-NEXT: return "clausec";
// IMPL-NEXT: }
// IMPL-NEXT: llvm_unreachable("Invalid Tdl Clause kind");
// IMPL-NEXT: }
@@ -171,7 +181,8 @@ def TDL_DirA : Directive<"dira"> {
// GEN-NEXT: #undef GEN_FLANG_CLAUSE_PARSER_CLASSES
// GEN-EMPTY:
// GEN-NEXT: EMPTY_CLASS(Clausea);
-// GEN-NEXT: WRAPPER_CLASS(Clauseb, IntExpr);
+// GEN-NEXT: WRAPPER_CLASS(Clauseb, std::list<IntExpr>);
+// GEN-NEXT: WRAPPER_CLASS(Clausec, std::optional<Name>);
// GEN-EMPTY:
// GEN-NEXT: #endif // GEN_FLANG_CLAUSE_PARSER_CLASSES
// GEN-EMPTY:
@@ -180,6 +191,7 @@ def TDL_DirA : Directive<"dira"> {
// GEN-EMPTY:
// GEN-NEXT: Clausea
// GEN-NEXT: , Clauseb
+// GEN-NEXT: , Clausec
// GEN-EMPTY:
// GEN-NEXT: #endif // GEN_FLANG_CLAUSE_PARSER_CLASSES_LIST
// GEN-EMPTY:
@@ -188,5 +200,28 @@ def TDL_DirA : Directive<"dira"> {
// GEN-EMPTY:
// GEN-NEXT: NODE(TdlClause, Clausea)
// GEN-NEXT: NODE(TdlClause, Clauseb)
-// GEN-EMPTY:
-// GEN-NEXT: #endif // GEN_FLANG_DUMP_PARSE_TREE_CLAUSES
\ No newline at end of file
+// GEN-NEXT: NODE(TdlClause, Clausec)
+// GEN-EMPTY:
+// GEN-NEXT: #endif // GEN_FLANG_DUMP_PARSE_TREE_CLAUSES
+// GEN-EMPTY:
+// GEN-NEXT: #ifdef GEN_FLANG_CLAUSE_UNPARSE
+// GEN-NEXT: #undef GEN_FLANG_CLAUSE_UNPARSE
+// GEN-EMPTY:
+// GEN-NEXT: void Before(const TdlClause::Clausea &) { Word("CLAUSEA"); }
+// GEN-NEXT: void Unparse(const TdlClause::Clauseb &x) {
+// GEN-NEXT: Word("CLAUSEB");
+// GEN-NEXT: Put("(");
+// GEN-NEXT: Walk(x.v, ",");
+// GEN-NEXT: Put(")");
+// GEN-NEXT: }
+// GEN-NEXT: void Unparse(const TdlClause::Clausec &x) {
+// GEN-NEXT: Word("CLAUSEC");
+// GEN-NEXT: Put("(");
+// GEN-NEXT: if (x.v.has_value())
+// GEN-NEXT: Walk(x.v);
+// GEN-NEXT: else
+// GEN-NEXT: Put("*");
+// GEN-NEXT: Put(")");
+// GEN-NEXT: }
+// GEN-EMPTY:
+// GEN-NEXT: #endif // GEN_FLANG_CLAUSE_UNPARSE
diff --git a/llvm/utils/TableGen/DirectiveEmitter.cpp b/llvm/utils/TableGen/DirectiveEmitter.cpp
index d89b17510113..426a2c76b50e 100644
--- a/llvm/utils/TableGen/DirectiveEmitter.cpp
+++ b/llvm/utils/TableGen/DirectiveEmitter.cpp
@@ -471,18 +471,22 @@ void GenerateFlangClauseParserClass(const std::vector<Record *> &Clauses,
// Clause has a non generic class.
if (!Clause.getFlangClass().empty())
continue;
- // G
if (!Clause.getFlangClassValue().empty()) {
- if (Clause.isValueOptional()) {
- OS << "WRAPPER_CLASS(" << Clause.getFormattedParserClassName()
- << ", std::optional<" << Clause.getFlangClassValue() << ">);\n";
+ OS << "WRAPPER_CLASS(" << Clause.getFormattedParserClassName() << ", ";
+ if (Clause.isValueOptional() && Clause.isValueList()) {
+ OS << "std::optional<std::list<" << Clause.getFlangClassValue()
+ << ">>";
+ } else if (Clause.isValueOptional()) {
+ OS << "std::optional<" << Clause.getFlangClassValue() << ">";
+ } else if (Clause.isValueList()) {
+ OS << "std::list<" << Clause.getFlangClassValue() << ">";
} else {
- OS << "WRAPPER_CLASS(" << Clause.getFormattedParserClassName() << ", "
- << Clause.getFlangClassValue() << ");\n";
+ OS << Clause.getFlangClassValue();
}
} else {
- OS << "EMPTY_CLASS(" << Clause.getFormattedParserClassName() << ");\n";
+ OS << "EMPTY_CLASS(" << Clause.getFormattedParserClassName();
}
+ OS << ");\n";
}
}
@@ -521,6 +525,63 @@ void GenerateFlangClauseDump(const std::vector<Record *> &Clauses,
}
}
+// Generate Unparse functions for clauses classes in the Flang parse-tree
+// If the clause is a non-generic class, no entry is generated.
+void GenerateFlangClauseUnparse(const std::vector<Record *> &Clauses,
+ const DirectiveLanguage &DirLang,
+ raw_ostream &OS) {
+
+ IfDefScope Scope("GEN_FLANG_CLAUSE_UNPARSE", OS);
+
+ OS << "\n";
+
+ for (const auto &C : Clauses) {
+ Clause Clause{C};
+ // Clause has a non generic class.
+ if (!Clause.getFlangClass().empty())
+ continue;
+ if (!Clause.getFlangClassValue().empty()) {
+ if (Clause.isValueOptional() && Clause.getDefaultValue().empty()) {
+ OS << "void Unparse(const " << DirLang.getFlangClauseBaseClass()
+ << "::" << Clause.getFormattedParserClassName() << " &x) {\n";
+ OS << " Word(\"" << Clause.getName().upper() << "\");\n";
+
+ OS << " Walk(\"(\", x.v, \")\");\n";
+ OS << "}\n";
+ } else if (Clause.isValueOptional()) {
+ OS << "void Unparse(const " << DirLang.getFlangClauseBaseClass()
+ << "::" << Clause.getFormattedParserClassName() << " &x) {\n";
+ OS << " Word(\"" << Clause.getName().upper() << "\");\n";
+ OS << " Put(\"(\");\n";
+ OS << " if (x.v.has_value())\n";
+ if (Clause.isValueList())
+ OS << " Walk(x.v, \",\");\n";
+ else
+ OS << " Walk(x.v);\n";
+ OS << " else\n";
+ OS << " Put(\"" << Clause.getDefaultValue() << "\");\n";
+ OS << " Put(\")\");\n";
+ OS << "}\n";
+ } else {
+ OS << "void Unparse(const " << DirLang.getFlangClauseBaseClass()
+ << "::" << Clause.getFormattedParserClassName() << " &x) {\n";
+ OS << " Word(\"" << Clause.getName().upper() << "\");\n";
+ OS << " Put(\"(\");\n";
+ if (Clause.isValueList())
+ OS << " Walk(x.v, \",\");\n";
+ else
+ OS << " Walk(x.v);\n";
+ OS << " Put(\")\");\n";
+ OS << "}\n";
+ }
+ } else {
+ OS << "void Before(const " << DirLang.getFlangClauseBaseClass()
+ << "::" << Clause.getFormattedParserClassName() << " &) { Word(\""
+ << Clause.getName().upper() << "\"); }\n";
+ }
+ }
+}
+
// Generate the implemenation section for the enumeration in the directive
// language
void EmitDirectivesFlangImpl(const std::vector<Record *> &Directives,
@@ -537,6 +598,8 @@ void EmitDirectivesFlangImpl(const std::vector<Record *> &Directives,
GenerateFlangClauseParserClassList(Clauses, OS);
GenerateFlangClauseDump(Clauses, DirectiveLanguage, OS);
+
+ GenerateFlangClauseUnparse(Clauses, DirectiveLanguage, OS);
}
// Generate the implemenation section for the enumeration in the directive
More information about the flang-commits
mailing list