[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
This commit is contained in:
Valentin Clement 2020-08-17 14:22:01 -04:00 committed by clementval
parent 6b6b4b3040
commit a11d8d3dcc
7 changed files with 139 additions and 17 deletions

View File

@ -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.

View File

@ -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

View File

@ -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"> {}

View File

@ -154,6 +154,12 @@ public:
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"); }
};

View File

@ -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

View File

@ -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-NEXT: NODE(TdlClause, Clausec)
// GEN-EMPTY:
// GEN-NEXT: #endif // GEN_FLANG_DUMP_PARSE_TREE_CLAUSES
// 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

View File

@ -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