1 //===-------- interface.cpp - Target independent OpenMP target RTL --------===//
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 // Implementation of the interface to be used by Clang during the codegen of a
10 // target region.
11 //
12 //===----------------------------------------------------------------------===//
13 
14 #include "device.h"
15 #include "private.h"
16 #include "rtl.h"
17 
18 #include <cassert>
19 #include <cstdio>
20 #include <cstdlib>
21 #include <mutex>
22 
23 ////////////////////////////////////////////////////////////////////////////////
24 /// manage the success or failure of a target construct
25 static void HandleDefaultTargetOffload() {
26   PM->TargetOffloadMtx.lock();
27   if (PM->TargetOffloadPolicy == tgt_default) {
28     if (omp_get_num_devices() > 0) {
29       DP("Default TARGET OFFLOAD policy is now mandatory "
30          "(devices were found)\n");
31       PM->TargetOffloadPolicy = tgt_mandatory;
32     } else {
33       DP("Default TARGET OFFLOAD policy is now disabled "
34          "(no devices were found)\n");
35       PM->TargetOffloadPolicy = tgt_disabled;
36     }
37   }
38   PM->TargetOffloadMtx.unlock();
39 }
40 
41 static int IsOffloadDisabled() {
42   if (PM->TargetOffloadPolicy == tgt_default)
43     HandleDefaultTargetOffload();
44   return PM->TargetOffloadPolicy == tgt_disabled;
45 }
46 
47 static void HandleTargetOutcome(bool success, ident_t *loc = nullptr) {
48   switch (PM->TargetOffloadPolicy) {
49   case tgt_disabled:
50     if (success) {
51       FATAL_MESSAGE0(1, "expected no offloading while offloading is disabled");
52     }
53     break;
54   case tgt_default:
55     FATAL_MESSAGE0(1, "default offloading policy must be switched to "
56                       "mandatory or disabled");
57     break;
58   case tgt_mandatory:
59     if (!success) {
60       if (getInfoLevel() & OMP_INFOTYPE_DUMP_TABLE)
61         for (auto &Device : PM->Devices)
62           dumpTargetPointerMappings(loc, Device);
63       else
64         FAILURE_MESSAGE("Run with LIBOMPTARGET_DEBUG=%d to dump host-target "
65                         "pointer mappings.\n",
66                         OMP_INFOTYPE_DUMP_TABLE);
67 
68       SourceInfo info(loc);
69       if (info.isAvailible())
70         fprintf(stderr, "%s:%d:%d: ", info.getFilename(), info.getLine(),
71                 info.getColumn());
72       else
73         FAILURE_MESSAGE("Source location information not present. Compile with "
74                         "-g or -gline-tables-only.\n");
75       FATAL_MESSAGE0(
76           1, "failure of target construct while offloading is mandatory");
77     } else {
78       if (getInfoLevel() & OMP_INFOTYPE_DUMP_TABLE)
79         for (auto &Device : PM->Devices)
80           dumpTargetPointerMappings(loc, Device);
81     }
82     break;
83   }
84 }
85 
86 ////////////////////////////////////////////////////////////////////////////////
87 /// adds requires flags
88 EXTERN void __tgt_register_requires(int64_t flags) {
89   TIMESCOPE();
90   PM->RTLs.RegisterRequires(flags);
91 }
92 
93 ////////////////////////////////////////////////////////////////////////////////
94 /// adds a target shared library to the target execution image
95 EXTERN void __tgt_register_lib(__tgt_bin_desc *desc) {
96   TIMESCOPE();
97   std::call_once(PM->RTLs.initFlag, &RTLsTy::LoadRTLs, &PM->RTLs);
98   for (auto &RTL : PM->RTLs.AllRTLs) {
99     if (RTL.register_lib) {
100       if ((*RTL.register_lib)(desc) != OFFLOAD_SUCCESS) {
101         DP("Could not register library with %s", RTL.RTLName.c_str());
102       }
103     }
104   }
105   PM->RTLs.RegisterLib(desc);
106 }
107 
108 ////////////////////////////////////////////////////////////////////////////////
109 /// unloads a target shared library
110 EXTERN void __tgt_unregister_lib(__tgt_bin_desc *desc) {
111   TIMESCOPE();
112   PM->RTLs.UnregisterLib(desc);
113   for (auto &RTL : PM->RTLs.UsedRTLs) {
114     if (RTL->unregister_lib) {
115       if ((*RTL->unregister_lib)(desc) != OFFLOAD_SUCCESS) {
116         DP("Could not register library with %s", RTL->RTLName.c_str());
117       }
118     }
119   }
120 }
121 
122 /// creates host-to-target data mapping, stores it in the
123 /// libomptarget.so internal structure (an entry in a stack of data maps)
124 /// and passes the data to the device.
125 EXTERN void __tgt_target_data_begin(int64_t device_id, int32_t arg_num,
126                                     void **args_base, void **args,
127                                     int64_t *arg_sizes, int64_t *arg_types) {
128   TIMESCOPE();
129   __tgt_target_data_begin_mapper(nullptr, device_id, arg_num, args_base, args,
130                                  arg_sizes, arg_types, nullptr, nullptr);
131 }
132 
133 EXTERN void __tgt_target_data_begin_nowait(int64_t device_id, int32_t arg_num,
134                                            void **args_base, void **args,
135                                            int64_t *arg_sizes,
136                                            int64_t *arg_types, int32_t depNum,
137                                            void *depList, int32_t noAliasDepNum,
138                                            void *noAliasDepList) {
139   TIMESCOPE();
140   if (depNum + noAliasDepNum > 0)
141     __kmpc_omp_taskwait(NULL, __kmpc_global_thread_num(NULL));
142 
143   __tgt_target_data_begin_mapper(nullptr, device_id, arg_num, args_base, args,
144                                  arg_sizes, arg_types, nullptr, nullptr);
145 }
146 
147 EXTERN void __tgt_target_data_begin_mapper(ident_t *loc, int64_t device_id,
148                                            int32_t arg_num, void **args_base,
149                                            void **args, int64_t *arg_sizes,
150                                            int64_t *arg_types,
151                                            map_var_info_t *arg_names,
152                                            void **arg_mappers) {
153   TIMESCOPE_WITH_IDENT(loc);
154   if (IsOffloadDisabled())
155     return;
156 
157   DP("Entering data begin region for device %" PRId64 " with %d mappings\n",
158      device_id, arg_num);
159 
160   // No devices available?
161   if (device_id == OFFLOAD_DEVICE_DEFAULT) {
162     device_id = omp_get_default_device();
163     DP("Use default device id %" PRId64 "\n", device_id);
164   }
165 
166   if (CheckDeviceAndCtors(device_id) != OFFLOAD_SUCCESS) {
167     DP("Failed to get device %" PRId64 " ready\n", device_id);
168     HandleTargetOutcome(false, loc);
169     return;
170   }
171 
172   DeviceTy &Device = PM->Devices[device_id];
173 
174   if (getInfoLevel() & OMP_INFOTYPE_KERNEL_ARGS)
175     printKernelArguments(loc, device_id, arg_num, arg_sizes, arg_types,
176                          arg_names, "Entering OpenMP data region");
177 #ifdef OMPTARGET_DEBUG
178   for (int i = 0; i < arg_num; ++i) {
179     DP("Entry %2d: Base=" DPxMOD ", Begin=" DPxMOD ", Size=%" PRId64
180        ", Type=0x%" PRIx64 ", Name=%s\n",
181        i, DPxPTR(args_base[i]), DPxPTR(args[i]), arg_sizes[i], arg_types[i],
182        (arg_names) ? getNameFromMapping(arg_names[i]).c_str() : "unknown");
183   }
184 #endif
185 
186   int rc = targetDataBegin(loc, Device, arg_num, args_base, args, arg_sizes,
187                            arg_types, arg_names, arg_mappers, nullptr);
188   HandleTargetOutcome(rc == OFFLOAD_SUCCESS, loc);
189 }
190 
191 EXTERN void __tgt_target_data_begin_nowait_mapper(
192     ident_t *loc, int64_t device_id, int32_t arg_num, void **args_base,
193     void **args, int64_t *arg_sizes, int64_t *arg_types,
194     map_var_info_t *arg_names, void **arg_mappers, int32_t depNum,
195     void *depList, int32_t noAliasDepNum, void *noAliasDepList) {
196   TIMESCOPE_WITH_IDENT(loc);
197   if (depNum + noAliasDepNum > 0)
198     __kmpc_omp_taskwait(loc, __kmpc_global_thread_num(loc));
199 
200   __tgt_target_data_begin_mapper(loc, device_id, arg_num, args_base, args,
201                                  arg_sizes, arg_types, arg_names, arg_mappers);
202 }
203 
204 /// passes data from the target, releases target memory and destroys
205 /// the host-target mapping (top entry from the stack of data maps)
206 /// created by the last __tgt_target_data_begin.
207 EXTERN void __tgt_target_data_end(int64_t device_id, int32_t arg_num,
208                                   void **args_base, void **args,
209                                   int64_t *arg_sizes, int64_t *arg_types) {
210   TIMESCOPE();
211   __tgt_target_data_end_mapper(nullptr, device_id, arg_num, args_base, args,
212                                arg_sizes, arg_types, nullptr, nullptr);
213 }
214 
215 EXTERN void __tgt_target_data_end_nowait(int64_t device_id, int32_t arg_num,
216                                          void **args_base, void **args,
217                                          int64_t *arg_sizes, int64_t *arg_types,
218                                          int32_t depNum, void *depList,
219                                          int32_t noAliasDepNum,
220                                          void *noAliasDepList) {
221   TIMESCOPE();
222   if (depNum + noAliasDepNum > 0)
223     __kmpc_omp_taskwait(NULL, __kmpc_global_thread_num(NULL));
224 
225   __tgt_target_data_end_mapper(nullptr, device_id, arg_num, args_base, args,
226                                arg_sizes, arg_types, nullptr, nullptr);
227 }
228 
229 EXTERN void __tgt_target_data_end_mapper(ident_t *loc, int64_t device_id,
230                                          int32_t arg_num, void **args_base,
231                                          void **args, int64_t *arg_sizes,
232                                          int64_t *arg_types,
233                                          map_var_info_t *arg_names,
234                                          void **arg_mappers) {
235   TIMESCOPE_WITH_IDENT(loc);
236   if (IsOffloadDisabled())
237     return;
238   DP("Entering data end region with %d mappings\n", arg_num);
239 
240   // No devices available?
241   if (device_id == OFFLOAD_DEVICE_DEFAULT) {
242     device_id = omp_get_default_device();
243   }
244 
245   PM->RTLsMtx.lock();
246   size_t DevicesSize = PM->Devices.size();
247   PM->RTLsMtx.unlock();
248   if (DevicesSize <= (size_t)device_id) {
249     DP("Device ID  %" PRId64 " does not have a matching RTL.\n", device_id);
250     HandleTargetOutcome(false, loc);
251     return;
252   }
253 
254   DeviceTy &Device = PM->Devices[device_id];
255   if (!Device.IsInit) {
256     DP("Uninit device: ignore");
257     HandleTargetOutcome(false, loc);
258     return;
259   }
260 
261   if (getInfoLevel() & OMP_INFOTYPE_KERNEL_ARGS)
262     printKernelArguments(loc, device_id, arg_num, arg_sizes, arg_types,
263                          arg_names, "Exiting OpenMP data region");
264 #ifdef OMPTARGET_DEBUG
265   for (int i = 0; i < arg_num; ++i) {
266     DP("Entry %2d: Base=" DPxMOD ", Begin=" DPxMOD ", Size=%" PRId64
267        ", Type=0x%" PRIx64 ", Name=%s\n",
268        i, DPxPTR(args_base[i]), DPxPTR(args[i]), arg_sizes[i], arg_types[i],
269        (arg_names) ? getNameFromMapping(arg_names[i]).c_str() : "unknown");
270   }
271 #endif
272 
273   int rc = targetDataEnd(loc, Device, arg_num, args_base, args, arg_sizes,
274                          arg_types, arg_names, arg_mappers, nullptr);
275   HandleTargetOutcome(rc == OFFLOAD_SUCCESS, loc);
276 }
277 
278 EXTERN void __tgt_target_data_end_nowait_mapper(
279     ident_t *loc, int64_t device_id, int32_t arg_num, void **args_base,
280     void **args, int64_t *arg_sizes, int64_t *arg_types,
281     map_var_info_t *arg_names, void **arg_mappers, int32_t depNum,
282     void *depList, int32_t noAliasDepNum, void *noAliasDepList) {
283   TIMESCOPE_WITH_IDENT(loc);
284   if (depNum + noAliasDepNum > 0)
285     __kmpc_omp_taskwait(loc, __kmpc_global_thread_num(loc));
286 
287   __tgt_target_data_end_mapper(loc, device_id, arg_num, args_base, args,
288                                arg_sizes, arg_types, arg_names, arg_mappers);
289 }
290 
291 EXTERN void __tgt_target_data_update(int64_t device_id, int32_t arg_num,
292                                      void **args_base, void **args,
293                                      int64_t *arg_sizes, int64_t *arg_types) {
294   TIMESCOPE();
295   __tgt_target_data_update_mapper(nullptr, device_id, arg_num, args_base, args,
296                                   arg_sizes, arg_types, nullptr, nullptr);
297 }
298 
299 EXTERN void __tgt_target_data_update_nowait(
300     int64_t device_id, int32_t arg_num, void **args_base, void **args,
301     int64_t *arg_sizes, int64_t *arg_types, int32_t depNum, void *depList,
302     int32_t noAliasDepNum, void *noAliasDepList) {
303   TIMESCOPE();
304   if (depNum + noAliasDepNum > 0)
305     __kmpc_omp_taskwait(NULL, __kmpc_global_thread_num(NULL));
306 
307   __tgt_target_data_update_mapper(nullptr, device_id, arg_num, args_base, args,
308                                   arg_sizes, arg_types, nullptr, nullptr);
309 }
310 
311 EXTERN void __tgt_target_data_update_mapper(ident_t *loc, int64_t device_id,
312                                             int32_t arg_num, void **args_base,
313                                             void **args, int64_t *arg_sizes,
314                                             int64_t *arg_types,
315                                             map_var_info_t *arg_names,
316                                             void **arg_mappers) {
317   TIMESCOPE_WITH_IDENT(loc);
318   if (IsOffloadDisabled())
319     return;
320   DP("Entering data update with %d mappings\n", arg_num);
321 
322   // No devices available?
323   if (device_id == OFFLOAD_DEVICE_DEFAULT) {
324     device_id = omp_get_default_device();
325   }
326 
327   if (CheckDeviceAndCtors(device_id) != OFFLOAD_SUCCESS) {
328     DP("Failed to get device %" PRId64 " ready\n", device_id);
329     HandleTargetOutcome(false, loc);
330     return;
331   }
332 
333   if (getInfoLevel() & OMP_INFOTYPE_KERNEL_ARGS)
334     printKernelArguments(loc, device_id, arg_num, arg_sizes, arg_types,
335                          arg_names, "Updating OpenMP data");
336 
337   DeviceTy &Device = PM->Devices[device_id];
338   int rc = targetDataUpdate(loc, Device, arg_num, args_base, args, arg_sizes,
339                             arg_types, arg_names, arg_mappers);
340   HandleTargetOutcome(rc == OFFLOAD_SUCCESS, loc);
341 }
342 
343 EXTERN void __tgt_target_data_update_nowait_mapper(
344     ident_t *loc, int64_t device_id, int32_t arg_num, void **args_base,
345     void **args, int64_t *arg_sizes, int64_t *arg_types,
346     map_var_info_t *arg_names, void **arg_mappers, int32_t depNum,
347     void *depList, int32_t noAliasDepNum, void *noAliasDepList) {
348   TIMESCOPE_WITH_IDENT(loc);
349   if (depNum + noAliasDepNum > 0)
350     __kmpc_omp_taskwait(loc, __kmpc_global_thread_num(loc));
351 
352   __tgt_target_data_update_mapper(loc, device_id, arg_num, args_base, args,
353                                   arg_sizes, arg_types, arg_names, arg_mappers);
354 }
355 
356 EXTERN int __tgt_target(int64_t device_id, void *host_ptr, int32_t arg_num,
357                         void **args_base, void **args, int64_t *arg_sizes,
358                         int64_t *arg_types) {
359   TIMESCOPE();
360   return __tgt_target_mapper(nullptr, device_id, host_ptr, arg_num, args_base,
361                              args, arg_sizes, arg_types, nullptr, nullptr);
362 }
363 
364 EXTERN int __tgt_target_nowait(int64_t device_id, void *host_ptr,
365                                int32_t arg_num, void **args_base, void **args,
366                                int64_t *arg_sizes, int64_t *arg_types,
367                                int32_t depNum, void *depList,
368                                int32_t noAliasDepNum, void *noAliasDepList) {
369   TIMESCOPE();
370   if (depNum + noAliasDepNum > 0)
371     __kmpc_omp_taskwait(NULL, __kmpc_global_thread_num(NULL));
372 
373   return __tgt_target_mapper(nullptr, device_id, host_ptr, arg_num, args_base,
374                              args, arg_sizes, arg_types, nullptr, nullptr);
375 }
376 
377 EXTERN int __tgt_target_mapper(ident_t *loc, int64_t device_id, void *host_ptr,
378                                int32_t arg_num, void **args_base, void **args,
379                                int64_t *arg_sizes, int64_t *arg_types,
380                                map_var_info_t *arg_names, void **arg_mappers) {
381   TIMESCOPE_WITH_IDENT(loc);
382   if (IsOffloadDisabled())
383     return OFFLOAD_FAIL;
384   DP("Entering target region with entry point " DPxMOD " and device Id %" PRId64
385      "\n",
386      DPxPTR(host_ptr), device_id);
387 
388   if (device_id == OFFLOAD_DEVICE_DEFAULT) {
389     device_id = omp_get_default_device();
390   }
391 
392   if (CheckDeviceAndCtors(device_id) != OFFLOAD_SUCCESS) {
393     REPORT("Failed to get device %" PRId64 " ready\n", device_id);
394     HandleTargetOutcome(false, loc);
395     return OFFLOAD_FAIL;
396   }
397 
398   if (getInfoLevel() & OMP_INFOTYPE_KERNEL_ARGS)
399     printKernelArguments(loc, device_id, arg_num, arg_sizes, arg_types,
400                          arg_names, "Entering OpenMP kernel");
401 #ifdef OMPTARGET_DEBUG
402   for (int i = 0; i < arg_num; ++i) {
403     DP("Entry %2d: Base=" DPxMOD ", Begin=" DPxMOD ", Size=%" PRId64
404        ", Type=0x%" PRIx64 ", Name=%s\n",
405        i, DPxPTR(args_base[i]), DPxPTR(args[i]), arg_sizes[i], arg_types[i],
406        (arg_names) ? getNameFromMapping(arg_names[i]).c_str() : "unknown");
407   }
408 #endif
409 
410   DeviceTy &Device = PM->Devices[device_id];
411   int rc = target(loc, Device, host_ptr, arg_num, args_base, args, arg_sizes,
412                   arg_types, arg_names, arg_mappers, 0, 0, false /*team*/);
413   HandleTargetOutcome(rc == OFFLOAD_SUCCESS, loc);
414   return rc;
415 }
416 
417 EXTERN int __tgt_target_nowait_mapper(
418     ident_t *loc, int64_t device_id, void *host_ptr, int32_t arg_num,
419     void **args_base, void **args, int64_t *arg_sizes, int64_t *arg_types,
420     map_var_info_t *arg_names, void **arg_mappers, int32_t depNum,
421     void *depList, int32_t noAliasDepNum, void *noAliasDepList) {
422   TIMESCOPE_WITH_IDENT(loc);
423   if (depNum + noAliasDepNum > 0)
424     __kmpc_omp_taskwait(loc, __kmpc_global_thread_num(loc));
425 
426   return __tgt_target_mapper(loc, device_id, host_ptr, arg_num, args_base, args,
427                              arg_sizes, arg_types, arg_names, arg_mappers);
428 }
429 
430 EXTERN int __tgt_target_teams(int64_t device_id, void *host_ptr,
431                               int32_t arg_num, void **args_base, void **args,
432                               int64_t *arg_sizes, int64_t *arg_types,
433                               int32_t team_num, int32_t thread_limit) {
434   TIMESCOPE();
435   return __tgt_target_teams_mapper(nullptr, device_id, host_ptr, arg_num,
436                                    args_base, args, arg_sizes, arg_types,
437                                    nullptr, nullptr, team_num, thread_limit);
438 }
439 
440 EXTERN int __tgt_target_teams_nowait(int64_t device_id, void *host_ptr,
441                                      int32_t arg_num, void **args_base,
442                                      void **args, int64_t *arg_sizes,
443                                      int64_t *arg_types, int32_t team_num,
444                                      int32_t thread_limit, int32_t depNum,
445                                      void *depList, int32_t noAliasDepNum,
446                                      void *noAliasDepList) {
447   TIMESCOPE();
448   if (depNum + noAliasDepNum > 0)
449     __kmpc_omp_taskwait(NULL, __kmpc_global_thread_num(NULL));
450 
451   return __tgt_target_teams_mapper(nullptr, device_id, host_ptr, arg_num,
452                                    args_base, args, arg_sizes, arg_types,
453                                    nullptr, nullptr, team_num, thread_limit);
454 }
455 
456 EXTERN int __tgt_target_teams_mapper(ident_t *loc, int64_t device_id,
457                                      void *host_ptr, int32_t arg_num,
458                                      void **args_base, void **args,
459                                      int64_t *arg_sizes, int64_t *arg_types,
460                                      map_var_info_t *arg_names,
461                                      void **arg_mappers, int32_t team_num,
462                                      int32_t thread_limit) {
463   if (IsOffloadDisabled())
464     return OFFLOAD_FAIL;
465   DP("Entering target region with entry point " DPxMOD " and device Id %" PRId64
466      "\n",
467      DPxPTR(host_ptr), device_id);
468 
469   if (device_id == OFFLOAD_DEVICE_DEFAULT) {
470     device_id = omp_get_default_device();
471   }
472 
473   if (CheckDeviceAndCtors(device_id) != OFFLOAD_SUCCESS) {
474     REPORT("Failed to get device %" PRId64 " ready\n", device_id);
475     HandleTargetOutcome(false, loc);
476     return OFFLOAD_FAIL;
477   }
478 
479   if (getInfoLevel() & OMP_INFOTYPE_KERNEL_ARGS)
480     printKernelArguments(loc, device_id, arg_num, arg_sizes, arg_types,
481                          arg_names, "Entering OpenMP kernel");
482 #ifdef OMPTARGET_DEBUG
483   for (int i = 0; i < arg_num; ++i) {
484     DP("Entry %2d: Base=" DPxMOD ", Begin=" DPxMOD ", Size=%" PRId64
485        ", Type=0x%" PRIx64 ", Name=%s\n",
486        i, DPxPTR(args_base[i]), DPxPTR(args[i]), arg_sizes[i], arg_types[i],
487        (arg_names) ? getNameFromMapping(arg_names[i]).c_str() : "unknown");
488   }
489 #endif
490 
491   DeviceTy &Device = PM->Devices[device_id];
492   int rc = target(loc, Device, host_ptr, arg_num, args_base, args, arg_sizes,
493                   arg_types, arg_names, arg_mappers, team_num, thread_limit,
494                   true /*team*/);
495   HandleTargetOutcome(rc == OFFLOAD_SUCCESS, loc);
496   return rc;
497 }
498 
499 EXTERN int __tgt_target_teams_nowait_mapper(
500     ident_t *loc, int64_t device_id, void *host_ptr, int32_t arg_num,
501     void **args_base, void **args, int64_t *arg_sizes, int64_t *arg_types,
502     map_var_info_t *arg_names, void **arg_mappers, int32_t team_num,
503     int32_t thread_limit, int32_t depNum, void *depList, int32_t noAliasDepNum,
504     void *noAliasDepList) {
505   TIMESCOPE_WITH_IDENT(loc);
506   if (depNum + noAliasDepNum > 0)
507     __kmpc_omp_taskwait(loc, __kmpc_global_thread_num(loc));
508 
509   return __tgt_target_teams_mapper(loc, device_id, host_ptr, arg_num, args_base,
510                                    args, arg_sizes, arg_types, arg_names,
511                                    arg_mappers, team_num, thread_limit);
512 }
513 
514 // Get the current number of components for a user-defined mapper.
515 EXTERN int64_t __tgt_mapper_num_components(void *rt_mapper_handle) {
516   TIMESCOPE();
517   auto *MapperComponentsPtr = (struct MapperComponentsTy *)rt_mapper_handle;
518   int64_t size = MapperComponentsPtr->Components.size();
519   DP("__tgt_mapper_num_components(Handle=" DPxMOD ") returns %" PRId64 "\n",
520      DPxPTR(rt_mapper_handle), size);
521   return size;
522 }
523 
524 // Push back one component for a user-defined mapper.
525 EXTERN void __tgt_push_mapper_component(void *rt_mapper_handle, void *base,
526                                         void *begin, int64_t size, int64_t type,
527                                         void *name) {
528   TIMESCOPE();
529   DP("__tgt_push_mapper_component(Handle=" DPxMOD
530      ") adds an entry (Base=" DPxMOD ", Begin=" DPxMOD ", Size=%" PRId64
531      ", Type=0x%" PRIx64 ", Name=%s).\n",
532      DPxPTR(rt_mapper_handle), DPxPTR(base), DPxPTR(begin), size, type,
533      (name) ? getNameFromMapping(name).c_str() : "unknown");
534   auto *MapperComponentsPtr = (struct MapperComponentsTy *)rt_mapper_handle;
535   MapperComponentsPtr->Components.push_back(
536       MapComponentInfoTy(base, begin, size, type, name));
537 }
538 
539 EXTERN void __kmpc_push_target_tripcount(ident_t *loc, int64_t device_id,
540                                          uint64_t loop_tripcount) {
541   TIMESCOPE_WITH_IDENT(loc);
542   if (IsOffloadDisabled())
543     return;
544 
545   if (device_id == OFFLOAD_DEVICE_DEFAULT) {
546     device_id = omp_get_default_device();
547   }
548 
549   if (CheckDeviceAndCtors(device_id) != OFFLOAD_SUCCESS) {
550     DP("Failed to get device %" PRId64 " ready\n", device_id);
551     HandleTargetOutcome(false, loc);
552     return;
553   }
554 
555   DP("__kmpc_push_target_tripcount(%" PRId64 ", %" PRIu64 ")\n", device_id,
556      loop_tripcount);
557   PM->TblMapMtx.lock();
558   PM->Devices[device_id].LoopTripCnt.emplace(__kmpc_global_thread_num(NULL),
559                                              loop_tripcount);
560   PM->TblMapMtx.unlock();
561 }
562