1 //===--- OpenMPKinds.cpp - Token Kinds Support ----------------------------===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
8 /// \file
9 /// This file implements the OpenMP enum and support functions.
10 ///
11 //===----------------------------------------------------------------------===//
12 
13 #include "clang/Basic/OpenMPKinds.h"
14 #include "clang/Basic/IdentifierTable.h"
15 #include "llvm/ADT/StringRef.h"
16 #include "llvm/ADT/StringSwitch.h"
17 #include "llvm/Support/ErrorHandling.h"
18 #include <cassert>
19 
20 using namespace clang;
21 
22 OpenMPContextSelectorSetKind
23 clang::getOpenMPContextSelectorSet(llvm::StringRef Str) {
24   return llvm::StringSwitch<OpenMPContextSelectorSetKind>(Str)
25 #define OPENMP_CONTEXT_SELECTOR_SET(Name) .Case(#Name, OMP_CTX_SET_##Name)
26 #include "clang/Basic/OpenMPKinds.def"
27       .Default(OMP_CTX_SET_unknown);
28 }
29 
30 llvm::StringRef
31 clang::getOpenMPContextSelectorSetName(OpenMPContextSelectorSetKind Kind) {
32   switch (Kind) {
33   case OMP_CTX_SET_unknown:
34     return "unknown";
35 #define OPENMP_CONTEXT_SELECTOR_SET(Name)                                      \
36   case OMP_CTX_SET_##Name:                                                     \
37     return #Name;
38 #include "clang/Basic/OpenMPKinds.def"
39     break;
40   }
41   llvm_unreachable("Invalid OpenMP context selector set kind");
42 }
43 
44 OpenMPContextSelectorKind clang::getOpenMPContextSelector(llvm::StringRef Str) {
45   return llvm::StringSwitch<OpenMPContextSelectorKind>(Str)
46 #define OPENMP_CONTEXT_SELECTOR(Name) .Case(#Name, OMP_CTX_##Name)
47 #include "clang/Basic/OpenMPKinds.def"
48       .Default(OMP_CTX_unknown);
49 }
50 
51 llvm::StringRef
52 clang::getOpenMPContextSelectorName(OpenMPContextSelectorKind Kind) {
53   switch (Kind) {
54   case OMP_CTX_unknown:
55     return "unknown";
56 #define OPENMP_CONTEXT_SELECTOR(Name)                                          \
57   case OMP_CTX_##Name:                                                         \
58     return #Name;
59 #include "clang/Basic/OpenMPKinds.def"
60     break;
61   }
62   llvm_unreachable("Invalid OpenMP context selector kind");
63 }
64 
65 OpenMPDirectiveKind clang::getOpenMPDirectiveKind(StringRef Str) {
66   return llvm::StringSwitch<OpenMPDirectiveKind>(Str)
67 #define OPENMP_DIRECTIVE(Name) .Case(#Name, OMPD_##Name)
68 #define OPENMP_DIRECTIVE_EXT(Name, Str) .Case(Str, OMPD_##Name)
69 #include "clang/Basic/OpenMPKinds.def"
70       .Default(OMPD_unknown);
71 }
72 
73 const char *clang::getOpenMPDirectiveName(OpenMPDirectiveKind Kind) {
74   assert(Kind <= OMPD_unknown);
75   switch (Kind) {
76   case OMPD_unknown:
77     return "unknown";
78 #define OPENMP_DIRECTIVE(Name)                                                 \
79   case OMPD_##Name:                                                            \
80     return #Name;
81 #define OPENMP_DIRECTIVE_EXT(Name, Str)                                        \
82   case OMPD_##Name:                                                            \
83     return Str;
84 #include "clang/Basic/OpenMPKinds.def"
85     break;
86   }
87   llvm_unreachable("Invalid OpenMP directive kind");
88 }
89 
90 OpenMPClauseKind clang::getOpenMPClauseKind(StringRef Str) {
91   // 'flush' clause cannot be specified explicitly, because this is an implicit
92   // clause for 'flush' directive. If the 'flush' clause is explicitly specified
93   // the Parser should generate a warning about extra tokens at the end of the
94   // directive.
95   if (Str == "flush")
96     return OMPC_unknown;
97   return llvm::StringSwitch<OpenMPClauseKind>(Str)
98 #define OPENMP_CLAUSE(Name, Class) .Case(#Name, OMPC_##Name)
99 #include "clang/Basic/OpenMPKinds.def"
100       .Case("uniform", OMPC_uniform)
101       .Case("device_type", OMPC_device_type)
102       .Case("match", OMPC_match)
103       .Default(OMPC_unknown);
104 }
105 
106 const char *clang::getOpenMPClauseName(OpenMPClauseKind Kind) {
107   assert(Kind <= OMPC_unknown);
108   switch (Kind) {
109   case OMPC_unknown:
110     return "unknown";
111 #define OPENMP_CLAUSE(Name, Class)                                             \
112   case OMPC_##Name:                                                            \
113     return #Name;
114 #include "clang/Basic/OpenMPKinds.def"
115   case OMPC_uniform:
116     return "uniform";
117   case OMPC_threadprivate:
118     return "threadprivate or thread local";
119   case OMPC_device_type:
120     return "device_type";
121   case OMPC_match:
122     return "match";
123   }
124   llvm_unreachable("Invalid OpenMP clause kind");
125 }
126 
127 unsigned clang::getOpenMPSimpleClauseType(OpenMPClauseKind Kind,
128                                           StringRef Str) {
129   switch (Kind) {
130   case OMPC_default:
131     return llvm::StringSwitch<OpenMPDefaultClauseKind>(Str)
132 #define OPENMP_DEFAULT_KIND(Name) .Case(#Name, OMPC_DEFAULT_##Name)
133 #include "clang/Basic/OpenMPKinds.def"
134         .Default(OMPC_DEFAULT_unknown);
135   case OMPC_proc_bind:
136     return llvm::StringSwitch<OpenMPProcBindClauseKind>(Str)
137 #define OPENMP_PROC_BIND_KIND(Name) .Case(#Name, OMPC_PROC_BIND_##Name)
138 #include "clang/Basic/OpenMPKinds.def"
139         .Default(OMPC_PROC_BIND_unknown);
140   case OMPC_schedule:
141     return llvm::StringSwitch<unsigned>(Str)
142 #define OPENMP_SCHEDULE_KIND(Name)                                             \
143   .Case(#Name, static_cast<unsigned>(OMPC_SCHEDULE_##Name))
144 #define OPENMP_SCHEDULE_MODIFIER(Name)                                         \
145   .Case(#Name, static_cast<unsigned>(OMPC_SCHEDULE_MODIFIER_##Name))
146 #include "clang/Basic/OpenMPKinds.def"
147         .Default(OMPC_SCHEDULE_unknown);
148   case OMPC_depend:
149     return llvm::StringSwitch<OpenMPDependClauseKind>(Str)
150 #define OPENMP_DEPEND_KIND(Name) .Case(#Name, OMPC_DEPEND_##Name)
151 #include "clang/Basic/OpenMPKinds.def"
152         .Default(OMPC_DEPEND_unknown);
153   case OMPC_linear:
154     return llvm::StringSwitch<OpenMPLinearClauseKind>(Str)
155 #define OPENMP_LINEAR_KIND(Name) .Case(#Name, OMPC_LINEAR_##Name)
156 #include "clang/Basic/OpenMPKinds.def"
157         .Default(OMPC_LINEAR_unknown);
158   case OMPC_map:
159     return llvm::StringSwitch<unsigned>(Str)
160 #define OPENMP_MAP_KIND(Name)                                                  \
161   .Case(#Name, static_cast<unsigned>(OMPC_MAP_##Name))
162 #define OPENMP_MAP_MODIFIER_KIND(Name)                                         \
163   .Case(#Name, static_cast<unsigned>(OMPC_MAP_MODIFIER_##Name))
164 #include "clang/Basic/OpenMPKinds.def"
165         .Default(OMPC_MAP_unknown);
166   case OMPC_to:
167     return llvm::StringSwitch<unsigned>(Str)
168 #define OPENMP_TO_MODIFIER_KIND(Name)                                          \
169   .Case(#Name, static_cast<unsigned>(OMPC_TO_MODIFIER_##Name))
170 #include "clang/Basic/OpenMPKinds.def"
171         .Default(OMPC_TO_MODIFIER_unknown);
172   case OMPC_from:
173     return llvm::StringSwitch<unsigned>(Str)
174 #define OPENMP_FROM_MODIFIER_KIND(Name)                                     \
175   .Case(#Name, static_cast<unsigned>(OMPC_FROM_MODIFIER_##Name))
176 #include "clang/Basic/OpenMPKinds.def"
177         .Default(OMPC_FROM_MODIFIER_unknown);
178   case OMPC_dist_schedule:
179     return llvm::StringSwitch<OpenMPDistScheduleClauseKind>(Str)
180 #define OPENMP_DIST_SCHEDULE_KIND(Name) .Case(#Name, OMPC_DIST_SCHEDULE_##Name)
181 #include "clang/Basic/OpenMPKinds.def"
182         .Default(OMPC_DIST_SCHEDULE_unknown);
183   case OMPC_defaultmap:
184     return llvm::StringSwitch<unsigned>(Str)
185 #define OPENMP_DEFAULTMAP_KIND(Name)                                           \
186   .Case(#Name, static_cast<unsigned>(OMPC_DEFAULTMAP_##Name))
187 #define OPENMP_DEFAULTMAP_MODIFIER(Name)                                       \
188   .Case(#Name, static_cast<unsigned>(OMPC_DEFAULTMAP_MODIFIER_##Name))
189 #include "clang/Basic/OpenMPKinds.def"
190         .Default(OMPC_DEFAULTMAP_unknown);
191   case OMPC_atomic_default_mem_order:
192      return llvm::StringSwitch<OpenMPAtomicDefaultMemOrderClauseKind>(Str)
193 #define OPENMP_ATOMIC_DEFAULT_MEM_ORDER_KIND(Name)       \
194   .Case(#Name, OMPC_ATOMIC_DEFAULT_MEM_ORDER_##Name)
195 #include "clang/Basic/OpenMPKinds.def"
196         .Default(OMPC_ATOMIC_DEFAULT_MEM_ORDER_unknown);
197   case OMPC_device_type:
198     return llvm::StringSwitch<OpenMPDeviceType>(Str)
199 #define OPENMP_DEVICE_TYPE_KIND(Name) .Case(#Name, OMPC_DEVICE_TYPE_##Name)
200 #include "clang/Basic/OpenMPKinds.def"
201         .Default(OMPC_DEVICE_TYPE_unknown);
202   case OMPC_unknown:
203   case OMPC_threadprivate:
204   case OMPC_if:
205   case OMPC_final:
206   case OMPC_num_threads:
207   case OMPC_safelen:
208   case OMPC_simdlen:
209   case OMPC_allocator:
210   case OMPC_allocate:
211   case OMPC_collapse:
212   case OMPC_private:
213   case OMPC_firstprivate:
214   case OMPC_lastprivate:
215   case OMPC_shared:
216   case OMPC_reduction:
217   case OMPC_task_reduction:
218   case OMPC_in_reduction:
219   case OMPC_aligned:
220   case OMPC_copyin:
221   case OMPC_copyprivate:
222   case OMPC_ordered:
223   case OMPC_nowait:
224   case OMPC_untied:
225   case OMPC_mergeable:
226   case OMPC_flush:
227   case OMPC_read:
228   case OMPC_write:
229   case OMPC_update:
230   case OMPC_capture:
231   case OMPC_seq_cst:
232   case OMPC_device:
233   case OMPC_threads:
234   case OMPC_simd:
235   case OMPC_num_teams:
236   case OMPC_thread_limit:
237   case OMPC_priority:
238   case OMPC_grainsize:
239   case OMPC_nogroup:
240   case OMPC_num_tasks:
241   case OMPC_hint:
242   case OMPC_uniform:
243   case OMPC_use_device_ptr:
244   case OMPC_is_device_ptr:
245   case OMPC_unified_address:
246   case OMPC_unified_shared_memory:
247   case OMPC_reverse_offload:
248   case OMPC_dynamic_allocators:
249   case OMPC_match:
250     break;
251   }
252   llvm_unreachable("Invalid OpenMP simple clause kind");
253 }
254 
255 const char *clang::getOpenMPSimpleClauseTypeName(OpenMPClauseKind Kind,
256                                                  unsigned Type) {
257   switch (Kind) {
258   case OMPC_default:
259     switch (Type) {
260     case OMPC_DEFAULT_unknown:
261       return "unknown";
262 #define OPENMP_DEFAULT_KIND(Name)                                              \
263   case OMPC_DEFAULT_##Name:                                                    \
264     return #Name;
265 #include "clang/Basic/OpenMPKinds.def"
266     }
267     llvm_unreachable("Invalid OpenMP 'default' clause type");
268   case OMPC_proc_bind:
269     switch (Type) {
270     case OMPC_PROC_BIND_unknown:
271       return "unknown";
272 #define OPENMP_PROC_BIND_KIND(Name)                                            \
273   case OMPC_PROC_BIND_##Name:                                                  \
274     return #Name;
275 #include "clang/Basic/OpenMPKinds.def"
276     }
277     llvm_unreachable("Invalid OpenMP 'proc_bind' clause type");
278   case OMPC_schedule:
279     switch (Type) {
280     case OMPC_SCHEDULE_unknown:
281     case OMPC_SCHEDULE_MODIFIER_last:
282       return "unknown";
283 #define OPENMP_SCHEDULE_KIND(Name)                                             \
284     case OMPC_SCHEDULE_##Name:                                                 \
285       return #Name;
286 #define OPENMP_SCHEDULE_MODIFIER(Name)                                         \
287     case OMPC_SCHEDULE_MODIFIER_##Name:                                        \
288       return #Name;
289 #include "clang/Basic/OpenMPKinds.def"
290     }
291     llvm_unreachable("Invalid OpenMP 'schedule' clause type");
292   case OMPC_depend:
293     switch (Type) {
294     case OMPC_DEPEND_unknown:
295       return "unknown";
296 #define OPENMP_DEPEND_KIND(Name)                                             \
297   case OMPC_DEPEND_##Name:                                                   \
298     return #Name;
299 #include "clang/Basic/OpenMPKinds.def"
300     }
301     llvm_unreachable("Invalid OpenMP 'depend' clause type");
302   case OMPC_linear:
303     switch (Type) {
304     case OMPC_LINEAR_unknown:
305       return "unknown";
306 #define OPENMP_LINEAR_KIND(Name)                                             \
307   case OMPC_LINEAR_##Name:                                                   \
308     return #Name;
309 #include "clang/Basic/OpenMPKinds.def"
310     }
311     llvm_unreachable("Invalid OpenMP 'linear' clause type");
312   case OMPC_map:
313     switch (Type) {
314     case OMPC_MAP_unknown:
315     case OMPC_MAP_MODIFIER_last:
316       return "unknown";
317 #define OPENMP_MAP_KIND(Name)                                                \
318   case OMPC_MAP_##Name:                                                      \
319     return #Name;
320 #define OPENMP_MAP_MODIFIER_KIND(Name)                                       \
321   case OMPC_MAP_MODIFIER_##Name:                                             \
322     return #Name;
323 #include "clang/Basic/OpenMPKinds.def"
324     default:
325       break;
326     }
327     llvm_unreachable("Invalid OpenMP 'map' clause type");
328   case OMPC_to:
329     switch (Type) {
330     case OMPC_TO_MODIFIER_unknown:
331       return "unknown";
332 #define OPENMP_TO_MODIFIER_KIND(Name)                                          \
333   case OMPC_TO_MODIFIER_##Name:                                                \
334     return #Name;
335 #include "clang/Basic/OpenMPKinds.def"
336     default:
337       break;
338     }
339     llvm_unreachable("Invalid OpenMP 'to' clause type");
340   case OMPC_from:
341     switch (Type) {
342     case OMPC_FROM_MODIFIER_unknown:
343       return "unknown";
344 #define OPENMP_FROM_MODIFIER_KIND(Name)                                        \
345   case OMPC_FROM_MODIFIER_##Name:                                              \
346     return #Name;
347 #include "clang/Basic/OpenMPKinds.def"
348     default:
349       break;
350     }
351     llvm_unreachable("Invalid OpenMP 'from' clause type");
352   case OMPC_dist_schedule:
353     switch (Type) {
354     case OMPC_DIST_SCHEDULE_unknown:
355       return "unknown";
356 #define OPENMP_DIST_SCHEDULE_KIND(Name)                                      \
357   case OMPC_DIST_SCHEDULE_##Name:                                            \
358     return #Name;
359 #include "clang/Basic/OpenMPKinds.def"
360     }
361     llvm_unreachable("Invalid OpenMP 'dist_schedule' clause type");
362   case OMPC_defaultmap:
363     switch (Type) {
364     case OMPC_DEFAULTMAP_unknown:
365     case OMPC_DEFAULTMAP_MODIFIER_last:
366       return "unknown";
367 #define OPENMP_DEFAULTMAP_KIND(Name)                                         \
368     case OMPC_DEFAULTMAP_##Name:                                             \
369       return #Name;
370 #define OPENMP_DEFAULTMAP_MODIFIER(Name)                                     \
371     case OMPC_DEFAULTMAP_MODIFIER_##Name:                                    \
372       return #Name;
373 #include "clang/Basic/OpenMPKinds.def"
374     }
375     llvm_unreachable("Invalid OpenMP 'schedule' clause type");
376   case OMPC_atomic_default_mem_order:
377     switch (Type) {
378     case OMPC_ATOMIC_DEFAULT_MEM_ORDER_unknown:
379       return "unknown";
380 #define OPENMP_ATOMIC_DEFAULT_MEM_ORDER_KIND(Name)                           \
381     case OMPC_ATOMIC_DEFAULT_MEM_ORDER_##Name:                               \
382       return #Name;
383 #include "clang/Basic/OpenMPKinds.def"
384 }
385     llvm_unreachable("Invalid OpenMP 'atomic_default_mem_order' clause type");
386   case OMPC_device_type:
387     switch (Type) {
388     case OMPC_DEVICE_TYPE_unknown:
389       return "unknown";
390 #define OPENMP_DEVICE_TYPE_KIND(Name)                                          \
391     case OMPC_DEVICE_TYPE_##Name:                                              \
392       return #Name;
393 #include "clang/Basic/OpenMPKinds.def"
394     }
395     llvm_unreachable("Invalid OpenMP 'device_type' clause type");
396   case OMPC_unknown:
397   case OMPC_threadprivate:
398   case OMPC_if:
399   case OMPC_final:
400   case OMPC_num_threads:
401   case OMPC_safelen:
402   case OMPC_simdlen:
403   case OMPC_allocator:
404   case OMPC_allocate:
405   case OMPC_collapse:
406   case OMPC_private:
407   case OMPC_firstprivate:
408   case OMPC_lastprivate:
409   case OMPC_shared:
410   case OMPC_reduction:
411   case OMPC_task_reduction:
412   case OMPC_in_reduction:
413   case OMPC_aligned:
414   case OMPC_copyin:
415   case OMPC_copyprivate:
416   case OMPC_ordered:
417   case OMPC_nowait:
418   case OMPC_untied:
419   case OMPC_mergeable:
420   case OMPC_flush:
421   case OMPC_read:
422   case OMPC_write:
423   case OMPC_update:
424   case OMPC_capture:
425   case OMPC_seq_cst:
426   case OMPC_device:
427   case OMPC_threads:
428   case OMPC_simd:
429   case OMPC_num_teams:
430   case OMPC_thread_limit:
431   case OMPC_priority:
432   case OMPC_grainsize:
433   case OMPC_nogroup:
434   case OMPC_num_tasks:
435   case OMPC_hint:
436   case OMPC_uniform:
437   case OMPC_use_device_ptr:
438   case OMPC_is_device_ptr:
439   case OMPC_unified_address:
440   case OMPC_unified_shared_memory:
441   case OMPC_reverse_offload:
442   case OMPC_dynamic_allocators:
443   case OMPC_match:
444     break;
445   }
446   llvm_unreachable("Invalid OpenMP simple clause kind");
447 }
448 
449 bool clang::isAllowedClauseForDirective(OpenMPDirectiveKind DKind,
450                                         OpenMPClauseKind CKind) {
451   assert(DKind <= OMPD_unknown);
452   assert(CKind <= OMPC_unknown);
453   switch (DKind) {
454   case OMPD_parallel:
455     switch (CKind) {
456 #define OPENMP_PARALLEL_CLAUSE(Name)                                           \
457   case OMPC_##Name:                                                            \
458     return true;
459 #include "clang/Basic/OpenMPKinds.def"
460     default:
461       break;
462     }
463     break;
464   case OMPD_simd:
465     switch (CKind) {
466 #define OPENMP_SIMD_CLAUSE(Name)                                               \
467   case OMPC_##Name:                                                            \
468     return true;
469 #include "clang/Basic/OpenMPKinds.def"
470     default:
471       break;
472     }
473     break;
474   case OMPD_for:
475     switch (CKind) {
476 #define OPENMP_FOR_CLAUSE(Name)                                                \
477   case OMPC_##Name:                                                            \
478     return true;
479 #include "clang/Basic/OpenMPKinds.def"
480     default:
481       break;
482     }
483     break;
484   case OMPD_for_simd:
485     switch (CKind) {
486 #define OPENMP_FOR_SIMD_CLAUSE(Name)                                           \
487   case OMPC_##Name:                                                            \
488     return true;
489 #include "clang/Basic/OpenMPKinds.def"
490     default:
491       break;
492     }
493     break;
494   case OMPD_sections:
495     switch (CKind) {
496 #define OPENMP_SECTIONS_CLAUSE(Name)                                           \
497   case OMPC_##Name:                                                            \
498     return true;
499 #include "clang/Basic/OpenMPKinds.def"
500     default:
501       break;
502     }
503     break;
504   case OMPD_single:
505     switch (CKind) {
506 #define OPENMP_SINGLE_CLAUSE(Name)                                             \
507   case OMPC_##Name:                                                            \
508     return true;
509 #include "clang/Basic/OpenMPKinds.def"
510     default:
511       break;
512     }
513     break;
514   case OMPD_parallel_for:
515     switch (CKind) {
516 #define OPENMP_PARALLEL_FOR_CLAUSE(Name)                                       \
517   case OMPC_##Name:                                                            \
518     return true;
519 #include "clang/Basic/OpenMPKinds.def"
520     default:
521       break;
522     }
523     break;
524   case OMPD_parallel_for_simd:
525     switch (CKind) {
526 #define OPENMP_PARALLEL_FOR_SIMD_CLAUSE(Name)                                  \
527   case OMPC_##Name:                                                            \
528     return true;
529 #include "clang/Basic/OpenMPKinds.def"
530     default:
531       break;
532     }
533     break;
534   case OMPD_parallel_sections:
535     switch (CKind) {
536 #define OPENMP_PARALLEL_SECTIONS_CLAUSE(Name)                                  \
537   case OMPC_##Name:                                                            \
538     return true;
539 #include "clang/Basic/OpenMPKinds.def"
540     default:
541       break;
542     }
543     break;
544   case OMPD_task:
545     switch (CKind) {
546 #define OPENMP_TASK_CLAUSE(Name)                                               \
547   case OMPC_##Name:                                                            \
548     return true;
549 #include "clang/Basic/OpenMPKinds.def"
550     default:
551       break;
552     }
553     break;
554   case OMPD_flush:
555     return CKind == OMPC_flush;
556     break;
557   case OMPD_atomic:
558     switch (CKind) {
559 #define OPENMP_ATOMIC_CLAUSE(Name)                                             \
560   case OMPC_##Name:                                                            \
561     return true;
562 #include "clang/Basic/OpenMPKinds.def"
563     default:
564       break;
565     }
566     break;
567   case OMPD_target:
568     switch (CKind) {
569 #define OPENMP_TARGET_CLAUSE(Name)                                             \
570   case OMPC_##Name:                                                            \
571     return true;
572 #include "clang/Basic/OpenMPKinds.def"
573     default:
574       break;
575     }
576     break;
577   case OMPD_requires:
578     switch (CKind) {
579 #define OPENMP_REQUIRES_CLAUSE(Name)                                             \
580   case OMPC_##Name:                                                            \
581     return true;
582 #include "clang/Basic/OpenMPKinds.def"
583     default:
584       break;
585     }
586     break;
587   case OMPD_target_data:
588     switch (CKind) {
589 #define OPENMP_TARGET_DATA_CLAUSE(Name)                                        \
590   case OMPC_##Name:                                                            \
591     return true;
592 #include "clang/Basic/OpenMPKinds.def"
593     default:
594       break;
595     }
596     break;
597   case OMPD_target_enter_data:
598     switch (CKind) {
599 #define OPENMP_TARGET_ENTER_DATA_CLAUSE(Name)                                  \
600   case OMPC_##Name:                                                            \
601     return true;
602 #include "clang/Basic/OpenMPKinds.def"
603     default:
604       break;
605     }
606     break;
607   case OMPD_target_exit_data:
608     switch (CKind) {
609 #define OPENMP_TARGET_EXIT_DATA_CLAUSE(Name)                                   \
610   case OMPC_##Name:                                                            \
611     return true;
612 #include "clang/Basic/OpenMPKinds.def"
613     default:
614       break;
615     }
616     break;
617   case OMPD_target_parallel:
618     switch (CKind) {
619 #define OPENMP_TARGET_PARALLEL_CLAUSE(Name)                                    \
620   case OMPC_##Name:                                                            \
621     return true;
622 #include "clang/Basic/OpenMPKinds.def"
623     default:
624       break;
625     }
626     break;
627   case OMPD_target_parallel_for:
628     switch (CKind) {
629 #define OPENMP_TARGET_PARALLEL_FOR_CLAUSE(Name)                                \
630   case OMPC_##Name:                                                            \
631     return true;
632 #include "clang/Basic/OpenMPKinds.def"
633     default:
634       break;
635     }
636     break;
637   case OMPD_target_update:
638     switch (CKind) {
639 #define OPENMP_TARGET_UPDATE_CLAUSE(Name)                                      \
640   case OMPC_##Name:                                                            \
641     return true;
642 #include "clang/Basic/OpenMPKinds.def"
643     default:
644       break;
645     }
646     break;
647   case OMPD_teams:
648     switch (CKind) {
649 #define OPENMP_TEAMS_CLAUSE(Name)                                              \
650   case OMPC_##Name:                                                            \
651     return true;
652 #include "clang/Basic/OpenMPKinds.def"
653     default:
654       break;
655     }
656     break;
657   case OMPD_cancel:
658     switch (CKind) {
659 #define OPENMP_CANCEL_CLAUSE(Name)                                             \
660   case OMPC_##Name:                                                            \
661     return true;
662 #include "clang/Basic/OpenMPKinds.def"
663     default:
664       break;
665     }
666     break;
667   case OMPD_ordered:
668     switch (CKind) {
669 #define OPENMP_ORDERED_CLAUSE(Name)                                            \
670   case OMPC_##Name:                                                            \
671     return true;
672 #include "clang/Basic/OpenMPKinds.def"
673     default:
674       break;
675     }
676     break;
677   case OMPD_taskloop:
678     switch (CKind) {
679 #define OPENMP_TASKLOOP_CLAUSE(Name)                                           \
680   case OMPC_##Name:                                                            \
681     return true;
682 #include "clang/Basic/OpenMPKinds.def"
683     default:
684       break;
685     }
686     break;
687   case OMPD_taskloop_simd:
688     switch (CKind) {
689 #define OPENMP_TASKLOOP_SIMD_CLAUSE(Name)                                      \
690   case OMPC_##Name:                                                            \
691     return true;
692 #include "clang/Basic/OpenMPKinds.def"
693     default:
694       break;
695     }
696     break;
697   case OMPD_master_taskloop:
698     switch (CKind) {
699 #define OPENMP_MASTER_TASKLOOP_CLAUSE(Name)                                    \
700   case OMPC_##Name:                                                            \
701     return true;
702 #include "clang/Basic/OpenMPKinds.def"
703     default:
704       break;
705     }
706     break;
707   case OMPD_master_taskloop_simd:
708     switch (CKind) {
709 #define OPENMP_MASTER_TASKLOOP_SIMD_CLAUSE(Name)                               \
710   case OMPC_##Name:                                                            \
711     return true;
712 #include "clang/Basic/OpenMPKinds.def"
713     default:
714       break;
715     }
716     break;
717   case OMPD_parallel_master_taskloop:
718     switch (CKind) {
719 #define OPENMP_PARALLEL_MASTER_TASKLOOP_CLAUSE(Name)                           \
720   case OMPC_##Name:                                                            \
721     return true;
722 #include "clang/Basic/OpenMPKinds.def"
723     default:
724       break;
725     }
726     break;
727   case OMPD_parallel_master_taskloop_simd:
728     switch (CKind) {
729 #define OPENMP_PARALLEL_MASTER_TASKLOOP_SIMD_CLAUSE(Name)                      \
730   case OMPC_##Name:                                                            \
731     return true;
732 #include "clang/Basic/OpenMPKinds.def"
733     default:
734       break;
735     }
736     break;
737   case OMPD_critical:
738     switch (CKind) {
739 #define OPENMP_CRITICAL_CLAUSE(Name)                                           \
740   case OMPC_##Name:                                                            \
741     return true;
742 #include "clang/Basic/OpenMPKinds.def"
743     default:
744       break;
745     }
746     break;
747   case OMPD_distribute:
748     switch (CKind) {
749 #define OPENMP_DISTRIBUTE_CLAUSE(Name)                                         \
750   case OMPC_##Name:                                                            \
751     return true;
752 #include "clang/Basic/OpenMPKinds.def"
753     default:
754       break;
755     }
756     break;
757   case OMPD_distribute_parallel_for:
758     switch (CKind) {
759 #define OPENMP_DISTRIBUTE_PARALLEL_FOR_CLAUSE(Name)                            \
760   case OMPC_##Name:                                                            \
761     return true;
762 #include "clang/Basic/OpenMPKinds.def"
763     default:
764       break;
765     }
766     break;
767   case OMPD_distribute_parallel_for_simd:
768     switch (CKind) {
769 #define OPENMP_DISTRIBUTE_PARALLEL_FOR_SIMD_CLAUSE(Name)                       \
770   case OMPC_##Name:                                                            \
771     return true;
772 #include "clang/Basic/OpenMPKinds.def"
773     default:
774       break;
775     }
776     break;
777   case OMPD_distribute_simd:
778     switch (CKind) {
779 #define OPENMP_DISTRIBUTE_SIMD_CLAUSE(Name)                                    \
780   case OMPC_##Name:                                                            \
781     return true;
782 #include "clang/Basic/OpenMPKinds.def"
783     default:
784       break;
785     }
786     break;
787   case OMPD_target_parallel_for_simd:
788     switch (CKind) {
789 #define OPENMP_TARGET_PARALLEL_FOR_SIMD_CLAUSE(Name)                           \
790   case OMPC_##Name:                                                            \
791     return true;
792 #include "clang/Basic/OpenMPKinds.def"
793     default:
794       break;
795     }
796     break;
797   case OMPD_target_simd:
798     switch (CKind) {
799 #define OPENMP_TARGET_SIMD_CLAUSE(Name)                                        \
800   case OMPC_##Name:                                                            \
801     return true;
802 #include "clang/Basic/OpenMPKinds.def"
803     default:
804       break;
805     }
806     break;
807   case OMPD_teams_distribute:
808     switch (CKind) {
809 #define OPENMP_TEAMS_DISTRIBUTE_CLAUSE(Name)                                   \
810   case OMPC_##Name:                                                            \
811     return true;
812 #include "clang/Basic/OpenMPKinds.def"
813     default:
814       break;
815     }
816     break;
817   case OMPD_teams_distribute_simd:
818     switch (CKind) {
819 #define OPENMP_TEAMS_DISTRIBUTE_SIMD_CLAUSE(Name)                              \
820   case OMPC_##Name:                                                            \
821     return true;
822 #include "clang/Basic/OpenMPKinds.def"
823     default:
824       break;
825     }
826     break;
827   case OMPD_teams_distribute_parallel_for_simd:
828     switch (CKind) {
829 #define OPENMP_TEAMS_DISTRIBUTE_PARALLEL_FOR_SIMD_CLAUSE(Name)                 \
830   case OMPC_##Name:                                                            \
831     return true;
832 #include "clang/Basic/OpenMPKinds.def"
833     default:
834       break;
835     }
836     break;
837   case OMPD_teams_distribute_parallel_for:
838     switch (CKind) {
839 #define OPENMP_TEAMS_DISTRIBUTE_PARALLEL_FOR_CLAUSE(Name)                      \
840   case OMPC_##Name:                                                            \
841     return true;
842 #include "clang/Basic/OpenMPKinds.def"
843     default:
844       break;
845     }
846     break;
847   case OMPD_target_teams:
848     switch (CKind) {
849 #define OPENMP_TARGET_TEAMS_CLAUSE(Name)                                       \
850   case OMPC_##Name:                                                            \
851     return true;
852 #include "clang/Basic/OpenMPKinds.def"
853     default:
854       break;
855     }
856     break;
857   case OMPD_target_teams_distribute:
858     switch (CKind) {
859 #define OPENMP_TARGET_TEAMS_DISTRIBUTE_CLAUSE(Name)                            \
860   case OMPC_##Name:                                                            \
861     return true;
862 #include "clang/Basic/OpenMPKinds.def"
863     default:
864       break;
865     }
866     break;
867   case OMPD_target_teams_distribute_parallel_for:
868     switch (CKind) {
869 #define OPENMP_TARGET_TEAMS_DISTRIBUTE_PARALLEL_FOR_CLAUSE(Name)               \
870   case OMPC_##Name:                                                            \
871     return true;
872 #include "clang/Basic/OpenMPKinds.def"
873     default:
874       break;
875     }
876     break;
877   case OMPD_target_teams_distribute_parallel_for_simd:
878     switch (CKind) {
879 #define OPENMP_TARGET_TEAMS_DISTRIBUTE_PARALLEL_FOR_SIMD_CLAUSE(Name)          \
880   case OMPC_##Name:                                                            \
881     return true;
882 #include "clang/Basic/OpenMPKinds.def"
883     default:
884       break;
885     }
886     break;
887   case OMPD_target_teams_distribute_simd:
888     switch (CKind) {
889 #define OPENMP_TARGET_TEAMS_DISTRIBUTE_SIMD_CLAUSE(Name)                       \
890   case OMPC_##Name:                                                            \
891     return true;
892 #include "clang/Basic/OpenMPKinds.def"
893     default:
894       break;
895     }
896     break;
897   case OMPD_taskgroup:
898     switch (CKind) {
899 #define OPENMP_TASKGROUP_CLAUSE(Name)                                          \
900   case OMPC_##Name:                                                            \
901     return true;
902 #include "clang/Basic/OpenMPKinds.def"
903     default:
904       break;
905     }
906     break;
907   case OMPD_declare_mapper:
908     switch (CKind) {
909 #define OPENMP_DECLARE_MAPPER_CLAUSE(Name)                                     \
910   case OMPC_##Name:                                                            \
911     return true;
912 #include "clang/Basic/OpenMPKinds.def"
913     default:
914       break;
915     }
916     break;
917   case OMPD_allocate:
918     switch (CKind) {
919 #define OPENMP_ALLOCATE_CLAUSE(Name)                                           \
920   case OMPC_##Name:                                                            \
921     return true;
922 #include "clang/Basic/OpenMPKinds.def"
923     default:
924       break;
925     }
926     break;
927   case OMPD_declare_variant:
928     switch (CKind) {
929 #define OPENMP_DECLARE_VARIANT_CLAUSE(Name)                                    \
930   case OMPC_##Name:                                                            \
931     return true;
932 #include "clang/Basic/OpenMPKinds.def"
933     default:
934       break;
935     }
936     break;
937   case OMPD_declare_target:
938   case OMPD_end_declare_target:
939   case OMPD_unknown:
940   case OMPD_threadprivate:
941   case OMPD_section:
942   case OMPD_master:
943   case OMPD_taskyield:
944   case OMPD_barrier:
945   case OMPD_taskwait:
946   case OMPD_cancellation_point:
947   case OMPD_declare_reduction:
948   case OMPD_declare_simd:
949     break;
950   }
951   return false;
952 }
953 
954 bool clang::isOpenMPLoopDirective(OpenMPDirectiveKind DKind) {
955   return DKind == OMPD_simd || DKind == OMPD_for || DKind == OMPD_for_simd ||
956          DKind == OMPD_parallel_for || DKind == OMPD_parallel_for_simd ||
957          DKind == OMPD_taskloop || DKind == OMPD_taskloop_simd ||
958          DKind == OMPD_master_taskloop || DKind == OMPD_master_taskloop_simd ||
959          DKind == OMPD_parallel_master_taskloop ||
960          DKind == OMPD_parallel_master_taskloop_simd ||
961          DKind == OMPD_distribute || DKind == OMPD_target_parallel_for ||
962          DKind == OMPD_distribute_parallel_for ||
963          DKind == OMPD_distribute_parallel_for_simd ||
964          DKind == OMPD_distribute_simd ||
965          DKind == OMPD_target_parallel_for_simd || DKind == OMPD_target_simd ||
966          DKind == OMPD_teams_distribute ||
967          DKind == OMPD_teams_distribute_simd ||
968          DKind == OMPD_teams_distribute_parallel_for_simd ||
969          DKind == OMPD_teams_distribute_parallel_for ||
970          DKind == OMPD_target_teams_distribute ||
971          DKind == OMPD_target_teams_distribute_parallel_for ||
972          DKind == OMPD_target_teams_distribute_parallel_for_simd ||
973          DKind == OMPD_target_teams_distribute_simd;
974 }
975 
976 bool clang::isOpenMPWorksharingDirective(OpenMPDirectiveKind DKind) {
977   return DKind == OMPD_for || DKind == OMPD_for_simd ||
978          DKind == OMPD_sections || DKind == OMPD_section ||
979          DKind == OMPD_single || DKind == OMPD_parallel_for ||
980          DKind == OMPD_parallel_for_simd || DKind == OMPD_parallel_sections ||
981          DKind == OMPD_target_parallel_for ||
982          DKind == OMPD_distribute_parallel_for ||
983          DKind == OMPD_distribute_parallel_for_simd ||
984          DKind == OMPD_target_parallel_for_simd ||
985          DKind == OMPD_teams_distribute_parallel_for_simd ||
986          DKind == OMPD_teams_distribute_parallel_for ||
987          DKind == OMPD_target_teams_distribute_parallel_for ||
988          DKind == OMPD_target_teams_distribute_parallel_for_simd;
989 }
990 
991 bool clang::isOpenMPTaskLoopDirective(OpenMPDirectiveKind DKind) {
992   return DKind == OMPD_taskloop || DKind == OMPD_taskloop_simd ||
993          DKind == OMPD_master_taskloop || DKind == OMPD_master_taskloop_simd ||
994          DKind == OMPD_parallel_master_taskloop ||
995          DKind == OMPD_parallel_master_taskloop_simd;
996 }
997 
998 bool clang::isOpenMPParallelDirective(OpenMPDirectiveKind DKind) {
999   return DKind == OMPD_parallel || DKind == OMPD_parallel_for ||
1000          DKind == OMPD_parallel_for_simd || DKind == OMPD_parallel_sections ||
1001          DKind == OMPD_target_parallel || DKind == OMPD_target_parallel_for ||
1002          DKind == OMPD_distribute_parallel_for ||
1003          DKind == OMPD_distribute_parallel_for_simd ||
1004          DKind == OMPD_target_parallel_for_simd ||
1005          DKind == OMPD_teams_distribute_parallel_for ||
1006          DKind == OMPD_teams_distribute_parallel_for_simd ||
1007          DKind == OMPD_target_teams_distribute_parallel_for ||
1008          DKind == OMPD_target_teams_distribute_parallel_for_simd ||
1009          DKind == OMPD_parallel_master_taskloop ||
1010          DKind == OMPD_parallel_master_taskloop_simd;
1011 }
1012 
1013 bool clang::isOpenMPTargetExecutionDirective(OpenMPDirectiveKind DKind) {
1014   return DKind == OMPD_target || DKind == OMPD_target_parallel ||
1015          DKind == OMPD_target_parallel_for ||
1016          DKind == OMPD_target_parallel_for_simd || DKind == OMPD_target_simd ||
1017          DKind == OMPD_target_teams || DKind == OMPD_target_teams_distribute ||
1018          DKind == OMPD_target_teams_distribute_parallel_for ||
1019          DKind == OMPD_target_teams_distribute_parallel_for_simd ||
1020          DKind == OMPD_target_teams_distribute_simd;
1021 }
1022 
1023 bool clang::isOpenMPTargetDataManagementDirective(OpenMPDirectiveKind DKind) {
1024   return DKind == OMPD_target_data || DKind == OMPD_target_enter_data ||
1025          DKind == OMPD_target_exit_data || DKind == OMPD_target_update;
1026 }
1027 
1028 bool clang::isOpenMPNestingTeamsDirective(OpenMPDirectiveKind DKind) {
1029   return DKind == OMPD_teams || DKind == OMPD_teams_distribute ||
1030          DKind == OMPD_teams_distribute_simd ||
1031          DKind == OMPD_teams_distribute_parallel_for_simd ||
1032          DKind == OMPD_teams_distribute_parallel_for;
1033 }
1034 
1035 bool clang::isOpenMPTeamsDirective(OpenMPDirectiveKind DKind) {
1036   return isOpenMPNestingTeamsDirective(DKind) ||
1037          DKind == OMPD_target_teams || DKind == OMPD_target_teams_distribute ||
1038          DKind == OMPD_target_teams_distribute_parallel_for ||
1039          DKind == OMPD_target_teams_distribute_parallel_for_simd ||
1040          DKind == OMPD_target_teams_distribute_simd;
1041 }
1042 
1043 bool clang::isOpenMPSimdDirective(OpenMPDirectiveKind DKind) {
1044   return DKind == OMPD_simd || DKind == OMPD_for_simd ||
1045          DKind == OMPD_parallel_for_simd || DKind == OMPD_taskloop_simd ||
1046          DKind == OMPD_master_taskloop_simd ||
1047          DKind == OMPD_parallel_master_taskloop_simd ||
1048          DKind == OMPD_distribute_parallel_for_simd ||
1049          DKind == OMPD_distribute_simd || DKind == OMPD_target_simd ||
1050          DKind == OMPD_teams_distribute_simd ||
1051          DKind == OMPD_teams_distribute_parallel_for_simd ||
1052          DKind == OMPD_target_teams_distribute_parallel_for_simd ||
1053          DKind == OMPD_target_teams_distribute_simd ||
1054          DKind == OMPD_target_parallel_for_simd;
1055 }
1056 
1057 bool clang::isOpenMPNestingDistributeDirective(OpenMPDirectiveKind Kind) {
1058   return Kind == OMPD_distribute || Kind == OMPD_distribute_parallel_for ||
1059          Kind == OMPD_distribute_parallel_for_simd ||
1060          Kind == OMPD_distribute_simd;
1061   // TODO add next directives.
1062 }
1063 
1064 bool clang::isOpenMPDistributeDirective(OpenMPDirectiveKind Kind) {
1065   return isOpenMPNestingDistributeDirective(Kind) ||
1066          Kind == OMPD_teams_distribute || Kind == OMPD_teams_distribute_simd ||
1067          Kind == OMPD_teams_distribute_parallel_for_simd ||
1068          Kind == OMPD_teams_distribute_parallel_for ||
1069          Kind == OMPD_target_teams_distribute ||
1070          Kind == OMPD_target_teams_distribute_parallel_for ||
1071          Kind == OMPD_target_teams_distribute_parallel_for_simd ||
1072          Kind == OMPD_target_teams_distribute_simd;
1073 }
1074 
1075 bool clang::isOpenMPPrivate(OpenMPClauseKind Kind) {
1076   return Kind == OMPC_private || Kind == OMPC_firstprivate ||
1077          Kind == OMPC_lastprivate || Kind == OMPC_linear ||
1078          Kind == OMPC_reduction || Kind == OMPC_task_reduction ||
1079          Kind == OMPC_in_reduction; // TODO add next clauses like 'reduction'.
1080 }
1081 
1082 bool clang::isOpenMPThreadPrivate(OpenMPClauseKind Kind) {
1083   return Kind == OMPC_threadprivate || Kind == OMPC_copyin;
1084 }
1085 
1086 bool clang::isOpenMPTaskingDirective(OpenMPDirectiveKind Kind) {
1087   return Kind == OMPD_task || isOpenMPTaskLoopDirective(Kind);
1088 }
1089 
1090 bool clang::isOpenMPLoopBoundSharingDirective(OpenMPDirectiveKind Kind) {
1091   return Kind == OMPD_distribute_parallel_for ||
1092          Kind == OMPD_distribute_parallel_for_simd ||
1093          Kind == OMPD_teams_distribute_parallel_for_simd ||
1094          Kind == OMPD_teams_distribute_parallel_for ||
1095          Kind == OMPD_target_teams_distribute_parallel_for ||
1096          Kind == OMPD_target_teams_distribute_parallel_for_simd;
1097 }
1098 
1099 void clang::getOpenMPCaptureRegions(
1100     SmallVectorImpl<OpenMPDirectiveKind> &CaptureRegions,
1101     OpenMPDirectiveKind DKind) {
1102   assert(DKind <= OMPD_unknown);
1103   switch (DKind) {
1104   case OMPD_parallel:
1105   case OMPD_parallel_for:
1106   case OMPD_parallel_for_simd:
1107   case OMPD_parallel_sections:
1108   case OMPD_distribute_parallel_for:
1109   case OMPD_distribute_parallel_for_simd:
1110     CaptureRegions.push_back(OMPD_parallel);
1111     break;
1112   case OMPD_target_teams:
1113   case OMPD_target_teams_distribute:
1114   case OMPD_target_teams_distribute_simd:
1115     CaptureRegions.push_back(OMPD_task);
1116     CaptureRegions.push_back(OMPD_target);
1117     CaptureRegions.push_back(OMPD_teams);
1118     break;
1119   case OMPD_teams:
1120   case OMPD_teams_distribute:
1121   case OMPD_teams_distribute_simd:
1122     CaptureRegions.push_back(OMPD_teams);
1123     break;
1124   case OMPD_target:
1125   case OMPD_target_simd:
1126     CaptureRegions.push_back(OMPD_task);
1127     CaptureRegions.push_back(OMPD_target);
1128     break;
1129   case OMPD_teams_distribute_parallel_for:
1130   case OMPD_teams_distribute_parallel_for_simd:
1131     CaptureRegions.push_back(OMPD_teams);
1132     CaptureRegions.push_back(OMPD_parallel);
1133     break;
1134   case OMPD_target_parallel:
1135   case OMPD_target_parallel_for:
1136   case OMPD_target_parallel_for_simd:
1137     CaptureRegions.push_back(OMPD_task);
1138     CaptureRegions.push_back(OMPD_target);
1139     CaptureRegions.push_back(OMPD_parallel);
1140     break;
1141   case OMPD_task:
1142   case OMPD_target_enter_data:
1143   case OMPD_target_exit_data:
1144   case OMPD_target_update:
1145     CaptureRegions.push_back(OMPD_task);
1146     break;
1147   case OMPD_taskloop:
1148   case OMPD_taskloop_simd:
1149   case OMPD_master_taskloop:
1150   case OMPD_master_taskloop_simd:
1151     CaptureRegions.push_back(OMPD_taskloop);
1152     break;
1153   case OMPD_parallel_master_taskloop:
1154   case OMPD_parallel_master_taskloop_simd:
1155     CaptureRegions.push_back(OMPD_parallel);
1156     CaptureRegions.push_back(OMPD_taskloop);
1157     break;
1158   case OMPD_target_teams_distribute_parallel_for:
1159   case OMPD_target_teams_distribute_parallel_for_simd:
1160     CaptureRegions.push_back(OMPD_task);
1161     CaptureRegions.push_back(OMPD_target);
1162     CaptureRegions.push_back(OMPD_teams);
1163     CaptureRegions.push_back(OMPD_parallel);
1164     break;
1165   case OMPD_simd:
1166   case OMPD_for:
1167   case OMPD_for_simd:
1168   case OMPD_sections:
1169   case OMPD_section:
1170   case OMPD_single:
1171   case OMPD_master:
1172   case OMPD_critical:
1173   case OMPD_taskgroup:
1174   case OMPD_distribute:
1175   case OMPD_ordered:
1176   case OMPD_atomic:
1177   case OMPD_target_data:
1178   case OMPD_distribute_simd:
1179     CaptureRegions.push_back(OMPD_unknown);
1180     break;
1181   case OMPD_threadprivate:
1182   case OMPD_allocate:
1183   case OMPD_taskyield:
1184   case OMPD_barrier:
1185   case OMPD_taskwait:
1186   case OMPD_cancellation_point:
1187   case OMPD_cancel:
1188   case OMPD_flush:
1189   case OMPD_declare_reduction:
1190   case OMPD_declare_mapper:
1191   case OMPD_declare_simd:
1192   case OMPD_declare_target:
1193   case OMPD_end_declare_target:
1194   case OMPD_requires:
1195   case OMPD_declare_variant:
1196     llvm_unreachable("OpenMP Directive is not allowed");
1197   case OMPD_unknown:
1198     llvm_unreachable("Unknown OpenMP directive");
1199   }
1200 }
1201