xref: /freebsd/contrib/llvm-project/llvm/include/llvm/Frontend/Offloading/Utility.h (revision 700637cbb5e582861067a11aaca4d053546871d2)
1 //===- Utility.h - Collection of geneirc offloading utilities -------------===//
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 #ifndef LLVM_FRONTEND_OFFLOADING_UTILITY_H
10 #define LLVM_FRONTEND_OFFLOADING_UTILITY_H
11 
12 #include "llvm/Support/Compiler.h"
13 #include <cstdint>
14 #include <memory>
15 
16 #include "llvm/ADT/StringMap.h"
17 #include "llvm/ADT/StringRef.h"
18 #include "llvm/IR/Module.h"
19 #include "llvm/Object/OffloadBinary.h"
20 #include "llvm/Support/Error.h"
21 #include "llvm/Support/MemoryBufferRef.h"
22 
23 namespace llvm {
24 namespace offloading {
25 
26 /// This is the record of an object that just be registered with the offloading
27 /// runtime.
28 struct EntryTy {
29   /// Reserved bytes used to detect an older version of the struct, always zero.
30   uint64_t Reserved = 0x0;
31   /// The current version of the struct for runtime forward compatibility.
32   uint16_t Version = 0x1;
33   /// The expected consumer of this entry, e.g. CUDA or OpenMP.
34   uint16_t Kind;
35   /// Flags associated with the global.
36   uint32_t Flags;
37   /// The address of the global to be registered by the runtime.
38   void *Address;
39   /// The name of the symbol in the device image.
40   char *SymbolName;
41   /// The number of bytes the symbol takes.
42   uint64_t Size;
43   /// Extra generic data used to register this entry.
44   uint64_t Data;
45   /// An extra pointer, usually null.
46   void *AuxAddr;
47 };
48 
49 /// Offloading entry flags for CUDA / HIP. The first three bits indicate the
50 /// type of entry while the others are a bit field for additional information.
51 enum OffloadEntryKindFlag : uint32_t {
52   /// Mark the entry as a global entry. This indicates the presense of a
53   /// kernel if the size size field is zero and a variable otherwise.
54   OffloadGlobalEntry = 0x0,
55   /// Mark the entry as a managed global variable.
56   OffloadGlobalManagedEntry = 0x1,
57   /// Mark the entry as a surface variable.
58   OffloadGlobalSurfaceEntry = 0x2,
59   /// Mark the entry as a texture variable.
60   OffloadGlobalTextureEntry = 0x3,
61   /// Mark the entry as being extern.
62   OffloadGlobalExtern = 0x1 << 3,
63   /// Mark the entry as being constant.
64   OffloadGlobalConstant = 0x1 << 4,
65   /// Mark the entry as being a normalized surface.
66   OffloadGlobalNormalized = 0x1 << 5,
67 };
68 
69 /// Returns the type of the offloading entry we use to store kernels and
70 /// globals that will be registered with the offloading runtime.
71 LLVM_ABI StructType *getEntryTy(Module &M);
72 
73 /// Create an offloading section struct used to register this global at
74 /// runtime.
75 ///
76 /// \param M The module to be used
77 /// \param Addr The pointer to the global being registered.
78 /// \param Kind The offloading language expected to consume this.
79 /// \param Name The symbol name associated with the global.
80 /// \param Size The size in bytes of the global (0 for functions).
81 /// \param Flags Flags associated with the entry.
82 /// \param Data Extra data storage associated with the entry.
83 /// \param SectionName The section this entry will be placed at.
84 /// \param AuxAddr An extra pointer if needed.
85 LLVM_ABI void
86 emitOffloadingEntry(Module &M, object::OffloadKind Kind, Constant *Addr,
87                     StringRef Name, uint64_t Size, uint32_t Flags,
88                     uint64_t Data, Constant *AuxAddr = nullptr,
89                     StringRef SectionName = "llvm_offload_entries");
90 
91 /// Create a constant struct initializer used to register this global at
92 /// runtime.
93 /// \return the constant struct and the global variable holding the symbol name.
94 LLVM_ABI std::pair<Constant *, GlobalVariable *>
95 getOffloadingEntryInitializer(Module &M, object::OffloadKind Kind,
96                               Constant *Addr, StringRef Name, uint64_t Size,
97                               uint32_t Flags, uint64_t Data, Constant *AuxAddr);
98 
99 /// Creates a pair of globals used to iterate the array of offloading entries by
100 /// accessing the section variables provided by the linker.
101 LLVM_ABI std::pair<GlobalVariable *, GlobalVariable *>
102 getOffloadEntryArray(Module &M, StringRef SectionName = "llvm_offload_entries");
103 
104 namespace amdgpu {
105 /// Check if an image is compatible with current system's environment. The
106 /// system environment is given as a 'target-id' which has the form:
107 ///
108 /// <target-id> := <processor> ( ":" <target-feature> ( "+" | "-" ) )*
109 ///
110 /// If a feature is not specific as '+' or '-' it is assumed to be in an 'any'
111 /// and is compatible with either '+' or '-'. The HSA runtime returns this
112 /// information using the target-id, while we use the ELF header to determine
113 /// these features.
114 LLVM_ABI bool isImageCompatibleWithEnv(StringRef ImageArch, uint32_t ImageFlags,
115                                        StringRef EnvTargetID);
116 
117 /// Struct for holding metadata related to AMDGPU kernels, for more information
118 /// about the metadata and its meaning see:
119 /// https://llvm.org/docs/AMDGPUUsage.html#code-object-v3
120 struct AMDGPUKernelMetaData {
121   /// Constant indicating that a value is invalid.
122   static constexpr uint32_t KInvalidValue =
123       std::numeric_limits<uint32_t>::max();
124   /// The amount of group segment memory required by a work-group in bytes.
125   uint32_t GroupSegmentList = KInvalidValue;
126   /// The amount of fixed private address space memory required for a work-item
127   /// in bytes.
128   uint32_t PrivateSegmentSize = KInvalidValue;
129   /// Number of scalar registers required by a wavefront.
130   uint32_t SGPRCount = KInvalidValue;
131   /// Number of vector registers required by each work-item.
132   uint32_t VGPRCount = KInvalidValue;
133   /// Number of stores from a scalar register to a register allocator created
134   /// spill location.
135   uint32_t SGPRSpillCount = KInvalidValue;
136   /// Number of stores from a vector register to a register allocator created
137   /// spill location.
138   uint32_t VGPRSpillCount = KInvalidValue;
139   /// Number of accumulator registers required by each work-item.
140   uint32_t AGPRCount = KInvalidValue;
141   /// Corresponds to the OpenCL reqd_work_group_size attribute.
142   uint32_t RequestedWorkgroupSize[3] = {KInvalidValue, KInvalidValue,
143                                         KInvalidValue};
144   /// Corresponds to the OpenCL work_group_size_hint attribute.
145   uint32_t WorkgroupSizeHint[3] = {KInvalidValue, KInvalidValue, KInvalidValue};
146   /// Wavefront size.
147   uint32_t WavefrontSize = KInvalidValue;
148   /// Maximum flat work-group size supported by the kernel in work-items.
149   uint32_t MaxFlatWorkgroupSize = KInvalidValue;
150 };
151 
152 /// Reads AMDGPU specific metadata from the ELF file and propagates the
153 /// KernelInfoMap.
154 LLVM_ABI Error getAMDGPUMetaDataFromImage(
155     MemoryBufferRef MemBuffer, StringMap<AMDGPUKernelMetaData> &KernelInfoMap,
156     uint16_t &ELFABIVersion);
157 } // namespace amdgpu
158 
159 namespace intel {
160 /// Containerizes an offloading binary into the ELF binary format expected by
161 /// the Intel runtime offload plugin.
162 LLVM_ABI Error
163 containerizeOpenMPSPIRVImage(std::unique_ptr<MemoryBuffer> &Binary);
164 } // namespace intel
165 } // namespace offloading
166 } // namespace llvm
167 
168 #endif // LLVM_FRONTEND_OFFLOADING_UTILITY_H
169