1 //===---------- Types.h - OpenMP types ---------------------------- C++ -*-===//
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 //
9 //
10 //===----------------------------------------------------------------------===//
11 
12 #ifndef OMPTARGET_TYPES_H
13 #define OMPTARGET_TYPES_H
14 
15 // Tell the compiler that we do not have any "call-like" inline assembly in the
16 // device rutime. That means we cannot have inline assembly which will call
17 // another function but only inline assembly that performs some operation or
18 // side-effect and then continues execution with something on the existing call
19 // stack.
20 //
21 // TODO: Find a good place for this
22 #pragma omp assumes ext_no_call_asm
23 
24 /// Base type declarations for freestanding mode
25 ///
26 ///{
27 using int8_t = char;
28 using uint8_t = unsigned char;
29 using int16_t = short;
30 using uint16_t = unsigned short;
31 using int32_t = int;
32 using uint32_t = unsigned int;
33 using int64_t = long;
34 using uint64_t = unsigned long;
35 
36 static_assert(sizeof(int8_t) == 1, "type size mismatch");
37 static_assert(sizeof(uint8_t) == 1, "type size mismatch");
38 static_assert(sizeof(int16_t) == 2, "type size mismatch");
39 static_assert(sizeof(uint16_t) == 2, "type size mismatch");
40 static_assert(sizeof(int32_t) == 4, "type size mismatch");
41 static_assert(sizeof(uint32_t) == 4, "type size mismatch");
42 static_assert(sizeof(int64_t) == 8, "type size mismatch");
43 static_assert(sizeof(uint64_t) == 8, "type size mismatch");
44 ///}
45 
46 enum omp_proc_bind_t {
47   omp_proc_bind_false = 0,
48   omp_proc_bind_true = 1,
49   omp_proc_bind_master = 2,
50   omp_proc_bind_close = 3,
51   omp_proc_bind_spread = 4
52 };
53 
54 enum omp_sched_t {
55   omp_sched_static = 1,  /* chunkSize >0 */
56   omp_sched_dynamic = 2, /* chunkSize >0 */
57   omp_sched_guided = 3,  /* chunkSize >0 */
58   omp_sched_auto = 4,    /* no chunkSize */
59 };
60 
61 enum kmp_sched_t {
62   kmp_sched_static_chunk = 33,
63   kmp_sched_static_nochunk = 34,
64   kmp_sched_dynamic = 35,
65   kmp_sched_guided = 36,
66   kmp_sched_runtime = 37,
67   kmp_sched_auto = 38,
68 
69   kmp_sched_static_balanced_chunk = 45,
70 
71   kmp_sched_static_ordered = 65,
72   kmp_sched_static_nochunk_ordered = 66,
73   kmp_sched_dynamic_ordered = 67,
74   kmp_sched_guided_ordered = 68,
75   kmp_sched_runtime_ordered = 69,
76   kmp_sched_auto_ordered = 70,
77 
78   kmp_sched_distr_static_chunk = 91,
79   kmp_sched_distr_static_nochunk = 92,
80   kmp_sched_distr_static_chunk_sched_static_chunkone = 93,
81 
82   kmp_sched_default = kmp_sched_static_nochunk,
83   kmp_sched_unordered_first = kmp_sched_static_chunk,
84   kmp_sched_unordered_last = kmp_sched_auto,
85   kmp_sched_ordered_first = kmp_sched_static_ordered,
86   kmp_sched_ordered_last = kmp_sched_auto_ordered,
87   kmp_sched_distribute_first = kmp_sched_distr_static_chunk,
88   kmp_sched_distribute_last =
89       kmp_sched_distr_static_chunk_sched_static_chunkone,
90 
91   /* Support for OpenMP 4.5 monotonic and nonmonotonic schedule modifiers.
92    * Since we need to distinguish the three possible cases (no modifier,
93    * monotonic modifier, nonmonotonic modifier), we need separate bits for
94    * each modifier. The absence of monotonic does not imply nonmonotonic,
95    * especially since 4.5 says that the behaviour of the "no modifier" case
96    * is implementation defined in 4.5, but will become "nonmonotonic" in 5.0.
97    *
98    * Since we're passing a full 32 bit value, we can use a couple of high
99    * bits for these flags; out of paranoia we avoid the sign bit.
100    *
101    * These modifiers can be or-ed into non-static schedules by the compiler
102    * to pass the additional information. They will be stripped early in the
103    * processing in __kmp_dispatch_init when setting up schedules, so
104    * most of the code won't ever see schedules with these bits set.
105    */
106   kmp_sched_modifier_monotonic = (1 << 29),
107   /**< Set if the monotonic schedule modifier was present */
108   kmp_sched_modifier_nonmonotonic = (1 << 30),
109 /**< Set if the nonmonotonic schedule modifier was present */
110 
111 #define SCHEDULE_WITHOUT_MODIFIERS(s)                                          \
112   (enum kmp_sched_t)(                                                          \
113       (s) & ~(kmp_sched_modifier_nonmonotonic | kmp_sched_modifier_monotonic))
114 #define SCHEDULE_HAS_MONOTONIC(s) (((s)&kmp_sched_modifier_monotonic) != 0)
115 #define SCHEDULE_HAS_NONMONOTONIC(s)                                           \
116   (((s)&kmp_sched_modifier_nonmonotonic) != 0)
117 #define SCHEDULE_HAS_NO_MODIFIERS(s)                                           \
118   (((s) & (kmp_sched_modifier_nonmonotonic | kmp_sched_modifier_monotonic)) == \
119    0)
120 
121 };
122 
123 struct TaskDescriptorTy;
124 using TaskFnTy = int32_t (*)(int32_t global_tid, TaskDescriptorTy *taskDescr);
125 struct TaskDescriptorTy {
126   void *Payload;
127   TaskFnTy TaskFn;
128 };
129 
130 #pragma omp begin declare variant match(device = {arch(amdgcn)})
131 using LaneMaskTy = uint64_t;
132 #pragma omp end declare variant
133 
134 #pragma omp begin declare variant match(                                       \
135     device = {arch(amdgcn)}, implementation = {extension(match_none)})
136 using LaneMaskTy = uint64_t;
137 #pragma omp end declare variant
138 
139 namespace lanes {
140 enum : LaneMaskTy { All = ~(LaneMaskTy)0 };
141 } // namespace lanes
142 
143 /// The ident structure that describes a source location. The struct is
144 /// identical to the one in the kmp.h file. We maintain the same data structure
145 /// for compatibility.
146 struct IdentTy {
147   int32_t reserved_1;  /**<  might be used in Fortran; see above  */
148   int32_t flags;       /**<  also f.flags; KMP_IDENT_xxx flags; KMP_IDENT_KMPC
149                             identifies this union member  */
150   int32_t reserved_2;  /**<  not really used in Fortran any more; see above */
151   int32_t reserved_3;  /**<  source[4] in Fortran, do not use for C++  */
152   char const *psource; /**<  String describing the source location.
153                        The string is composed of semi-colon separated fields
154                        which describe the source file, the function and a pair
155                        of line numbers that delimit the construct. */
156 };
157 
158 using __kmpc_impl_lanemask_t = LaneMaskTy;
159 
160 using ParallelRegionFnTy = void *;
161 
162 using CriticalNameTy = int32_t[8];
163 
164 struct omp_lock_t {
165   void *Lock;
166 };
167 
168 using InterWarpCopyFnTy = void (*)(void *src, int32_t warp_num);
169 using ShuffleReductFnTy = void (*)(void *rhsData, int16_t lane_id,
170                                    int16_t lane_offset, int16_t shortCircuit);
171 using ListGlobalFnTy = void (*)(void *buffer, int idx, void *reduce_data);
172 
173 /// Macros for allocating variables in different address spaces.
174 ///{
175 
176 // Follows the pattern in interface.h
177 typedef enum omp_allocator_handle_t {
178   omp_null_allocator = 0,
179   omp_default_mem_alloc = 1,
180   omp_large_cap_mem_alloc = 2,
181   omp_const_mem_alloc = 3,
182   omp_high_bw_mem_alloc = 4,
183   omp_low_lat_mem_alloc = 5,
184   omp_cgroup_mem_alloc = 6,
185   omp_pteam_mem_alloc = 7,
186   omp_thread_mem_alloc = 8,
187   KMP_ALLOCATOR_MAX_HANDLE = ~(0U)
188 } omp_allocator_handle_t;
189 
190 enum OMPTgtExecModeFlags : int8_t {
191   OMP_TGT_EXEC_MODE_GENERIC = 1 << 0,
192   OMP_TGT_EXEC_MODE_SPMD = 1 << 1,
193 };
194 
195 #define __PRAGMA(STR) _Pragma(#STR)
196 #define OMP_PRAGMA(STR) __PRAGMA(omp STR)
197 
198 #define SHARED(NAME)                                                           \
199   NAME [[clang::loader_uninitialized]];                                        \
200   OMP_PRAGMA(allocate(NAME) allocator(omp_pteam_mem_alloc))
201 
202 // TODO: clang should use address space 5 for omp_thread_mem_alloc, but right
203 //       now that's not the case.
204 #define THREAD_LOCAL(NAME)                                                     \
205   [[clang::address_space(5)]] NAME [[clang::loader_uninitialized]]
206 
207 // TODO: clang should use address space 4 for omp_const_mem_alloc, maybe it
208 //       does?
209 #define CONSTANT(NAME)                                                         \
210   [[clang::address_space(4)]] NAME [[clang::loader_uninitialized]]
211 
212 // Attribute to keep alive certain definition for the bitcode library.
213 #ifdef LIBOMPTARGET_BC_TARGET
214 #define KEEP_ALIVE __attribute__((used, retain))
215 #else
216 #define KEEP_ALIVE
217 #endif
218 
219 ///}
220 
221 #endif
222