[llvm-branch-commits] [llvm] [Frontend] Introduce `getDirectiveCategory` for ACC/OMP directives (PR #94689)

Krzysztof Parzyszek via llvm-branch-commits llvm-branch-commits at lists.llvm.org
Thu Jun 6 15:04:51 PDT 2024


https://github.com/kparzysz created https://github.com/llvm/llvm-project/pull/94689

The categories are primarily meant for OpenMP, where the spec assigns a category to each directive. It's one of declarative, executable, informational, meta, subsidiary, and utility.

These will be used in clang to avoid listing directives belonging to certain categories by hand.

>From 64fcf25e2158de44bccf725a0f91d8228b7cb7a5 Mon Sep 17 00:00:00 2001
From: Krzysztof Parzyszek <Krzysztof.Parzyszek at amd.com>
Date: Thu, 6 Jun 2024 15:10:13 -0500
Subject: [PATCH] [Frontend] Introduce `getDirectiveCategory` for ACC/OMP
 directives

The categories are primarily meant for OpenMP, where the spec assigns
a category to each directive. It's one of declarative, executable,
informational, meta, subsidiary, and utility.

These will be used in clang to avoid listing directives belonging
to certain categories by hand.
---
 .../llvm/Frontend/Directive/DirectiveBase.td  |  15 +++
 llvm/include/llvm/Frontend/OpenACC/ACC.td     |  21 ++++
 llvm/include/llvm/Frontend/OpenMP/OMP.td      | 109 ++++++++++++++++++
 llvm/include/llvm/TableGen/DirectiveEmitter.h |   6 +
 llvm/test/TableGen/directive1.td              |  23 +++-
 llvm/test/TableGen/directive2.td              |  23 +++-
 llvm/utils/TableGen/DirectiveEmitter.cpp      |  31 ++++-
 7 files changed, 225 insertions(+), 3 deletions(-)

diff --git a/llvm/include/llvm/Frontend/Directive/DirectiveBase.td b/llvm/include/llvm/Frontend/Directive/DirectiveBase.td
index ce532e0cfae29..6889c7e642ec6 100644
--- a/llvm/include/llvm/Frontend/Directive/DirectiveBase.td
+++ b/llvm/include/llvm/Frontend/Directive/DirectiveBase.td
@@ -156,6 +156,18 @@ def AS_FromLeaves : Association<"FromLeaves"> {}    // See below
 // The name "AS_FromLeaves" is recognized by TableGen, and there is no enum
 // generated for it.
 
+// Kinds of directive categories.
+class Category<string n> {
+  string name = n;  // Name of the enum value in enum class Category.
+}
+
+def CA_Declarative: Category<"Declarative"> {}
+def CA_Executable: Category<"Executable"> {}
+def CA_Informational: Category<"Informational"> {}
+def CA_Meta: Category<"Meta"> {}
+def CA_Subsidiary: Category<"Subsidiary"> {}
+def CA_Utility: Category<"Utility"> {}
+
 // Information about a specific directive.
 class Directive<string d> {
   // Name of the directive. Can be composite directive sepearted by whitespace.
@@ -190,4 +202,7 @@ class Directive<string d> {
 
   // What the directive is associated with.
   Association association = AS_FromLeaves;
+
+  // The category if the directive.
+  Category category = ?;
 }
diff --git a/llvm/include/llvm/Frontend/OpenACC/ACC.td b/llvm/include/llvm/Frontend/OpenACC/ACC.td
index dfa6a222e9f77..30a81efe7f8a6 100644
--- a/llvm/include/llvm/Frontend/OpenACC/ACC.td
+++ b/llvm/include/llvm/Frontend/OpenACC/ACC.td
@@ -268,6 +268,7 @@ def ACCC_Unknown : Clause<"unknown"> {
 // 2.12
 def ACC_Atomic : Directive<"atomic"> {
   let association = AS_Block;
+  let category = CA_Executable;
 }
 
 // 2.6.5
@@ -293,6 +294,7 @@ def ACC_Data : Directive<"data"> {
     VersionedClause<ACCC_Present>
   ];
   let association = AS_Block;
+  let category = CA_Executable;
 }
 
 // 2.13
@@ -308,6 +310,7 @@ def ACC_Declare : Directive<"declare"> {
     VersionedClause<ACCC_Link>
   ];
   let association = AS_None;
+  let category = CA_Executable;
 }
 
 // 2.5.3
@@ -334,6 +337,7 @@ def ACC_Kernels : Directive<"kernels"> {
     VersionedClause<ACCC_VectorLength>
   ];
   let association = AS_Block;
+  let category = CA_Executable;
 }
 
 // 2.5.1
@@ -363,6 +367,7 @@ def ACC_Parallel : Directive<"parallel"> {
     VersionedClause<ACCC_Self>
   ];
   let association = AS_Block;
+  let category = CA_Executable;
 }
 
 // 2.5.2
@@ -391,6 +396,7 @@ def ACC_Serial : Directive<"serial"> {
     VersionedClause<ACCC_Self>
   ];
   let association = AS_Block;
+  let category = CA_Executable;
 }
 
 // 2.9
@@ -411,11 +417,13 @@ def ACC_Loop : Directive<"loop"> {
     VersionedClause<ACCC_Seq>
   ];
   let association = AS_Loop;
+  let category = CA_Executable;
 }
 
 // 2.10
 def ACC_Cache : Directive<"cache"> {
   let association = AS_None;
+  let category = CA_Executable;
 }
 
 // 2.14.1
@@ -426,6 +434,7 @@ def ACC_Init : Directive<"init"> {
     VersionedClause<ACCC_If>
   ];
   let association = AS_None;
+  let category = CA_Executable;
 }
 
 // 2.15.1
@@ -442,6 +451,7 @@ def ACC_Routine : Directive<"routine"> {
     VersionedClause<ACCC_NoHost>
   ];
   let association = AS_Declaration;
+  let category = CA_Declarative;
 }
 
 // 2.14.3
@@ -461,6 +471,7 @@ def ACC_Set : Directive<"set"> {
     VersionedClause<ACCC_DeviceType>
   ];
   let association = AS_None;
+  let category = CA_Executable;
 }
 
 // 2.14.2
@@ -471,6 +482,7 @@ def ACC_Shutdown : Directive<"shutdown"> {
     VersionedClause<ACCC_If>
   ];
   let association = AS_None;
+  let category = CA_Executable;
 }
 
 // 2.14.4
@@ -490,6 +502,7 @@ def ACC_Update : Directive<"update"> {
     VersionedClause<ACCC_Self>
   ];
   let association = AS_None;
+  let category = CA_Executable;
 }
 
 // 2.16.3
@@ -499,6 +512,7 @@ def ACC_Wait : Directive<"wait"> {
     VersionedClause<ACCC_If>
   ];
   let association = AS_None;
+  let category = CA_Executable;
 }
 
 // 2.14.6
@@ -516,6 +530,7 @@ def ACC_EnterData : Directive<"enter data"> {
     VersionedClause<ACCC_Copyin>
   ];
   let association = AS_None;
+  let category = CA_Executable;
 }
 
 // 2.14.7
@@ -534,6 +549,7 @@ def ACC_ExitData : Directive<"exit data"> {
     VersionedClause<ACCC_Detach>
   ];
   let association = AS_None;
+  let category = CA_Executable;
 }
 
 // 2.8
@@ -546,6 +562,7 @@ def ACC_HostData : Directive<"host_data"> {
     VersionedClause<ACCC_UseDevice>
   ];
   let association = AS_Block;
+  let category = CA_Executable;
 }
 
 // 2.11
@@ -584,6 +601,7 @@ def ACC_KernelsLoop : Directive<"kernels loop"> {
     VersionedClause<ACCC_Seq>
   ];
   let leafConstructs = [ACC_Kernels, ACC_Loop];
+  let category = CA_Executable;
 }
 
 // 2.11
@@ -623,6 +641,7 @@ def ACC_ParallelLoop : Directive<"parallel loop"> {
     VersionedClause<ACCC_Seq>
   ];
   let leafConstructs = [ACC_Parallel, ACC_Loop];
+  let category = CA_Executable;
 }
 
 // 2.11
@@ -659,9 +678,11 @@ def ACC_SerialLoop : Directive<"serial loop"> {
     VersionedClause<ACCC_Seq>
   ];
   let leafConstructs = [ACC_Serial, ACC_Loop];
+  let category = CA_Executable;
 }
 
 def ACC_Unknown : Directive<"unknown"> {
   let isDefault = true;
   let association = AS_None;
+  let category = CA_Utility;
 }
diff --git a/llvm/include/llvm/Frontend/OpenMP/OMP.td b/llvm/include/llvm/Frontend/OpenMP/OMP.td
index afb8d5f725753..12a944e34c414 100644
--- a/llvm/include/llvm/Frontend/OpenMP/OMP.td
+++ b/llvm/include/llvm/Frontend/OpenMP/OMP.td
@@ -493,18 +493,22 @@ def OMP_Allocate : Directive<"allocate"> {
     VersionedClause<OMPC_Allocator>,
   ];
   let association = AS_None;
+  let category = CA_Declarative;
 }
 def OMP_Allocators : Directive<"allocators"> {
   let allowedClauses = [
     VersionedClause<OMPC_Allocate>,
   ];
   let association = AS_Block;
+  let category = CA_Executable;
 }
 def OMP_Assumes : Directive<"assumes"> {
   let association = AS_None;
+  let category = CA_Informational;
 }
 def OMP_EndAssumes : Directive<"end assumes"> {
   let association = AS_Delimited;
+  let category = OMP_Assumes.category;
 }
 def OMP_Atomic : Directive<"atomic"> {
   let allowedClauses = [
@@ -525,12 +529,15 @@ def OMP_Atomic : Directive<"atomic"> {
     VersionedClause<OMPC_Weak, 51>,
   ];
   let association = AS_Block;
+  let category = CA_Executable;
 }
 def OMP_Barrier : Directive<"barrier"> {
   let association = AS_None;
+  let category = CA_Executable;
 }
 def OMP_BeginAssumes : Directive<"begin assumes"> {
   let association = AS_Delimited;
+  let category = CA_Informational;
 }
 def OMP_BeginDeclareTarget : Directive<"begin declare target"> {
   let allowedClauses = [
@@ -540,33 +547,40 @@ def OMP_BeginDeclareTarget : Directive<"begin declare target"> {
     VersionedClause<OMPC_To>,
   ];
   let association = AS_Delimited;
+  let category = CA_Declarative;
 }
 def OMP_BeginDeclareVariant : Directive<"begin declare variant"> {
   let association = AS_Delimited;
+  let category = CA_Declarative;
 }
 def OMP_Cancel : Directive<"cancel"> {
   let allowedOnceClauses = [
     VersionedClause<OMPC_If>,
   ];
   let association = AS_None;
+  let category = CA_Executable;
 }
 def OMP_CancellationPoint : Directive<"cancellation point"> {
   let association = AS_None;
+  let category = CA_Executable;
 }
 def OMP_Critical : Directive<"critical"> {
   let allowedClauses = [
     VersionedClause<OMPC_Hint>,
   ];
   let association = AS_Block;
+  let category = CA_Executable;
 }
 def OMP_DeclareMapper : Directive<"declare mapper"> {
   let allowedClauses = [
     VersionedClause<OMPC_Map>,
   ];
   let association = AS_None;
+  let category = CA_Declarative;
 }
 def OMP_DeclareReduction : Directive<"declare reduction"> {
   let association = AS_None;
+  let category = CA_Declarative;
 }
 def OMP_DeclareSimd : Directive<"declare simd"> {
   let allowedClauses = [
@@ -582,6 +596,7 @@ def OMP_DeclareSimd : Directive<"declare simd"> {
     VersionedClause<OMPC_Notinbranch>,
   ];
   let association = AS_Declaration;
+  let category = CA_Declarative;
 }
 def OMP_DeclareTarget : Directive<"declare target"> {
   let allowedClauses = [
@@ -594,9 +609,11 @@ def OMP_DeclareTarget : Directive<"declare target"> {
     VersionedClause<OMPC_DeviceType, 50>,
   ];
   let association = AS_None;
+  let category = CA_Declarative;
 }
 def OMP_EndDeclareTarget : Directive<"end declare target"> {
   let association = AS_Delimited;
+  let category = OMP_DeclareTarget.category;
 }
 def OMP_DeclareVariant : Directive<"declare variant"> {
   let allowedClauses = [
@@ -607,9 +624,11 @@ def OMP_DeclareVariant : Directive<"declare variant"> {
     VersionedClause<OMPC_AppendArgs, 51>,
   ];
   let association = AS_Declaration;
+  let category = CA_Declarative;
 }
 def OMP_EndDeclareVariant : Directive<"end declare variant"> {
   let association = AS_Delimited;
+  let category = OMP_DeclareVariant.category;
 }
 def OMP_Depobj : Directive<"depobj"> {
   let allowedClauses = [
@@ -621,6 +640,7 @@ def OMP_Depobj : Directive<"depobj"> {
     VersionedClause<OMPC_Update, 50>,
   ];
   let association = AS_None;
+  let category = CA_Executable;
 }
 def OMP_dispatch : Directive<"dispatch"> {
   let allowedClauses = [
@@ -633,6 +653,7 @@ def OMP_dispatch : Directive<"dispatch"> {
     VersionedClause<OMPC_NoWait>,
   ];
   let association = AS_Block;
+  let category = CA_Executable;
 }
 def OMP_Distribute : Directive<"distribute"> {
   let allowedClauses = [
@@ -646,6 +667,7 @@ def OMP_Distribute : Directive<"distribute"> {
     VersionedClause<OMPC_DistSchedule>,
   ];
   let association = AS_Loop;
+  let category = CA_Executable;
 }
 def OMP_Do : Directive<"do"> {
   let allowedClauses = [
@@ -663,6 +685,7 @@ def OMP_Do : Directive<"do"> {
     VersionedClause<OMPC_Schedule>,
   ];
   let association = AS_Loop;
+  let category = CA_Executable;
 }
 def OMP_EndDo : Directive<"end do"> {
   let allowedOnceClauses = [
@@ -671,6 +694,7 @@ def OMP_EndDo : Directive<"end do"> {
   // Needed for association computation, since OMP_Do has it "from leafConstructs".
   let leafConstructs = OMP_Do.leafConstructs;
   let association = OMP_Do.association;
+  let category = OMP_Do.category;
 }
 def OMP_Error : Directive<"error"> {
   let allowedClauses = [
@@ -679,6 +703,7 @@ def OMP_Error : Directive<"error"> {
     VersionedClause<OMPC_Severity, 51>,
   ];
   let association = AS_None;
+  let category = CA_Utility;
 }
 def OMP_Flush : Directive<"flush"> {
   let allowedOnceClauses = [
@@ -690,6 +715,7 @@ def OMP_Flush : Directive<"flush"> {
     VersionedClause<OMPC_Release, 50>,
   ];
   let association = AS_None;
+  let category = CA_Executable;
 }
 def OMP_For : Directive<"for"> {
   let allowedClauses = [
@@ -706,6 +732,7 @@ def OMP_For : Directive<"for"> {
     VersionedClause<OMPC_Schedule>,
   ];
   let association = AS_Loop;
+  let category = CA_Executable;
 }
 def OMP_interop : Directive<"interop"> {
   let allowedClauses = [
@@ -717,6 +744,7 @@ def OMP_interop : Directive<"interop"> {
     VersionedClause<OMPC_Use>,
   ];
   let association = AS_None;
+  let category = CA_Executable;
 }
 def OMP_loop : Directive<"loop"> {
   let allowedClauses = [
@@ -730,15 +758,18 @@ def OMP_loop : Directive<"loop"> {
     VersionedClause<OMPC_Order, 50>,
   ];
   let association = AS_Loop;
+  let category = CA_Executable;
 }
 def OMP_masked : Directive<"masked"> {
   let allowedOnceClauses = [
     VersionedClause<OMPC_Filter>,
   ];
   let association = AS_Block;
+  let category = CA_Executable;
 }
 def OMP_Master : Directive<"master"> {
   let association = AS_Block;
+  let category = CA_Executable;
 }
 def OMP_Metadirective : Directive<"metadirective"> {
   let allowedClauses = [
@@ -748,9 +779,11 @@ def OMP_Metadirective : Directive<"metadirective"> {
     VersionedClause<OMPC_Default>,
   ];
   let association = AS_None;
+  let category = CA_Meta;
 }
 def OMP_Nothing : Directive<"nothing"> {
   let association = AS_None;
+  let category = CA_Utility;
 }
 def OMP_Ordered : Directive<"ordered"> {
   let allowedClauses = [
@@ -763,6 +796,7 @@ def OMP_Ordered : Directive<"ordered"> {
   ];
   let association = AS_None;
   // There is also a block-associated "ordered" directive.
+  let category = CA_Executable;
 }
 def OMP_Parallel : Directive<"parallel"> {
   let allowedClauses = [
@@ -781,6 +815,7 @@ def OMP_Parallel : Directive<"parallel"> {
     VersionedClause<OMPC_ProcBind>,
   ];
   let association = AS_Block;
+  let category = CA_Executable;
 }
 def OMP_Requires : Directive<"requires"> {
   let allowedOnceClauses = [
@@ -799,6 +834,7 @@ def OMP_Requires : Directive<"requires"> {
     VersionedClause<OMPC_ReverseOffload, 99>,
   ];
   let association = AS_None;
+  let category = CA_Informational;
 }
 def OMP_Scan : Directive<"scan"> {
   let allowedClauses = [
@@ -806,6 +842,7 @@ def OMP_Scan : Directive<"scan"> {
     VersionedClause<OMPC_Inclusive, 50>,
   ];
   let association = AS_Separating;
+  let category = CA_Subsidiary;
 }
 def OMP_scope : Directive<"scope"> {
   let allowedClauses = [
@@ -816,9 +853,11 @@ def OMP_scope : Directive<"scope"> {
     VersionedClause<OMPC_NoWait, 51>,
   ];
   let association = AS_Block;
+  let category = CA_Executable;
 }
 def OMP_Section : Directive<"section"> {
   let association = AS_Separating;
+  let category = CA_Subsidiary;
 }
 def OMP_Sections : Directive<"sections"> {
   let allowedClauses = [
@@ -830,6 +869,7 @@ def OMP_Sections : Directive<"sections"> {
     VersionedClause<OMPC_Reduction>,
   ];
   let association = AS_Block;
+  let category = CA_Executable;
 }
 def OMP_EndSections : Directive<"end sections"> {
   let allowedOnceClauses = [
@@ -837,6 +877,7 @@ def OMP_EndSections : Directive<"end sections"> {
   ];
   let leafConstructs = OMP_Sections.leafConstructs;
   let association = OMP_Sections.association;
+  let category = OMP_Sections.category;
 }
 def OMP_Simd : Directive<"simd"> {
   let allowedClauses = [
@@ -856,6 +897,7 @@ def OMP_Simd : Directive<"simd"> {
     VersionedClause<OMPC_SimdLen>,
   ];
   let association = AS_Loop;
+  let category = CA_Executable;
 }
 def OMP_Single : Directive<"single"> {
   let allowedClauses = [
@@ -866,6 +908,7 @@ def OMP_Single : Directive<"single"> {
     VersionedClause<OMPC_Private>,
   ];
   let association = AS_Block;
+  let category = CA_Executable;
 }
 def OMP_EndSingle : Directive<"end single"> {
   let allowedClauses = [
@@ -876,6 +919,7 @@ def OMP_EndSingle : Directive<"end single"> {
   ];
   let leafConstructs = OMP_Single.leafConstructs;
   let association = OMP_Single.association;
+  let category = OMP_Single.category;
 }
 def OMP_Target : Directive<"target"> {
   let allowedClauses = [
@@ -899,6 +943,7 @@ def OMP_Target : Directive<"target"> {
     VersionedClause<OMPC_ThreadLimit, 51>,
   ];
   let association = AS_Block;
+  let category = CA_Executable;
 }
 def OMP_TargetData : Directive<"target data"> {
   let allowedOnceClauses = [
@@ -911,6 +956,7 @@ def OMP_TargetData : Directive<"target data"> {
     VersionedClause<OMPC_UseDevicePtr>,
   ];
   let association = AS_Block;
+  let category = CA_Executable;
 }
 def OMP_TargetEnterData : Directive<"target enter data"> {
   let allowedClauses = [
@@ -925,6 +971,7 @@ def OMP_TargetEnterData : Directive<"target enter data"> {
     VersionedClause<OMPC_Map>,
   ];
   let association = AS_None;
+  let category = CA_Executable;
 }
 def OMP_TargetExitData : Directive<"target exit data"> {
   let allowedClauses = [
@@ -939,6 +986,7 @@ def OMP_TargetExitData : Directive<"target exit data"> {
     VersionedClause<OMPC_Map>,
   ];
   let association = AS_None;
+  let category = CA_Executable;
 }
 def OMP_TargetUpdate : Directive<"target update"> {
   let allowedClauses = [
@@ -952,6 +1000,7 @@ def OMP_TargetUpdate : Directive<"target update"> {
     VersionedClause<OMPC_NoWait>,
   ];
   let association = AS_None;
+  let category = CA_Executable;
 }
 def OMP_Task : Directive<"task"> {
   let allowedClauses = [
@@ -973,6 +1022,7 @@ def OMP_Task : Directive<"task"> {
     VersionedClause<OMPC_Priority>,
   ];
   let association = AS_Block;
+  let category = CA_Executable;
 }
 def OMP_TaskGroup : Directive<"taskgroup"> {
   let allowedClauses = [
@@ -980,6 +1030,7 @@ def OMP_TaskGroup : Directive<"taskgroup"> {
     VersionedClause<OMPC_TaskReduction, 50>,
   ];
   let association = AS_Block;
+  let category = CA_Executable;
 }
 def OMP_TaskLoop : Directive<"taskloop"> {
   let allowedClauses = [
@@ -1006,6 +1057,7 @@ def OMP_TaskLoop : Directive<"taskloop"> {
     VersionedClause<OMPC_NumTasks>,
   ];
   let association = AS_Loop;
+  let category = CA_Executable;
 }
 def OMP_TaskWait : Directive<"taskwait"> {
   let allowedClauses = [
@@ -1013,9 +1065,11 @@ def OMP_TaskWait : Directive<"taskwait"> {
     VersionedClause<OMPC_NoWait, 51>,
   ];
   let association = AS_None;
+  let category = CA_Executable;
 }
 def OMP_TaskYield : Directive<"taskyield"> {
   let association = AS_None;
+  let category = CA_Executable;
 }
 def OMP_Teams : Directive<"teams"> {
   let allowedClauses = [
@@ -1033,19 +1087,23 @@ def OMP_Teams : Directive<"teams"> {
     VersionedClause<OMPC_ThreadLimit>,
   ];
   let association = AS_Block;
+  let category = CA_Executable;
 }
 def OMP_ThreadPrivate : Directive<"threadprivate"> {
   let association = AS_None;
+  let category = CA_Declarative;
 }
 def OMP_Tile : Directive<"tile"> {
   let allowedOnceClauses = [
     VersionedClause<OMPC_Sizes, 51>,
   ];
   let association = AS_Loop;
+  let category = CA_Executable;
 }
 def OMP_Unknown : Directive<"unknown"> {
   let isDefault = true;
   let association = AS_None;
+  let category = CA_Utility;
 }
 def OMP_Unroll : Directive<"unroll"> {
   let allowedOnceClauses = [
@@ -1053,12 +1111,14 @@ def OMP_Unroll : Directive<"unroll"> {
     VersionedClause<OMPC_Partial, 51>,
   ];
   let association = AS_Loop;
+  let category = CA_Executable;
 }
 def OMP_Workshare : Directive<"workshare"> {
   let allowedOnceClauses = [
     VersionedClause<OMPC_NoWait>,
   ];
   let association = AS_Block;
+  let category = CA_Executable;
 }
 def OMP_EndWorkshare : Directive<"end workshare"> {
   let allowedClauses = [
@@ -1066,6 +1126,7 @@ def OMP_EndWorkshare : Directive<"end workshare"> {
   ];
   let leafConstructs = OMP_Workshare.leafConstructs;
   let association = OMP_Workshare.association;
+  let category = OMP_Workshare.category;
 }
 
 //===----------------------------------------------------------------------===//
@@ -1097,6 +1158,7 @@ def OMP_DistributeParallelDo : Directive<"distribute parallel do"> {
     VersionedClause<OMPC_Schedule>,
   ];
   let leafConstructs = [OMP_Distribute, OMP_Parallel, OMP_Do];
+  let category = CA_Executable;
 }
 def OMP_DistributeParallelDoSimd : Directive<"distribute parallel do simd"> {
   let allowedClauses = [
@@ -1122,6 +1184,7 @@ def OMP_DistributeParallelDoSimd : Directive<"distribute parallel do simd"> {
     VersionedClause<OMPC_SimdLen>,
   ];
   let leafConstructs = [OMP_Distribute, OMP_Parallel, OMP_Do, OMP_Simd];
+  let category = CA_Executable;
 }
 def OMP_DistributeParallelFor : Directive<"distribute parallel for"> {
   let allowedClauses = [
@@ -1143,6 +1206,7 @@ def OMP_DistributeParallelFor : Directive<"distribute parallel for"> {
     VersionedClause<OMPC_Shared>,
   ];
   let leafConstructs = [OMP_Distribute, OMP_Parallel, OMP_For];
+  let category = CA_Executable;
 }
 def OMP_DistributeParallelForSimd : Directive<"distribute parallel for simd"> {
   let allowedClauses = [
@@ -1169,6 +1233,7 @@ def OMP_DistributeParallelForSimd : Directive<"distribute parallel for simd"> {
     VersionedClause<OMPC_SimdLen>,
   ];
   let leafConstructs = [OMP_Distribute, OMP_Parallel, OMP_For, OMP_Simd];
+  let category = CA_Executable;
 }
 def OMP_DistributeSimd : Directive<"distribute simd"> {
   let allowedClauses = [
@@ -1196,6 +1261,7 @@ def OMP_DistributeSimd : Directive<"distribute simd"> {
     VersionedClause<OMPC_SimdLen>,
   ];
   let leafConstructs = [OMP_Distribute, OMP_Simd];
+  let category = CA_Executable;
 }
 def OMP_DoSimd : Directive<"do simd"> {
   let allowedClauses = [
@@ -1217,6 +1283,7 @@ def OMP_DoSimd : Directive<"do simd"> {
     VersionedClause<OMPC_SimdLen>,
   ];
   let leafConstructs = [OMP_Do, OMP_Simd];
+  let category = CA_Executable;
 }
 def OMP_EndDoSimd : Directive<"end do simd"> {
   let allowedOnceClauses = [
@@ -1224,6 +1291,7 @@ def OMP_EndDoSimd : Directive<"end do simd"> {
   ];
   let leafConstructs = OMP_DoSimd.leafConstructs;
   let association = OMP_DoSimd.association;
+  let category = OMP_DoSimd.category;
 }
 def OMP_ForSimd : Directive<"for simd"> {
   let allowedClauses = [
@@ -1245,6 +1313,7 @@ def OMP_ForSimd : Directive<"for simd"> {
     VersionedClause<OMPC_SimdLen>,
   ];
   let leafConstructs = [OMP_For, OMP_Simd];
+  let category = CA_Executable;
 }
 def OMP_MaskedTaskloop : Directive<"masked taskloop"> {
   let allowedClauses = [
@@ -1268,6 +1337,7 @@ def OMP_MaskedTaskloop : Directive<"masked taskloop"> {
     VersionedClause<OMPC_Untied>,
   ];
   let leafConstructs = [OMP_masked, OMP_TaskLoop];
+  let category = CA_Executable;
 }
 def OMP_MaskedTaskloopSimd : Directive<"masked taskloop simd"> {
   let allowedClauses = [
@@ -1297,6 +1367,7 @@ def OMP_MaskedTaskloopSimd : Directive<"masked taskloop simd"> {
     VersionedClause<OMPC_Untied>,
   ];
   let leafConstructs = [OMP_masked, OMP_TaskLoop, OMP_Simd];
+  let category = CA_Executable;
 }
 def OMP_MasterTaskloop : Directive<"master taskloop"> {
   let allowedClauses = [
@@ -1319,6 +1390,7 @@ def OMP_MasterTaskloop : Directive<"master taskloop"> {
     VersionedClause<OMPC_Untied>,
   ];
   let leafConstructs = [OMP_Master, OMP_TaskLoop];
+  let category = CA_Executable;
 }
 def OMP_MasterTaskloopSimd : Directive<"master taskloop simd"> {
   let allowedClauses = [
@@ -1347,6 +1419,7 @@ def OMP_MasterTaskloopSimd : Directive<"master taskloop simd"> {
     VersionedClause<OMPC_Untied>,
   ];
   let leafConstructs = [OMP_Master, OMP_TaskLoop, OMP_Simd];
+  let category = CA_Executable;
 }
 def OMP_ParallelDo : Directive<"parallel do"> {
   let allowedClauses = [
@@ -1369,6 +1442,7 @@ def OMP_ParallelDo : Directive<"parallel do"> {
     VersionedClause<OMPC_Schedule>,
   ];
   let leafConstructs = [OMP_Parallel, OMP_Do];
+  let category = CA_Executable;
 }
 def OMP_ParallelDoSimd : Directive<"parallel do simd"> {
   let allowedClauses = [
@@ -1396,6 +1470,7 @@ def OMP_ParallelDoSimd : Directive<"parallel do simd"> {
     VersionedClause<OMPC_SimdLen>,
   ];
   let leafConstructs = [OMP_Parallel, OMP_Do, OMP_Simd];
+  let category = CA_Executable;
 }
 def OMP_ParallelFor : Directive<"parallel for"> {
   let allowedClauses = [
@@ -1418,6 +1493,7 @@ def OMP_ParallelFor : Directive<"parallel for"> {
     VersionedClause<OMPC_Shared>,
   ];
   let leafConstructs = [OMP_Parallel, OMP_For];
+  let category = CA_Executable;
 }
 def OMP_ParallelForSimd : Directive<"parallel for simd"> {
   let allowedClauses = [
@@ -1444,6 +1520,7 @@ def OMP_ParallelForSimd : Directive<"parallel for simd"> {
     VersionedClause<OMPC_SimdLen>,
   ];
   let leafConstructs = [OMP_Parallel, OMP_For, OMP_Simd];
+  let category = CA_Executable;
 }
 def OMP_parallel_loop : Directive<"parallel loop"> {
   let allowedClauses = [
@@ -1466,6 +1543,7 @@ def OMP_parallel_loop : Directive<"parallel loop"> {
     VersionedClause<OMPC_ProcBind>,
   ];
   let leafConstructs = [OMP_Parallel, OMP_loop];
+  let category = CA_Executable;
 }
 def OMP_ParallelMasked : Directive<"parallel masked"> {
   let allowedClauses = [
@@ -1483,6 +1561,7 @@ def OMP_ParallelMasked : Directive<"parallel masked"> {
     VersionedClause<OMPC_Shared>,
   ];
   let leafConstructs = [OMP_Parallel, OMP_masked];
+  let category = CA_Executable;
 }
 def OMP_ParallelMaskedTaskloop :
     Directive<"parallel masked taskloop"> {
@@ -1510,6 +1589,7 @@ def OMP_ParallelMaskedTaskloop :
     VersionedClause<OMPC_Untied>,
   ];
   let leafConstructs = [OMP_Parallel, OMP_masked, OMP_TaskLoop];
+  let category = CA_Executable;
 }
 def OMP_ParallelMaskedTaskloopSimd :
     Directive<"parallel masked taskloop simd"> {
@@ -1543,6 +1623,7 @@ def OMP_ParallelMaskedTaskloopSimd :
     VersionedClause<OMPC_Untied>,
   ];
   let leafConstructs = [OMP_Parallel, OMP_masked, OMP_TaskLoop, OMP_Simd];
+  let category = CA_Executable;
 }
 def OMP_ParallelMaster : Directive<"parallel master"> {
   let allowedClauses = [
@@ -1559,6 +1640,7 @@ def OMP_ParallelMaster : Directive<"parallel master"> {
     VersionedClause<OMPC_Shared>,
   ];
   let leafConstructs = [OMP_Parallel, OMP_Master];
+  let category = CA_Executable;
 }
 def OMP_ParallelMasterTaskloop :
     Directive<"parallel master taskloop"> {
@@ -1585,6 +1667,7 @@ def OMP_ParallelMasterTaskloop :
     VersionedClause<OMPC_Untied>,
   ];
   let leafConstructs = [OMP_Parallel, OMP_Master, OMP_TaskLoop];
+  let category = CA_Executable;
 }
 def OMP_ParallelMasterTaskloopSimd :
     Directive<"parallel master taskloop simd"> {
@@ -1617,6 +1700,7 @@ def OMP_ParallelMasterTaskloopSimd :
     VersionedClause<OMPC_Untied>,
   ];
   let leafConstructs = [OMP_Parallel, OMP_Master, OMP_TaskLoop, OMP_Simd];
+  let category = CA_Executable;
 }
 def OMP_ParallelSections : Directive<"parallel sections"> {
   let allowedClauses = [
@@ -1636,6 +1720,7 @@ def OMP_ParallelSections : Directive<"parallel sections"> {
     VersionedClause<OMPC_NumThreads>,
   ];
   let leafConstructs = [OMP_Parallel, OMP_Sections];
+  let category = CA_Executable;
 }
 def OMP_ParallelWorkshare : Directive<"parallel workshare"> {
   let allowedClauses = [
@@ -1653,6 +1738,7 @@ def OMP_ParallelWorkshare : Directive<"parallel workshare"> {
     VersionedClause<OMPC_ProcBind>,
   ];
   let leafConstructs = [OMP_Parallel, OMP_Workshare];
+  let category = CA_Executable;
 }
 def OMP_TargetParallel : Directive<"target parallel"> {
   let allowedClauses = [
@@ -1680,6 +1766,7 @@ def OMP_TargetParallel : Directive<"target parallel"> {
     VersionedClause<OMPC_ThreadLimit, 51>,
   ];
   let leafConstructs = [OMP_Target, OMP_Parallel];
+  let category = CA_Executable;
 }
 def OMP_TargetParallelDo : Directive<"target parallel do"> {
   let allowedClauses = [
@@ -1711,6 +1798,7 @@ def OMP_TargetParallelDo : Directive<"target parallel do"> {
     VersionedClause<OMPC_Schedule>,
   ];
   let leafConstructs = [OMP_Target, OMP_Parallel, OMP_Do];
+  let category = CA_Executable;
 }
 def OMP_TargetParallelDoSimd : Directive<"target parallel do simd"> {
   let allowedClauses = [
@@ -1743,6 +1831,7 @@ def OMP_TargetParallelDoSimd : Directive<"target parallel do simd"> {
     VersionedClause<OMPC_UsesAllocators>,
   ];
   let leafConstructs = [OMP_Target, OMP_Parallel, OMP_Do, OMP_Simd];
+  let category = CA_Executable;
 }
 def OMP_TargetParallelFor : Directive<"target parallel for"> {
   let allowedClauses = [
@@ -1776,6 +1865,7 @@ def OMP_TargetParallelFor : Directive<"target parallel for"> {
     VersionedClause<OMPC_ThreadLimit, 51>,
   ];
   let leafConstructs = [OMP_Target, OMP_Parallel, OMP_For];
+  let category = CA_Executable;
 }
 def OMP_TargetParallelForSimd : Directive<"target parallel for simd"> {
   let allowedClauses = [
@@ -1813,6 +1903,7 @@ def OMP_TargetParallelForSimd : Directive<"target parallel for simd"> {
     VersionedClause<OMPC_ThreadLimit, 51>,
   ];
   let leafConstructs = [OMP_Target, OMP_Parallel, OMP_For, OMP_Simd];
+  let category = CA_Executable;
 }
 def OMP_target_parallel_loop : Directive<"target parallel loop"> {
   let allowedClauses = [
@@ -1845,6 +1936,7 @@ def OMP_target_parallel_loop : Directive<"target parallel loop"> {
     VersionedClause<OMPC_ThreadLimit, 51>,
   ];
   let leafConstructs = [OMP_Target, OMP_Parallel, OMP_loop];
+  let category = CA_Executable;
 }
 def OMP_TargetSimd : Directive<"target simd"> {
   let allowedClauses = [
@@ -1880,6 +1972,7 @@ def OMP_TargetSimd : Directive<"target simd"> {
     VersionedClause<OMPC_ThreadLimit, 51>,
   ];
   let leafConstructs = [OMP_Target, OMP_Simd];
+  let category = CA_Executable;
 }
 def OMP_TargetTeams : Directive<"target teams"> {
   let allowedClauses = [
@@ -1907,6 +2000,7 @@ def OMP_TargetTeams : Directive<"target teams"> {
     VersionedClause<OMPC_ThreadLimit>,
   ];
   let leafConstructs = [OMP_Target, OMP_Teams];
+  let category = CA_Executable;
 }
 def OMP_TargetTeamsDistribute : Directive<"target teams distribute"> {
   let allowedClauses = [
@@ -1936,6 +2030,7 @@ def OMP_TargetTeamsDistribute : Directive<"target teams distribute"> {
     VersionedClause<OMPC_ThreadLimit>,
   ];
   let leafConstructs = [OMP_Target, OMP_Teams, OMP_Distribute];
+  let category = CA_Executable;
 }
 def OMP_TargetTeamsDistributeParallelDo :
     Directive<"target teams distribute parallel do"> {
@@ -1971,6 +2066,7 @@ def OMP_TargetTeamsDistributeParallelDo :
     VersionedClause<OMPC_ThreadLimit>,
   ];
   let leafConstructs = [OMP_Target, OMP_Teams, OMP_Distribute, OMP_Parallel, OMP_Do];
+  let category = CA_Executable;
 }
 def OMP_TargetTeamsDistributeParallelDoSimd :
     Directive<"target teams distribute parallel do simd"> {
@@ -2010,6 +2106,7 @@ def OMP_TargetTeamsDistributeParallelDoSimd :
     VersionedClause<OMPC_ThreadLimit>,
   ];
   let leafConstructs = [OMP_Target, OMP_Teams, OMP_Distribute, OMP_Parallel, OMP_Do, OMP_Simd];
+  let category = CA_Executable;
 }
 def OMP_TargetTeamsDistributeParallelFor :
     Directive<"target teams distribute parallel for"> {
@@ -2044,6 +2141,7 @@ def OMP_TargetTeamsDistributeParallelFor :
     VersionedClause<OMPC_OMPX_DynCGroupMem>,
   ];
   let leafConstructs = [OMP_Target, OMP_Teams, OMP_Distribute, OMP_Parallel, OMP_For];
+  let category = CA_Executable;
 }
 def OMP_TargetTeamsDistributeParallelForSimd :
     Directive<"target teams distribute parallel for simd"> {
@@ -2083,6 +2181,7 @@ def OMP_TargetTeamsDistributeParallelForSimd :
     VersionedClause<OMPC_OMPX_DynCGroupMem>,
   ];
   let leafConstructs = [OMP_Target, OMP_Teams, OMP_Distribute, OMP_Parallel, OMP_For, OMP_Simd];
+  let category = CA_Executable;
 }
 def OMP_TargetTeamsDistributeSimd :
     Directive<"target teams distribute simd"> {
@@ -2118,6 +2217,7 @@ def OMP_TargetTeamsDistributeSimd :
     VersionedClause<OMPC_ThreadLimit>,
   ];
   let leafConstructs = [OMP_Target, OMP_Teams, OMP_Distribute, OMP_Simd];
+  let category = CA_Executable;
 }
 def OMP_target_teams_loop : Directive<"target teams loop"> {
   let allowedClauses = [
@@ -2148,6 +2248,7 @@ def OMP_target_teams_loop : Directive<"target teams loop"> {
     VersionedClause<OMPC_ThreadLimit>,
   ];
   let leafConstructs = [OMP_Target, OMP_Teams, OMP_loop];
+  let category = CA_Executable;
 }
 def OMP_TaskLoopSimd : Directive<"taskloop simd"> {
   let allowedClauses = [
@@ -2180,6 +2281,7 @@ def OMP_TaskLoopSimd : Directive<"taskloop simd"> {
     VersionedClause<OMPC_NumTasks>,
   ];
   let leafConstructs = [OMP_TaskLoop, OMP_Simd];
+  let category = CA_Executable;
 }
 def OMP_TeamsDistribute : Directive<"teams distribute"> {
   let allowedClauses = [
@@ -2200,6 +2302,7 @@ def OMP_TeamsDistribute : Directive<"teams distribute"> {
     VersionedClause<OMPC_If>,
   ];
   let leafConstructs = [OMP_Teams, OMP_Distribute];
+  let category = CA_Executable;
 }
 def OMP_TeamsDistributeParallelDo :
     Directive<"teams distribute parallel do"> {
@@ -2227,6 +2330,7 @@ def OMP_TeamsDistributeParallelDo :
     VersionedClause<OMPC_ThreadLimit>,
   ];
   let leafConstructs = [OMP_Teams, OMP_Distribute, OMP_Parallel, OMP_Do];
+  let category = CA_Executable;
 }
 def OMP_TeamsDistributeParallelDoSimd :
     Directive<"teams distribute parallel do simd"> {
@@ -2256,6 +2360,7 @@ def OMP_TeamsDistributeParallelDoSimd :
     VersionedClause<OMPC_ThreadLimit>,
   ];
   let leafConstructs = [OMP_Teams, OMP_Distribute, OMP_Parallel, OMP_Do, OMP_Simd];
+  let category = CA_Executable;
 }
 def OMP_TeamsDistributeParallelFor :
     Directive<"teams distribute parallel for"> {
@@ -2280,6 +2385,7 @@ def OMP_TeamsDistributeParallelFor :
     VersionedClause<OMPC_ThreadLimit>,
   ];
   let leafConstructs = [OMP_Teams, OMP_Distribute, OMP_Parallel, OMP_For];
+  let category = CA_Executable;
 }
 def OMP_TeamsDistributeParallelForSimd :
     Directive<"teams distribute parallel for simd"> {
@@ -2308,6 +2414,7 @@ def OMP_TeamsDistributeParallelForSimd :
     VersionedClause<OMPC_ThreadLimit>,
   ];
   let leafConstructs = [OMP_Teams, OMP_Distribute, OMP_Parallel, OMP_For, OMP_Simd];
+  let category = CA_Executable;
 }
 def OMP_TeamsDistributeSimd : Directive<"teams distribute simd"> {
   let allowedClauses = [
@@ -2334,6 +2441,7 @@ def OMP_TeamsDistributeSimd : Directive<"teams distribute simd"> {
     VersionedClause<OMPC_ThreadLimit>,
   ];
   let leafConstructs = [OMP_Teams, OMP_Distribute, OMP_Simd];
+  let category = CA_Executable;
 }
 def OMP_teams_loop : Directive<"teams loop"> {
   let allowedClauses = [
@@ -2354,4 +2462,5 @@ def OMP_teams_loop : Directive<"teams loop"> {
     VersionedClause<OMPC_ThreadLimit>,
   ];
   let leafConstructs = [OMP_Teams, OMP_loop];
+  let category = CA_Executable;
 }
diff --git a/llvm/include/llvm/TableGen/DirectiveEmitter.h b/llvm/include/llvm/TableGen/DirectiveEmitter.h
index bd536d4a2b7f8..1121459be6ce7 100644
--- a/llvm/include/llvm/TableGen/DirectiveEmitter.h
+++ b/llvm/include/llvm/TableGen/DirectiveEmitter.h
@@ -55,6 +55,10 @@ class DirectiveLanguage {
     return Records.getAllDerivedDefinitions("Association");
   }
 
+  std::vector<Record *> getCategories() const {
+    return Records.getAllDerivedDefinitions("Category");
+  }
+
   std::vector<Record *> getDirectives() const {
     return Records.getAllDerivedDefinitions("Directive");
   }
@@ -131,6 +135,8 @@ class Directive : public BaseRecord {
   }
 
   Record *getAssociation() const { return Def->getValueAsDef("association"); }
+
+  Record *getCategory() const { return Def->getValueAsDef("category"); }
 };
 
 // Wrapper class that contains Clause's information defined in DirectiveBase.td
diff --git a/llvm/test/TableGen/directive1.td b/llvm/test/TableGen/directive1.td
index 56bce5bfb89c7..3af3b04dc0093 100644
--- a/llvm/test/TableGen/directive1.td
+++ b/llvm/test/TableGen/directive1.td
@@ -45,6 +45,7 @@ def TDL_DirA : Directive<"dira"> {
   ];
   let isDefault = 1;
   let association = AS_None;
+  let category = CA_Executable;
 }
 
 // CHECK:       #ifndef LLVM_Tdl_INC
@@ -71,6 +72,17 @@ def TDL_DirA : Directive<"dira"> {
 // CHECK-EMPTY:
 // CHECK-NEXT:  static constexpr std::size_t Association_enumSize = 6;
 // CHECK-EMPTY:
+// CHECK-NEXT:  enum class Category {
+// CHECK-NEXT:    Declarative,
+// CHECK-NEXT:    Executable,
+// CHECK-NEXT:    Informational,
+// CHECK-NEXT:    Meta,
+// CHECK-NEXT:    Subsidiary,
+// CHECK-NEXT:    Utility,
+// CHECK-NEXT:  };
+// CHECK-EMPTY:
+// CHECK-NEXT:  static constexpr std::size_t Category_enumSize = 6;
+// CHECK-EMPTY:
 // CHECK-NEXT:  enum class Directive {
 // CHECK-NEXT:    TDLD_dira,
 // CHECK-NEXT:  };
@@ -115,6 +127,7 @@ def TDL_DirA : Directive<"dira"> {
 // CHECK-EMPTY:
 // CHECK-NEXT:  constexpr std::size_t getMaxLeafCount() { return 0; }
 // CHECK-NEXT:  Association getDirectiveAssociation(Directive D);
+// CHECK-NEXT:  Category getDirectiveCategory(Directive D);
 // CHECK-NEXT:  AKind getAKind(StringRef);
 // CHECK-NEXT:  llvm::StringRef getTdlAKindName(AKind);
 // CHECK-EMPTY:
@@ -364,7 +377,15 @@ def TDL_DirA : Directive<"dira"> {
 // IMPL-NEXT:    switch (Dir) {
 // IMPL-NEXT:    case llvm::tdl::Directive::TDLD_dira:
 // IMPL-NEXT:      return llvm::tdl::Association::None;
-// IMPL-NEXT:    } // switch(Dir)
+// IMPL-NEXT:    } // switch (Dir)
+// IMPL-NEXT:    llvm_unreachable("Unexpected directive");
+// IMPL-NEXT:  }
+// IMPL-EMPTY:
+// IMPL-NEXT:  llvm::tdl::Category llvm::tdl::getDirectiveCategory(llvm::tdl::Directive Dir) {
+// IMPL-NEXT:    switch (Dir) {
+// IMPL-NEXT:    case llvm::tdl::TDLD_dira:
+// IMPL-NEXT:      return llvm::tdl::Category::Executable;
+// IMPL-NEXT:    } // switch (Dir)
 // IMPL-NEXT:    llvm_unreachable("Unexpected directive");
 // IMPL-NEXT:  }
 // IMPL-EMPTY:
diff --git a/llvm/test/TableGen/directive2.td b/llvm/test/TableGen/directive2.td
index 3c092113593b7..209901bb616f4 100644
--- a/llvm/test/TableGen/directive2.td
+++ b/llvm/test/TableGen/directive2.td
@@ -39,6 +39,7 @@ def TDL_DirA : Directive<"dira"> {
   ];
   let isDefault = 1;
   let association = AS_Block;
+  let category = CA_Declarative;
 }
 
 // CHECK:       #ifndef LLVM_Tdl_INC
@@ -62,6 +63,17 @@ def TDL_DirA : Directive<"dira"> {
 // CHECK-EMPTY:
 // CHECK-NEXT:  static constexpr std::size_t Association_enumSize = 6;
 // CHECK-EMPTY:
+// CHECK-NEXT:  enum class Category {
+// CHECK-NEXT:    Declarative,
+// CHECK-NEXT:    Executable,
+// CHECK-NEXT:    Informational,
+// CHECK-NEXT:    Meta,
+// CHECK-NEXT:    Subsidiary,
+// CHECK-NEXT:    Utility,
+// CHECK-NEXT:  };
+// CHECK-EMPTY:
+// CHECK-NEXT:  static constexpr std::size_t Category_enumSize = 6;
+// CHECK-EMPTY:
 // CHECK-NEXT:  enum class Directive {
 // CHECK-NEXT:    TDLD_dira,
 // CHECK-NEXT:  };
@@ -91,6 +103,7 @@ def TDL_DirA : Directive<"dira"> {
 // CHECK-EMPTY:
 // CHECK-NEXT:  constexpr std::size_t getMaxLeafCount() { return 0; }
 // CHECK-NEXT:  Association getDirectiveAssociation(Directive D);
+// CHECK-NEXT:  Category getDirectiveCategory(Directive D);
 // CHECK-NEXT:  } // namespace tdl
 // CHECK-NEXT:  } // namespace llvm
 // CHECK-NEXT:  #endif // LLVM_Tdl_INC
@@ -295,7 +308,15 @@ def TDL_DirA : Directive<"dira"> {
 // IMPL-NEXT:    switch (Dir) {
 // IMPL-NEXT:    case llvm::tdl::Directive::TDLD_dira:
 // IMPL-NEXT:      return llvm::tdl::Association::Block;
-// IMPL-NEXT:    } // switch(Dir)
+// IMPL-NEXT:    } // switch (Dir)
+// IMPL-NEXT:    llvm_unreachable("Unexpected directive");
+// IMPL-NEXT:  }
+// IMPL-EMPTY:
+// IMPL-NEXT:  llvm::tdl::Category llvm::tdl::getDirectiveCategory(llvm::tdl::Directive Dir) {
+// IMPL-NEXT:    switch (Dir) {
+// IMPL-NEXT:    case llvm::tdl::TDLD_dira:
+// IMPL-NEXT:      return llvm::tdl::Category::Declarative;
+// IMPL-NEXT:    } // switch (Dir)
 // IMPL-NEXT:    llvm_unreachable("Unexpected directive");
 // IMPL-NEXT:  }
 // IMPL-EMPTY:
diff --git a/llvm/utils/TableGen/DirectiveEmitter.cpp b/llvm/utils/TableGen/DirectiveEmitter.cpp
index 8bc3f026853cc..581bc09d5e053 100644
--- a/llvm/utils/TableGen/DirectiveEmitter.cpp
+++ b/llvm/utils/TableGen/DirectiveEmitter.cpp
@@ -228,6 +228,9 @@ static void EmitDirectivesDecl(RecordKeeper &Records, raw_ostream &OS) {
   GenerateEnumClass(associations, OS, "Association",
                     /*Prefix=*/"", DirLang, /*ExportEnums=*/false);
 
+  GenerateEnumClass(DirLang.getCategories(), OS, "Category", /*Prefix=*/"",
+                    DirLang, /*ExportEnums=*/false);
+
   // Emit Directive enumeration
   GenerateEnumClass(DirLang.getDirectives(), OS, "Directive",
                     DirLang.getDirectivePrefix(), DirLang,
@@ -264,6 +267,7 @@ static void EmitDirectivesDecl(RecordKeeper &Records, raw_ostream &OS) {
   OS << "constexpr std::size_t getMaxLeafCount() { return "
      << GetMaxLeafCount(DirLang) << "; }\n";
   OS << "Association getDirectiveAssociation(Directive D);\n";
+  OS << "Category getDirectiveCategory(Directive D);\n";
   if (EnumHelperFuncs.length() > 0) {
     OS << EnumHelperFuncs;
     OS << "\n";
@@ -743,7 +747,29 @@ static void GenerateGetDirectiveAssociation(const DirectiveLanguage &DirLang,
          << "::" << getAssocName(F->second) << ";\n";
     }
   }
-  OS << "  } // switch(Dir)\n";
+  OS << "  } // switch (Dir)\n";
+  OS << "  llvm_unreachable(\"Unexpected directive\");\n";
+  OS << "}\n";
+}
+
+static void GenerateGetDirectiveCategory(const DirectiveLanguage &DirLang,
+                                         raw_ostream &OS) {
+  std::string LangNamespace = "llvm::" + DirLang.getCppNamespace().str();
+  std::string CategoryTypeName = LangNamespace + "::Category";
+  std::string CategoryNamespace = CategoryTypeName + "::";
+
+  OS << '\n';
+  OS << CategoryTypeName << ' ' << LangNamespace << "::getDirectiveCategory("
+     << GetDirectiveType(DirLang) << " Dir) {\n";
+  OS << "  switch (Dir) {\n";
+
+  for (Record *R : DirLang.getDirectives()) {
+    Directive D{R};
+    OS << "  case " << GetDirectiveName(DirLang, R) << ":\n";
+    OS << "    return " << CategoryNamespace
+       << D.getCategory()->getValueAsString("name") << ";\n";
+  }
+  OS << "  } // switch (Dir)\n";
   OS << "  llvm_unreachable(\"Unexpected directive\");\n";
   OS << "}\n";
 }
@@ -1196,6 +1222,9 @@ void EmitDirectivesBasicImpl(const DirectiveLanguage &DirLang,
   // getDirectiveAssociation(Directive D)
   GenerateGetDirectiveAssociation(DirLang, OS);
 
+  // getDirectiveCategory(Directive D)
+  GenerateGetDirectiveCategory(DirLang, OS);
+
   // Leaf table for getLeafConstructs, etc.
   EmitLeafTable(DirLang, OS, "LeafConstructTable");
 }



More information about the llvm-branch-commits mailing list