1274958Sdim//===----- CGOpenMPRuntime.h - Interface to OpenMP Runtimes -----*- C++ -*-===//
2274958Sdim//
3274958Sdim//                     The LLVM Compiler Infrastructure
4274958Sdim//
5274958Sdim// This file is distributed under the University of Illinois Open Source
6274958Sdim// License. See LICENSE.TXT for details.
7274958Sdim//
8274958Sdim//===----------------------------------------------------------------------===//
9274958Sdim//
10274958Sdim// This provides a class for OpenMP runtime code generation.
11274958Sdim//
12274958Sdim//===----------------------------------------------------------------------===//
13274958Sdim
14280031Sdim#ifndef LLVM_CLANG_LIB_CODEGEN_CGOPENMPRUNTIME_H
15280031Sdim#define LLVM_CLANG_LIB_CODEGEN_CGOPENMPRUNTIME_H
16274958Sdim
17288943Sdim#include "clang/AST/Type.h"
18280031Sdim#include "clang/Basic/OpenMPKinds.h"
19280031Sdim#include "clang/Basic/SourceLocation.h"
20274958Sdim#include "llvm/ADT/DenseMap.h"
21280031Sdim#include "llvm/ADT/DenseSet.h"
22280031Sdim#include "llvm/ADT/StringMap.h"
23280031Sdim#include "llvm/IR/ValueHandle.h"
24274958Sdim
25274958Sdimnamespace llvm {
26280031Sdimclass ArrayType;
27274958Sdimclass Constant;
28274958Sdimclass Function;
29274958Sdimclass FunctionType;
30280031Sdimclass GlobalVariable;
31274958Sdimclass StructType;
32274958Sdimclass Type;
33274958Sdimclass Value;
34274958Sdim} // namespace llvm
35274958Sdim
36274958Sdimnamespace clang {
37280031Sdimclass Expr;
38296417Sdimclass GlobalDecl;
39280031Sdimclass OMPExecutableDirective;
40280031Sdimclass VarDecl;
41274958Sdim
42274958Sdimnamespace CodeGen {
43296417Sdimclass Address;
44274958Sdimclass CodeGenFunction;
45274958Sdimclass CodeGenModule;
46274958Sdim
47288943Sdimtypedef llvm::function_ref<void(CodeGenFunction &)> RegionCodeGenTy;
48288943Sdim
49274958Sdimclass CGOpenMPRuntime {
50280031Sdimprivate:
51280031Sdim  enum OpenMPRTLFunction {
52280031Sdim    /// \brief Call to void __kmpc_fork_call(ident_t *loc, kmp_int32 argc,
53280031Sdim    /// kmpc_micro microtask, ...);
54280031Sdim    OMPRTL__kmpc_fork_call,
55280031Sdim    /// \brief Call to void *__kmpc_threadprivate_cached(ident_t *loc,
56280031Sdim    /// kmp_int32 global_tid, void *data, size_t size, void ***cache);
57280031Sdim    OMPRTL__kmpc_threadprivate_cached,
58280031Sdim    /// \brief Call to void __kmpc_threadprivate_register( ident_t *,
59280031Sdim    /// void *data, kmpc_ctor ctor, kmpc_cctor cctor, kmpc_dtor dtor);
60280031Sdim    OMPRTL__kmpc_threadprivate_register,
61280031Sdim    // Call to __kmpc_int32 kmpc_global_thread_num(ident_t *loc);
62280031Sdim    OMPRTL__kmpc_global_thread_num,
63280031Sdim    // Call to void __kmpc_critical(ident_t *loc, kmp_int32 global_tid,
64280031Sdim    // kmp_critical_name *crit);
65280031Sdim    OMPRTL__kmpc_critical,
66296417Sdim    // Call to void __kmpc_critical_with_hint(ident_t *loc, kmp_int32
67296417Sdim    // global_tid, kmp_critical_name *crit, uintptr_t hint);
68296417Sdim    OMPRTL__kmpc_critical_with_hint,
69280031Sdim    // Call to void __kmpc_end_critical(ident_t *loc, kmp_int32 global_tid,
70280031Sdim    // kmp_critical_name *crit);
71280031Sdim    OMPRTL__kmpc_end_critical,
72280031Sdim    // Call to kmp_int32 __kmpc_cancel_barrier(ident_t *loc, kmp_int32
73280031Sdim    // global_tid);
74280031Sdim    OMPRTL__kmpc_cancel_barrier,
75288943Sdim    // Call to void __kmpc_barrier(ident_t *loc, kmp_int32 global_tid);
76288943Sdim    OMPRTL__kmpc_barrier,
77288943Sdim    // Call to void __kmpc_for_static_fini(ident_t *loc, kmp_int32 global_tid);
78280031Sdim    OMPRTL__kmpc_for_static_fini,
79280031Sdim    // Call to void __kmpc_serialized_parallel(ident_t *loc, kmp_int32
80280031Sdim    // global_tid);
81280031Sdim    OMPRTL__kmpc_serialized_parallel,
82280031Sdim    // Call to void __kmpc_end_serialized_parallel(ident_t *loc, kmp_int32
83280031Sdim    // global_tid);
84280031Sdim    OMPRTL__kmpc_end_serialized_parallel,
85280031Sdim    // Call to void __kmpc_push_num_threads(ident_t *loc, kmp_int32 global_tid,
86280031Sdim    // kmp_int32 num_threads);
87280031Sdim    OMPRTL__kmpc_push_num_threads,
88288943Sdim    // Call to void __kmpc_flush(ident_t *loc);
89280031Sdim    OMPRTL__kmpc_flush,
90280031Sdim    // Call to kmp_int32 __kmpc_master(ident_t *, kmp_int32 global_tid);
91280031Sdim    OMPRTL__kmpc_master,
92280031Sdim    // Call to void __kmpc_end_master(ident_t *, kmp_int32 global_tid);
93280031Sdim    OMPRTL__kmpc_end_master,
94288943Sdim    // Call to kmp_int32 __kmpc_omp_taskyield(ident_t *, kmp_int32 global_tid,
95288943Sdim    // int end_part);
96288943Sdim    OMPRTL__kmpc_omp_taskyield,
97288943Sdim    // Call to kmp_int32 __kmpc_single(ident_t *, kmp_int32 global_tid);
98288943Sdim    OMPRTL__kmpc_single,
99288943Sdim    // Call to void __kmpc_end_single(ident_t *, kmp_int32 global_tid);
100288943Sdim    OMPRTL__kmpc_end_single,
101288943Sdim    // Call to kmp_task_t * __kmpc_omp_task_alloc(ident_t *, kmp_int32 gtid,
102288943Sdim    // kmp_int32 flags, size_t sizeof_kmp_task_t, size_t sizeof_shareds,
103288943Sdim    // kmp_routine_entry_t *task_entry);
104288943Sdim    OMPRTL__kmpc_omp_task_alloc,
105288943Sdim    // Call to kmp_int32 __kmpc_omp_task(ident_t *, kmp_int32 gtid, kmp_task_t *
106288943Sdim    // new_task);
107288943Sdim    OMPRTL__kmpc_omp_task,
108288943Sdim    // Call to void __kmpc_copyprivate(ident_t *loc, kmp_int32 global_tid,
109288943Sdim    // size_t cpy_size, void *cpy_data, void(*cpy_func)(void *, void *),
110288943Sdim    // kmp_int32 didit);
111288943Sdim    OMPRTL__kmpc_copyprivate,
112288943Sdim    // Call to kmp_int32 __kmpc_reduce(ident_t *loc, kmp_int32 global_tid,
113288943Sdim    // kmp_int32 num_vars, size_t reduce_size, void *reduce_data, void
114288943Sdim    // (*reduce_func)(void *lhs_data, void *rhs_data), kmp_critical_name *lck);
115288943Sdim    OMPRTL__kmpc_reduce,
116288943Sdim    // Call to kmp_int32 __kmpc_reduce_nowait(ident_t *loc, kmp_int32
117288943Sdim    // global_tid, kmp_int32 num_vars, size_t reduce_size, void *reduce_data,
118288943Sdim    // void (*reduce_func)(void *lhs_data, void *rhs_data), kmp_critical_name
119288943Sdim    // *lck);
120288943Sdim    OMPRTL__kmpc_reduce_nowait,
121288943Sdim    // Call to void __kmpc_end_reduce(ident_t *loc, kmp_int32 global_tid,
122288943Sdim    // kmp_critical_name *lck);
123288943Sdim    OMPRTL__kmpc_end_reduce,
124288943Sdim    // Call to void __kmpc_end_reduce_nowait(ident_t *loc, kmp_int32 global_tid,
125288943Sdim    // kmp_critical_name *lck);
126288943Sdim    OMPRTL__kmpc_end_reduce_nowait,
127288943Sdim    // Call to void __kmpc_omp_task_begin_if0(ident_t *, kmp_int32 gtid,
128288943Sdim    // kmp_task_t * new_task);
129288943Sdim    OMPRTL__kmpc_omp_task_begin_if0,
130288943Sdim    // Call to void __kmpc_omp_task_complete_if0(ident_t *, kmp_int32 gtid,
131288943Sdim    // kmp_task_t * new_task);
132288943Sdim    OMPRTL__kmpc_omp_task_complete_if0,
133288943Sdim    // Call to void __kmpc_ordered(ident_t *loc, kmp_int32 global_tid);
134288943Sdim    OMPRTL__kmpc_ordered,
135288943Sdim    // Call to void __kmpc_end_ordered(ident_t *loc, kmp_int32 global_tid);
136288943Sdim    OMPRTL__kmpc_end_ordered,
137288943Sdim    // Call to kmp_int32 __kmpc_omp_taskwait(ident_t *loc, kmp_int32
138288943Sdim    // global_tid);
139288943Sdim    OMPRTL__kmpc_omp_taskwait,
140288943Sdim    // Call to void __kmpc_taskgroup(ident_t *loc, kmp_int32 global_tid);
141288943Sdim    OMPRTL__kmpc_taskgroup,
142288943Sdim    // Call to void __kmpc_end_taskgroup(ident_t *loc, kmp_int32 global_tid);
143288943Sdim    OMPRTL__kmpc_end_taskgroup,
144288943Sdim    // Call to void __kmpc_push_proc_bind(ident_t *loc, kmp_int32 global_tid,
145288943Sdim    // int proc_bind);
146288943Sdim    OMPRTL__kmpc_push_proc_bind,
147288943Sdim    // Call to kmp_int32 __kmpc_omp_task_with_deps(ident_t *loc_ref, kmp_int32
148288943Sdim    // gtid, kmp_task_t * new_task, kmp_int32 ndeps, kmp_depend_info_t
149288943Sdim    // *dep_list, kmp_int32 ndeps_noalias, kmp_depend_info_t *noalias_dep_list);
150288943Sdim    OMPRTL__kmpc_omp_task_with_deps,
151288943Sdim    // Call to void __kmpc_omp_wait_deps(ident_t *loc_ref, kmp_int32
152288943Sdim    // gtid, kmp_int32 ndeps, kmp_depend_info_t *dep_list, kmp_int32
153288943Sdim    // ndeps_noalias, kmp_depend_info_t *noalias_dep_list);
154288943Sdim    OMPRTL__kmpc_omp_wait_deps,
155288943Sdim    // Call to kmp_int32 __kmpc_cancellationpoint(ident_t *loc, kmp_int32
156288943Sdim    // global_tid, kmp_int32 cncl_kind);
157288943Sdim    OMPRTL__kmpc_cancellationpoint,
158288943Sdim    // Call to kmp_int32 __kmpc_cancel(ident_t *loc, kmp_int32 global_tid,
159288943Sdim    // kmp_int32 cncl_kind);
160288943Sdim    OMPRTL__kmpc_cancel,
161296417Sdim
162296417Sdim    //
163296417Sdim    // Offloading related calls
164296417Sdim    //
165296417Sdim    // Call to int32_t __tgt_target(int32_t device_id, void *host_ptr, int32_t
166296417Sdim    // arg_num, void** args_base, void **args, size_t *arg_sizes, int32_t
167296417Sdim    // *arg_types);
168296417Sdim    OMPRTL__tgt_target,
169296417Sdim    // Call to void __tgt_register_lib(__tgt_bin_desc *desc);
170296417Sdim    OMPRTL__tgt_register_lib,
171296417Sdim    // Call to void __tgt_unregister_lib(__tgt_bin_desc *desc);
172296417Sdim    OMPRTL__tgt_unregister_lib,
173280031Sdim  };
174280031Sdim
175274958Sdim  /// \brief Values for bit flags used in the ident_t to describe the fields.
176274958Sdim  /// All enumeric elements are named and described in accordance with the code
177274958Sdim  /// from http://llvm.org/svn/llvm-project/openmp/trunk/runtime/src/kmp.h
178274958Sdim  enum OpenMPLocationFlags {
179274958Sdim    /// \brief Use trampoline for internal microtask.
180274958Sdim    OMP_IDENT_IMD = 0x01,
181274958Sdim    /// \brief Use c-style ident structure.
182274958Sdim    OMP_IDENT_KMPC = 0x02,
183274958Sdim    /// \brief Atomic reduction option for kmpc_reduce.
184274958Sdim    OMP_ATOMIC_REDUCE = 0x10,
185274958Sdim    /// \brief Explicit 'barrier' directive.
186274958Sdim    OMP_IDENT_BARRIER_EXPL = 0x20,
187274958Sdim    /// \brief Implicit barrier in code.
188274958Sdim    OMP_IDENT_BARRIER_IMPL = 0x40,
189274958Sdim    /// \brief Implicit barrier in 'for' directive.
190274958Sdim    OMP_IDENT_BARRIER_IMPL_FOR = 0x40,
191274958Sdim    /// \brief Implicit barrier in 'sections' directive.
192274958Sdim    OMP_IDENT_BARRIER_IMPL_SECTIONS = 0xC0,
193274958Sdim    /// \brief Implicit barrier in 'single' directive.
194274958Sdim    OMP_IDENT_BARRIER_IMPL_SINGLE = 0x140
195274958Sdim  };
196274958Sdim  CodeGenModule &CGM;
197274958Sdim  /// \brief Default const ident_t object used for initialization of all other
198274958Sdim  /// ident_t objects.
199274958Sdim  llvm::Constant *DefaultOpenMPPSource;
200280031Sdim  /// \brief Map of flags and corresponding default locations.
201274958Sdim  typedef llvm::DenseMap<unsigned, llvm::Value *> OpenMPDefaultLocMapTy;
202274958Sdim  OpenMPDefaultLocMapTy OpenMPDefaultLocMap;
203296417Sdim  Address getOrCreateDefaultLocation(OpenMPLocationFlags Flags);
204296417Sdim
205296417Sdimpublic:
206274958Sdim  /// \brief Describes ident structure that describes a source location.
207274958Sdim  /// All descriptions are taken from
208274958Sdim  /// http://llvm.org/svn/llvm-project/openmp/trunk/runtime/src/kmp.h
209274958Sdim  /// Original structure:
210274958Sdim  /// typedef struct ident {
211274958Sdim  ///    kmp_int32 reserved_1;   /**<  might be used in Fortran;
212274958Sdim  ///                                  see above  */
213274958Sdim  ///    kmp_int32 flags;        /**<  also f.flags; KMP_IDENT_xxx flags;
214274958Sdim  ///                                  KMP_IDENT_KMPC identifies this union
215274958Sdim  ///                                  member  */
216274958Sdim  ///    kmp_int32 reserved_2;   /**<  not really used in Fortran any more;
217274958Sdim  ///                                  see above */
218274958Sdim  ///#if USE_ITT_BUILD
219274958Sdim  ///                            /*  but currently used for storing
220274958Sdim  ///                                region-specific ITT */
221274958Sdim  ///                            /*  contextual information. */
222274958Sdim  ///#endif /* USE_ITT_BUILD */
223274958Sdim  ///    kmp_int32 reserved_3;   /**< source[4] in Fortran, do not use for
224274958Sdim  ///                                 C++  */
225274958Sdim  ///    char const *psource;    /**< String describing the source location.
226274958Sdim  ///                            The string is composed of semi-colon separated
227274958Sdim  //                             fields which describe the source file,
228274958Sdim  ///                            the function and a pair of line numbers that
229274958Sdim  ///                            delimit the construct.
230274958Sdim  ///                             */
231274958Sdim  /// } ident_t;
232274958Sdim  enum IdentFieldIndex {
233274958Sdim    /// \brief might be used in Fortran
234274958Sdim    IdentField_Reserved_1,
235274958Sdim    /// \brief OMP_IDENT_xxx flags; OMP_IDENT_KMPC identifies this union member.
236274958Sdim    IdentField_Flags,
237274958Sdim    /// \brief Not really used in Fortran any more
238274958Sdim    IdentField_Reserved_2,
239274958Sdim    /// \brief Source[4] in Fortran, do not use for C++
240274958Sdim    IdentField_Reserved_3,
241274958Sdim    /// \brief String describing the source location. The string is composed of
242274958Sdim    /// semi-colon separated fields which describe the source file, the function
243274958Sdim    /// and a pair of line numbers that delimit the construct.
244274958Sdim    IdentField_PSource
245274958Sdim  };
246296417Sdimprivate:
247274958Sdim  llvm::StructType *IdentTy;
248280031Sdim  /// \brief Map for SourceLocation and OpenMP runtime library debug locations.
249274958Sdim  typedef llvm::DenseMap<unsigned, llvm::Value *> OpenMPDebugLocMapTy;
250274958Sdim  OpenMPDebugLocMapTy OpenMPDebugLocMap;
251274958Sdim  /// \brief The type for a microtask which gets passed to __kmpc_fork_call().
252274958Sdim  /// Original representation is:
253274958Sdim  /// typedef void (kmpc_micro)(kmp_int32 global_tid, kmp_int32 bound_tid,...);
254274958Sdim  llvm::FunctionType *Kmpc_MicroTy;
255280031Sdim  /// \brief Stores debug location and ThreadID for the function.
256280031Sdim  struct DebugLocThreadIdTy {
257280031Sdim    llvm::Value *DebugLoc;
258280031Sdim    llvm::Value *ThreadID;
259280031Sdim  };
260280031Sdim  /// \brief Map of local debug location, ThreadId and functions.
261280031Sdim  typedef llvm::DenseMap<llvm::Function *, DebugLocThreadIdTy>
262280031Sdim      OpenMPLocThreadIDMapTy;
263280031Sdim  OpenMPLocThreadIDMapTy OpenMPLocThreadIDMap;
264280031Sdim  /// \brief Type kmp_critical_name, originally defined as typedef kmp_int32
265280031Sdim  /// kmp_critical_name[8];
266280031Sdim  llvm::ArrayType *KmpCriticalNameTy;
267280031Sdim  /// \brief An ordered map of auto-generated variables to their unique names.
268280031Sdim  /// It stores variables with the following names: 1) ".gomp_critical_user_" +
269280031Sdim  /// <critical_section_name> + ".var" for "omp critical" directives; 2)
270280031Sdim  /// <mangled_name_for_global_var> + ".cache." for cache for threadprivate
271280031Sdim  /// variables.
272280031Sdim  llvm::StringMap<llvm::AssertingVH<llvm::Constant>, llvm::BumpPtrAllocator>
273280031Sdim      InternalVars;
274288943Sdim  /// \brief Type typedef kmp_int32 (* kmp_routine_entry_t)(kmp_int32, void *);
275288943Sdim  llvm::Type *KmpRoutineEntryPtrTy;
276288943Sdim  QualType KmpRoutineEntryPtrQTy;
277288943Sdim  /// \brief Type typedef struct kmp_task {
278288943Sdim  ///    void *              shareds; /**< pointer to block of pointers to
279288943Sdim  ///    shared vars   */
280288943Sdim  ///    kmp_routine_entry_t routine; /**< pointer to routine to call for
281288943Sdim  ///    executing task */
282288943Sdim  ///    kmp_int32           part_id; /**< part id for the task */
283288943Sdim  ///    kmp_routine_entry_t destructors; /* pointer to function to invoke
284288943Sdim  ///    deconstructors of firstprivate C++ objects */
285288943Sdim  /// } kmp_task_t;
286288943Sdim  QualType KmpTaskTQTy;
287288943Sdim  /// \brief Type typedef struct kmp_depend_info {
288288943Sdim  ///    kmp_intptr_t               base_addr;
289288943Sdim  ///    size_t                     len;
290288943Sdim  ///    struct {
291288943Sdim  ///             bool                   in:1;
292288943Sdim  ///             bool                   out:1;
293288943Sdim  ///    } flags;
294288943Sdim  /// } kmp_depend_info_t;
295288943Sdim  QualType KmpDependInfoTy;
296296417Sdim  /// \brief Type struct __tgt_offload_entry{
297296417Sdim  ///   void      *addr;       // Pointer to the offload entry info.
298296417Sdim  ///                          // (function or global)
299296417Sdim  ///   char      *name;       // Name of the function or global.
300296417Sdim  ///   size_t     size;       // Size of the entry info (0 if it a function).
301296417Sdim  /// };
302296417Sdim  QualType TgtOffloadEntryQTy;
303296417Sdim  /// struct __tgt_device_image{
304296417Sdim  /// void   *ImageStart;       // Pointer to the target code start.
305296417Sdim  /// void   *ImageEnd;         // Pointer to the target code end.
306296417Sdim  /// // We also add the host entries to the device image, as it may be useful
307296417Sdim  /// // for the target runtime to have access to that information.
308296417Sdim  /// __tgt_offload_entry  *EntriesBegin;   // Begin of the table with all
309296417Sdim  ///                                       // the entries.
310296417Sdim  /// __tgt_offload_entry  *EntriesEnd;     // End of the table with all the
311296417Sdim  ///                                       // entries (non inclusive).
312296417Sdim  /// };
313296417Sdim  QualType TgtDeviceImageQTy;
314296417Sdim  /// struct __tgt_bin_desc{
315296417Sdim  ///   int32_t              NumDevices;      // Number of devices supported.
316296417Sdim  ///   __tgt_device_image   *DeviceImages;   // Arrays of device images
317296417Sdim  ///                                         // (one per device).
318296417Sdim  ///   __tgt_offload_entry  *EntriesBegin;   // Begin of the table with all the
319296417Sdim  ///                                         // entries.
320296417Sdim  ///   __tgt_offload_entry  *EntriesEnd;     // End of the table with all the
321296417Sdim  ///                                         // entries (non inclusive).
322296417Sdim  /// };
323296417Sdim  QualType TgtBinaryDescriptorQTy;
324296417Sdim  /// \brief Entity that registers the offloading constants that were emitted so
325296417Sdim  /// far.
326296417Sdim  class OffloadEntriesInfoManagerTy {
327296417Sdim    CodeGenModule &CGM;
328274958Sdim
329296417Sdim    /// \brief Number of entries registered so far.
330296417Sdim    unsigned OffloadingEntriesNum;
331288943Sdim
332296417Sdim  public:
333296417Sdim    /// \brief Base class of the entries info.
334296417Sdim    class OffloadEntryInfo {
335296417Sdim    public:
336296417Sdim      /// \brief Kind of a given entry. Currently, only target regions are
337296417Sdim      /// supported.
338296417Sdim      enum OffloadingEntryInfoKinds : unsigned {
339296417Sdim        // Entry is a target region.
340296417Sdim        OFFLOAD_ENTRY_INFO_TARGET_REGION = 0,
341296417Sdim        // Invalid entry info.
342296417Sdim        OFFLOAD_ENTRY_INFO_INVALID = ~0u
343296417Sdim      };
344296417Sdim
345296417Sdim      OffloadEntryInfo() : Order(~0u), Kind(OFFLOAD_ENTRY_INFO_INVALID) {}
346296417Sdim      explicit OffloadEntryInfo(OffloadingEntryInfoKinds Kind, unsigned Order)
347296417Sdim          : Order(Order), Kind(Kind) {}
348296417Sdim
349296417Sdim      bool isValid() const { return Order != ~0u; }
350296417Sdim      unsigned getOrder() const { return Order; }
351296417Sdim      OffloadingEntryInfoKinds getKind() const { return Kind; }
352296417Sdim      static bool classof(const OffloadEntryInfo *Info) { return true; }
353296417Sdim
354296417Sdim    protected:
355296417Sdim      // \brief Order this entry was emitted.
356296417Sdim      unsigned Order;
357296417Sdim
358296417Sdim      OffloadingEntryInfoKinds Kind;
359296417Sdim    };
360296417Sdim
361296417Sdim    /// \brief Return true if a there are no entries defined.
362296417Sdim    bool empty() const;
363296417Sdim    /// \brief Return number of entries defined so far.
364296417Sdim    unsigned size() const { return OffloadingEntriesNum; }
365296417Sdim    OffloadEntriesInfoManagerTy(CodeGenModule &CGM)
366296417Sdim        : CGM(CGM), OffloadingEntriesNum(0) {}
367296417Sdim
368296417Sdim    ///
369296417Sdim    /// Target region entries related.
370296417Sdim    ///
371296417Sdim    /// \brief Target region entries info.
372296417Sdim    class OffloadEntryInfoTargetRegion : public OffloadEntryInfo {
373296417Sdim      // \brief Address of the entity that has to be mapped for offloading.
374296417Sdim      llvm::Constant *Addr;
375296417Sdim      // \brief Address that can be used as the ID of the entry.
376296417Sdim      llvm::Constant *ID;
377296417Sdim
378296417Sdim    public:
379296417Sdim      OffloadEntryInfoTargetRegion()
380296417Sdim          : OffloadEntryInfo(OFFLOAD_ENTRY_INFO_TARGET_REGION, ~0u),
381296417Sdim            Addr(nullptr), ID(nullptr) {}
382296417Sdim      explicit OffloadEntryInfoTargetRegion(unsigned Order,
383296417Sdim                                            llvm::Constant *Addr,
384296417Sdim                                            llvm::Constant *ID)
385296417Sdim          : OffloadEntryInfo(OFFLOAD_ENTRY_INFO_TARGET_REGION, Order),
386296417Sdim            Addr(Addr), ID(ID) {}
387296417Sdim
388296417Sdim      llvm::Constant *getAddress() const { return Addr; }
389296417Sdim      llvm::Constant *getID() const { return ID; }
390296417Sdim      void setAddress(llvm::Constant *V) {
391296417Sdim        assert(!Addr && "Address as been set before!");
392296417Sdim        Addr = V;
393296417Sdim      }
394296417Sdim      void setID(llvm::Constant *V) {
395296417Sdim        assert(!ID && "ID as been set before!");
396296417Sdim        ID = V;
397296417Sdim      }
398296417Sdim      static bool classof(const OffloadEntryInfo *Info) {
399296417Sdim        return Info->getKind() == OFFLOAD_ENTRY_INFO_TARGET_REGION;
400296417Sdim      }
401296417Sdim    };
402296417Sdim    /// \brief Initialize target region entry.
403296417Sdim    void initializeTargetRegionEntryInfo(unsigned DeviceID, unsigned FileID,
404296417Sdim                                         StringRef ParentName, unsigned LineNum,
405296417Sdim                                         unsigned ColNum, unsigned Order);
406296417Sdim    /// \brief Register target region entry.
407296417Sdim    void registerTargetRegionEntryInfo(unsigned DeviceID, unsigned FileID,
408296417Sdim                                       StringRef ParentName, unsigned LineNum,
409296417Sdim                                       unsigned ColNum, llvm::Constant *Addr,
410296417Sdim                                       llvm::Constant *ID);
411296417Sdim    /// \brief Return true if a target region entry with the provided
412296417Sdim    /// information exists.
413296417Sdim    bool hasTargetRegionEntryInfo(unsigned DeviceID, unsigned FileID,
414296417Sdim                                  StringRef ParentName, unsigned LineNum,
415296417Sdim                                  unsigned ColNum) const;
416296417Sdim    /// brief Applies action \a Action on all registered entries.
417296417Sdim    typedef llvm::function_ref<void(unsigned, unsigned, StringRef, unsigned,
418296417Sdim                                    unsigned, OffloadEntryInfoTargetRegion &)>
419296417Sdim        OffloadTargetRegionEntryInfoActTy;
420296417Sdim    void actOnTargetRegionEntriesInfo(
421296417Sdim        const OffloadTargetRegionEntryInfoActTy &Action);
422296417Sdim
423296417Sdim  private:
424296417Sdim    // Storage for target region entries kind. The storage is to be indexed by
425296417Sdim    // file ID, device ID, parent function name, lane number, and column number.
426296417Sdim    typedef llvm::DenseMap<unsigned, OffloadEntryInfoTargetRegion>
427296417Sdim        OffloadEntriesTargetRegionPerColumn;
428296417Sdim    typedef llvm::DenseMap<unsigned, OffloadEntriesTargetRegionPerColumn>
429296417Sdim        OffloadEntriesTargetRegionPerLine;
430296417Sdim    typedef llvm::StringMap<OffloadEntriesTargetRegionPerLine>
431296417Sdim        OffloadEntriesTargetRegionPerParentName;
432296417Sdim    typedef llvm::DenseMap<unsigned, OffloadEntriesTargetRegionPerParentName>
433296417Sdim        OffloadEntriesTargetRegionPerFile;
434296417Sdim    typedef llvm::DenseMap<unsigned, OffloadEntriesTargetRegionPerFile>
435296417Sdim        OffloadEntriesTargetRegionPerDevice;
436296417Sdim    typedef OffloadEntriesTargetRegionPerDevice OffloadEntriesTargetRegionTy;
437296417Sdim    OffloadEntriesTargetRegionTy OffloadEntriesTargetRegion;
438296417Sdim  };
439296417Sdim  OffloadEntriesInfoManagerTy OffloadEntriesInfoManager;
440296417Sdim
441296417Sdim  /// \brief Creates and registers offloading binary descriptor for the current
442296417Sdim  /// compilation unit. The function that does the registration is returned.
443296417Sdim  llvm::Function *createOffloadingBinaryDescriptorRegistration();
444296417Sdim
445296417Sdim  /// \brief Creates offloading entry for the provided address \a Addr,
446296417Sdim  /// name \a Name and size \a Size.
447296417Sdim  void createOffloadEntry(llvm::Constant *Addr, StringRef Name, uint64_t Size);
448296417Sdim
449296417Sdim  /// \brief Creates all the offload entries in the current compilation unit
450296417Sdim  /// along with the associated metadata.
451296417Sdim  void createOffloadEntriesAndInfoMetadata();
452296417Sdim
453296417Sdim  /// \brief Loads all the offload entries information from the host IR
454296417Sdim  /// metadata.
455296417Sdim  void loadOffloadInfoMetadata();
456296417Sdim
457296417Sdim  /// \brief Returns __tgt_offload_entry type.
458296417Sdim  QualType getTgtOffloadEntryQTy();
459296417Sdim
460296417Sdim  /// \brief Returns __tgt_device_image type.
461296417Sdim  QualType getTgtDeviceImageQTy();
462296417Sdim
463296417Sdim  /// \brief Returns __tgt_bin_desc type.
464296417Sdim  QualType getTgtBinaryDescriptorQTy();
465296417Sdim
466296417Sdim  /// \brief Start scanning from statement \a S and and emit all target regions
467296417Sdim  /// found along the way.
468296417Sdim  /// \param S Starting statement.
469296417Sdim  /// \param ParentName Name of the function declaration that is being scanned.
470296417Sdim  void scanForTargetRegionsFunctions(const Stmt *S, StringRef ParentName);
471296417Sdim
472288943Sdim  /// \brief Build type kmp_routine_entry_t (if not built yet).
473288943Sdim  void emitKmpRoutineEntryT(QualType KmpInt32Ty);
474288943Sdim
475280031Sdim  /// \brief Emits object of ident_t type with info for source location.
476280031Sdim  /// \param Flags Flags for OpenMP location.
477280031Sdim  ///
478288943Sdim  llvm::Value *emitUpdateLocation(CodeGenFunction &CGF, SourceLocation Loc,
479288943Sdim                                  OpenMPLocationFlags Flags = OMP_IDENT_KMPC);
480280031Sdim
481280031Sdim  /// \brief Returns pointer to ident_t type.
482280031Sdim  llvm::Type *getIdentTyPointerTy();
483280031Sdim
484280031Sdim  /// \brief Returns pointer to kmpc_micro type.
485280031Sdim  llvm::Type *getKmpc_MicroPointerTy();
486280031Sdim
487280031Sdim  /// \brief Returns specified OpenMP runtime function.
488280031Sdim  /// \param Function OpenMP runtime function.
489280031Sdim  /// \return Specified function.
490288943Sdim  llvm::Constant *createRuntimeFunction(OpenMPRTLFunction Function);
491280031Sdim
492288943Sdim  /// \brief Returns __kmpc_for_static_init_* runtime function for the specified
493288943Sdim  /// size \a IVSize and sign \a IVSigned.
494288943Sdim  llvm::Constant *createForStaticInitFunction(unsigned IVSize, bool IVSigned);
495288943Sdim
496288943Sdim  /// \brief Returns __kmpc_dispatch_init_* runtime function for the specified
497288943Sdim  /// size \a IVSize and sign \a IVSigned.
498288943Sdim  llvm::Constant *createDispatchInitFunction(unsigned IVSize, bool IVSigned);
499288943Sdim
500288943Sdim  /// \brief Returns __kmpc_dispatch_next_* runtime function for the specified
501288943Sdim  /// size \a IVSize and sign \a IVSigned.
502288943Sdim  llvm::Constant *createDispatchNextFunction(unsigned IVSize, bool IVSigned);
503288943Sdim
504288943Sdim  /// \brief Returns __kmpc_dispatch_fini_* runtime function for the specified
505288943Sdim  /// size \a IVSize and sign \a IVSigned.
506288943Sdim  llvm::Constant *createDispatchFiniFunction(unsigned IVSize, bool IVSigned);
507288943Sdim
508280031Sdim  /// \brief If the specified mangled name is not in the module, create and
509280031Sdim  /// return threadprivate cache object. This object is a pointer's worth of
510280031Sdim  /// storage that's reserved for use by the OpenMP runtime.
511280031Sdim  /// \param VD Threadprivate variable.
512280031Sdim  /// \return Cache variable for the specified threadprivate.
513280031Sdim  llvm::Constant *getOrCreateThreadPrivateCache(const VarDecl *VD);
514280031Sdim
515280031Sdim  /// \brief Emits address of the word in a memory where current thread id is
516280031Sdim  /// stored.
517296417Sdim  virtual Address emitThreadIDAddress(CodeGenFunction &CGF, SourceLocation Loc);
518280031Sdim
519280031Sdim  /// \brief Gets thread id value for the current thread.
520280031Sdim  ///
521288943Sdim  llvm::Value *getThreadID(CodeGenFunction &CGF, SourceLocation Loc);
522280031Sdim
523280031Sdim  /// \brief Gets (if variable with the given name already exist) or creates
524280031Sdim  /// internal global variable with the specified Name. The created variable has
525280031Sdim  /// linkage CommonLinkage by default and is initialized by null value.
526280031Sdim  /// \param Ty Type of the global variable. If it is exist already the type
527280031Sdim  /// must be the same.
528280031Sdim  /// \param Name Name of the variable.
529288943Sdim  llvm::Constant *getOrCreateInternalVariable(llvm::Type *Ty,
530280031Sdim                                              const llvm::Twine &Name);
531280031Sdim
532280031Sdim  /// \brief Set of threadprivate variables with the generated initializer.
533280031Sdim  llvm::DenseSet<const VarDecl *> ThreadPrivateWithDefinition;
534280031Sdim
535280031Sdim  /// \brief Emits initialization code for the threadprivate variables.
536280031Sdim  /// \param VDAddr Address of the global variable \a VD.
537280031Sdim  /// \param Ctor Pointer to a global init function for \a VD.
538280031Sdim  /// \param CopyCtor Pointer to a global copy function for \a VD.
539280031Sdim  /// \param Dtor Pointer to a global destructor function for \a VD.
540280031Sdim  /// \param Loc Location of threadprivate declaration.
541296417Sdim  void emitThreadPrivateVarInit(CodeGenFunction &CGF, Address VDAddr,
542288943Sdim                                llvm::Value *Ctor, llvm::Value *CopyCtor,
543288943Sdim                                llvm::Value *Dtor, SourceLocation Loc);
544280031Sdim
545280031Sdim  /// \brief Returns corresponding lock object for the specified critical region
546280031Sdim  /// name. If the lock object does not exist it is created, otherwise the
547280031Sdim  /// reference to the existing copy is returned.
548280031Sdim  /// \param CriticalName Name of the critical region.
549280031Sdim  ///
550288943Sdim  llvm::Value *getCriticalRegionLock(StringRef CriticalName);
551280031Sdim
552274958Sdimpublic:
553274958Sdim  explicit CGOpenMPRuntime(CodeGenModule &CGM);
554280031Sdim  virtual ~CGOpenMPRuntime() {}
555288943Sdim  virtual void clear();
556274958Sdim
557288943Sdim  /// \brief Emits outlined function for the specified OpenMP parallel directive
558288943Sdim  /// \a D. This outlined function has type void(*)(kmp_int32 *ThreadID,
559288943Sdim  /// kmp_int32 BoundID, struct context_vars*).
560280031Sdim  /// \param D OpenMP directive.
561280031Sdim  /// \param ThreadIDVar Variable for thread id in the current OpenMP region.
562288943Sdim  /// \param InnermostKind Kind of innermost directive (for simple directives it
563288943Sdim  /// is a directive itself, for combined - its innermost directive).
564288943Sdim  /// \param CodeGen Code generation sequence for the \a D directive.
565288943Sdim  virtual llvm::Value *emitParallelOutlinedFunction(
566288943Sdim      const OMPExecutableDirective &D, const VarDecl *ThreadIDVar,
567288943Sdim      OpenMPDirectiveKind InnermostKind, const RegionCodeGenTy &CodeGen);
568288943Sdim
569288943Sdim  /// \brief Emits outlined function for the OpenMP task directive \a D. This
570288943Sdim  /// outlined function has type void(*)(kmp_int32 ThreadID, kmp_int32
571288943Sdim  /// PartID, struct context_vars*).
572288943Sdim  /// \param D OpenMP directive.
573288943Sdim  /// \param ThreadIDVar Variable for thread id in the current OpenMP region.
574288943Sdim  /// \param InnermostKind Kind of innermost directive (for simple directives it
575288943Sdim  /// is a directive itself, for combined - its innermost directive).
576288943Sdim  /// \param CodeGen Code generation sequence for the \a D directive.
577280031Sdim  ///
578288943Sdim  virtual llvm::Value *emitTaskOutlinedFunction(
579288943Sdim      const OMPExecutableDirective &D, const VarDecl *ThreadIDVar,
580288943Sdim      OpenMPDirectiveKind InnermostKind, const RegionCodeGenTy &CodeGen);
581280031Sdim
582274958Sdim  /// \brief Cleans up references to the objects in finished function.
583274958Sdim  ///
584288943Sdim  void functionFinished(CodeGenFunction &CGF);
585274958Sdim
586288943Sdim  /// \brief Emits code for parallel or serial call of the \a OutlinedFn with
587288943Sdim  /// variables captured in a record which address is stored in \a
588288943Sdim  /// CapturedStruct.
589280031Sdim  /// \param OutlinedFn Outlined function to be run in parallel threads. Type of
590288943Sdim  /// this function is void(*)(kmp_int32 *, kmp_int32, struct context_vars*).
591296417Sdim  /// \param CapturedVars A pointer to the record with the references to
592280031Sdim  /// variables used in \a OutlinedFn function.
593288943Sdim  /// \param IfCond Condition in the associated 'if' clause, if it was
594288943Sdim  /// specified, nullptr otherwise.
595280031Sdim  ///
596288943Sdim  virtual void emitParallelCall(CodeGenFunction &CGF, SourceLocation Loc,
597288943Sdim                                llvm::Value *OutlinedFn,
598296417Sdim                                ArrayRef<llvm::Value *> CapturedVars,
599288943Sdim                                const Expr *IfCond);
600280031Sdim
601280031Sdim  /// \brief Emits a critical region.
602280031Sdim  /// \param CriticalName Name of the critical region.
603280031Sdim  /// \param CriticalOpGen Generator for the statement associated with the given
604280031Sdim  /// critical region.
605296417Sdim  /// \param Hint Value of the 'hint' clause (optional).
606288943Sdim  virtual void emitCriticalRegion(CodeGenFunction &CGF, StringRef CriticalName,
607288943Sdim                                  const RegionCodeGenTy &CriticalOpGen,
608296417Sdim                                  SourceLocation Loc,
609296417Sdim                                  const Expr *Hint = nullptr);
610280031Sdim
611280031Sdim  /// \brief Emits a master region.
612280031Sdim  /// \param MasterOpGen Generator for the statement associated with the given
613280031Sdim  /// master region.
614288943Sdim  virtual void emitMasterRegion(CodeGenFunction &CGF,
615288943Sdim                                const RegionCodeGenTy &MasterOpGen,
616288943Sdim                                SourceLocation Loc);
617288943Sdim
618288943Sdim  /// \brief Emits code for a taskyield directive.
619288943Sdim  virtual void emitTaskyieldCall(CodeGenFunction &CGF, SourceLocation Loc);
620288943Sdim
621288943Sdim  /// \brief Emit a taskgroup region.
622288943Sdim  /// \param TaskgroupOpGen Generator for the statement associated with the
623288943Sdim  /// given taskgroup region.
624288943Sdim  virtual void emitTaskgroupRegion(CodeGenFunction &CGF,
625288943Sdim                                   const RegionCodeGenTy &TaskgroupOpGen,
626280031Sdim                                   SourceLocation Loc);
627280031Sdim
628288943Sdim  /// \brief Emits a single region.
629288943Sdim  /// \param SingleOpGen Generator for the statement associated with the given
630288943Sdim  /// single region.
631288943Sdim  virtual void emitSingleRegion(CodeGenFunction &CGF,
632288943Sdim                                const RegionCodeGenTy &SingleOpGen,
633288943Sdim                                SourceLocation Loc,
634288943Sdim                                ArrayRef<const Expr *> CopyprivateVars,
635288943Sdim                                ArrayRef<const Expr *> DestExprs,
636288943Sdim                                ArrayRef<const Expr *> SrcExprs,
637288943Sdim                                ArrayRef<const Expr *> AssignmentOps);
638288943Sdim
639288943Sdim  /// \brief Emit an ordered region.
640288943Sdim  /// \param OrderedOpGen Generator for the statement associated with the given
641288943Sdim  /// ordered region.
642288943Sdim  virtual void emitOrderedRegion(CodeGenFunction &CGF,
643288943Sdim                                 const RegionCodeGenTy &OrderedOpGen,
644296417Sdim                                 SourceLocation Loc, bool IsThreads);
645288943Sdim
646288943Sdim  /// \brief Emit an implicit/explicit barrier for OpenMP threads.
647288943Sdim  /// \param Kind Directive for which this implicit barrier call must be
648288943Sdim  /// generated. Must be OMPD_barrier for explicit barrier generation.
649296417Sdim  /// \param EmitChecks true if need to emit checks for cancellation barriers.
650296417Sdim  /// \param ForceSimpleCall true simple barrier call must be emitted, false if
651296417Sdim  /// runtime class decides which one to emit (simple or with cancellation
652296417Sdim  /// checks).
653280031Sdim  ///
654288943Sdim  virtual void emitBarrierCall(CodeGenFunction &CGF, SourceLocation Loc,
655288943Sdim                               OpenMPDirectiveKind Kind,
656296417Sdim                               bool EmitChecks = true,
657296417Sdim                               bool ForceSimpleCall = false);
658280031Sdim
659280031Sdim  /// \brief Check if the specified \a ScheduleKind is static non-chunked.
660280031Sdim  /// This kind of worksharing directive is emitted without outer loop.
661280031Sdim  /// \param ScheduleKind Schedule kind specified in the 'schedule' clause.
662280031Sdim  /// \param Chunked True if chunk is specified in the clause.
663280031Sdim  ///
664280031Sdim  virtual bool isStaticNonchunked(OpenMPScheduleClauseKind ScheduleKind,
665280031Sdim                                  bool Chunked) const;
666280031Sdim
667288943Sdim  /// \brief Check if the specified \a ScheduleKind is dynamic.
668288943Sdim  /// This kind of worksharing directive is emitted without outer loop.
669288943Sdim  /// \param ScheduleKind Schedule Kind specified in the 'schedule' clause.
670288943Sdim  ///
671288943Sdim  virtual bool isDynamic(OpenMPScheduleClauseKind ScheduleKind) const;
672288943Sdim
673296417Sdim  virtual void emitForDispatchInit(CodeGenFunction &CGF, SourceLocation Loc,
674296417Sdim                                   OpenMPScheduleClauseKind SchedKind,
675296417Sdim                                   unsigned IVSize, bool IVSigned,
676296417Sdim                                   bool Ordered, llvm::Value *UB,
677296417Sdim                                   llvm::Value *Chunk = nullptr);
678296417Sdim
679280031Sdim  /// \brief Call the appropriate runtime routine to initialize it before start
680280031Sdim  /// of loop.
681280031Sdim  ///
682280031Sdim  /// Depending on the loop schedule, it is nesessary to call some runtime
683280031Sdim  /// routine before start of the OpenMP loop to get the loop upper / lower
684280031Sdim  /// bounds \a LB and \a UB and stride \a ST.
685280031Sdim  ///
686274958Sdim  /// \param CGF Reference to current CodeGenFunction.
687274958Sdim  /// \param Loc Clang source location.
688280031Sdim  /// \param SchedKind Schedule kind, specified by the 'schedule' clause.
689280031Sdim  /// \param IVSize Size of the iteration variable in bits.
690280031Sdim  /// \param IVSigned Sign of the interation variable.
691288943Sdim  /// \param Ordered true if loop is ordered, false otherwise.
692280031Sdim  /// \param IL Address of the output variable in which the flag of the
693280031Sdim  /// last iteration is returned.
694280031Sdim  /// \param LB Address of the output variable in which the lower iteration
695280031Sdim  /// number is returned.
696280031Sdim  /// \param UB Address of the output variable in which the upper iteration
697280031Sdim  /// number is returned.
698280031Sdim  /// \param ST Address of the output variable in which the stride value is
699280031Sdim  /// returned nesessary to generated the static_chunked scheduled loop.
700280031Sdim  /// \param Chunk Value of the chunk for the static_chunked scheduled loop.
701280031Sdim  /// For the default (nullptr) value, the chunk 1 will be used.
702274958Sdim  ///
703296417Sdim  virtual void emitForStaticInit(CodeGenFunction &CGF, SourceLocation Loc,
704296417Sdim                                 OpenMPScheduleClauseKind SchedKind,
705296417Sdim                                 unsigned IVSize, bool IVSigned, bool Ordered,
706296417Sdim                                 Address IL, Address LB,
707296417Sdim                                 Address UB, Address ST,
708296417Sdim                                 llvm::Value *Chunk = nullptr);
709274958Sdim
710280031Sdim  /// \brief Call the appropriate runtime routine to notify that we finished
711288943Sdim  /// iteration of the ordered loop with the dynamic scheduling.
712288943Sdim  ///
713288943Sdim  /// \param CGF Reference to current CodeGenFunction.
714288943Sdim  /// \param Loc Clang source location.
715288943Sdim  /// \param IVSize Size of the iteration variable in bits.
716288943Sdim  /// \param IVSigned Sign of the interation variable.
717288943Sdim  ///
718288943Sdim  virtual void emitForOrderedIterationEnd(CodeGenFunction &CGF,
719288943Sdim                                          SourceLocation Loc, unsigned IVSize,
720288943Sdim                                          bool IVSigned);
721288943Sdim
722288943Sdim  /// \brief Call the appropriate runtime routine to notify that we finished
723280031Sdim  /// all the work with current loop.
724280031Sdim  ///
725274958Sdim  /// \param CGF Reference to current CodeGenFunction.
726274958Sdim  /// \param Loc Clang source location.
727274958Sdim  ///
728288943Sdim  virtual void emitForStaticFinish(CodeGenFunction &CGF, SourceLocation Loc);
729274958Sdim
730288943Sdim  /// Call __kmpc_dispatch_next(
731288943Sdim  ///          ident_t *loc, kmp_int32 tid, kmp_int32 *p_lastiter,
732288943Sdim  ///          kmp_int[32|64] *p_lower, kmp_int[32|64] *p_upper,
733288943Sdim  ///          kmp_int[32|64] *p_stride);
734288943Sdim  /// \param IVSize Size of the iteration variable in bits.
735288943Sdim  /// \param IVSigned Sign of the interation variable.
736288943Sdim  /// \param IL Address of the output variable in which the flag of the
737288943Sdim  /// last iteration is returned.
738288943Sdim  /// \param LB Address of the output variable in which the lower iteration
739288943Sdim  /// number is returned.
740288943Sdim  /// \param UB Address of the output variable in which the upper iteration
741288943Sdim  /// number is returned.
742288943Sdim  /// \param ST Address of the output variable in which the stride value is
743288943Sdim  /// returned.
744288943Sdim  virtual llvm::Value *emitForNext(CodeGenFunction &CGF, SourceLocation Loc,
745288943Sdim                                   unsigned IVSize, bool IVSigned,
746296417Sdim                                   Address IL, Address LB,
747296417Sdim                                   Address UB, Address ST);
748288943Sdim
749280031Sdim  /// \brief Emits call to void __kmpc_push_num_threads(ident_t *loc, kmp_int32
750280031Sdim  /// global_tid, kmp_int32 num_threads) to generate code for 'num_threads'
751280031Sdim  /// clause.
752280031Sdim  /// \param NumThreads An integer value of threads.
753288943Sdim  virtual void emitNumThreadsClause(CodeGenFunction &CGF,
754288943Sdim                                    llvm::Value *NumThreads,
755288943Sdim                                    SourceLocation Loc);
756274958Sdim
757288943Sdim  /// \brief Emit call to void __kmpc_push_proc_bind(ident_t *loc, kmp_int32
758288943Sdim  /// global_tid, int proc_bind) to generate code for 'proc_bind' clause.
759288943Sdim  virtual void emitProcBindClause(CodeGenFunction &CGF,
760288943Sdim                                  OpenMPProcBindClauseKind ProcBind,
761288943Sdim                                  SourceLocation Loc);
762288943Sdim
763280031Sdim  /// \brief Returns address of the threadprivate variable for the current
764280031Sdim  /// thread.
765280031Sdim  /// \param VD Threadprivate variable.
766280031Sdim  /// \param VDAddr Address of the global variable \a VD.
767280031Sdim  /// \param Loc Location of the reference to threadprivate var.
768280031Sdim  /// \return Address of the threadprivate variable for the current thread.
769296417Sdim  virtual Address getAddrOfThreadPrivate(CodeGenFunction &CGF,
770296417Sdim                                         const VarDecl *VD,
771296417Sdim                                         Address VDAddr,
772296417Sdim                                         SourceLocation Loc);
773274958Sdim
774280031Sdim  /// \brief Emit a code for initialization of threadprivate variable. It emits
775280031Sdim  /// a call to runtime library which adds initial value to the newly created
776280031Sdim  /// threadprivate variable (if it is not constant) and registers destructor
777280031Sdim  /// for the variable (if any).
778280031Sdim  /// \param VD Threadprivate variable.
779280031Sdim  /// \param VDAddr Address of the global variable \a VD.
780280031Sdim  /// \param Loc Location of threadprivate declaration.
781280031Sdim  /// \param PerformInit true if initialization expression is not constant.
782280031Sdim  virtual llvm::Function *
783296417Sdim  emitThreadPrivateVarDefinition(const VarDecl *VD, Address VDAddr,
784288943Sdim                                 SourceLocation Loc, bool PerformInit,
785288943Sdim                                 CodeGenFunction *CGF = nullptr);
786280031Sdim
787280031Sdim  /// \brief Emit flush of the variables specified in 'omp flush' directive.
788280031Sdim  /// \param Vars List of variables to flush.
789288943Sdim  virtual void emitFlush(CodeGenFunction &CGF, ArrayRef<const Expr *> Vars,
790288943Sdim                         SourceLocation Loc);
791288943Sdim
792288943Sdim  /// \brief Emit task region for the task directive. The task region is
793288943Sdim  /// emitted in several steps:
794288943Sdim  /// 1. Emit a call to kmp_task_t *__kmpc_omp_task_alloc(ident_t *, kmp_int32
795288943Sdim  /// gtid, kmp_int32 flags, size_t sizeof_kmp_task_t, size_t sizeof_shareds,
796288943Sdim  /// kmp_routine_entry_t *task_entry). Here task_entry is a pointer to the
797288943Sdim  /// function:
798288943Sdim  /// kmp_int32 .omp_task_entry.(kmp_int32 gtid, kmp_task_t *tt) {
799288943Sdim  ///   TaskFunction(gtid, tt->part_id, tt->shareds);
800288943Sdim  ///   return 0;
801288943Sdim  /// }
802288943Sdim  /// 2. Copy a list of shared variables to field shareds of the resulting
803288943Sdim  /// structure kmp_task_t returned by the previous call (if any).
804288943Sdim  /// 3. Copy a pointer to destructions function to field destructions of the
805288943Sdim  /// resulting structure kmp_task_t.
806288943Sdim  /// 4. Emit a call to kmp_int32 __kmpc_omp_task(ident_t *, kmp_int32 gtid,
807288943Sdim  /// kmp_task_t *new_task), where new_task is a resulting structure from
808288943Sdim  /// previous items.
809288943Sdim  /// \param D Current task directive.
810288943Sdim  /// \param Tied true if the task is tied (the task is tied to the thread that
811288943Sdim  /// can suspend its task region), false - untied (the task is not tied to any
812288943Sdim  /// thread).
813288943Sdim  /// \param Final Contains either constant bool value, or llvm::Value * of i1
814288943Sdim  /// type for final clause. If the value is true, the task forces all of its
815288943Sdim  /// child tasks to become final and included tasks.
816288943Sdim  /// \param TaskFunction An LLVM function with type void (*)(i32 /*gtid*/, i32
817288943Sdim  /// /*part_id*/, captured_struct */*__context*/);
818288943Sdim  /// \param SharedsTy A type which contains references the shared variables.
819288943Sdim  /// \param Shareds Context with the list of shared variables from the \p
820288943Sdim  /// TaskFunction.
821288943Sdim  /// \param IfCond Not a nullptr if 'if' clause was specified, nullptr
822288943Sdim  /// otherwise.
823288943Sdim  /// \param PrivateVars List of references to private variables for the task
824288943Sdim  /// directive.
825288943Sdim  /// \param PrivateCopies List of private copies for each private variable in
826288943Sdim  /// \p PrivateVars.
827288943Sdim  /// \param FirstprivateVars List of references to private variables for the
828288943Sdim  /// task directive.
829288943Sdim  /// \param FirstprivateCopies List of private copies for each private variable
830288943Sdim  /// in \p FirstprivateVars.
831288943Sdim  /// \param FirstprivateInits List of references to auto generated variables
832288943Sdim  /// used for initialization of a single array element. Used if firstprivate
833288943Sdim  /// variable is of array type.
834288943Sdim  /// \param Dependences List of dependences for the 'task' construct, including
835288943Sdim  /// original expression and dependency type.
836288943Sdim  virtual void emitTaskCall(
837288943Sdim      CodeGenFunction &CGF, SourceLocation Loc, const OMPExecutableDirective &D,
838288943Sdim      bool Tied, llvm::PointerIntPair<llvm::Value *, 1, bool> Final,
839296417Sdim      llvm::Value *TaskFunction, QualType SharedsTy, Address Shareds,
840288943Sdim      const Expr *IfCond, ArrayRef<const Expr *> PrivateVars,
841288943Sdim      ArrayRef<const Expr *> PrivateCopies,
842288943Sdim      ArrayRef<const Expr *> FirstprivateVars,
843288943Sdim      ArrayRef<const Expr *> FirstprivateCopies,
844288943Sdim      ArrayRef<const Expr *> FirstprivateInits,
845288943Sdim      ArrayRef<std::pair<OpenMPDependClauseKind, const Expr *>> Dependences);
846288943Sdim
847288943Sdim  /// \brief Emit code for the directive that does not require outlining.
848288943Sdim  ///
849288943Sdim  /// \param InnermostKind Kind of innermost directive (for simple directives it
850288943Sdim  /// is a directive itself, for combined - its innermost directive).
851288943Sdim  /// \param CodeGen Code generation sequence for the \a D directive.
852296417Sdim  /// \param HasCancel true if region has inner cancel directive, false
853296417Sdim  /// otherwise.
854288943Sdim  virtual void emitInlinedDirective(CodeGenFunction &CGF,
855288943Sdim                                    OpenMPDirectiveKind InnermostKind,
856296417Sdim                                    const RegionCodeGenTy &CodeGen,
857296417Sdim                                    bool HasCancel = false);
858288943Sdim  /// \brief Emit a code for reduction clause. Next code should be emitted for
859288943Sdim  /// reduction:
860288943Sdim  /// \code
861288943Sdim  ///
862288943Sdim  /// static kmp_critical_name lock = { 0 };
863288943Sdim  ///
864288943Sdim  /// void reduce_func(void *lhs[<n>], void *rhs[<n>]) {
865288943Sdim  ///  ...
866288943Sdim  ///  *(Type<i>*)lhs[i] = RedOp<i>(*(Type<i>*)lhs[i], *(Type<i>*)rhs[i]);
867288943Sdim  ///  ...
868288943Sdim  /// }
869288943Sdim  ///
870288943Sdim  /// ...
871288943Sdim  /// void *RedList[<n>] = {&<RHSExprs>[0], ..., &<RHSExprs>[<n>-1]};
872288943Sdim  /// switch (__kmpc_reduce{_nowait}(<loc>, <gtid>, <n>, sizeof(RedList),
873288943Sdim  /// RedList, reduce_func, &<lock>)) {
874288943Sdim  /// case 1:
875288943Sdim  ///  ...
876288943Sdim  ///  <LHSExprs>[i] = RedOp<i>(*<LHSExprs>[i], *<RHSExprs>[i]);
877288943Sdim  ///  ...
878288943Sdim  /// __kmpc_end_reduce{_nowait}(<loc>, <gtid>, &<lock>);
879288943Sdim  /// break;
880288943Sdim  /// case 2:
881288943Sdim  ///  ...
882288943Sdim  ///  Atomic(<LHSExprs>[i] = RedOp<i>(*<LHSExprs>[i], *<RHSExprs>[i]));
883288943Sdim  ///  ...
884288943Sdim  /// break;
885288943Sdim  /// default:;
886288943Sdim  /// }
887288943Sdim  /// \endcode
888288943Sdim  ///
889296417Sdim  /// \param Privates List of private copies for original reduction arguments.
890288943Sdim  /// \param LHSExprs List of LHS in \a ReductionOps reduction operations.
891288943Sdim  /// \param RHSExprs List of RHS in \a ReductionOps reduction operations.
892288943Sdim  /// \param ReductionOps List of reduction operations in form 'LHS binop RHS'
893288943Sdim  /// or 'operator binop(LHS, RHS)'.
894288943Sdim  /// \param WithNowait true if parent directive has also nowait clause, false
895288943Sdim  /// otherwise.
896288943Sdim  virtual void emitReduction(CodeGenFunction &CGF, SourceLocation Loc,
897296417Sdim                             ArrayRef<const Expr *> Privates,
898288943Sdim                             ArrayRef<const Expr *> LHSExprs,
899288943Sdim                             ArrayRef<const Expr *> RHSExprs,
900288943Sdim                             ArrayRef<const Expr *> ReductionOps,
901288943Sdim                             bool WithNowait, bool SimpleReduction);
902288943Sdim
903288943Sdim  /// \brief Emit code for 'taskwait' directive.
904288943Sdim  virtual void emitTaskwaitCall(CodeGenFunction &CGF, SourceLocation Loc);
905288943Sdim
906288943Sdim  /// \brief Emit code for 'cancellation point' construct.
907288943Sdim  /// \param CancelRegion Region kind for which the cancellation point must be
908288943Sdim  /// emitted.
909288943Sdim  ///
910288943Sdim  virtual void emitCancellationPointCall(CodeGenFunction &CGF,
911288943Sdim                                         SourceLocation Loc,
912288943Sdim                                         OpenMPDirectiveKind CancelRegion);
913288943Sdim
914288943Sdim  /// \brief Emit code for 'cancel' construct.
915296417Sdim  /// \param IfCond Condition in the associated 'if' clause, if it was
916296417Sdim  /// specified, nullptr otherwise.
917288943Sdim  /// \param CancelRegion Region kind for which the cancel must be emitted.
918288943Sdim  ///
919288943Sdim  virtual void emitCancelCall(CodeGenFunction &CGF, SourceLocation Loc,
920296417Sdim                              const Expr *IfCond,
921288943Sdim                              OpenMPDirectiveKind CancelRegion);
922296417Sdim
923296417Sdim  /// \brief Emit outilined function for 'target' directive.
924296417Sdim  /// \param D Directive to emit.
925296417Sdim  /// \param ParentName Name of the function that encloses the target region.
926296417Sdim  /// \param OutlinedFn Outlined function value to be defined by this call.
927296417Sdim  /// \param OutlinedFnID Outlined function ID value to be defined by this call.
928296417Sdim  /// \param IsOffloadEntry True if the outlined function is an offload entry.
929296417Sdim  /// An oulined function may not be an entry if, e.g. the if clause always
930296417Sdim  /// evaluates to false.
931296417Sdim  virtual void emitTargetOutlinedFunction(const OMPExecutableDirective &D,
932296417Sdim                                          StringRef ParentName,
933296417Sdim                                          llvm::Function *&OutlinedFn,
934296417Sdim                                          llvm::Constant *&OutlinedFnID,
935296417Sdim                                          bool IsOffloadEntry);
936296417Sdim
937296417Sdim  /// \brief Emit the target offloading code associated with \a D. The emitted
938296417Sdim  /// code attempts offloading the execution to the device, an the event of
939296417Sdim  /// a failure it executes the host version outlined in \a OutlinedFn.
940296417Sdim  /// \param D Directive to emit.
941296417Sdim  /// \param OutlinedFn Host version of the code to be offloaded.
942296417Sdim  /// \param OutlinedFnID ID of host version of the code to be offloaded.
943296417Sdim  /// \param IfCond Expression evaluated in if clause associated with the target
944296417Sdim  /// directive, or null if no if clause is used.
945296417Sdim  /// \param Device Expression evaluated in device clause associated with the
946296417Sdim  /// target directive, or null if no device clause is used.
947296417Sdim  /// \param CapturedVars Values captured in the current region.
948296417Sdim  virtual void emitTargetCall(CodeGenFunction &CGF,
949296417Sdim                              const OMPExecutableDirective &D,
950296417Sdim                              llvm::Value *OutlinedFn,
951296417Sdim                              llvm::Value *OutlinedFnID, const Expr *IfCond,
952296417Sdim                              const Expr *Device,
953296417Sdim                              ArrayRef<llvm::Value *> CapturedVars);
954296417Sdim
955296417Sdim  /// \brief Emit the target regions enclosed in \a GD function definition or
956296417Sdim  /// the function itself in case it is a valid device function. Returns true if
957296417Sdim  /// \a GD was dealt with successfully.
958296417Sdim  /// \param GD Function to scan.
959296417Sdim  virtual bool emitTargetFunctions(GlobalDecl GD);
960296417Sdim
961296417Sdim  /// \brief Emit the global variable if it is a valid device global variable.
962296417Sdim  /// Returns true if \a GD was dealt with successfully.
963296417Sdim  /// \param GD Variable declaration to emit.
964296417Sdim  virtual bool emitTargetGlobalVariable(GlobalDecl GD);
965296417Sdim
966296417Sdim  /// \brief Emit the global \a GD if it is meaningful for the target. Returns
967296417Sdim  /// if it was emitted succesfully.
968296417Sdim  /// \param GD Global to scan.
969296417Sdim  virtual bool emitTargetGlobal(GlobalDecl GD);
970296417Sdim
971296417Sdim  /// \brief Creates the offloading descriptor in the event any target region
972296417Sdim  /// was emitted in the current module and return the function that registers
973296417Sdim  /// it.
974296417Sdim  virtual llvm::Function *emitRegistrationFunction();
975274958Sdim};
976288943Sdim
977274958Sdim} // namespace CodeGen
978274958Sdim} // namespace clang
979274958Sdim
980274958Sdim#endif
981