[utils][TableGen] Implement clause aliases as alternative spellings (#141765)
Use the spellings in the generated clause parser. The functions
`get<lang>ClauseKind` and `get<lang>ClauseName` are not yet updated.
The definitions of both clauses and directives now take a list of
"Spelling"s instead of a single string. For example
```
def ACCC_Copyin : Clause<[Spelling<"copyin">,
Spelling<"present_or_copyin">,
Spelling<"pcopyin">]> { ... }
```
A "Spelling" is a versioned string, defaulting to "all versions".
For background information see
https://discourse.llvm.org/t/rfc-alternative-spellings-of-openmp-directives/85507
This commit is contained in:
parent
1be7c6fb40
commit
4dcc159485
@ -51,6 +51,20 @@ class DirectiveLanguage {
|
||||
string flangClauseBaseClass = "";
|
||||
}
|
||||
|
||||
// Base class for versioned entities.
|
||||
class Versioned<int min = 1, int max = 0x7FFFFFFF> {
|
||||
// Mininum version number where this object is valid.
|
||||
int minVersion = min;
|
||||
|
||||
// Maximum version number where this object is valid.
|
||||
int maxVersion = max;
|
||||
}
|
||||
|
||||
class Spelling<string s, int min = 1, int max = 0x7FFFFFFF>
|
||||
: Versioned<min, max> {
|
||||
string spelling = s;
|
||||
}
|
||||
|
||||
// Some clauses take an argument from a predefined list of allowed keyword
|
||||
// values. For example, assume a clause "someclause" with an argument from
|
||||
// the list "foo", "bar", "baz". In the user source code this would look
|
||||
@ -81,12 +95,9 @@ class EnumVal<string n, int v, bit uv> {
|
||||
}
|
||||
|
||||
// Information about a specific clause.
|
||||
class Clause<string c> {
|
||||
// Name of the clause.
|
||||
string name = c;
|
||||
|
||||
// Define aliases used in the parser.
|
||||
list<string> aliases = [];
|
||||
class Clause<list<Spelling> ss> {
|
||||
// Spellings of the clause.
|
||||
list<Spelling> spellings = ss;
|
||||
|
||||
// Optional class holding value of the clause in clang AST.
|
||||
string clangClass = "";
|
||||
@ -134,15 +145,9 @@ class Clause<string c> {
|
||||
}
|
||||
|
||||
// Hold information about clause validity by version.
|
||||
class VersionedClause<Clause c, int min = 1, int max = 0x7FFFFFFF> {
|
||||
// Actual clause.
|
||||
class VersionedClause<Clause c, int min = 1, int max = 0x7FFFFFFF>
|
||||
: Versioned<min, max> {
|
||||
Clause clause = c;
|
||||
|
||||
// Mininum version number where this clause is valid.
|
||||
int minVersion = min;
|
||||
|
||||
// Maximum version number where this clause is valid.
|
||||
int maxVersion = max;
|
||||
}
|
||||
|
||||
// Kinds of directive associations.
|
||||
@ -190,15 +195,15 @@ class SourceLanguage<string n> {
|
||||
string name = n; // Name of the enum value in enum class Association.
|
||||
}
|
||||
|
||||
// The C languages also implies C++ until there is a reason to add C++
|
||||
// The C language also implies C++ until there is a reason to add C++
|
||||
// separately.
|
||||
def L_C : SourceLanguage<"C"> {}
|
||||
def L_Fortran : SourceLanguage<"Fortran"> {}
|
||||
|
||||
// Information about a specific directive.
|
||||
class Directive<string d> {
|
||||
// Name of the directive. Can be composite directive sepearted by whitespace.
|
||||
string name = d;
|
||||
class Directive<list<Spelling> ss> {
|
||||
// Spellings of the directive.
|
||||
list<Spelling> spellings = ss;
|
||||
|
||||
// Clauses cannot appear twice in the three allowed lists below. Also, since
|
||||
// required implies allowed, the same clause cannot appear in both the
|
||||
|
||||
@ -32,64 +32,65 @@ def OpenACC : DirectiveLanguage {
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
// 2.16.1
|
||||
def ACCC_Async : Clause<"async"> {
|
||||
def ACCC_Async : Clause<[Spelling<"async">]> {
|
||||
let flangClass = "ScalarIntExpr";
|
||||
let isValueOptional = true;
|
||||
}
|
||||
|
||||
// 2.9.7
|
||||
def ACCC_Auto : Clause<"auto"> {}
|
||||
def ACCC_Auto : Clause<[Spelling<"auto">]> {}
|
||||
|
||||
// 2.7.12
|
||||
def ACCC_Attach : Clause<"attach"> {
|
||||
def ACCC_Attach : Clause<[Spelling<"attach">]> {
|
||||
let flangClass = "AccObjectList";
|
||||
}
|
||||
|
||||
// 2.15.1
|
||||
def ACCC_Bind : Clause<"bind"> {
|
||||
def ACCC_Bind : Clause<[Spelling<"bind">]> {
|
||||
let flangClass = "AccBindClause";
|
||||
}
|
||||
|
||||
// 2.12
|
||||
def ACCC_Capture : Clause<"capture"> {
|
||||
def ACCC_Capture : Clause<[Spelling<"capture">]> {
|
||||
}
|
||||
|
||||
// 2.9.1
|
||||
def ACCC_Collapse : Clause<"collapse"> {
|
||||
def ACCC_Collapse : Clause<[Spelling<"collapse">]> {
|
||||
let flangClass = "AccCollapseArg";
|
||||
}
|
||||
|
||||
// 2.7.6
|
||||
def ACCC_Copy : Clause<"copy"> {
|
||||
def ACCC_Copy
|
||||
: Clause<[Spelling<"copy">, Spelling<"present_or_copy">,
|
||||
Spelling<"pcopy">]> {
|
||||
let flangClass = "AccObjectList";
|
||||
let aliases = ["present_or_copy", "pcopy"];
|
||||
}
|
||||
|
||||
// 2.7.7
|
||||
def ACCC_Copyin : Clause<"copyin"> {
|
||||
def ACCC_Copyin : Clause<[Spelling<"copyin">, Spelling<"present_or_copyin">,
|
||||
Spelling<"pcopyin">]> {
|
||||
let flangClass = "AccObjectListWithModifier";
|
||||
let clangAccSpelling = "CopyIn";
|
||||
let aliases = ["present_or_copyin", "pcopyin"];
|
||||
}
|
||||
|
||||
// 2.7.8
|
||||
def ACCC_Copyout : Clause<"copyout"> {
|
||||
def ACCC_Copyout : Clause<[Spelling<"copyout">, Spelling<"present_or_copyout">,
|
||||
Spelling<"pcopyout">]> {
|
||||
let flangClass = "AccObjectListWithModifier";
|
||||
let clangAccSpelling = "CopyOut";
|
||||
let aliases = ["present_or_copyout", "pcopyout"];
|
||||
}
|
||||
|
||||
// 2.7.9
|
||||
def ACCC_Create : Clause<"create"> {
|
||||
def ACCC_Create : Clause<[Spelling<"create">, Spelling<"present_or_create">,
|
||||
Spelling<"pcreate">]> {
|
||||
let flangClass = "AccObjectListWithModifier";
|
||||
let aliases = ["present_or_create", "pcreate"];
|
||||
}
|
||||
|
||||
// 2.5.16
|
||||
def ACC_Default_none : EnumVal<"none", 1, 1> { let isDefault = 1; }
|
||||
def ACC_Default_present : EnumVal<"present", 0, 1> {}
|
||||
|
||||
def ACCC_Default : Clause<"default"> {
|
||||
def ACCC_Default : Clause<[Spelling<"default">]> {
|
||||
let flangClass = "AccDefaultClause";
|
||||
let enumClauseValue = "DefaultValue";
|
||||
let allowedClauseValues = [
|
||||
@ -99,174 +100,173 @@ def ACCC_Default : Clause<"default"> {
|
||||
}
|
||||
|
||||
// 2.14.3
|
||||
def ACCC_DefaultAsync : Clause<"default_async"> {
|
||||
def ACCC_DefaultAsync : Clause<[Spelling<"default_async">]> {
|
||||
let flangClass = "ScalarIntExpr";
|
||||
}
|
||||
|
||||
// 2.7.11
|
||||
def ACCC_Delete : Clause<"delete"> {
|
||||
def ACCC_Delete : Clause<[Spelling<"delete">]> {
|
||||
let flangClass = "AccObjectList";
|
||||
}
|
||||
|
||||
// 2.7.13
|
||||
def ACCC_Detach : Clause<"detach"> {
|
||||
def ACCC_Detach : Clause<[Spelling<"detach">]> {
|
||||
let flangClass = "AccObjectList";
|
||||
}
|
||||
|
||||
// 2.14.4
|
||||
def ACCC_Device : Clause<"device"> {
|
||||
def ACCC_Device : Clause<[Spelling<"device">]> {
|
||||
let flangClass = "AccObjectList";
|
||||
}
|
||||
|
||||
// 2.14.1 - 2.14.2
|
||||
def ACCC_DeviceNum : Clause<"device_num"> {
|
||||
def ACCC_DeviceNum : Clause<[Spelling<"device_num">]> {
|
||||
let flangClass = "ScalarIntExpr";
|
||||
}
|
||||
|
||||
// 2.7.4
|
||||
def ACCC_DevicePtr : Clause<"deviceptr"> {
|
||||
def ACCC_DevicePtr : Clause<[Spelling<"deviceptr">]> {
|
||||
let flangClass = "AccObjectList";
|
||||
let clangAccSpelling = "DevicePtr";
|
||||
}
|
||||
|
||||
// 2.13.1
|
||||
def ACCC_DeviceResident : Clause<"device_resident"> {
|
||||
def ACCC_DeviceResident : Clause<[Spelling<"device_resident">]> {
|
||||
let flangClass = "AccObjectList";
|
||||
}
|
||||
|
||||
// 2.4
|
||||
def ACCC_DeviceType : Clause<"device_type"> {
|
||||
def ACCC_DeviceType : Clause<[Spelling<"device_type">, Spelling<"dtype">]> {
|
||||
let flangClass = "AccDeviceTypeExprList";
|
||||
let defaultValue = "*";
|
||||
let aliases = ["dtype"];
|
||||
}
|
||||
|
||||
// 2.6.6
|
||||
def ACCC_Finalize : Clause<"finalize"> {}
|
||||
def ACCC_Finalize : Clause<[Spelling<"finalize">]> {}
|
||||
|
||||
// 2.5.14
|
||||
def ACCC_FirstPrivate : Clause<"firstprivate"> {
|
||||
def ACCC_FirstPrivate : Clause<[Spelling<"firstprivate">]> {
|
||||
let flangClass = "AccObjectList";
|
||||
let clangAccSpelling = "FirstPrivate";
|
||||
}
|
||||
|
||||
// 2.9.2
|
||||
def ACCC_Gang : Clause<"gang"> {
|
||||
def ACCC_Gang : Clause<[Spelling<"gang">]> {
|
||||
let flangClass = "AccGangArgList";
|
||||
let isValueOptional = true;
|
||||
}
|
||||
|
||||
// 2.14.4
|
||||
def ACCC_Host : Clause<"host"> {
|
||||
def ACCC_Host : Clause<[Spelling<"host">]> {
|
||||
let flangClass = "AccObjectList";
|
||||
}
|
||||
|
||||
// 2.5.6
|
||||
def ACCC_If : Clause <"if"> {
|
||||
def ACCC_If : Clause<[Spelling<"if">]> {
|
||||
let flangClass = "ScalarExpr";
|
||||
}
|
||||
|
||||
// 2.14.4
|
||||
def ACCC_IfPresent : Clause<"if_present"> {}
|
||||
def ACCC_IfPresent : Clause<[Spelling<"if_present">]> {}
|
||||
|
||||
// 2.9.6
|
||||
def ACCC_Independent : Clause<"independent"> {}
|
||||
def ACCC_Independent : Clause<[Spelling<"independent">]> {}
|
||||
|
||||
// 2.13.3
|
||||
def ACCC_Link : Clause<"link"> {
|
||||
def ACCC_Link : Clause<[Spelling<"link">]> {
|
||||
let flangClass = "AccObjectList";
|
||||
}
|
||||
|
||||
// 2.7.10
|
||||
def ACCC_NoCreate : Clause<"no_create"> {
|
||||
def ACCC_NoCreate : Clause<[Spelling<"no_create">]> {
|
||||
let flangClass = "AccObjectList";
|
||||
}
|
||||
|
||||
// 2.15.1
|
||||
def ACCC_NoHost : Clause<"nohost"> {
|
||||
let clangAccSpelling = "NoHost";
|
||||
def ACCC_NoHost : Clause<[Spelling<"nohost">]> {
|
||||
let clangAccSpelling = "NoHost";
|
||||
}
|
||||
|
||||
// 2.5.10
|
||||
def ACCC_NumGangs : Clause<"num_gangs"> {
|
||||
def ACCC_NumGangs : Clause<[Spelling<"num_gangs">]> {
|
||||
let flangClass = "ScalarIntExpr";
|
||||
let isValueList = 1;
|
||||
}
|
||||
|
||||
// 2.5.11
|
||||
def ACCC_NumWorkers : Clause<"num_workers"> {
|
||||
def ACCC_NumWorkers : Clause<[Spelling<"num_workers">]> {
|
||||
let flangClass = "ScalarIntExpr";
|
||||
}
|
||||
|
||||
// 2.7.5
|
||||
def ACCC_Present : Clause<"present"> {
|
||||
def ACCC_Present : Clause<[Spelling<"present">]> {
|
||||
let flangClass = "AccObjectList";
|
||||
}
|
||||
|
||||
// 2.5.13
|
||||
def ACCC_Private : Clause<"private"> {
|
||||
def ACCC_Private : Clause<[Spelling<"private">]> {
|
||||
let flangClass = "AccObjectList";
|
||||
}
|
||||
|
||||
// 2.9.8
|
||||
def ACCC_Tile : Clause <"tile"> {
|
||||
def ACCC_Tile : Clause<[Spelling<"tile">]> {
|
||||
let flangClass = "AccTileExprList";
|
||||
}
|
||||
|
||||
// 2.8.1
|
||||
def ACCC_UseDevice : Clause <"use_device"> {
|
||||
def ACCC_UseDevice : Clause<[Spelling<"use_device">]> {
|
||||
let flangClass = "AccObjectList";
|
||||
}
|
||||
|
||||
// 2.12
|
||||
def ACCC_Read : Clause<"read"> {}
|
||||
def ACCC_Read : Clause<[Spelling<"read">]> {}
|
||||
|
||||
// 2.5.15
|
||||
def ACCC_Reduction : Clause<"reduction"> {
|
||||
def ACCC_Reduction : Clause<[Spelling<"reduction">]> {
|
||||
let flangClass = "AccObjectListWithReduction";
|
||||
}
|
||||
|
||||
// 2.5.7
|
||||
def ACCC_Self : Clause<"self"> {
|
||||
def ACCC_Self : Clause<[Spelling<"self">]> {
|
||||
let flangClass = "AccSelfClause";
|
||||
let isValueOptional = true;
|
||||
}
|
||||
|
||||
// 2.9.5
|
||||
def ACCC_Seq : Clause<"seq"> {}
|
||||
def ACCC_Seq : Clause<[Spelling<"seq">]> {}
|
||||
|
||||
// Non-standard extension
|
||||
def ACCC_ShortLoop : Clause<"shortloop"> {}
|
||||
def ACCC_ShortLoop : Clause<[Spelling<"shortloop">]> {}
|
||||
|
||||
// 2.9.4
|
||||
def ACCC_Vector : Clause<"vector"> {
|
||||
def ACCC_Vector : Clause<[Spelling<"vector">]> {
|
||||
let flangClass = "ScalarIntExpr";
|
||||
let isValueOptional = true;
|
||||
let prefix = "length";
|
||||
}
|
||||
|
||||
// 2.5.12
|
||||
def ACCC_VectorLength : Clause<"vector_length"> {
|
||||
def ACCC_VectorLength : Clause<[Spelling<"vector_length">]> {
|
||||
let flangClass = "ScalarIntExpr";
|
||||
}
|
||||
|
||||
// 2.16.2
|
||||
def ACCC_Wait : Clause<"wait"> {
|
||||
def ACCC_Wait : Clause<[Spelling<"wait">]> {
|
||||
let flangClass = "AccWaitArgument";
|
||||
let isValueOptional = true;
|
||||
}
|
||||
|
||||
// 2.9.3
|
||||
def ACCC_Worker: Clause<"worker"> {
|
||||
def ACCC_Worker: Clause<[Spelling<"worker">]> {
|
||||
let flangClass = "ScalarIntExpr";
|
||||
let isValueOptional = true;
|
||||
let prefix = "num";
|
||||
}
|
||||
|
||||
// 2.12
|
||||
def ACCC_Write : Clause<"write"> {}
|
||||
def ACCC_Write : Clause<[Spelling<"write">]> {}
|
||||
|
||||
def ACCC_Unknown : Clause<"unknown"> {
|
||||
def ACCC_Unknown : Clause<[Spelling<"unknown">]> {
|
||||
let isDefault = true;
|
||||
}
|
||||
|
||||
@ -275,14 +275,14 @@ def ACCC_Unknown : Clause<"unknown"> {
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
// 2.12
|
||||
def ACC_Atomic : Directive<"atomic"> {
|
||||
def ACC_Atomic : Directive<[Spelling<"atomic">]> {
|
||||
let allowedOnceClauses = [VersionedClause<ACCC_If, 34>];
|
||||
let association = AS_Block;
|
||||
let category = CA_Executable;
|
||||
}
|
||||
|
||||
// 2.6.5
|
||||
def ACC_Data : Directive<"data"> {
|
||||
def ACC_Data : Directive<[Spelling<"data">]> {
|
||||
let allowedOnceClauses = [
|
||||
VersionedClause<ACCC_If>,
|
||||
VersionedClause<ACCC_Default>
|
||||
@ -308,7 +308,7 @@ def ACC_Data : Directive<"data"> {
|
||||
}
|
||||
|
||||
// 2.13
|
||||
def ACC_Declare : Directive<"declare"> {
|
||||
def ACC_Declare : Directive<[Spelling<"declare">]> {
|
||||
let allowedClauses = [
|
||||
VersionedClause<ACCC_Copy>,
|
||||
VersionedClause<ACCC_Copyin>,
|
||||
@ -324,7 +324,7 @@ def ACC_Declare : Directive<"declare"> {
|
||||
}
|
||||
|
||||
// 2.5.3
|
||||
def ACC_Kernels : Directive<"kernels"> {
|
||||
def ACC_Kernels : Directive<[Spelling<"kernels">]> {
|
||||
let allowedClauses = [VersionedClause<ACCC_Async>,
|
||||
VersionedClause<ACCC_Attach>,
|
||||
VersionedClause<ACCC_Copy>,
|
||||
@ -347,7 +347,7 @@ def ACC_Kernels : Directive<"kernels"> {
|
||||
}
|
||||
|
||||
// 2.5.1
|
||||
def ACC_Parallel : Directive<"parallel"> {
|
||||
def ACC_Parallel : Directive<[Spelling<"parallel">]> {
|
||||
let allowedClauses = [
|
||||
VersionedClause<ACCC_Attach>,
|
||||
VersionedClause<ACCC_Async>,
|
||||
@ -377,7 +377,7 @@ def ACC_Parallel : Directive<"parallel"> {
|
||||
}
|
||||
|
||||
// 2.5.2
|
||||
def ACC_Serial : Directive<"serial"> {
|
||||
def ACC_Serial : Directive<[Spelling<"serial">]> {
|
||||
// Spec line 950-951: clause is as for the parallel construct except that the
|
||||
// num_gangs, num_workers, and vector_length clauses are not permitted.
|
||||
let allowedClauses = [VersionedClause<ACCC_Async>,
|
||||
@ -402,7 +402,7 @@ def ACC_Serial : Directive<"serial"> {
|
||||
}
|
||||
|
||||
// 2.9
|
||||
def ACC_Loop : Directive<"loop"> {
|
||||
def ACC_Loop : Directive<[Spelling<"loop">]> {
|
||||
let allowedClauses = [
|
||||
VersionedClause<ACCC_DeviceType>,
|
||||
VersionedClause<ACCC_Private>,
|
||||
@ -424,13 +424,13 @@ def ACC_Loop : Directive<"loop"> {
|
||||
}
|
||||
|
||||
// 2.10
|
||||
def ACC_Cache : Directive<"cache"> {
|
||||
def ACC_Cache : Directive<[Spelling<"cache">]> {
|
||||
let association = AS_None;
|
||||
let category = CA_Executable;
|
||||
}
|
||||
|
||||
// 2.14.1
|
||||
def ACC_Init : Directive<"init"> {
|
||||
def ACC_Init : Directive<[Spelling<"init">]> {
|
||||
let allowedOnceClauses = [VersionedClause<ACCC_DeviceNum>,
|
||||
VersionedClause<ACCC_If>];
|
||||
let allowedClauses = [VersionedClause<ACCC_DeviceType>];
|
||||
@ -439,7 +439,7 @@ def ACC_Init : Directive<"init"> {
|
||||
}
|
||||
|
||||
// 2.15.1
|
||||
def ACC_Routine : Directive<"routine"> {
|
||||
def ACC_Routine : Directive<[Spelling<"routine">]> {
|
||||
let allowedClauses = [
|
||||
VersionedClause<ACCC_Bind>,
|
||||
VersionedClause<ACCC_DeviceType>,
|
||||
@ -456,7 +456,7 @@ def ACC_Routine : Directive<"routine"> {
|
||||
}
|
||||
|
||||
// 2.14.3
|
||||
def ACC_Set : Directive<"set"> {
|
||||
def ACC_Set : Directive<[Spelling<"set">]> {
|
||||
let allowedOnceClauses = [
|
||||
VersionedClause<ACCC_DefaultAsync>,
|
||||
VersionedClause<ACCC_DeviceNum>,
|
||||
@ -476,7 +476,7 @@ def ACC_Set : Directive<"set"> {
|
||||
}
|
||||
|
||||
// 2.14.2
|
||||
def ACC_Shutdown : Directive<"shutdown"> {
|
||||
def ACC_Shutdown : Directive<[Spelling<"shutdown">]> {
|
||||
let allowedOnceClauses = [VersionedClause<ACCC_DeviceNum>,
|
||||
VersionedClause<ACCC_If>];
|
||||
let allowedClauses = [VersionedClause<ACCC_DeviceType>];
|
||||
@ -485,7 +485,7 @@ def ACC_Shutdown : Directive<"shutdown"> {
|
||||
}
|
||||
|
||||
// 2.14.4
|
||||
def ACC_Update : Directive<"update"> {
|
||||
def ACC_Update : Directive<[Spelling<"update">]> {
|
||||
let allowedClauses = [VersionedClause<ACCC_DeviceType>,
|
||||
VersionedClause<ACCC_IfPresent>,
|
||||
VersionedClause<ACCC_Wait>];
|
||||
@ -501,7 +501,7 @@ def ACC_Update : Directive<"update"> {
|
||||
}
|
||||
|
||||
// 2.16.3
|
||||
def ACC_Wait : Directive<"wait"> {
|
||||
def ACC_Wait : Directive<[Spelling<"wait">]> {
|
||||
let allowedOnceClauses = [
|
||||
VersionedClause<ACCC_Async>,
|
||||
VersionedClause<ACCC_If>
|
||||
@ -511,7 +511,7 @@ def ACC_Wait : Directive<"wait"> {
|
||||
}
|
||||
|
||||
// 2.14.6
|
||||
def ACC_EnterData : Directive<"enter data"> {
|
||||
def ACC_EnterData : Directive<[Spelling<"enter data">]> {
|
||||
let allowedClauses = [
|
||||
VersionedClause<ACCC_Wait>
|
||||
];
|
||||
@ -529,7 +529,7 @@ def ACC_EnterData : Directive<"enter data"> {
|
||||
}
|
||||
|
||||
// 2.14.7
|
||||
def ACC_ExitData : Directive<"exit data"> {
|
||||
def ACC_ExitData : Directive<[Spelling<"exit data">]> {
|
||||
let allowedClauses = [VersionedClause<ACCC_Finalize>,
|
||||
VersionedClause<ACCC_Wait>];
|
||||
let allowedOnceClauses = [VersionedClause<ACCC_Async>,
|
||||
@ -544,7 +544,7 @@ def ACC_ExitData : Directive<"exit data"> {
|
||||
}
|
||||
|
||||
// 2.8
|
||||
def ACC_HostData : Directive<"host_data"> {
|
||||
def ACC_HostData : Directive<[Spelling<"host_data">]> {
|
||||
let allowedClauses = [VersionedClause<ACCC_IfPresent>];
|
||||
let allowedOnceClauses = [VersionedClause<ACCC_If>];
|
||||
let requiredClauses = [
|
||||
@ -555,7 +555,7 @@ def ACC_HostData : Directive<"host_data"> {
|
||||
}
|
||||
|
||||
// 2.11
|
||||
def ACC_KernelsLoop : Directive<"kernels loop"> {
|
||||
def ACC_KernelsLoop : Directive<[Spelling<"kernels loop">]> {
|
||||
let allowedClauses = [VersionedClause<ACCC_Async>,
|
||||
VersionedClause<ACCC_Attach>,
|
||||
VersionedClause<ACCC_Collapse>,
|
||||
@ -591,7 +591,7 @@ def ACC_KernelsLoop : Directive<"kernels loop"> {
|
||||
}
|
||||
|
||||
// 2.11
|
||||
def ACC_ParallelLoop : Directive<"parallel loop"> {
|
||||
def ACC_ParallelLoop : Directive<[Spelling<"parallel loop">]> {
|
||||
let allowedClauses = [VersionedClause<ACCC_Async>,
|
||||
VersionedClause<ACCC_Attach>,
|
||||
VersionedClause<ACCC_Collapse>,
|
||||
@ -628,7 +628,7 @@ def ACC_ParallelLoop : Directive<"parallel loop"> {
|
||||
}
|
||||
|
||||
// 2.11
|
||||
def ACC_SerialLoop : Directive<"serial loop"> {
|
||||
def ACC_SerialLoop : Directive<[Spelling<"serial loop">]> {
|
||||
let allowedClauses = [VersionedClause<ACCC_Async>,
|
||||
VersionedClause<ACCC_Attach>,
|
||||
VersionedClause<ACCC_Collapse>,
|
||||
@ -661,7 +661,7 @@ def ACC_SerialLoop : Directive<"serial loop"> {
|
||||
let category = CA_Executable;
|
||||
}
|
||||
|
||||
def ACC_Unknown : Directive<"unknown"> {
|
||||
def ACC_Unknown : Directive<[Spelling<"unknown">]> {
|
||||
let isDefault = true;
|
||||
let association = AS_None;
|
||||
let category = CA_Utility;
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@ -17,6 +17,7 @@
|
||||
#include "llvm/ADT/STLExtras.h"
|
||||
#include "llvm/ADT/StringExtras.h"
|
||||
#include "llvm/ADT/StringRef.h"
|
||||
#include "llvm/Support/MathExtras.h"
|
||||
#include "llvm/TableGen/Record.h"
|
||||
#include <algorithm>
|
||||
#include <string>
|
||||
@ -94,6 +95,52 @@ private:
|
||||
}
|
||||
};
|
||||
|
||||
class Versioned {
|
||||
public:
|
||||
int getMinVersion(const Record *R) const {
|
||||
int64_t Min = R->getValueAsInt("minVersion");
|
||||
assert(llvm::isInt<IntWidth>(Min) && "Value out of range of 'int'");
|
||||
return Min;
|
||||
}
|
||||
|
||||
int getMaxVersion(const Record *R) const {
|
||||
int64_t Max = R->getValueAsInt("maxVersion");
|
||||
assert(llvm::isInt<IntWidth>(Max) && "Value out of range of 'int'");
|
||||
return Max;
|
||||
}
|
||||
|
||||
private:
|
||||
constexpr static int IntWidth = 8 * sizeof(int);
|
||||
};
|
||||
|
||||
// Range of specification versions: [Min, Max]
|
||||
// Default value: all possible versions.
|
||||
// This is the same structure as the one emitted into the generated sources.
|
||||
#define STRUCT_VERSION_RANGE \
|
||||
struct VersionRange { \
|
||||
int Min = 1; \
|
||||
int Max = 0x7fffffff; \
|
||||
}
|
||||
|
||||
STRUCT_VERSION_RANGE;
|
||||
|
||||
class Spelling : public Versioned {
|
||||
public:
|
||||
using Value = std::pair<StringRef, VersionRange>;
|
||||
|
||||
Spelling(const Record *Def) : Def(Def) {}
|
||||
|
||||
StringRef getText() const { return Def->getValueAsString("spelling"); }
|
||||
VersionRange getVersions() const {
|
||||
return VersionRange{getMinVersion(Def), getMaxVersion(Def)};
|
||||
}
|
||||
|
||||
Value get() const { return std::make_pair(getText(), getVersions()); }
|
||||
|
||||
private:
|
||||
const Record *Def;
|
||||
};
|
||||
|
||||
// Note: In all the classes below, allow implicit construction from Record *,
|
||||
// to allow writing code like:
|
||||
// for (const Directive D : getDirectives()) {
|
||||
@ -109,7 +156,31 @@ class BaseRecord {
|
||||
public:
|
||||
BaseRecord(const Record *Def) : Def(Def) {}
|
||||
|
||||
StringRef getName() const { return Def->getValueAsString("name"); }
|
||||
std::vector<Spelling::Value> getSpellings() const {
|
||||
std::vector<Spelling::Value> List;
|
||||
llvm::transform(Def->getValueAsListOfDefs("spellings"),
|
||||
std::back_inserter(List),
|
||||
[](const Record *R) { return Spelling(R).get(); });
|
||||
return List;
|
||||
}
|
||||
|
||||
StringRef getSpellingForIdentifier() const {
|
||||
// From all spellings, pick the first one with the minimum version
|
||||
// (i.e. pick the first from all the oldest ones). This guarantees
|
||||
// that given several equivalent (in terms of versions) names, the
|
||||
// first one is used, e.g. given
|
||||
// Clause<[Spelling<"foo">, Spelling<"bar">]> ...
|
||||
// "foo" will be the selected spelling.
|
||||
//
|
||||
// This is a suitable spelling for generating an identifier name,
|
||||
// since it will remain unchanged when any potential new spellings
|
||||
// are added.
|
||||
Spelling::Value Oldest{"not found", {/*Min=*/INT_MAX, 0}};
|
||||
for (auto V : getSpellings())
|
||||
if (V.second.Min < Oldest.second.Min)
|
||||
Oldest = V;
|
||||
return Oldest.first;
|
||||
}
|
||||
|
||||
// Returns the name of the directive formatted for output. Whitespace are
|
||||
// replaced with underscores.
|
||||
@ -149,7 +220,9 @@ public:
|
||||
}
|
||||
|
||||
std::string getFormattedName() const {
|
||||
return getSnakeName(Def->getValueAsString("name"));
|
||||
if (auto maybeName = Def->getValueAsOptionalString("name"))
|
||||
return getSnakeName(*maybeName);
|
||||
return getSnakeName(getSpellingForIdentifier());
|
||||
}
|
||||
|
||||
bool isDefault() const { return Def->getValueAsBit("isDefault"); }
|
||||
@ -201,7 +274,7 @@ public:
|
||||
|
||||
// Clang uses a different format for names of its directives enum.
|
||||
std::string getClangAccSpelling() const {
|
||||
StringRef Name = Def->getValueAsString("name");
|
||||
StringRef Name = getSpellingForIdentifier();
|
||||
|
||||
// Clang calls the 'unknown' value 'invalid'.
|
||||
if (Name == "unknown")
|
||||
@ -233,7 +306,7 @@ public:
|
||||
// ex: async -> Async
|
||||
// num_threads -> NumThreads
|
||||
std::string getFormattedParserClassName() const {
|
||||
StringRef Name = Def->getValueAsString("name");
|
||||
StringRef Name = getSpellingForIdentifier();
|
||||
return BaseRecord::getUpperCamelName(Name, "_");
|
||||
}
|
||||
|
||||
@ -245,7 +318,7 @@ public:
|
||||
!ClangSpelling.empty())
|
||||
return ClangSpelling.str();
|
||||
|
||||
StringRef Name = Def->getValueAsString("name");
|
||||
StringRef Name = getSpellingForIdentifier();
|
||||
return BaseRecord::getUpperCamelName(Name, "_");
|
||||
}
|
||||
|
||||
|
||||
@ -18,7 +18,7 @@ def TDLCV_vala : EnumVal<"vala",1,1> {}
|
||||
def TDLCV_valb : EnumVal<"valb",2,1> {}
|
||||
def TDLCV_valc : EnumVal<"valc",3,0> { let isDefault = 1; }
|
||||
|
||||
def TDLC_ClauseA : Clause<"clausea"> {
|
||||
def TDLC_ClauseA : Clause<[Spelling<"clausea">]> {
|
||||
let enumClauseValue = "AKind";
|
||||
let allowedClauseValues = [
|
||||
TDLCV_vala,
|
||||
@ -27,19 +27,18 @@ def TDLC_ClauseA : Clause<"clausea"> {
|
||||
];
|
||||
}
|
||||
|
||||
def TDLC_ClauseB : Clause<"clauseb"> {
|
||||
def TDLC_ClauseB : Clause<[Spelling<"clauseb">]> {
|
||||
let flangClass = "IntExpr";
|
||||
let isValueOptional = 1;
|
||||
let isDefault = 1;
|
||||
}
|
||||
|
||||
def TDLC_ClauseC : Clause<"clausec"> {
|
||||
let aliases = ["ccccccc"];
|
||||
def TDLC_ClauseC : Clause<[Spelling<"clausec">, Spelling<"ccccccc">]> {
|
||||
let flangClass = "IntExpr";
|
||||
let isValueList = 1;
|
||||
}
|
||||
|
||||
def TDL_DirA : Directive<"dira"> {
|
||||
def TDL_DirA : Directive<[Spelling<"dira">]> {
|
||||
let allowedClauses = [
|
||||
VersionedClause<TDLC_ClauseA>,
|
||||
VersionedClause<TDLC_ClauseB>
|
||||
@ -54,15 +53,18 @@ def TDL_DirA : Directive<"dira"> {
|
||||
// CHECK-EMPTY:
|
||||
// CHECK-NEXT: #include "llvm/ADT/ArrayRef.h"
|
||||
// CHECK-NEXT: #include "llvm/ADT/BitmaskEnum.h"
|
||||
// CHECK-NEXT: #include "llvm/ADT/StringRef.h"
|
||||
// CHECK-NEXT: #include "llvm/Support/Compiler.h"
|
||||
// CHECK-NEXT: #include <cstddef>
|
||||
// CHECK-NEXT: #include <utility>
|
||||
// CHECK-EMPTY:
|
||||
// CHECK-NEXT: namespace llvm {
|
||||
// CHECK-NEXT: class StringRef;
|
||||
// CHECK-NEXT: namespace tdl {
|
||||
// CHECK-EMPTY:
|
||||
// CHECK-NEXT: LLVM_ENABLE_BITMASK_ENUMS_IN_NAMESPACE();
|
||||
// CHECK-EMPTY:
|
||||
// CHECK-NEXT: struct VersionRange { int Min = 1; int Max = 0x7fffffff; };
|
||||
// CHECK-EMPTY:
|
||||
// CHECK-NEXT: enum class Association {
|
||||
// CHECK-NEXT: Block,
|
||||
// CHECK-NEXT: Declaration,
|
||||
@ -124,13 +126,20 @@ def TDL_DirA : Directive<"dira"> {
|
||||
// CHECK-NEXT: constexpr auto TDLCV_valc = AKind::TDLCV_valc;
|
||||
// CHECK-EMPTY:
|
||||
// CHECK-NEXT: // Enumeration helper functions
|
||||
// CHECK-NEXT: LLVM_ABI Directive getTdlDirectiveKind(StringRef Str);
|
||||
// CHECK-NEXT: LLVM_ABI std::pair<Directive, VersionRange> getTdlDirectiveKindAndVersions(StringRef Str);
|
||||
// CHECK-NEXT: inline Directive getTdlDirectiveKind(StringRef Str) {
|
||||
// CHECK-NEXT: return getTdlDirectiveKindAndVersions(Str).first;
|
||||
// CHECK-NEXT: }
|
||||
// CHECK-EMPTY:
|
||||
// CHECK-NEXT: LLVM_ABI StringRef getTdlDirectiveName(Directive D);
|
||||
// CHECK-NEXT: LLVM_ABI StringRef getTdlDirectiveName(Directive D, unsigned Ver = 0);
|
||||
// CHECK-EMPTY:
|
||||
// CHECK-NEXT: LLVM_ABI Clause getTdlClauseKind(StringRef Str);
|
||||
// CHECK-NEXT: LLVM_ABI std::pair<Clause, VersionRange> getTdlClauseKindAndVersions(StringRef Str);
|
||||
// CHECK-EMPTY:
|
||||
// CHECK-NEXT: LLVM_ABI StringRef getTdlClauseName(Clause C);
|
||||
// CHECK-NEXT: inline Clause getTdlClauseKind(StringRef Str) {
|
||||
// CHECK-NEXT: return getTdlClauseKindAndVersions(Str).first;
|
||||
// CHECK-NEXT: }
|
||||
// CHECK-EMPTY:
|
||||
// CHECK-NEXT: LLVM_ABI StringRef getTdlClauseName(Clause C, unsigned Ver = 0);
|
||||
// CHECK-EMPTY:
|
||||
// CHECK-NEXT: /// Return true if \p C is a valid clause for \p D in version \p Version.
|
||||
// CHECK-NEXT: LLVM_ABI bool isAllowedClauseForDirective(Directive D, Clause C, unsigned Version);
|
||||
@ -312,14 +321,16 @@ def TDL_DirA : Directive<"dira"> {
|
||||
// IMPL-NEXT: #undef GEN_DIRECTIVES_IMPL
|
||||
// IMPL-EMPTY:
|
||||
// IMPL-NEXT: #include "llvm/Support/ErrorHandling.h"
|
||||
// IMPL-NEXT: #include <utility>
|
||||
// IMPL-EMPTY:
|
||||
// IMPL-NEXT: llvm::tdl::Directive llvm::tdl::getTdlDirectiveKind(llvm::StringRef Str) {
|
||||
// IMPL-NEXT: return StringSwitch<Directive>(Str)
|
||||
// IMPL-NEXT: .Case("dira",TDLD_dira)
|
||||
// IMPL-NEXT: .Default(TDLD_dira);
|
||||
// IMPL-NEXT: }
|
||||
// IMPL-NEXT: std::pair<llvm::tdl::Directive, llvm::tdl::VersionRange> llvm::tdl::getTdlDirectiveKindAndVersions(llvm::StringRef Str) {
|
||||
// IMPL-NEXT: VersionRange All{}; // Default-initialized to "all-versions"
|
||||
// IMPL-NEXT: return StringSwitch<std::pair<Directive, VersionRange>>(Str)
|
||||
// IMPL-NEXT: .Case("dira", {TDLD_dira, All})
|
||||
// IMPL-NEXT: .Default({TDLD_dira, All});
|
||||
// IMPL-NEXT: }
|
||||
// IMPL-EMPTY:
|
||||
// IMPL-NEXT: llvm::StringRef llvm::tdl::getTdlDirectiveName(llvm::tdl::Directive Kind) {
|
||||
// IMPL-NEXT: llvm::StringRef llvm::tdl::getTdlDirectiveName(llvm::tdl::Directive Kind, unsigned) {
|
||||
// IMPL-NEXT: switch (Kind) {
|
||||
// IMPL-NEXT: case TDLD_dira:
|
||||
// IMPL-NEXT: return "dira";
|
||||
@ -327,15 +338,16 @@ def TDL_DirA : Directive<"dira"> {
|
||||
// IMPL-NEXT: llvm_unreachable("Invalid Tdl Directive kind");
|
||||
// IMPL-NEXT: }
|
||||
// IMPL-EMPTY:
|
||||
// IMPL-NEXT: llvm::tdl::Clause llvm::tdl::getTdlClauseKind(llvm::StringRef Str) {
|
||||
// IMPL-NEXT: return StringSwitch<Clause>(Str)
|
||||
// IMPL-NEXT: .Case("clausea",TDLC_clausea)
|
||||
// IMPL-NEXT: .Case("clauseb",TDLC_clauseb)
|
||||
// IMPL-NEXT: .Case("clausec",TDLC_clausec)
|
||||
// IMPL-NEXT: .Default(TDLC_clauseb);
|
||||
// IMPL-NEXT: }
|
||||
// IMPL-NEXT: std::pair<llvm::tdl::Clause, llvm::tdl::VersionRange> llvm::tdl::getTdlClauseKindAndVersions(llvm::StringRef Str) {
|
||||
// IMPL-NEXT: VersionRange All{}; // Default-initialized to "all-versions"
|
||||
// IMPL-NEXT: return StringSwitch<std::pair<Clause, VersionRange>>(Str)
|
||||
// IMPL-NEXT: .Case("clausea", {TDLC_clausea, All})
|
||||
// IMPL-NEXT: .Case("clauseb", {TDLC_clauseb, All})
|
||||
// IMPL-NEXT: .Case("clausec", {TDLC_clausec, All})
|
||||
// IMPL-NEXT: .Default({TDLC_clauseb, All});
|
||||
// IMPL-NEXT: }
|
||||
// IMPL-EMPTY:
|
||||
// IMPL-NEXT: llvm::StringRef llvm::tdl::getTdlClauseName(llvm::tdl::Clause Kind) {
|
||||
// IMPL-NEXT: llvm::StringRef llvm::tdl::getTdlClauseName(llvm::tdl::Clause Kind, unsigned) {
|
||||
// IMPL-NEXT: switch (Kind) {
|
||||
// IMPL-NEXT: case TDLC_clausea:
|
||||
// IMPL-NEXT: return "clausea";
|
||||
|
||||
@ -13,26 +13,26 @@ def TestDirectiveLanguage : DirectiveLanguage {
|
||||
let flangClauseBaseClass = "TdlClause";
|
||||
}
|
||||
|
||||
def TDLC_ClauseA : Clause<"clausea"> {
|
||||
def TDLC_ClauseA : Clause<[Spelling<"clausea">]> {
|
||||
let isImplicit = 1;
|
||||
}
|
||||
def TDLC_ClauseB : Clause<"clauseb"> {
|
||||
def TDLC_ClauseB : Clause<[Spelling<"clauseb">]> {
|
||||
let isDefault = 1;
|
||||
let flangClass = "IntExpr";
|
||||
let isValueList = 1;
|
||||
}
|
||||
def TDLC_ClauseC : Clause<"clausec"> {
|
||||
def TDLC_ClauseC : Clause<[Spelling<"clausec">]> {
|
||||
let clangClass = "ClauseC";
|
||||
let flangClass = "Name";
|
||||
let defaultValue = "*";
|
||||
let isValueOptional = 1;
|
||||
}
|
||||
def TDLC_ClauseD : Clause<"claused"> {
|
||||
def TDLC_ClauseD : Clause<[Spelling<"claused">]> {
|
||||
let clangClass = "ClauseD";
|
||||
let isImplicit = 1;
|
||||
}
|
||||
|
||||
def TDL_DirA : Directive<"dira"> {
|
||||
def TDL_DirA : Directive<[Spelling<"dira">]> {
|
||||
let allowedClauses = [
|
||||
VersionedClause<TDLC_ClauseA, 2, 4>,
|
||||
VersionedClause<TDLC_ClauseB, 2>
|
||||
@ -46,13 +46,16 @@ def TDL_DirA : Directive<"dira"> {
|
||||
// CHECK-NEXT: #define LLVM_Tdl_INC
|
||||
// CHECK-EMPTY:
|
||||
// CHECK-NEXT: #include "llvm/ADT/ArrayRef.h"
|
||||
// CHECK-NEXT: #include "llvm/ADT/StringRef.h"
|
||||
// CHECK-NEXT: #include "llvm/Support/Compiler.h"
|
||||
// CHECK-NEXT: #include <cstddef>
|
||||
// CHECK-NEXT: #include <utility>
|
||||
// CHECK-EMPTY:
|
||||
// CHECK-NEXT: namespace llvm {
|
||||
// CHECK-NEXT: class StringRef;
|
||||
// CHECK-NEXT: namespace tdl {
|
||||
// CHECK-EMPTY:
|
||||
// CHECK-NEXT: struct VersionRange { int Min = 1; int Max = 0x7fffffff; };
|
||||
// CHECK-EMPTY:
|
||||
// CHECK-NEXT: enum class Association {
|
||||
// CHECK-NEXT: Block,
|
||||
// CHECK-NEXT: Declaration,
|
||||
@ -99,13 +102,20 @@ def TDL_DirA : Directive<"dira"> {
|
||||
// CHECK-NEXT: static constexpr std::size_t Clause_enumSize = 4;
|
||||
// CHECK-EMPTY:
|
||||
// CHECK-NEXT: // Enumeration helper functions
|
||||
// CHECK-NEXT: LLVM_ABI Directive getTdlDirectiveKind(StringRef Str);
|
||||
// CHECK-NEXT: LLVM_ABI std::pair<Directive, VersionRange> getTdlDirectiveKindAndVersions(StringRef Str);
|
||||
// CHECK-NEXT: inline Directive getTdlDirectiveKind(StringRef Str) {
|
||||
// CHECK-NEXT: return getTdlDirectiveKindAndVersions(Str).first;
|
||||
// CHECK-NEXT: }
|
||||
// CHECK-EMPTY:
|
||||
// CHECK-NEXT: LLVM_ABI StringRef getTdlDirectiveName(Directive D);
|
||||
// CHECK-NEXT: LLVM_ABI StringRef getTdlDirectiveName(Directive D, unsigned Ver = 0);
|
||||
// CHECK-EMPTY:
|
||||
// CHECK-NEXT: LLVM_ABI Clause getTdlClauseKind(StringRef Str);
|
||||
// CHECK-NEXT: LLVM_ABI std::pair<Clause, VersionRange> getTdlClauseKindAndVersions(StringRef Str);
|
||||
// CHECK-EMPTY:
|
||||
// CHECK-NEXT: LLVM_ABI StringRef getTdlClauseName(Clause C);
|
||||
// CHECK-NEXT: inline Clause getTdlClauseKind(StringRef Str) {
|
||||
// CHECK-NEXT: return getTdlClauseKindAndVersions(Str).first;
|
||||
// CHECK-NEXT: }
|
||||
// CHECK-EMPTY:
|
||||
// CHECK-NEXT: LLVM_ABI StringRef getTdlClauseName(Clause C, unsigned Ver = 0);
|
||||
// CHECK-EMPTY:
|
||||
// CHECK-NEXT: /// Return true if \p C is a valid clause for \p D in version \p Version.
|
||||
// CHECK-NEXT: LLVM_ABI bool isAllowedClauseForDirective(Directive D, Clause C, unsigned Version);
|
||||
@ -258,14 +268,16 @@ def TDL_DirA : Directive<"dira"> {
|
||||
// IMPL-NEXT: #undef GEN_DIRECTIVES_IMPL
|
||||
// IMPL-EMPTY:
|
||||
// IMPL-NEXT: #include "llvm/Support/ErrorHandling.h"
|
||||
// IMPL-NEXT: #include <utility>
|
||||
// IMPL-EMPTY:
|
||||
// IMPL-NEXT: llvm::tdl::Directive llvm::tdl::getTdlDirectiveKind(llvm::StringRef Str) {
|
||||
// IMPL-NEXT: return StringSwitch<Directive>(Str)
|
||||
// IMPL-NEXT: .Case("dira",TDLD_dira)
|
||||
// IMPL-NEXT: .Default(TDLD_dira);
|
||||
// IMPL-NEXT: }
|
||||
// IMPL-NEXT: std::pair<llvm::tdl::Directive, llvm::tdl::VersionRange> llvm::tdl::getTdlDirectiveKindAndVersions(llvm::StringRef Str) {
|
||||
// IMPL-NEXT: VersionRange All{}; // Default-initialized to "all-versions"
|
||||
// IMPL-NEXT: return StringSwitch<std::pair<Directive, VersionRange>>(Str)
|
||||
// IMPL-NEXT: .Case("dira", {TDLD_dira, All})
|
||||
// IMPL-NEXT: .Default({TDLD_dira, All});
|
||||
// IMPL-NEXT: }
|
||||
// IMPL-EMPTY:
|
||||
// IMPL-NEXT: llvm::StringRef llvm::tdl::getTdlDirectiveName(llvm::tdl::Directive Kind) {
|
||||
// IMPL-NEXT: llvm::StringRef llvm::tdl::getTdlDirectiveName(llvm::tdl::Directive Kind, unsigned) {
|
||||
// IMPL-NEXT: switch (Kind) {
|
||||
// IMPL-NEXT: case TDLD_dira:
|
||||
// IMPL-NEXT: return "dira";
|
||||
@ -273,16 +285,17 @@ def TDL_DirA : Directive<"dira"> {
|
||||
// IMPL-NEXT: llvm_unreachable("Invalid Tdl Directive kind");
|
||||
// IMPL-NEXT: }
|
||||
// IMPL-EMPTY:
|
||||
// IMPL-NEXT: llvm::tdl::Clause llvm::tdl::getTdlClauseKind(llvm::StringRef Str) {
|
||||
// IMPL-NEXT: return StringSwitch<Clause>(Str)
|
||||
// IMPL-NEXT: .Case("clausea",TDLC_clauseb)
|
||||
// IMPL-NEXT: .Case("clauseb",TDLC_clauseb)
|
||||
// IMPL-NEXT: .Case("clausec",TDLC_clausec)
|
||||
// IMPL-NEXT: .Case("claused",TDLC_clauseb)
|
||||
// IMPL-NEXT: .Default(TDLC_clauseb);
|
||||
// IMPL-NEXT: }
|
||||
// IMPL-NEXT: std::pair<llvm::tdl::Clause, llvm::tdl::VersionRange> llvm::tdl::getTdlClauseKindAndVersions(llvm::StringRef Str) {
|
||||
// IMPL-NEXT: VersionRange All{}; // Default-initialized to "all-versions"
|
||||
// IMPL-NEXT: return StringSwitch<std::pair<Clause, VersionRange>>(Str)
|
||||
// IMPL-NEXT: .Case("clausea", {TDLC_clauseb, All})
|
||||
// IMPL-NEXT: .Case("clauseb", {TDLC_clauseb, All})
|
||||
// IMPL-NEXT: .Case("clausec", {TDLC_clausec, All})
|
||||
// IMPL-NEXT: .Case("claused", {TDLC_clauseb, All})
|
||||
// IMPL-NEXT: .Default({TDLC_clauseb, All});
|
||||
// IMPL-NEXT: }
|
||||
// IMPL-EMPTY:
|
||||
// IMPL-NEXT: llvm::StringRef llvm::tdl::getTdlClauseName(llvm::tdl::Clause Kind) {
|
||||
// IMPL-NEXT: llvm::StringRef llvm::tdl::getTdlClauseName(llvm::tdl::Clause Kind, unsigned) {
|
||||
// IMPL-NEXT: switch (Kind) {
|
||||
// IMPL-NEXT: case TDLC_clausea:
|
||||
// IMPL-NEXT: return "clausea";
|
||||
|
||||
@ -7,20 +7,20 @@ def TestDirectiveLanguage : DirectiveLanguage {
|
||||
let name = "TdlError";
|
||||
}
|
||||
|
||||
def TDLC_ClauseA : Clause<"clausea"> {
|
||||
def TDLC_ClauseA : Clause<[Spelling<"clausea">]> {
|
||||
let isDefault = 1;
|
||||
}
|
||||
|
||||
def TDLC_ClauseB : Clause<"clauseb"> {
|
||||
def TDLC_ClauseB : Clause<[Spelling<"clauseb">]> {
|
||||
}
|
||||
|
||||
def TDLC_ClauseC : Clause<"clausec"> {
|
||||
def TDLC_ClauseC : Clause<[Spelling<"clausec">]> {
|
||||
}
|
||||
|
||||
def TDLC_ClauseD : Clause<"claused"> {
|
||||
def TDLC_ClauseD : Clause<[Spelling<"claused">]> {
|
||||
}
|
||||
|
||||
def TDL_DirA : Directive<"dira"> {
|
||||
def TDL_DirA : Directive<[Spelling<"dira">]> {
|
||||
let allowedClauses = [
|
||||
VersionedClause<TDLC_ClauseA>,
|
||||
VersionedClause<TDLC_ClauseB>,
|
||||
|
||||
@ -24,6 +24,7 @@
|
||||
#include "llvm/TableGen/TableGenBackend.h"
|
||||
|
||||
#include <numeric>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
using namespace llvm;
|
||||
@ -193,10 +194,11 @@ static bool hasDuplicateClauses(ArrayRef<const Record *> Clauses,
|
||||
StringSet<> &CrtClauses) {
|
||||
bool HasError = false;
|
||||
for (const VersionedClause VerClause : Clauses) {
|
||||
const auto InsRes = CrtClauses.insert(VerClause.getClause().getName());
|
||||
StringRef Name = VerClause.getClause().getRecordName();
|
||||
const auto InsRes = CrtClauses.insert(Name);
|
||||
if (!InsRes.second) {
|
||||
PrintError("Clause " + VerClause.getClause().getRecordName() +
|
||||
" already defined on directive " + Directive.getRecordName());
|
||||
PrintError("Clause " + Name + " already defined on directive " +
|
||||
Directive.getRecordName());
|
||||
HasError = true;
|
||||
}
|
||||
}
|
||||
@ -267,11 +269,12 @@ static void emitDirectivesDecl(const RecordKeeper &Records, raw_ostream &OS) {
|
||||
if (DirLang.hasEnableBitmaskEnumInNamespace())
|
||||
OS << "#include \"llvm/ADT/BitmaskEnum.h\"\n";
|
||||
|
||||
OS << "#include \"llvm/ADT/StringRef.h\"\n";
|
||||
OS << "#include \"llvm/Support/Compiler.h\"\n";
|
||||
OS << "#include <cstddef>\n"; // for size_t
|
||||
OS << "#include <utility>\n"; // for std::pair
|
||||
OS << "\n";
|
||||
OS << "namespace llvm {\n";
|
||||
OS << "class StringRef;\n";
|
||||
|
||||
// Open namespaces defined in the directive language
|
||||
SmallVector<StringRef, 2> Namespaces;
|
||||
@ -282,6 +285,13 @@ static void emitDirectivesDecl(const RecordKeeper &Records, raw_ostream &OS) {
|
||||
if (DirLang.hasEnableBitmaskEnumInNamespace())
|
||||
OS << "\nLLVM_ENABLE_BITMASK_ENUMS_IN_NAMESPACE();\n";
|
||||
|
||||
#define AS_STRING_HELPER_TO_GET_THE_ARGUMENT_MACRO_EXPANDED(x) #x
|
||||
#define AS_STRING(x) AS_STRING_HELPER_TO_GET_THE_ARGUMENT_MACRO_EXPANDED(x)
|
||||
OS << "\n";
|
||||
OS << AS_STRING(STRUCT_VERSION_RANGE) << ";\n";
|
||||
#undef AS_STRING
|
||||
#undef AS_STRING_HELPER_TO_GET_THE_ARGUMENT_MACRO_EXPANDED
|
||||
|
||||
// Emit Directive associations
|
||||
std::vector<const Record *> Associations;
|
||||
copy_if(DirLang.getAssociations(), std::back_inserter(Associations),
|
||||
@ -313,22 +323,32 @@ static void emitDirectivesDecl(const RecordKeeper &Records, raw_ostream &OS) {
|
||||
// Generic function signatures
|
||||
OS << "\n";
|
||||
OS << "// Enumeration helper functions\n";
|
||||
OS << "LLVM_ABI Directive get" << Lang << "DirectiveKind(StringRef Str);\n";
|
||||
|
||||
OS << "LLVM_ABI std::pair<Directive, VersionRange> get" << Lang
|
||||
<< "DirectiveKindAndVersions(StringRef Str);\n";
|
||||
|
||||
OS << "inline Directive get" << Lang << "DirectiveKind(StringRef Str) {\n";
|
||||
OS << " return get" << Lang << "DirectiveKindAndVersions(Str).first;\n";
|
||||
OS << "}\n";
|
||||
OS << "\n";
|
||||
|
||||
// For OpenMP the signature is
|
||||
// getOpenMPDirectiveName(Directive D, unsigned V)
|
||||
OS << "LLVM_ABI StringRef get" << DirLang.getName()
|
||||
<< "DirectiveName(Directive D";
|
||||
if (DirLang.getCppNamespace() == "omp")
|
||||
OS << ", unsigned = 0";
|
||||
OS << ");\n";
|
||||
OS << "LLVM_ABI StringRef get" << Lang
|
||||
<< "DirectiveName(Directive D, unsigned Ver = 0);\n";
|
||||
OS << "\n";
|
||||
|
||||
OS << "LLVM_ABI Clause get" << Lang << "ClauseKind(StringRef Str);\n";
|
||||
OS << "LLVM_ABI std::pair<Clause, VersionRange> get" << Lang
|
||||
<< "ClauseKindAndVersions(StringRef Str);\n";
|
||||
OS << "\n";
|
||||
OS << "LLVM_ABI StringRef get" << Lang << "ClauseName(Clause C);\n";
|
||||
|
||||
OS << "inline Clause get" << Lang << "ClauseKind(StringRef Str) {\n";
|
||||
OS << " return get" << Lang << "ClauseKindAndVersions(Str).first;\n";
|
||||
OS << "}\n";
|
||||
OS << "\n";
|
||||
|
||||
OS << "LLVM_ABI StringRef get" << Lang
|
||||
<< "ClauseName(Clause C, unsigned Ver = 0);\n";
|
||||
OS << "\n";
|
||||
|
||||
OS << "/// Return true if \\p C is a valid clause for \\p D in version \\p "
|
||||
<< "Version.\n";
|
||||
OS << "LLVM_ABI bool isAllowedClauseForDirective(Directive D, "
|
||||
@ -359,25 +379,23 @@ static void generateGetName(ArrayRef<const Record *> Records, raw_ostream &OS,
|
||||
StringRef Prefix) {
|
||||
StringRef Lang = DirLang.getName();
|
||||
std::string Qual = getQualifier(DirLang);
|
||||
// For OpenMP the "Directive" signature is
|
||||
// getOpenMPDirectiveName(Directive D, unsigned V)
|
||||
OS << "\n";
|
||||
OS << "llvm::StringRef " << Qual << "get" << Lang << Enum << "Name(" << Qual
|
||||
<< Enum << " Kind";
|
||||
if (DirLang.getCppNamespace() == "omp" && Enum == "Directive")
|
||||
OS << ", unsigned";
|
||||
OS << ") {\n";
|
||||
<< Enum << " Kind, unsigned) {\n";
|
||||
OS << " switch (Kind) {\n";
|
||||
for (const Record *R : Records) {
|
||||
OS << " case " << getIdentifierName(R, Prefix) << ":\n";
|
||||
OS << " return \"" << BaseRecord(R).getName() << "\";\n";
|
||||
// FIXME: This will need to recognize different spellings for different
|
||||
// versions.
|
||||
OS << " return \"" << BaseRecord(R).getSpellingForIdentifier()
|
||||
<< "\";\n";
|
||||
}
|
||||
OS << " }\n"; // switch
|
||||
OS << " llvm_unreachable(\"Invalid " << Lang << " " << Enum << " kind\");\n";
|
||||
OS << "}\n";
|
||||
}
|
||||
|
||||
// Generate function implementation for get<Enum>Kind(StringRef Str)
|
||||
// Generate function implementation for get<Enum>KindAndVersions(StringRef Str)
|
||||
static void generateGetKind(ArrayRef<const Record *> Records, raw_ostream &OS,
|
||||
StringRef Enum, const DirectiveLanguage &DirLang,
|
||||
StringRef Prefix, bool ImplicitAsUnknown) {
|
||||
@ -394,21 +412,29 @@ static void generateGetKind(ArrayRef<const Record *> Records, raw_ostream &OS,
|
||||
std::string Qual = getQualifier(DirLang);
|
||||
std::string DefaultName = getIdentifierName(*DefaultIt, Prefix);
|
||||
|
||||
// std::pair<<Enum>, VersionRange>
|
||||
// get<DirLang><Enum>KindAndVersions(StringRef Str);
|
||||
OS << "\n";
|
||||
OS << Qual << Enum << " " << Qual << "get" << DirLang.getName() << Enum
|
||||
<< "Kind(llvm::StringRef Str) {\n";
|
||||
OS << " return StringSwitch<" << Enum << ">(Str)\n";
|
||||
OS << "std::pair<" << Qual << Enum << ", " << Qual << "VersionRange> " << Qual
|
||||
<< "get" << DirLang.getName() << Enum
|
||||
<< "KindAndVersions(llvm::StringRef Str) {\n";
|
||||
OS << " VersionRange All{}; // Default-initialized to \"all-versions\"\n";
|
||||
OS << " return StringSwitch<std::pair<" << Enum << ", "
|
||||
<< "VersionRange>>(Str)\n";
|
||||
|
||||
for (const Record *R : Records) {
|
||||
BaseRecord Rec(R);
|
||||
// FIXME: This will need to recognize different spellings for different
|
||||
// versions.
|
||||
StringRef Name = Rec.getSpellingForIdentifier();
|
||||
if (ImplicitAsUnknown && R->getValueAsBit("isImplicit")) {
|
||||
OS << " .Case(\"" << Rec.getName() << "\"," << DefaultName << ")\n";
|
||||
OS << " .Case(\"" << Name << "\", {" << DefaultName << ", All})\n";
|
||||
} else {
|
||||
OS << " .Case(\"" << Rec.getName() << "\","
|
||||
<< getIdentifierName(R, Prefix) << ")\n";
|
||||
OS << " .Case(\"" << Name << "\", {" << getIdentifierName(R, Prefix)
|
||||
<< ", All})\n";
|
||||
}
|
||||
}
|
||||
OS << " .Default(" << DefaultName << ");\n";
|
||||
OS << " .Default({" << DefaultName << ", All});\n";
|
||||
OS << "}\n";
|
||||
}
|
||||
|
||||
@ -430,7 +456,7 @@ static void generateGetClauseVal(const DirectiveLanguage &DirLang,
|
||||
});
|
||||
|
||||
if (DefaultIt == ClauseVals.end()) {
|
||||
PrintError("At least one val in Clause " + C.getFormattedName() +
|
||||
PrintError("At least one val in Clause " + C.getRecordName() +
|
||||
" must be defined as default.");
|
||||
return;
|
||||
}
|
||||
@ -438,8 +464,8 @@ static void generateGetClauseVal(const DirectiveLanguage &DirLang,
|
||||
|
||||
StringRef Enum = C.getEnumName();
|
||||
if (Enum.empty()) {
|
||||
PrintError("enumClauseValue field not set in Clause" +
|
||||
C.getFormattedName() + ".");
|
||||
PrintError("enumClauseValue field not set in Clause" + C.getRecordName() +
|
||||
".");
|
||||
return;
|
||||
}
|
||||
|
||||
@ -599,7 +625,10 @@ static void emitLeafTable(const DirectiveLanguage &DirLang, raw_ostream &OS,
|
||||
// (such as "end declare target").
|
||||
DenseSet<int> EndDirectives;
|
||||
for (auto [Rec, Id] : DirId) {
|
||||
if (Directive(Rec).getName().starts_with_insensitive("end "))
|
||||
// FIXME: This will need to recognize different spellings for different
|
||||
// versions.
|
||||
StringRef Name = Directive(Rec).getSpellingForIdentifier();
|
||||
if (Name.starts_with_insensitive("end "))
|
||||
EndDirectives.insert(Id);
|
||||
}
|
||||
|
||||
@ -710,7 +739,7 @@ static void generateGetDirectiveAssociation(const DirectiveLanguage &DirLang,
|
||||
};
|
||||
|
||||
auto ErrorPrefixFor = [&](Directive D) -> std::string {
|
||||
return (Twine("Directive '") + D.getName() + "' in namespace '" +
|
||||
return (Twine("Directive '") + D.getRecordName() + "' in namespace '" +
|
||||
DirLang.getCppNamespace() + "' ")
|
||||
.str();
|
||||
};
|
||||
@ -752,7 +781,6 @@ static void generateGetDirectiveAssociation(const DirectiveLanguage &DirLang,
|
||||
// Compute the association from leaf constructs.
|
||||
std::vector<const Record *> Leaves = D.getLeafConstructs();
|
||||
if (Leaves.empty()) {
|
||||
errs() << D.getName() << '\n';
|
||||
PrintFatalError(ErrorPrefixFor(D) +
|
||||
"requests association to be computed from leaves, "
|
||||
"but it has no leaves");
|
||||
@ -899,7 +927,7 @@ static void generateDirectiveClauseSets(const DirectiveLanguage &DirLang,
|
||||
|
||||
for (const Directive Dir : DirLang.getDirectives()) {
|
||||
OS << "\n";
|
||||
OS << "// Sets for " << Dir.getName() << "\n";
|
||||
OS << "// Sets for " << Dir.getSpellingForIdentifier() << "\n";
|
||||
|
||||
generateClauseSet(Dir.getAllowedClauses(), OS, "allowedClauses_", Dir,
|
||||
DirLang, FE);
|
||||
@ -1034,8 +1062,11 @@ static void generateFlangClauseUnparse(const DirectiveLanguage &DirLang,
|
||||
for (const Clause Clause : DirLang.getClauses()) {
|
||||
if (Clause.skipFlangUnparser())
|
||||
continue;
|
||||
// The unparser doesn't know the effective version, so just pick some
|
||||
// spelling.
|
||||
StringRef SomeSpelling = Clause.getSpellingForIdentifier();
|
||||
std::string Parser = Clause.getFormattedParserClassName();
|
||||
std::string Upper = Clause.getName().upper();
|
||||
std::string Upper = SomeSpelling.upper();
|
||||
|
||||
if (!Clause.getFlangClass().empty()) {
|
||||
if (Clause.isValueOptional() && Clause.getDefaultValue().empty()) {
|
||||
@ -1125,9 +1156,9 @@ getSpellingTexts(ArrayRef<const Record *> Records) {
|
||||
std::vector<RecordWithText> List;
|
||||
for (const Record *R : Records) {
|
||||
Clause C(R);
|
||||
List.push_back(std::make_pair(R, C.getName()));
|
||||
llvm::transform(C.getAliases(), std::back_inserter(List),
|
||||
[R](StringRef S) { return std::make_pair(R, S); });
|
||||
llvm::transform(
|
||||
C.getSpellings(), std::back_inserter(List),
|
||||
[R](Spelling::Value V) { return std::make_pair(R, V.first); });
|
||||
}
|
||||
return List;
|
||||
}
|
||||
@ -1305,7 +1336,9 @@ void emitDirectivesBasicImpl(const DirectiveLanguage &DirLang,
|
||||
StringRef DPrefix = DirLang.getDirectivePrefix();
|
||||
StringRef CPrefix = DirLang.getClausePrefix();
|
||||
|
||||
OS << "\n#include \"llvm/Support/ErrorHandling.h\"\n";
|
||||
OS << "\n";
|
||||
OS << "#include \"llvm/Support/ErrorHandling.h\"\n";
|
||||
OS << "#include <utility>\n";
|
||||
|
||||
// getDirectiveKind(StringRef Str)
|
||||
generateGetKind(DirLang.getDirectives(), OS, "Directive", DirLang, DPrefix,
|
||||
|
||||
@ -11,7 +11,7 @@ def TDLCV_vala : EnumVal<"vala",1,1> {}
|
||||
def TDLCV_valb : EnumVal<"valb",2,1> {}
|
||||
def TDLCV_valc : EnumVal<"valc",3,0> { let isDefault = 1; }
|
||||
|
||||
def TDLC_ClauseA : Clause<"clausea"> {
|
||||
def TDLC_ClauseA : Clause<[Spelling<"clausea">]> {
|
||||
let flangClass = "TdlClauseA";
|
||||
let enumClauseValue = "AKind";
|
||||
let allowedClauseValues = [
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user