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