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