Skip to content

Commit ff1a7bd

Browse files
committed
Modify tablegen to emit something clang can just consume.
In an attempt to reduce the amount of hackery that clang had to do, I've added some tablegen stuff. There is some things that are perhaps not well isolated, but hopefully this'll improve the codebase at least a little.
1 parent 82cb486 commit ff1a7bd

File tree

11 files changed

+153
-29
lines changed

11 files changed

+153
-29
lines changed

clang/include/clang/Basic/OpenACCKinds.h

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -328,6 +328,11 @@ enum class OpenACCClauseKind : uint8_t {
328328
/// constructs.
329329
Wait,
330330

331+
/// 'shortloop' is represented in the ACC.td file, but isn't present in the
332+
/// standard. This appears to be an old extension for the nvidia fortran
333+
// compiler, but seemingly not elsewhere. Put it here as a placeholder, but it
334+
// is never expected to be generated.
335+
Shortloop,
331336
/// Represents an invalid clause, for the purposes of parsing. Should be
332337
/// 'last'.
333338
Invalid,
@@ -486,6 +491,9 @@ inline StreamTy &printOpenACCClauseKind(StreamTy &Out, OpenACCClauseKind K) {
486491
case OpenACCClauseKind::Wait:
487492
return Out << "wait";
488493

494+
case OpenACCClauseKind::Shortloop:
495+
llvm_unreachable("Shortloop shouldn't be generated in clang");
496+
LLVM_FALLTHROUGH;
489497
case OpenACCClauseKind::Invalid:
490498
return Out << "<invalid>";
491499
}

clang/lib/AST/TextNodeDumper.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -433,6 +433,7 @@ void TextNodeDumper::Visit(const OpenACCClause *C) {
433433
case OpenACCClauseKind::Vector:
434434
case OpenACCClauseKind::VectorLength:
435435
case OpenACCClauseKind::Invalid:
436+
case OpenACCClauseKind::Shortloop:
436437
// The condition expression will be printed as a part of the 'children',
437438
// but print 'clause' here so it is clear what is happening from the dump.
438439
OS << " clause";

clang/lib/Parse/ParseOpenACC.cpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -536,6 +536,8 @@ ClauseParensKind getClauseParensKind(OpenACCDirectiveKind DirKind,
536536
case OpenACCClauseKind::Tile:
537537
return ClauseParensKind::Required;
538538

539+
case OpenACCClauseKind::Shortloop:
540+
llvm_unreachable("Shortloop shouldn't be generated in clang");
539541
case OpenACCClauseKind::Auto:
540542
case OpenACCClauseKind::Finalize:
541543
case OpenACCClauseKind::IfPresent:

clang/lib/Sema/SemaOpenACCClause.cpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -215,6 +215,8 @@ class SemaOpenACCClauseVisitor {
215215
return nullptr;
216216

217217
switch (Clause.getClauseKind()) {
218+
case OpenACCClauseKind::Shortloop:
219+
llvm_unreachable("Shortloop shouldn't be generated in clang");
218220
case OpenACCClauseKind::Invalid:
219221
return nullptr;
220222
#define VISIT_CLAUSE(CLAUSE_NAME) \

clang/lib/Sema/SemaOpenACCClauseAppertainment.cpp

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ namespace {
2626
class AccClauseSet {
2727
// We're just using a uint64_t as our underlying rep, so if this size ever
2828
// gets bigger than 64, we probably need a pair of uint64_ts.
29-
static_assert(static_assert<unsigned>(OpenACCClauseKind::Invalid) < 64);
29+
static_assert(static_cast<unsigned>(OpenACCClauseKind::Invalid) < 64);
3030
uint64_t Data;
3131

3232
void setBit(OpenACCClauseKind C) {
@@ -61,13 +61,14 @@ struct LLVMClauseLists {
6161
AccClauseSet Required;
6262
};
6363
struct LLVMDirectiveClauseRelationships {
64-
llvm::acc::Directive DirKind;
64+
OpenACCDirectiveKind DirKind;
6565
LLVMClauseLists Lists;
6666
};
6767

6868
} // namespace
6969

70-
// TODO: ERICH: WOULD NEED Own DIRECTIVE_CLAUSE_SETS
70+
// This introduces these in a llvm::acc namespace, so make sure this stays in
71+
// the global namespace.
7172
#define GEN_CLANG_DIRECTIVE_CLAUSE_SETS
7273
#include "llvm/Frontend/OpenACC/ACC.inc"
7374

@@ -81,10 +82,9 @@ LLVMDirectiveClauseRelationships Relations[] =
8182

8283
const LLVMClauseLists &getListsForDirective(OpenACCDirectiveKind DK) {
8384

84-
llvm::acc::Directive Dir = getLLVMDirectiveFromClangDirective(DK);
8585
auto Res = llvm::find_if(Relations,
8686
[=](const LLVMDirectiveClauseRelationships &Rel) {
87-
return Rel.DirKind == Dir;
87+
return Rel.DirKind == DK;
8888
});
8989
assert(Res != std::end(Relations) && "Unknown directive kind?");
9090

clang/lib/Serialization/ASTReader.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12897,6 +12897,7 @@ OpenACCClause *ASTRecordReader::readOpenACCClause() {
1289712897
return OpenACCBindClause::Create(getContext(), BeginLoc, LParenLoc,
1289812898
readIdentifier(), EndLoc);
1289912899
}
12900+
case OpenACCClauseKind::Shortloop:
1290012901
case OpenACCClauseKind::Invalid:
1290112902
llvm_unreachable("Clause serialization not yet implemented");
1290212903
}

clang/lib/Serialization/ASTWriter.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8860,6 +8860,7 @@ void ASTRecordWriter::writeOpenACCClause(const OpenACCClause *C) {
88608860
return;
88618861
}
88628862
case OpenACCClauseKind::Invalid:
8863+
case OpenACCClauseKind::Shortloop:
88638864
llvm_unreachable("Clause serialization not yet implemented");
88648865
}
88658866
llvm_unreachable("Invalid Clause Kind");

llvm/include/llvm/Frontend/Directive/DirectiveBase.td

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -113,6 +113,10 @@ class Clause<string c> {
113113
// Set the prefix as optional.
114114
// `clause([prefix]: value)`
115115
bit isPrefixOptional = true;
116+
117+
// When necessary because it isn't covered by rules, the name used in the
118+
// clause in the clang::OpenACCClauseKind enum.
119+
string clangAccSpelling = "";
116120
}
117121

118122
// Hold information about clause validity by version.

llvm/include/llvm/Frontend/OpenACC/ACC.td

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -68,12 +68,14 @@ def ACCC_Copy : Clause<"copy"> {
6868
// 2.7.7
6969
def ACCC_Copyin : Clause<"copyin"> {
7070
let flangClass = "AccObjectListWithModifier";
71+
let clangAccSpelling = "CopyIn";
7172
let aliases = ["present_or_copyin", "pcopyin"];
7273
}
7374

7475
// 2.7.8
7576
def ACCC_Copyout : Clause<"copyout"> {
7677
let flangClass = "AccObjectListWithModifier";
78+
let clangAccSpelling = "CopyOut";
7779
let aliases = ["present_or_copyout", "pcopyout"];
7880
}
7981

@@ -124,6 +126,7 @@ def ACCC_DeviceNum : Clause<"device_num"> {
124126
// 2.7.4
125127
def ACCC_DevicePtr : Clause<"deviceptr"> {
126128
let flangClass = "AccObjectList";
129+
let clangAccSpelling = "DevicePtr";
127130
}
128131

129132
// 2.13.1
@@ -144,6 +147,7 @@ def ACCC_Finalize : Clause<"finalize"> {}
144147
// 2.5.14
145148
def ACCC_FirstPrivate : Clause<"firstprivate"> {
146149
let flangClass = "AccObjectList";
150+
let clangAccSpelling = "FirstPrivate";
147151
}
148152

149153
// 2.9.2
@@ -179,7 +183,9 @@ def ACCC_NoCreate : Clause<"no_create"> {
179183
}
180184

181185
// 2.15.1
182-
def ACCC_NoHost : Clause<"nohost"> {}
186+
def ACCC_NoHost : Clause<"nohost"> {
187+
let clangAccSpelling = "NoHost";
188+
}
183189

184190
// 2.5.10
185191
def ACCC_NumGangs : Clause<"num_gangs"> {

llvm/include/llvm/TableGen/DirectiveEmitter.h

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -160,6 +160,29 @@ class Directive : public BaseRecord {
160160
}
161161

162162
const Record *getCategory() const { return Def->getValueAsDef("category"); }
163+
164+
// Clang uses a different format for names of its directives enum.
165+
std::string getClangAccSpelling() const {
166+
std::string Name = Def->getValueAsString("name").str();
167+
168+
// Clang calls the 'unknown' value 'invalid'.
169+
if (Name == "unknown") return "Invalid";
170+
171+
// Clang entries all start with a capital letter, so apply that.
172+
Name[0] = std::toupper(Name[0]);
173+
// Additionally, spaces/underscores are handled by capitalizing the next
174+
// letter of the name and removing the space/underscore.
175+
for (unsigned I = 0; I < Name.size(); ++I) {
176+
if (Name[I] == ' ' || Name[I] == '_') {
177+
Name.erase(I, 1);
178+
assert(Name[I] != ' ' && Name[I] != '_' &&
179+
"No double spaces/underscores");
180+
Name[I] = std::toupper(Name[I]);
181+
}
182+
}
183+
184+
return Name;
185+
}
163186
};
164187

165188
// Wrapper class that contains Clause's information defined in DirectiveBase.td
@@ -200,6 +223,30 @@ class Clause : public BaseRecord {
200223
return N;
201224
}
202225

226+
// Clang uses a different format for names of its clause enum, which can be
227+
// overwritten with the `clangSpelling` value. So get the proper spelling
228+
// here.
229+
std::string getClangAccSpelling() const {
230+
if (StringRef ClangSpelling = Def->getValueAsString("clangAccSpelling");
231+
!ClangSpelling.empty())
232+
return ClangSpelling.str();
233+
234+
std::string Name = Def->getValueAsString("name").str();
235+
// Clang entries all start with a capital letter, so apply that.
236+
Name[0] = std::toupper(Name[0]);
237+
// Additionally, underscores are handled by capitalizing the next letter of
238+
// the name and removing the underscore.
239+
for (unsigned I = 0; I < Name.size(); ++I) {
240+
if (Name[I] == '_') {
241+
Name.erase(I, 1);
242+
assert(Name[I] != '_' && "No double underscores");
243+
Name[I] = std::toupper(Name[I]);
244+
}
245+
}
246+
247+
return Name;
248+
}
249+
203250
// Optional field.
204251
StringRef getEnumName() const {
205252
return Def->getValueAsString("enumClauseValue");

llvm/utils/TableGen/Basic/DirectiveEmitter.cpp

Lines changed: 75 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -759,32 +759,62 @@ static void generateGetDirectiveCategory(const DirectiveLanguage &DirLang,
759759
OS << "}\n";
760760
}
761761

762+
namespace {
763+
enum class DirectiveClauseFE { Flang, Clang };
764+
765+
StringRef getFESpelling(DirectiveClauseFE FE) {
766+
switch (FE) {
767+
case DirectiveClauseFE::Flang:
768+
return "flang";
769+
case DirectiveClauseFE::Clang:
770+
return "clang";
771+
}
772+
llvm_unreachable("unknown FE kind");
773+
}
774+
} // namespace
775+
762776
// Generate a simple enum set with the give clauses.
763777
static void generateClauseSet(ArrayRef<const Record *> Clauses, raw_ostream &OS,
764778
StringRef ClauseSetPrefix, const Directive &Dir,
765-
const DirectiveLanguage &DirLang) {
779+
const DirectiveLanguage &DirLang,
780+
DirectiveClauseFE FE) {
766781

767782
OS << "\n";
768783
OS << " static " << DirLang.getClauseEnumSetClass() << " " << ClauseSetPrefix
769784
<< DirLang.getDirectivePrefix() << Dir.getFormattedName() << " {\n";
770785

771786
for (const auto &C : Clauses) {
772787
VersionedClause VerClause(C);
788+
if (FE == DirectiveClauseFE::Flang) {
773789
OS << " llvm::" << DirLang.getCppNamespace()
774790
<< "::Clause::" << DirLang.getClausePrefix()
775791
<< VerClause.getClause().getFormattedName() << ",\n";
792+
} else {
793+
assert(FE == DirectiveClauseFE::Clang);
794+
assert(DirLang.getName() == "OpenACC");
795+
OS << " clang::OpenACCClauseKind::"
796+
<< VerClause.getClause().getClangAccSpelling() << ",\n";
797+
}
776798
}
777799
OS << " };\n";
778800
}
779801

780802
// Generate an enum set for the 4 kinds of clauses linked to a directive.
781803
static void generateDirectiveClauseSets(const DirectiveLanguage &DirLang,
804+
DirectiveClauseFE FE,
782805
raw_ostream &OS) {
783806

784-
IfDefScope Scope("GEN_FLANG_DIRECTIVE_CLAUSE_SETS", OS);
807+
std::string IfDefName{"GEN_"};
808+
IfDefName += getFESpelling(FE).upper();
809+
IfDefName += "_DIRECTIVE_CLAUSE_SETS";
810+
IfDefScope Scope(IfDefName, OS);
785811

786812
OS << "\n";
787-
OS << "namespace llvm {\n";
813+
// The namespace has to be different for clang vs flang, as 2 structs with the
814+
// same name but different layout is UB. So just put the 'clang' on in the
815+
// clang namespace.
816+
OS << "namespace " << (FE == DirectiveClauseFE::Flang ? "llvm" : "clang")
817+
<< "{\n";
788818

789819
// Open namespaces defined in the directive language.
790820
SmallVector<StringRef, 2> Namespaces;
@@ -797,13 +827,13 @@ static void generateDirectiveClauseSets(const DirectiveLanguage &DirLang,
797827
OS << " // Sets for " << Dir.getName() << "\n";
798828

799829
generateClauseSet(Dir.getAllowedClauses(), OS, "allowedClauses_", Dir,
800-
DirLang);
830+
DirLang, FE);
801831
generateClauseSet(Dir.getAllowedOnceClauses(), OS, "allowedOnceClauses_",
802-
Dir, DirLang);
832+
Dir, DirLang, FE);
803833
generateClauseSet(Dir.getAllowedExclusiveClauses(), OS,
804-
"allowedExclusiveClauses_", Dir, DirLang);
834+
"allowedExclusiveClauses_", Dir, DirLang, FE);
805835
generateClauseSet(Dir.getRequiredClauses(), OS, "requiredClauses_", Dir,
806-
DirLang);
836+
DirLang, FE);
807837
}
808838

809839
// Closing namespaces
@@ -817,27 +847,46 @@ static void generateDirectiveClauseSets(const DirectiveLanguage &DirLang,
817847
// The struct holds the 4 sets of enumeration for the 4 kinds of clauses
818848
// allowances (allowed, allowed once, allowed exclusive and required).
819849
static void generateDirectiveClauseMap(const DirectiveLanguage &DirLang,
820-
raw_ostream &OS) {
821-
822-
IfDefScope Scope("GEN_FLANG_DIRECTIVE_CLAUSE_MAP", OS);
850+
DirectiveClauseFE FE, raw_ostream &OS) {
851+
std::string IfDefName{"GEN_"};
852+
IfDefName += getFESpelling(FE).upper();
853+
IfDefName += "_DIRECTIVE_CLAUSE_MAP";
854+
IfDefScope Scope(IfDefName, OS);
823855

824856
OS << "\n";
825857
OS << "{\n";
826858

859+
// The namespace has to be different for clang vs flang, as 2 structs with the
860+
// same name but different layout is UB. So just put the 'clang' on in the
861+
// clang namespace.
862+
StringRef TopLevelNS = (FE == DirectiveClauseFE::Flang ? "llvm" : "clang");
863+
827864
for (const Directive Dir : DirLang.getDirectives()) {
828-
OS << " {llvm::" << DirLang.getCppNamespace()
829-
<< "::Directive::" << DirLang.getDirectivePrefix()
830-
<< Dir.getFormattedName() << ",\n";
865+
OS << " {";
866+
if (FE == DirectiveClauseFE::Flang) {
867+
OS << TopLevelNS << "::" << DirLang.getCppNamespace()
868+
<< "::Directive::" << DirLang.getDirectivePrefix()
869+
<< Dir.getFormattedName() << ",\n";
870+
} else {
871+
assert(FE == DirectiveClauseFE::Clang);
872+
assert(DirLang.getName() == "OpenACC");
873+
OS << "clang::OpenACCDirectiveKind::" << Dir.getClangAccSpelling()
874+
<< ",\n";
875+
}
876+
831877
OS << " {\n";
832-
OS << " llvm::" << DirLang.getCppNamespace() << "::allowedClauses_"
833-
<< DirLang.getDirectivePrefix() << Dir.getFormattedName() << ",\n";
834-
OS << " llvm::" << DirLang.getCppNamespace() << "::allowedOnceClauses_"
835-
<< DirLang.getDirectivePrefix() << Dir.getFormattedName() << ",\n";
836-
OS << " llvm::" << DirLang.getCppNamespace()
878+
OS << " " << TopLevelNS << "::" << DirLang.getCppNamespace()
879+
<< "::allowedClauses_" << DirLang.getDirectivePrefix()
880+
<< Dir.getFormattedName() << ",\n";
881+
OS << " " << TopLevelNS << "::" << DirLang.getCppNamespace()
882+
<< "::allowedOnceClauses_" << DirLang.getDirectivePrefix()
883+
<< Dir.getFormattedName() << ",\n";
884+
OS << " " << TopLevelNS << "::" << DirLang.getCppNamespace()
837885
<< "::allowedExclusiveClauses_" << DirLang.getDirectivePrefix()
838886
<< Dir.getFormattedName() << ",\n";
839-
OS << " llvm::" << DirLang.getCppNamespace() << "::requiredClauses_"
840-
<< DirLang.getDirectivePrefix() << Dir.getFormattedName() << ",\n";
887+
OS << " " << TopLevelNS << "::" << DirLang.getCppNamespace()
888+
<< "::requiredClauses_" << DirLang.getDirectivePrefix()
889+
<< Dir.getFormattedName() << ",\n";
841890
OS << " }\n";
842891
OS << " },\n";
843892
}
@@ -1076,17 +1125,20 @@ static void generateFlangClausesParser(const DirectiveLanguage &DirLang,
10761125
// language
10771126
static void emitDirectivesClangImpl(const DirectiveLanguage &DirLang,
10781127
raw_ostream &OS) {
1079-
// Currently we only have work to do for OpenACC, so skip.
1128+
// Currently we only have work to do for OpenACC, so skip otherwise.
10801129
if (DirLang.getName() != "OpenACC")
10811130
return;
1131+
1132+
generateDirectiveClauseSets(DirLang, DirectiveClauseFE::Clang, OS);
1133+
generateDirectiveClauseMap(DirLang, DirectiveClauseFE::Clang, OS);
10821134
}
10831135
// Generate the implementation section for the enumeration in the directive
10841136
// language
10851137
static void emitDirectivesFlangImpl(const DirectiveLanguage &DirLang,
10861138
raw_ostream &OS) {
1087-
generateDirectiveClauseSets(DirLang, OS);
1139+
generateDirectiveClauseSets(DirLang, DirectiveClauseFE::Flang, OS);
10881140

1089-
generateDirectiveClauseMap(DirLang, OS);
1141+
generateDirectiveClauseMap(DirLang, DirectiveClauseFE::Flang, OS);
10901142

10911143
generateFlangClauseParserClass(DirLang, OS);
10921144

0 commit comments

Comments
 (0)