diff --git a/flang/include/flang/Parser/dump-parse-tree.h b/flang/include/flang/Parser/dump-parse-tree.h index 185a514e648fc2..e8c6244d7474fa 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 695121f8395950..49e91789fdce65 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); + // 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 2f076561707742..cd5ee0de556dc0 100644 --- a/flang/lib/Parser/openmp-parsers.cpp +++ b/flang/lib/Parser/openmp-parsers.cpp @@ -169,7 +169,7 @@ TYPE_PARSER("ALIGNED" >> "DEVICE" >> construct(construct( parenthesized(scalarIntExpr))) || "DIST_SCHEDULE" >> - construct(construct( + construct(construct( parenthesized("STATIC" >> maybe("," >> scalarIntExpr)))) || "FINAL" >> construct(construct( parenthesized(scalarLogicalExpr))) || diff --git a/flang/lib/Parser/unparse.cpp b/flang/lib/Parser/unparse.cpp index 85ed1a2bd60b9d..3dbf8fb8d96160 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>(x.t), ":"); Walk(std::get(x.t)); @@ -2263,138 +2060,14 @@ class UnparseVisitor { std::get>(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 b4e4ad46ef952f..6a4980ebcd5444 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 4dc318429890d0..9a0c1e2c0a2d42 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 b691bf8c3a7b49..aa415b3f0abceb 100644 --- a/llvm/include/llvm/Frontend/Directive/DirectiveBase.td +++ b/llvm/include/llvm/Frontend/Directive/DirectiveBase.td @@ -95,6 +95,11 @@ class Clause { // List of allowed clause values list 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 getClauseKind instead of their own kind. diff --git a/llvm/include/llvm/Frontend/OpenACC/ACC.td b/llvm/include/llvm/Frontend/OpenACC/ACC.td index 4c686aad050bfe..d6ed93374013a3 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"; + 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 2e392156766c1c..de1651369ebc44 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"; + let flangClassValue = "Name"; + let isValueList = 1; } def OMPC_IsDevicePtr : Clause<"is_device_ptr"> { let clangClass = "OMPIsDevicePtrClause"; - let flangClassValue = "std::list"; + 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"; + 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 8a7664afa98b52..0964e7b144c87c 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 268999e3f0cec9..5d9be74e9fce5f 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 685fa6a351bf90..bf5ec02d5f0c19 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(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); +// GEN-NEXT: WRAPPER_CLASS(Clausec, std::optional); // 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 d89b17510113b2..426a2c76b50e6a 100644 --- a/llvm/utils/TableGen/DirectiveEmitter.cpp +++ b/llvm/utils/TableGen/DirectiveEmitter.cpp @@ -471,18 +471,22 @@ void GenerateFlangClauseParserClass(const std::vector &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>"; + } 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 &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 &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 &Directives, @@ -537,6 +598,8 @@ void EmitDirectivesFlangImpl(const std::vector &Directives, GenerateFlangClauseParserClassList(Clauses, OS); GenerateFlangClauseDump(Clauses, DirectiveLanguage, OS); + + GenerateFlangClauseUnparse(Clauses, DirectiveLanguage, OS); } // Generate the implemenation section for the enumeration in the directive