LLVM 23.0.0git
OffloadWrapper.cpp
Go to the documentation of this file.
1//===- OffloadWrapper.cpp ---------------------------------------*- C++ -*-===//
2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//
7//===----------------------------------------------------------------------===//
8
10#include "llvm/ADT/ArrayRef.h"
12#include "llvm/ADT/StringRef.h"
13#include "llvm/ADT/Twine.h"
16#include "llvm/IR/Constants.h"
19#include "llvm/IR/IRBuilder.h"
20#include "llvm/IR/LLVMContext.h"
21#include "llvm/IR/Module.h"
22#include "llvm/IR/Type.h"
24#include "llvm/Support/Error.h"
30
31#include <memory>
32#include <utility>
33
34using namespace llvm;
35using namespace llvm::object;
36using namespace llvm::offloading;
37
38namespace {
39/// Magic number that begins the section containing the CUDA fatbinary.
40constexpr unsigned CudaFatMagic = 0x466243b1;
41constexpr unsigned HIPFatMagic = 0x48495046;
42
44 return M.getDataLayout().getIntPtrType(M.getContext());
45}
46
47// struct __tgt_device_image {
48// void *ImageStart;
49// void *ImageEnd;
50// __tgt_offload_entry *EntriesBegin;
51// __tgt_offload_entry *EntriesEnd;
52// };
53StructType *getDeviceImageTy(Module &M) {
54 LLVMContext &C = M.getContext();
55 StructType *ImageTy = StructType::getTypeByName(C, "__tgt_device_image");
56 if (!ImageTy)
57 ImageTy =
58 StructType::create("__tgt_device_image", PointerType::getUnqual(C),
61 return ImageTy;
62}
63
64PointerType *getDeviceImagePtrTy(Module &M) {
65 return PointerType::getUnqual(M.getContext());
66}
67
68// struct __tgt_bin_desc {
69// int32_t NumDeviceImages;
70// __tgt_device_image *DeviceImages;
71// __tgt_offload_entry *HostEntriesBegin;
72// __tgt_offload_entry *HostEntriesEnd;
73// };
74StructType *getBinDescTy(Module &M) {
75 LLVMContext &C = M.getContext();
76 StructType *DescTy = StructType::getTypeByName(C, "__tgt_bin_desc");
77 if (!DescTy)
78 DescTy = StructType::create(
79 "__tgt_bin_desc", Type::getInt32Ty(C), getDeviceImagePtrTy(M),
81 return DescTy;
82}
83
84PointerType *getBinDescPtrTy(Module &M) {
85 return PointerType::getUnqual(M.getContext());
86}
87
88/// Creates binary descriptor for the given device images. Binary descriptor
89/// is an object that is passed to the offloading runtime at program startup
90/// and it describes all device images available in the executable or shared
91/// library. It is defined as follows
92///
93/// __attribute__((visibility("hidden")))
94/// extern __tgt_offload_entry *__start_omp_offloading_entries;
95/// __attribute__((visibility("hidden")))
96/// extern __tgt_offload_entry *__stop_omp_offloading_entries;
97///
98/// static const char Image0[] = { <Bufs.front() contents> };
99/// ...
100/// static const char ImageN[] = { <Bufs.back() contents> };
101///
102/// static const __tgt_device_image Images[] = {
103/// {
104/// Image0, /*ImageStart*/
105/// Image0 + sizeof(Image0), /*ImageEnd*/
106/// __start_omp_offloading_entries, /*EntriesBegin*/
107/// __stop_omp_offloading_entries /*EntriesEnd*/
108/// },
109/// ...
110/// {
111/// ImageN, /*ImageStart*/
112/// ImageN + sizeof(ImageN), /*ImageEnd*/
113/// __start_omp_offloading_entries, /*EntriesBegin*/
114/// __stop_omp_offloading_entries /*EntriesEnd*/
115/// }
116/// };
117///
118/// static const __tgt_bin_desc BinDesc = {
119/// sizeof(Images) / sizeof(Images[0]), /*NumDeviceImages*/
120/// Images, /*DeviceImages*/
121/// __start_omp_offloading_entries, /*HostEntriesBegin*/
122/// __stop_omp_offloading_entries /*HostEntriesEnd*/
123/// };
124///
125/// Global variable that represents BinDesc is returned.
126GlobalVariable *createBinDesc(Module &M, ArrayRef<ArrayRef<char>> Bufs,
127 EntryArrayTy EntryArray, StringRef Suffix,
128 bool Relocatable) {
129 LLVMContext &C = M.getContext();
130 auto [EntriesB, EntriesE] = EntryArray;
131
132 auto *Zero = ConstantInt::get(getSizeTTy(M), 0u);
133
134 // Create initializer for the images array.
135 SmallVector<Constant *, 4u> ImagesInits;
136 ImagesInits.reserve(Bufs.size());
137 for (ArrayRef<char> Buf : Bufs) {
138 // We embed the full offloading entry so the binary utilities can parse it.
139 auto *Data = ConstantDataArray::get(C, Buf);
140 auto *Image = new GlobalVariable(M, Data->getType(), /*isConstant=*/true,
142 ".omp_offloading.device_image" + Suffix);
144 Image->setSection(Relocatable ? ".llvm.offloading.relocatable"
145 : ".llvm.offloading");
147
148 StringRef Binary(Buf.data(), Buf.size());
149
150 uint64_t BeginOffset = 0;
151 uint64_t EndOffset = Binary.size();
152
153 // Optionally use an offload binary for its offload dumping support.
154 // The device image struct contains the pointer to the beginning and end of
155 // the image stored inside of the offload binary. There should only be one
156 // of these for each buffer so we parse it out manually.
158 const auto *Header =
159 reinterpret_cast<const object::OffloadBinary::Header *>(
160 Binary.bytes_begin());
161 const auto *Entry =
162 reinterpret_cast<const object::OffloadBinary::Entry *>(
163 Binary.bytes_begin() + Header->EntriesOffset);
164 BeginOffset = Entry->ImageOffset;
165 EndOffset = Entry->ImageOffset + Entry->ImageSize;
166 }
167
168 auto *Begin = ConstantInt::get(getSizeTTy(M), BeginOffset);
169 auto *Size = ConstantInt::get(getSizeTTy(M), EndOffset);
170 Constant *ZeroBegin[] = {Zero, Begin};
171 Constant *ZeroSize[] = {Zero, Size};
172
173 auto *ImageB =
174 ConstantExpr::getGetElementPtr(Image->getValueType(), Image, ZeroBegin);
175 auto *ImageE =
176 ConstantExpr::getGetElementPtr(Image->getValueType(), Image, ZeroSize);
177
178 ImagesInits.push_back(ConstantStruct::get(getDeviceImageTy(M), ImageB,
179 ImageE, EntriesB, EntriesE));
180 }
181
182 // Then create images array.
183 auto *ImagesData = ConstantArray::get(
184 ArrayType::get(getDeviceImageTy(M), ImagesInits.size()), ImagesInits);
185
186 auto *Images =
187 new GlobalVariable(M, ImagesData->getType(), /*isConstant*/ true,
189 ".omp_offloading.device_images" + Suffix);
190 Images->setUnnamedAddr(GlobalValue::UnnamedAddr::Global);
191
192 // And finally create the binary descriptor object.
193 auto *DescInit = ConstantStruct::get(
194 getBinDescTy(M),
195 ConstantInt::get(Type::getInt32Ty(C), ImagesInits.size()), Images,
196 EntriesB, EntriesE);
197
198 return new GlobalVariable(M, DescInit->getType(), /*isConstant=*/true,
200 ".omp_offloading.descriptor" + Suffix);
201}
202
203Function *createUnregisterFunction(Module &M, GlobalVariable *BinDesc,
204 StringRef Suffix) {
205 LLVMContext &C = M.getContext();
206 auto *FuncTy = FunctionType::get(Type::getVoidTy(C), /*isVarArg*/ false);
207 auto *Func =
209 ".omp_offloading.descriptor_unreg" + Suffix, &M);
210 Func->setSection(".text.startup");
211
212 // Get __tgt_unregister_lib function declaration.
213 auto *UnRegFuncTy = FunctionType::get(Type::getVoidTy(C), getBinDescPtrTy(M),
214 /*isVarArg*/ false);
215 FunctionCallee UnRegFuncC =
216 M.getOrInsertFunction("__tgt_unregister_lib", UnRegFuncTy);
217
218 // Construct function body
219 IRBuilder<> Builder(BasicBlock::Create(C, "entry", Func));
220 Builder.CreateCall(UnRegFuncC, BinDesc);
221 Builder.CreateRetVoid();
222
223 return Func;
224}
225
226void createRegisterFunction(Module &M, GlobalVariable *BinDesc,
227 StringRef Suffix) {
228 LLVMContext &C = M.getContext();
229 auto *FuncTy = FunctionType::get(Type::getVoidTy(C), /*isVarArg*/ false);
231 ".omp_offloading.descriptor_reg" + Suffix, &M);
232 Func->setSection(".text.startup");
233
234 // Get __tgt_register_lib function declaration.
235 auto *RegFuncTy = FunctionType::get(Type::getVoidTy(C), getBinDescPtrTy(M),
236 /*isVarArg*/ false);
237 FunctionCallee RegFuncC =
238 M.getOrInsertFunction("__tgt_register_lib", RegFuncTy);
239
240 auto *AtExitTy = FunctionType::get(
241 Type::getInt32Ty(C), PointerType::getUnqual(C), /*isVarArg=*/false);
242 FunctionCallee AtExit = M.getOrInsertFunction("atexit", AtExitTy);
243
244 Function *UnregFunc = createUnregisterFunction(M, BinDesc, Suffix);
245
246 // Construct function body
247 IRBuilder<> Builder(BasicBlock::Create(C, "entry", Func));
248
249 Builder.CreateCall(RegFuncC, BinDesc);
250
251 // Register the destructors with 'atexit'. This is expected by the CUDA
252 // runtime and ensures that we clean up before dynamic objects are destroyed.
253 // This needs to be done after plugin initialization to ensure that it is
254 // called before the plugin runtime is destroyed.
255 Builder.CreateCall(AtExit, UnregFunc);
256 Builder.CreateRetVoid();
257
258 // Add this function to constructors.
259 appendToGlobalCtors(M, Func, /*Priority=*/101);
260}
261
262// struct fatbin_wrapper {
263// int32_t magic;
264// int32_t version;
265// void *image;
266// void *reserved;
267//};
268StructType *getFatbinWrapperTy(Module &M) {
269 LLVMContext &C = M.getContext();
270 StructType *FatbinTy = StructType::getTypeByName(C, "fatbin_wrapper");
271 if (!FatbinTy)
272 FatbinTy = StructType::create(
273 "fatbin_wrapper", Type::getInt32Ty(C), Type::getInt32Ty(C),
275 return FatbinTy;
276}
277
278/// Embed the image \p Image into the module \p M so it can be found by the
279/// runtime.
280GlobalVariable *createFatbinDesc(Module &M, ArrayRef<char> Image, bool IsHIP,
281 StringRef Suffix) {
282 LLVMContext &C = M.getContext();
283 llvm::Type *Int8PtrTy = PointerType::getUnqual(C);
284 const llvm::Triple &Triple = M.getTargetTriple();
285
286 // Create the global string containing the fatbinary.
287 StringRef FatbinConstantSection =
288 IsHIP ? ".hip_fatbin"
289 : (Triple.isMacOSX() ? "__NV_CUDA,__nv_fatbin" : ".nv_fatbin");
290 auto *Data = ConstantDataArray::get(C, Image);
291 auto *Fatbin = new GlobalVariable(M, Data->getType(), /*isConstant*/ true,
293 ".fatbin_image" + Suffix);
294 Fatbin->setSection(FatbinConstantSection);
295
296 // Create the fatbinary wrapper
297 StringRef FatbinWrapperSection = IsHIP ? ".hipFatBinSegment"
298 : Triple.isMacOSX() ? "__NV_CUDA,__fatbin"
299 : ".nvFatBinSegment";
300 Constant *FatbinWrapper[] = {
301 ConstantInt::get(Type::getInt32Ty(C), IsHIP ? HIPFatMagic : CudaFatMagic),
302 ConstantInt::get(Type::getInt32Ty(C), 1),
305
306 Constant *FatbinInitializer =
307 ConstantStruct::get(getFatbinWrapperTy(M), FatbinWrapper);
308
309 auto *FatbinDesc =
310 new GlobalVariable(M, getFatbinWrapperTy(M),
311 /*isConstant*/ true, GlobalValue::InternalLinkage,
312 FatbinInitializer, ".fatbin_wrapper" + Suffix);
313 FatbinDesc->setSection(FatbinWrapperSection);
314 FatbinDesc->setAlignment(Align(8));
315
316 return FatbinDesc;
317}
318
319/// Create the register globals function. We will iterate all of the offloading
320/// entries stored at the begin / end symbols and register them according to
321/// their type. This creates the following function in IR:
322///
323/// extern struct __tgt_offload_entry __start_cuda_offloading_entries;
324/// extern struct __tgt_offload_entry __stop_cuda_offloading_entries;
325///
326/// extern void __cudaRegisterFunction(void **, void *, void *, void *, int,
327/// void *, void *, void *, void *, int *);
328/// extern void __cudaRegisterVar(void **, void *, void *, void *, int32_t,
329/// int64_t, int32_t, int32_t);
330///
331/// void __cudaRegisterTest(void **fatbinHandle) {
332/// for (struct __tgt_offload_entry *entry = &__start_cuda_offloading_entries;
333/// entry != &__stop_cuda_offloading_entries; ++entry) {
334/// if (entry->Kind != OFK_CUDA)
335/// continue
336///
337/// if (!entry->Size)
338/// __cudaRegisterFunction(fatbinHandle, entry->addr, entry->name,
339/// entry->name, -1, 0, 0, 0, 0, 0);
340/// else
341/// __cudaRegisterVar(fatbinHandle, entry->addr, entry->name, entry->name,
342/// 0, entry->size, 0, 0);
343/// }
344/// }
345Function *createRegisterGlobalsFunction(Module &M, bool IsHIP,
346 EntryArrayTy EntryArray,
347 StringRef Suffix,
348 bool EmitSurfacesAndTextures) {
349 LLVMContext &C = M.getContext();
350 auto [EntriesB, EntriesE] = EntryArray;
351
352 // Get the __cudaRegisterFunction function declaration.
353 PointerType *Int8PtrTy = PointerType::get(C, 0);
354 PointerType *Int8PtrPtrTy = PointerType::get(C, 0);
355 PointerType *Int32PtrTy = PointerType::get(C, 0);
356 auto *RegFuncTy = FunctionType::get(
358 {Int8PtrPtrTy, Int8PtrTy, Int8PtrTy, Int8PtrTy, Type::getInt32Ty(C),
359 Int8PtrTy, Int8PtrTy, Int8PtrTy, Int8PtrTy, Int32PtrTy},
360 /*isVarArg*/ false);
361 FunctionCallee RegFunc = M.getOrInsertFunction(
362 IsHIP ? "__hipRegisterFunction" : "__cudaRegisterFunction", RegFuncTy);
363
364 // Get the __cudaRegisterVar function declaration.
365 auto *RegVarTy = FunctionType::get(
367 {Int8PtrPtrTy, Int8PtrTy, Int8PtrTy, Int8PtrTy, Type::getInt32Ty(C),
369 /*isVarArg*/ false);
370 FunctionCallee RegVar = M.getOrInsertFunction(
371 IsHIP ? "__hipRegisterVar" : "__cudaRegisterVar", RegVarTy);
372
373 // Get the __cudaRegisterSurface function declaration.
374 FunctionType *RegManagedVarTy =
376 {Int8PtrPtrTy, Int8PtrTy, Int8PtrTy, Int8PtrTy,
378 /*isVarArg=*/false);
379 FunctionCallee RegManagedVar = M.getOrInsertFunction(
380 IsHIP ? "__hipRegisterManagedVar" : "__cudaRegisterManagedVar",
381 RegManagedVarTy);
382
383 // Get the __cudaRegisterSurface function declaration.
384 FunctionType *RegSurfaceTy =
386 {Int8PtrPtrTy, Int8PtrTy, Int8PtrTy, Int8PtrTy,
388 /*isVarArg=*/false);
389 FunctionCallee RegSurface = M.getOrInsertFunction(
390 IsHIP ? "__hipRegisterSurface" : "__cudaRegisterSurface", RegSurfaceTy);
391
392 // Get the __cudaRegisterTexture function declaration.
393 FunctionType *RegTextureTy = FunctionType::get(
395 {Int8PtrPtrTy, Int8PtrTy, Int8PtrTy, Int8PtrTy, Type::getInt32Ty(C),
397 /*isVarArg=*/false);
398 FunctionCallee RegTexture = M.getOrInsertFunction(
399 IsHIP ? "__hipRegisterTexture" : "__cudaRegisterTexture", RegTextureTy);
400
401 auto *RegGlobalsTy = FunctionType::get(Type::getVoidTy(C), Int8PtrPtrTy,
402 /*isVarArg*/ false);
403 auto *RegGlobalsFn =
405 IsHIP ? ".hip.globals_reg" : ".cuda.globals_reg", &M);
406 RegGlobalsFn->setSection(".text.startup");
407
408 // Create the loop to register all the entries.
409 IRBuilder<> Builder(BasicBlock::Create(C, "entry", RegGlobalsFn));
410 auto *EntryBB = BasicBlock::Create(C, "while.entry", RegGlobalsFn);
411 auto *IfKindBB = BasicBlock::Create(C, "if.kind", RegGlobalsFn);
412 auto *IfThenBB = BasicBlock::Create(C, "if.then", RegGlobalsFn);
413 auto *IfElseBB = BasicBlock::Create(C, "if.else", RegGlobalsFn);
414 auto *SwGlobalBB = BasicBlock::Create(C, "sw.global", RegGlobalsFn);
415 auto *SwManagedBB = BasicBlock::Create(C, "sw.managed", RegGlobalsFn);
416 auto *SwSurfaceBB = BasicBlock::Create(C, "sw.surface", RegGlobalsFn);
417 auto *SwTextureBB = BasicBlock::Create(C, "sw.texture", RegGlobalsFn);
418 auto *IfEndBB = BasicBlock::Create(C, "if.end", RegGlobalsFn);
419 auto *ExitBB = BasicBlock::Create(C, "while.end", RegGlobalsFn);
420
421 auto *EntryCmp = Builder.CreateICmpNE(EntriesB, EntriesE);
422 Builder.CreateCondBr(EntryCmp, EntryBB, ExitBB);
423 Builder.SetInsertPoint(EntryBB);
424 auto *Entry = Builder.CreatePHI(PointerType::getUnqual(C), 2, "entry");
425 auto *AddrPtr =
426 Builder.CreateInBoundsGEP(offloading::getEntryTy(M), Entry,
427 {ConstantInt::get(Type::getInt32Ty(C), 0),
428 ConstantInt::get(Type::getInt32Ty(C), 4)});
429 auto *Addr = Builder.CreateLoad(Int8PtrTy, AddrPtr, "addr");
430 auto *AuxAddrPtr =
431 Builder.CreateInBoundsGEP(offloading::getEntryTy(M), Entry,
432 {ConstantInt::get(Type::getInt32Ty(C), 0),
433 ConstantInt::get(Type::getInt32Ty(C), 8)});
434 auto *AuxAddr = Builder.CreateLoad(Int8PtrTy, AuxAddrPtr, "aux_addr");
435 auto *KindPtr =
436 Builder.CreateInBoundsGEP(offloading::getEntryTy(M), Entry,
437 {ConstantInt::get(Type::getInt32Ty(C), 0),
438 ConstantInt::get(Type::getInt32Ty(C), 2)});
439 auto *Kind = Builder.CreateLoad(Type::getInt16Ty(C), KindPtr, "kind");
440 auto *NamePtr =
441 Builder.CreateInBoundsGEP(offloading::getEntryTy(M), Entry,
442 {ConstantInt::get(Type::getInt32Ty(C), 0),
443 ConstantInt::get(Type::getInt32Ty(C), 5)});
444 auto *Name = Builder.CreateLoad(Int8PtrTy, NamePtr, "name");
445 auto *SizePtr =
446 Builder.CreateInBoundsGEP(offloading::getEntryTy(M), Entry,
447 {ConstantInt::get(Type::getInt32Ty(C), 0),
448 ConstantInt::get(Type::getInt32Ty(C), 6)});
449 auto *Size = Builder.CreateLoad(Type::getInt64Ty(C), SizePtr, "size");
450 auto *FlagsPtr =
451 Builder.CreateInBoundsGEP(offloading::getEntryTy(M), Entry,
452 {ConstantInt::get(Type::getInt32Ty(C), 0),
453 ConstantInt::get(Type::getInt32Ty(C), 3)});
454 auto *Flags = Builder.CreateLoad(Type::getInt32Ty(C), FlagsPtr, "flags");
455 auto *DataPtr =
456 Builder.CreateInBoundsGEP(offloading::getEntryTy(M), Entry,
457 {ConstantInt::get(Type::getInt32Ty(C), 0),
458 ConstantInt::get(Type::getInt32Ty(C), 7)});
459 auto *Data = Builder.CreateTrunc(
460 Builder.CreateLoad(Type::getInt64Ty(C), DataPtr, "data"),
462 auto *Type = Builder.CreateAnd(
463 Flags, ConstantInt::get(Type::getInt32Ty(C), 0x7), "type");
464
465 // Extract the flags stored in the bit-field and convert them to C booleans.
466 auto *ExternBit = Builder.CreateAnd(
467 Flags, ConstantInt::get(Type::getInt32Ty(C),
469 auto *Extern = Builder.CreateLShr(
470 ExternBit, ConstantInt::get(Type::getInt32Ty(C), 3), "extern");
471 auto *ConstantBit = Builder.CreateAnd(
472 Flags, ConstantInt::get(Type::getInt32Ty(C),
474 auto *Const = Builder.CreateLShr(
475 ConstantBit, ConstantInt::get(Type::getInt32Ty(C), 4), "constant");
476 auto *NormalizedBit = Builder.CreateAnd(
477 Flags, ConstantInt::get(Type::getInt32Ty(C),
479 auto *Normalized = Builder.CreateLShr(
480 NormalizedBit, ConstantInt::get(Type::getInt32Ty(C), 5), "normalized");
481 auto *KindCond = Builder.CreateICmpEQ(
482 Kind, ConstantInt::get(Type::getInt16Ty(C),
485 Builder.CreateCondBr(KindCond, IfKindBB, IfEndBB);
486 Builder.SetInsertPoint(IfKindBB);
487 auto *FnCond = Builder.CreateICmpEQ(
489 Builder.CreateCondBr(FnCond, IfThenBB, IfElseBB);
490
491 // Create kernel registration code.
492 Builder.SetInsertPoint(IfThenBB);
493 Builder.CreateCall(
494 RegFunc,
495 {RegGlobalsFn->arg_begin(), Addr, Name, Name,
499 ConstantPointerNull::get(Int32PtrTy)});
500 Builder.CreateBr(IfEndBB);
501 Builder.SetInsertPoint(IfElseBB);
502
503 auto *Switch = Builder.CreateSwitch(Type, IfEndBB);
504 // Create global variable registration code.
505 Builder.SetInsertPoint(SwGlobalBB);
506 Builder.CreateCall(RegVar,
507 {RegGlobalsFn->arg_begin(), Addr, Name, Name, Extern, Size,
508 Const, ConstantInt::get(Type::getInt32Ty(C), 0)});
509 Builder.CreateBr(IfEndBB);
510 Switch->addCase(Builder.getInt32(llvm::offloading::OffloadGlobalEntry),
511 SwGlobalBB);
512
513 // Create managed variable registration code.
514 Builder.SetInsertPoint(SwManagedBB);
515 Builder.CreateCall(RegManagedVar, {RegGlobalsFn->arg_begin(), AuxAddr, Addr,
516 Name, Size, Data});
517 Builder.CreateBr(IfEndBB);
518 Switch->addCase(Builder.getInt32(llvm::offloading::OffloadGlobalManagedEntry),
519 SwManagedBB);
520 // Create surface variable registration code.
521 Builder.SetInsertPoint(SwSurfaceBB);
522 if (EmitSurfacesAndTextures)
523 Builder.CreateCall(RegSurface, {RegGlobalsFn->arg_begin(), Addr, Name, Name,
524 Data, Extern});
525 Builder.CreateBr(IfEndBB);
526 Switch->addCase(Builder.getInt32(llvm::offloading::OffloadGlobalSurfaceEntry),
527 SwSurfaceBB);
528
529 // Create texture variable registration code.
530 Builder.SetInsertPoint(SwTextureBB);
531 if (EmitSurfacesAndTextures)
532 Builder.CreateCall(RegTexture, {RegGlobalsFn->arg_begin(), Addr, Name, Name,
533 Data, Normalized, Extern});
534 Builder.CreateBr(IfEndBB);
535 Switch->addCase(Builder.getInt32(llvm::offloading::OffloadGlobalTextureEntry),
536 SwTextureBB);
537
538 Builder.SetInsertPoint(IfEndBB);
539 auto *NewEntry = Builder.CreateInBoundsGEP(
540 offloading::getEntryTy(M), Entry, ConstantInt::get(getSizeTTy(M), 1));
541 auto *Cmp = Builder.CreateICmpEQ(NewEntry, EntriesE);
542 Entry->addIncoming(EntriesB, &RegGlobalsFn->getEntryBlock());
543 Entry->addIncoming(NewEntry, IfEndBB);
544 Builder.CreateCondBr(Cmp, ExitBB, EntryBB);
545 Builder.SetInsertPoint(ExitBB);
546 Builder.CreateRetVoid();
547
548 return RegGlobalsFn;
549}
550
551// Create the constructor and destructor to register the fatbinary with the CUDA
552// runtime.
553void createRegisterFatbinFunction(Module &M, GlobalVariable *FatbinDesc,
554 bool IsHIP, EntryArrayTy EntryArray,
555 StringRef Suffix,
556 bool EmitSurfacesAndTextures) {
557 LLVMContext &C = M.getContext();
558 auto *CtorFuncTy = FunctionType::get(Type::getVoidTy(C), /*isVarArg*/ false);
559 auto *CtorFunc = Function::Create(
561 (IsHIP ? ".hip.fatbin_reg" : ".cuda.fatbin_reg") + Suffix, &M);
562 CtorFunc->setSection(".text.startup");
563
564 auto *DtorFuncTy = FunctionType::get(Type::getVoidTy(C), /*isVarArg*/ false);
565 auto *DtorFunc = Function::Create(
567 (IsHIP ? ".hip.fatbin_unreg" : ".cuda.fatbin_unreg") + Suffix, &M);
568 DtorFunc->setSection(".text.startup");
569
570 auto *PtrTy = PointerType::getUnqual(C);
571
572 // Get the __cudaRegisterFatBinary function declaration.
573 auto *RegFatTy = FunctionType::get(PtrTy, PtrTy, /*isVarArg=*/false);
574 FunctionCallee RegFatbin = M.getOrInsertFunction(
575 IsHIP ? "__hipRegisterFatBinary" : "__cudaRegisterFatBinary", RegFatTy);
576 // Get the __cudaRegisterFatBinaryEnd function declaration.
577 auto *RegFatEndTy =
578 FunctionType::get(Type::getVoidTy(C), PtrTy, /*isVarArg=*/false);
579 FunctionCallee RegFatbinEnd =
580 M.getOrInsertFunction("__cudaRegisterFatBinaryEnd", RegFatEndTy);
581 // Get the __cudaUnregisterFatBinary function declaration.
582 auto *UnregFatTy =
583 FunctionType::get(Type::getVoidTy(C), PtrTy, /*isVarArg=*/false);
584 FunctionCallee UnregFatbin = M.getOrInsertFunction(
585 IsHIP ? "__hipUnregisterFatBinary" : "__cudaUnregisterFatBinary",
586 UnregFatTy);
587
588 auto *AtExitTy =
589 FunctionType::get(Type::getInt32Ty(C), PtrTy, /*isVarArg=*/false);
590 FunctionCallee AtExit = M.getOrInsertFunction("atexit", AtExitTy);
591
592 auto *BinaryHandleGlobal = new llvm::GlobalVariable(
593 M, PtrTy, false, llvm::GlobalValue::InternalLinkage,
595 (IsHIP ? ".hip.binary_handle" : ".cuda.binary_handle") + Suffix);
596
597 // Create the constructor to register this image with the runtime.
598 IRBuilder<> CtorBuilder(BasicBlock::Create(C, "entry", CtorFunc));
599 CallInst *Handle = CtorBuilder.CreateCall(
600 RegFatbin,
602 CtorBuilder.CreateAlignedStore(
603 Handle, BinaryHandleGlobal,
604 Align(M.getDataLayout().getPointerTypeSize(PtrTy)));
605 CtorBuilder.CreateCall(createRegisterGlobalsFunction(M, IsHIP, EntryArray,
606 Suffix,
607 EmitSurfacesAndTextures),
608 Handle);
609 if (!IsHIP)
610 CtorBuilder.CreateCall(RegFatbinEnd, Handle);
611 CtorBuilder.CreateCall(AtExit, DtorFunc);
612 CtorBuilder.CreateRetVoid();
613
614 // Create the destructor to unregister the image with the runtime. We cannot
615 // use a standard global destructor after CUDA 9.2 so this must be called by
616 // `atexit()` instead.
617 IRBuilder<> DtorBuilder(BasicBlock::Create(C, "entry", DtorFunc));
618 LoadInst *BinaryHandle = DtorBuilder.CreateAlignedLoad(
619 PtrTy, BinaryHandleGlobal,
620 Align(M.getDataLayout().getPointerTypeSize(PtrTy)));
621 DtorBuilder.CreateCall(UnregFatbin, BinaryHandle);
622 DtorBuilder.CreateRetVoid();
623
624 // Add this function to constructors.
625 appendToGlobalCtors(M, CtorFunc, /*Priority=*/101);
626}
627
628/// SYCLWrapper helper class that creates all LLVM IRs wrapping given images.
629class SYCLWrapper {
630public:
631 SYCLWrapper(Module &M, const SYCLJITOptions &Options)
632 : M(M), C(M.getContext()), Options(Options) {
633 EntryTy = offloading::getEntryTy(M);
634 SyclDeviceImageTy = getSyclDeviceImageTy();
635 SyclBinDescTy = getSyclBinDescTy();
636 }
637
638 /// Creates binary descriptor for the given device images. Binary descriptor
639 /// is an object that is passed to the offloading runtime at program startup
640 /// and it describes all device images available in the executable or shared
641 /// library. It is defined as follows:
642 ///
643 /// \code
644 /// __attribute__((visibility("hidden")))
645 /// __tgt_offload_entry *__sycl_offload_entries_arr0[];
646 /// ...
647 /// __attribute__((visibility("hidden")))
648 /// __tgt_offload_entry *__sycl_offload_entries_arrN[];
649 ///
650 /// __attribute__((visibility("hidden")))
651 /// extern const char *CompileOptions = "...";
652 /// ...
653 /// __attribute__((visibility("hidden")))
654 /// extern const char *LinkOptions = "...";
655 /// ...
656 ///
657 /// static const char Image0[] = { ... };
658 /// ...
659 /// static const char ImageN[] = { ... };
660 ///
661 /// static const __sycl.tgt_device_image Images[] = {
662 /// {
663 /// Version, // Version
664 /// OffloadKind, // OffloadKind
665 /// Format, // Format of the image.
666 // TripleString, // Arch
667 /// CompileOptions, // CompileOptions
668 /// LinkOptions, // LinkOptions
669 /// Image0, // ImageStart
670 /// Image0 + IMAGE0_SIZE, // ImageEnd
671 /// __sycl_offload_entries_arr0, // EntriesBegin
672 /// __sycl_offload_entries_arr0 + ENTRIES0_SIZE, // EntriesEnd
673 /// NULL, // PropertiesBegin
674 /// NULL, // PropertiesEnd
675 /// },
676 /// ...
677 /// };
678 ///
679 /// static const __sycl.tgt_bin_desc FatbinDesc = {
680 /// Version, //Version
681 /// sizeof(Images) / sizeof(Images[0]), //NumDeviceImages
682 /// Images, //DeviceImages
683 /// NULL, //HostEntriesBegin
684 /// NULL //HostEntriesEnd
685 /// };
686 /// \endcode
687 ///
688 /// \returns Global variable that represents FatbinDesc.
689 GlobalVariable *createFatbinDesc(ArrayRef<OffloadFile> OffloadFiles) {
690 StringRef OffloadKindTag = ".sycl_offloading.";
691 SmallVector<Constant *> WrappedImages;
692 WrappedImages.reserve(OffloadFiles.size());
693 for (size_t I = 0, E = OffloadFiles.size(); I != E; ++I)
694 WrappedImages.push_back(
695 wrapImage(*OffloadFiles[I].getBinary(), Twine(I), OffloadKindTag));
696
697 return combineWrappedImages(WrappedImages, OffloadKindTag);
698 }
699
700 void createRegisterFatbinFunction(GlobalVariable *FatbinDesc) {
701 FunctionType *FuncTy =
702 FunctionType::get(Type::getVoidTy(C), /*isVarArg*/ false);
704 Twine("sycl") + ".descriptor_reg", &M);
705 Func->setSection(".text.startup");
706
707 // Get RegFuncName function declaration.
708 FunctionType *RegFuncTy =
709 FunctionType::get(Type::getVoidTy(C), PointerType::getUnqual(C),
710 /*isVarArg=*/false);
711 FunctionCallee RegFuncC =
712 M.getOrInsertFunction("__sycl_register_lib", RegFuncTy);
713
714 // Construct function body.
715 IRBuilder Builder(BasicBlock::Create(C, "entry", Func));
716 Builder.CreateCall(RegFuncC, FatbinDesc);
717 Builder.CreateRetVoid();
718
719 // Add this function to constructors.
720 appendToGlobalCtors(M, Func, /*Priority*/ 1);
721 }
722
723 void createUnregisterFunction(GlobalVariable *FatbinDesc) {
724 FunctionType *FuncTy =
725 FunctionType::get(Type::getVoidTy(C), /*isVarArg*/ false);
727 "sycl.descriptor_unreg", &M);
728 Func->setSection(".text.startup");
729
730 // Get UnregFuncName function declaration.
731 FunctionType *UnRegFuncTy =
732 FunctionType::get(Type::getVoidTy(C), PointerType::getUnqual(C),
733 /*isVarArg=*/false);
734 FunctionCallee UnRegFuncC =
735 M.getOrInsertFunction("__sycl_unregister_lib", UnRegFuncTy);
736
737 // Construct function body
738 IRBuilder<> Builder(BasicBlock::Create(C, "entry", Func));
739 Builder.CreateCall(UnRegFuncC, FatbinDesc);
740 Builder.CreateRetVoid();
741
742 // Add this function to global destructors.
743 appendToGlobalDtors(M, Func, /*Priority*/ 1);
744 }
745
746private:
747 IntegerType *getSizeTTy() {
748 switch (M.getDataLayout().getPointerSize()) {
749 case 4:
750 return Type::getInt32Ty(C);
751 case 8:
752 return Type::getInt64Ty(C);
753 }
754 llvm_unreachable("unsupported pointer type size");
755 }
756
757 SmallVector<Constant *, 2> getSizetConstPair(size_t First, size_t Second) {
758 IntegerType *SizeTTy = getSizeTTy();
759 return SmallVector<Constant *, 2>{ConstantInt::get(SizeTTy, First),
760 ConstantInt::get(SizeTTy, Second)};
761 }
762
763 /// Note: Properties aren't supported and the support is going
764 /// to be added later.
765 /// Creates a structure corresponding to:
766 /// SYCL specific image descriptor type.
767 /// \code
768 /// struct __sycl.tgt_device_image {
769 /// // Version of this structure - for backward compatibility;
770 /// // all modifications which change order/type/offsets of existing fields
771 /// // should increment the version.
772 /// uint16_t Version;
773 /// // The kind of offload model the image employs.
774 /// uint8_t OffloadKind;
775 /// // Format of the image data - SPIRV, LLVMIR bitcode, etc.
776 /// uint8_t Format;
777 /// // Null-terminated string representation of the device's target
778 /// // architecture.
779 /// const char *Arch;
780 /// // A null-terminated string; target- and compiler-specific options
781 /// // which are passed to the device compiler at runtime.
782 /// const char *CompileOptions;
783 /// // A null-terminated string; target- and compiler-specific options
784 /// // which are passed to the device linker at runtime.
785 /// const char *LinkOptions;
786 /// // Pointer to the device binary image start.
787 /// void *ImageStart;
788 /// // Pointer to the device binary image end.
789 /// void *ImageEnd;
790 /// // The entry table.
791 /// __tgt_offload_entry *EntriesBegin;
792 /// __tgt_offload_entry *EntriesEnd;
793 /// const char *PropertiesBegin;
794 /// const char *PropertiesEnd;
795 /// };
796 /// \endcode
797 StructType *getSyclDeviceImageTy() {
798 return StructType::create(
799 {
800 Type::getInt16Ty(C), // Version
801 Type::getInt8Ty(C), // OffloadKind
802 Type::getInt8Ty(C), // Format
803 PointerType::getUnqual(C), // Arch
804 PointerType::getUnqual(C), // CompileOptions
805 PointerType::getUnqual(C), // LinkOptions
806 PointerType::getUnqual(C), // ImageStart
807 PointerType::getUnqual(C), // ImageEnd
808 PointerType::getUnqual(C), // EntriesBegin
809 PointerType::getUnqual(C), // EntriesEnd
810 PointerType::getUnqual(C), // PropertiesBegin
811 PointerType::getUnqual(C) // PropertiesEnd
812 },
813 "__sycl.tgt_device_image");
814 }
815
816 /// Creates a structure for SYCL specific binary descriptor type. Corresponds
817 /// to:
818 ///
819 /// \code
820 /// struct __sycl.tgt_bin_desc {
821 /// // version of this structure - for backward compatibility;
822 /// // all modifications which change order/type/offsets of existing fields
823 /// // should increment the version.
824 /// uint16_t Version;
825 /// uint16_t NumDeviceImages;
826 /// __sycl.tgt_device_image *DeviceImages;
827 /// // the offload entry table
828 /// __tgt_offload_entry *HostEntriesBegin;
829 /// __tgt_offload_entry *HostEntriesEnd;
830 /// };
831 /// \endcode
832 StructType *getSyclBinDescTy() {
833 return StructType::create(
834 {Type::getInt16Ty(C), Type::getInt16Ty(C), PointerType::getUnqual(C),
835 PointerType::getUnqual(C), PointerType::getUnqual(C)},
836 "__sycl.tgt_bin_desc");
837 }
838
839 /// Adds a global readonly variable that is initialized by given
840 /// \p Initializer to the module.
841 GlobalVariable *addGlobalArrayVariable(const Twine &Name,
842 ArrayRef<char> Initializer,
843 const Twine &Section = "") {
844 Constant *Arr = ConstantDataArray::get(M.getContext(), Initializer);
845 GlobalVariable *Var =
846 new GlobalVariable(M, Arr->getType(), /*isConstant*/ true,
847 GlobalVariable::InternalLinkage, Arr, Name);
848 Var->setUnnamedAddr(GlobalValue::UnnamedAddr::Global);
849
850 SmallVector<char, 32> NameBuf;
851 StringRef SectionName = Section.toStringRef(NameBuf);
852 if (!SectionName.empty())
853 Var->setSection(SectionName);
854 return Var;
855 }
856
857 /// Adds given \p Buf as a global variable into the module.
858 /// \returns Pair of pointers that point at the beginning and the end of the
859 /// variable.
860 std::pair<Constant *, Constant *>
861 addArrayToModule(ArrayRef<char> Buf, const Twine &Name,
862 const Twine &Section = "") {
863 GlobalVariable *Var = addGlobalArrayVariable(Name, Buf, Section);
865 getSizetConstPair(0, 0));
867 Var->getValueType(), Var, getSizetConstPair(0, Buf.size()));
868 return std::make_pair(ImageB, ImageE);
869 }
870
871 /// Adds given \p Data as constant byte array in the module.
872 /// \returns Constant pointer to the added data. The pointer type does not
873 /// carry size information.
874 Constant *addRawDataToModule(ArrayRef<char> Data, const Twine &Name) {
875 GlobalVariable *Var = addGlobalArrayVariable(Name, Data);
877 getSizetConstPair(0, 0));
878 return DataPtr;
879 }
880
881 /// Creates a global variable of const char* type and creates an
882 /// initializer that initializes it with \p Str.
883 ///
884 /// \returns Link-time constant pointer (constant expr) to that
885 /// variable.
886 Constant *addStringToModule(StringRef Str, const Twine &Name) {
888 GlobalVariable *Var =
889 new GlobalVariable(M, Arr->getType(), /*isConstant*/ true,
890 GlobalVariable::InternalLinkage, Arr, Name);
891 Var->setUnnamedAddr(GlobalValue::UnnamedAddr::Global);
892 return Var;
893 }
894
895 /// Each image contains its own set of symbols, which may contain different
896 /// symbols than other images. This function constructs an array of
897 /// symbol entries for a particular image.
898 ///
899 /// \returns Pointers to the beginning and end of the array.
900 std::pair<Constant *, Constant *>
901 initOffloadEntriesPerImage(StringRef Entries, const Twine &OffloadKindTag) {
902 SmallVector<Constant *> EntriesInits;
903 const char *Current = Entries.data();
904 const char *End = Current + Entries.size();
905 while (Current < End) {
906 StringRef Name(Current);
907 Current += Name.size() + 1;
908
909 if (Name.empty())
910 continue;
911
912 GlobalVariable *GV = emitOffloadingEntry(
913 M, /*Kind*/ OffloadKind::OFK_SYCL,
914 Constant::getNullValue(PointerType::getUnqual(C)), Name, /*Size*/ 0,
915 /*Flags*/ 0, /*Data*/ 0);
916 EntriesInits.push_back(GV->getInitializer());
917 }
918
920 ArrayType::get(EntryTy, EntriesInits.size()), EntriesInits);
921 GlobalVariable *EntriesGV = new GlobalVariable(
922 M, Arr->getType(), /*isConstant*/ true, GlobalVariable::InternalLinkage,
923 Arr, OffloadKindTag + "entries_arr");
924
926 EntriesGV->getValueType(), EntriesGV, getSizetConstPair(0, 0));
928 EntriesGV->getValueType(), EntriesGV,
929 getSizetConstPair(0, EntriesInits.size()));
930 return std::make_pair(EntriesB, EntriesE);
931 }
932
933 Constant *wrapImage(const OffloadBinary &OB, const Twine &ImageID,
934 StringRef OffloadKindTag) {
935 // Note: Intel DPC++ compiler had 2 versions of this structure
936 // and clang++ has a third different structure. To avoid ABI incompatibility
937 // between generated device images the Version here starts from 3.
938 constexpr uint16_t DeviceImageStructVersion = 3;
940 ConstantInt::get(Type::getInt16Ty(C), DeviceImageStructVersion);
941 Constant *OffloadKindConstant = ConstantInt::get(
942 Type::getInt8Ty(C), static_cast<uint8_t>(OB.getOffloadKind()));
943 Constant *ImageKindConstant = ConstantInt::get(
944 Type::getInt8Ty(C), static_cast<uint8_t>(OB.getImageKind()));
945 StringRef Triple = OB.getString("triple");
946 Constant *TripleConstant =
947 addStringToModule(Triple, Twine(OffloadKindTag) + "target." + ImageID);
948 Constant *CompileOptions =
949 addStringToModule(Options.CompileOptions,
950 Twine(OffloadKindTag) + "opts.compile." + ImageID);
951 Constant *LinkOptions = addStringToModule(
952 Options.LinkOptions, Twine(OffloadKindTag) + "opts.link." + ImageID);
953
954 // Note: NULL for now.
955 std::pair<Constant *, Constant *> PropertiesConstants = {
956 Constant::getNullValue(PointerType::getUnqual(C)),
957 Constant::getNullValue(PointerType::getUnqual(C))};
958
959 StringRef RawImage = OB.getImage();
960 std::pair<Constant *, Constant *> Binary = addArrayToModule(
961 ArrayRef<char>(RawImage.begin(), RawImage.end()),
962 Twine(OffloadKindTag) + ImageID + ".data", ".llvm.offloading");
963
964 // For SYCL images offload entries are defined here per image.
965 std::pair<Constant *, Constant *> ImageEntriesPtrs =
966 initOffloadEntriesPerImage(OB.getString("symbols"), OffloadKindTag);
967
968 // .first and .second arguments below correspond to start and end pointers
969 // respectively.
970 Constant *WrappedBinary = ConstantStruct::get(
971 SyclDeviceImageTy, Version, OffloadKindConstant, ImageKindConstant,
972 TripleConstant, CompileOptions, LinkOptions, Binary.first,
973 Binary.second, ImageEntriesPtrs.first, ImageEntriesPtrs.second,
974 PropertiesConstants.first, PropertiesConstants.second);
975
976 return WrappedBinary;
977 }
978
979 GlobalVariable *combineWrappedImages(ArrayRef<Constant *> WrappedImages,
980 StringRef OffloadKindTag) {
981 Constant *ImagesData = ConstantArray::get(
982 ArrayType::get(SyclDeviceImageTy, WrappedImages.size()), WrappedImages);
983 GlobalVariable *ImagesGV =
984 new GlobalVariable(M, ImagesData->getType(), /*isConstant*/ true,
986 Twine(OffloadKindTag) + "device_images");
987 ImagesGV->setUnnamedAddr(GlobalValue::UnnamedAddr::Global);
988
989 Constant *EntriesB = Constant::getNullValue(PointerType::getUnqual(C));
990 Constant *EntriesE = Constant::getNullValue(PointerType::getUnqual(C));
991 static constexpr uint16_t BinDescStructVersion = 1;
992 Constant *DescInit = ConstantStruct::get(
993 SyclBinDescTy,
994 ConstantInt::get(Type::getInt16Ty(C), BinDescStructVersion),
995 ConstantInt::get(Type::getInt16Ty(C), WrappedImages.size()), ImagesGV,
996 EntriesB, EntriesE);
997
998 return new GlobalVariable(M, DescInit->getType(), /*isConstant*/ true,
1000 Twine(OffloadKindTag) + "descriptor");
1001 }
1002
1003 Module &M;
1004 LLVMContext &C;
1005 SYCLJITOptions Options;
1006
1007 StructType *EntryTy = nullptr;
1008 StructType *SyclDeviceImageTy = nullptr;
1009 StructType *SyclBinDescTy = nullptr;
1010}; // end of SYCLWrapper
1011
1012} // namespace
1013
1015 EntryArrayTy EntryArray,
1016 llvm::StringRef Suffix, bool Relocatable) {
1018 createBinDesc(M, Images, EntryArray, Suffix, Relocatable);
1019 if (!Desc)
1021 "No binary descriptors created.");
1022 createRegisterFunction(M, Desc, Suffix);
1023 return Error::success();
1024}
1025
1027 EntryArrayTy EntryArray,
1028 llvm::StringRef Suffix,
1029 bool EmitSurfacesAndTextures) {
1030 GlobalVariable *Desc = createFatbinDesc(M, Image, /*IsHip=*/false, Suffix);
1031 if (!Desc)
1033 "No fatbin section created.");
1034
1035 createRegisterFatbinFunction(M, Desc, /*IsHip=*/false, EntryArray, Suffix,
1036 EmitSurfacesAndTextures);
1037 return Error::success();
1038}
1039
1041 EntryArrayTy EntryArray, llvm::StringRef Suffix,
1042 bool EmitSurfacesAndTextures) {
1043 GlobalVariable *Desc = createFatbinDesc(M, Image, /*IsHip=*/true, Suffix);
1044 if (!Desc)
1046 "No fatbin section created.");
1047
1048 createRegisterFatbinFunction(M, Desc, /*IsHip=*/true, EntryArray, Suffix,
1049 EmitSurfacesAndTextures);
1050 return Error::success();
1051}
1052
1055 SYCLWrapper W(M, Options);
1056 MemoryBufferRef MBR(StringRef(Buffer.begin(), Buffer.size()),
1057 /*Identifier*/ "");
1058 SmallVector<OffloadFile> OffloadFiles;
1059 if (Error E = extractOffloadBinaries(MBR, OffloadFiles))
1060 return E;
1061
1062 GlobalVariable *Desc = W.createFatbinDesc(OffloadFiles);
1063 if (!Desc)
1065 "No binary descriptors created.");
1066
1067 W.createRegisterFatbinFunction(Desc);
1068 W.createUnregisterFunction(Desc);
1069 return Error::success();
1070}
static IntegerType * getSizeTTy(IRBuilderBase &B, const TargetLibraryInfo *TLI)
static GCRegistry::Add< CoreCLRGC > E("coreclr", "CoreCLR-compatible GC")
This file contains the declarations for the subclasses of Constant, which represent the different fla...
Module.h This file contains the declarations for the Module class.
static LVOptions Options
Definition LVOptions.cpp:25
#define I(x, y, z)
Definition MD5.cpp:57
Machine Check Debug Module
This file defines the SmallVector class.
@ ConstantBit
ArrayRef - Represent a constant reference to an array (0 or more elements consecutively in memory),...
Definition ArrayRef.h:40
size_t size() const
size - Get the array size.
Definition ArrayRef.h:142
iterator begin() const
Definition ArrayRef.h:130
static LLVM_ABI ArrayType * get(Type *ElementType, uint64_t NumElements)
This static method is the primary way to construct an ArrayType.
static BasicBlock * Create(LLVMContext &Context, const Twine &Name="", Function *Parent=nullptr, BasicBlock *InsertBefore=nullptr)
Creates a new BasicBlock.
Definition BasicBlock.h:206
This class represents a function call, abstracting a target machine's calling convention.
static LLVM_ABI Constant * get(ArrayType *T, ArrayRef< Constant * > V)
static LLVM_ABI Constant * getString(LLVMContext &Context, StringRef Initializer, bool AddNull=true)
This method constructs a CDS and initializes it with a text string.
static Constant * get(LLVMContext &Context, ArrayRef< ElementTy > Elts)
get() constructor - Return a constant with array type with an element count and element type matching...
Definition Constants.h:720
static LLVM_ABI Constant * getPointerBitCastOrAddrSpaceCast(Constant *C, Type *Ty)
Create a BitCast or AddrSpaceCast for a pointer type depending on the address space.
static Constant * getGetElementPtr(Type *Ty, Constant *C, ArrayRef< Constant * > IdxList, GEPNoWrapFlags NW=GEPNoWrapFlags::none(), std::optional< ConstantRange > InRange=std::nullopt, Type *OnlyIfReducedTy=nullptr)
Getelementptr form.
Definition Constants.h:1284
static LLVM_ABI ConstantPointerNull * get(PointerType *T)
Static factory methods - Return objects of the specified value.
static LLVM_ABI Constant * get(StructType *T, ArrayRef< Constant * > V)
This is an important base class in LLVM.
Definition Constant.h:43
static LLVM_ABI Constant * getAllOnesValue(Type *Ty)
static LLVM_ABI Constant * getNullValue(Type *Ty)
Constructor to create a '0' constant of arbitrary type.
Lightweight error class with error context and mandatory checking.
Definition Error.h:159
static ErrorSuccess success()
Create a success value.
Definition Error.h:336
A handy container for a FunctionType+Callee-pointer pair, which can be passed around as a single enti...
static LLVM_ABI FunctionType * get(Type *Result, ArrayRef< Type * > Params, bool isVarArg)
This static method is the primary way of constructing a FunctionType.
static Function * Create(FunctionType *Ty, LinkageTypes Linkage, unsigned AddrSpace, const Twine &N="", Module *M=nullptr)
Definition Function.h:168
LLVM_ABI void setSection(StringRef S)
Change the section for this global.
Definition Globals.cpp:276
void setUnnamedAddr(UnnamedAddr Val)
@ InternalLinkage
Rename collisions when linking (static functions).
Definition GlobalValue.h:60
Type * getValueType() const
const Constant * getInitializer() const
getInitializer - Return the initializer for this global variable.
This provides a uniform API for creating instructions and inserting them into a basic block: either a...
Definition IRBuilder.h:2788
Class to represent integer types.
This is an important class for using LLVM in a threaded context.
Definition LLVMContext.h:68
An instruction for reading from memory.
A Module instance is used to store all the information related to an LLVM module.
Definition Module.h:67
static PointerType * getUnqual(Type *ElementType)
This constructs a pointer to an object of the specified type in the default address space (address sp...
static LLVM_ABI PointerType * get(Type *ElementType, unsigned AddressSpace)
This constructs a pointer to an object of the specified type in a numbered address space.
void reserve(size_type N)
void push_back(const T &Elt)
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
StringRef - Represent a constant reference to a string, i.e.
Definition StringRef.h:55
iterator begin() const
Definition StringRef.h:113
constexpr size_t size() const
size - Get the string size.
Definition StringRef.h:143
constexpr const char * data() const
data - Get a pointer to the start of the string (which may not be null terminated).
Definition StringRef.h:137
iterator end() const
Definition StringRef.h:115
Class to represent struct types.
static LLVM_ABI StructType * getTypeByName(LLVMContext &C, StringRef Name)
Return the type with the specified name, or null if there is none by that name.
Definition Type.cpp:738
static LLVM_ABI StructType * create(LLVMContext &Context, StringRef Name)
This creates an identified struct.
Definition Type.cpp:619
Triple - Helper class for working with autoconf configuration names.
Definition Triple.h:47
bool isMacOSX() const
Is this a Mac OS X triple.
Definition Triple.h:589
The instances of the Type class are immutable: once they are created, they are never changed.
Definition Type.h:45
static LLVM_ABI IntegerType * getInt64Ty(LLVMContext &C)
Definition Type.cpp:297
static LLVM_ABI IntegerType * getInt32Ty(LLVMContext &C)
Definition Type.cpp:296
static LLVM_ABI Type * getVoidTy(LLVMContext &C)
Definition Type.cpp:280
static LLVM_ABI IntegerType * getInt16Ty(LLVMContext &C)
Definition Type.cpp:295
Type * getType() const
All values are typed, get the type of this value.
Definition Value.h:256
static uint64_t getAlignment()
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
const char SectionName[]
@ C
The default llvm calling convention, compatible with C.
Definition CallingConv.h:34
@ OB
OB - OneByte - Set if this instruction has a one byte opcode.
@ Switch
The "resume-switch" lowering, where there are separate resume and destroy functions that are shared b...
Definition CoroShape.h:31
LLVM_ABI Error extractOffloadBinaries(MemoryBufferRef Buffer, SmallVectorImpl< OffloadFile > &Binaries)
Extracts embedded device offloading code from a memory Buffer to a list of Binaries.
LLVM_ABI GlobalVariable * emitOffloadingEntry(Module &M, object::OffloadKind Kind, Constant *Addr, StringRef Name, uint64_t Size, uint32_t Flags, uint64_t Data, Constant *AuxAddr=nullptr, StringRef SectionName="llvm_offload_entries")
Create an offloading section struct used to register this global at runtime.
Definition Utility.cpp:86
LLVM_ABI StructType * getEntryTy(Module &M)
Returns the type of the offloading entry we use to store kernels and globals that will be registered ...
Definition Utility.cpp:26
LLVM_ABI llvm::Error wrapSYCLBinaries(llvm::Module &M, llvm::ArrayRef< char > Buffer, SYCLJITOptions Options=SYCLJITOptions())
Wraps OffloadBinaries in the given Buffers into the module M as global symbols and registers the imag...
@ OffloadGlobalSurfaceEntry
Mark the entry as a surface variable.
Definition Utility.h:58
@ OffloadGlobalTextureEntry
Mark the entry as a texture variable.
Definition Utility.h:60
@ OffloadGlobalNormalized
Mark the entry as being a normalized surface.
Definition Utility.h:66
@ OffloadGlobalEntry
Mark the entry as a global entry.
Definition Utility.h:54
@ OffloadGlobalManagedEntry
Mark the entry as a managed global variable.
Definition Utility.h:56
@ OffloadGlobalExtern
Mark the entry as being extern.
Definition Utility.h:62
@ OffloadGlobalConstant
Mark the entry as being constant.
Definition Utility.h:64
LLVM_ABI llvm::Error wrapOpenMPBinaries(llvm::Module &M, llvm::ArrayRef< llvm::ArrayRef< char > > Images, EntryArrayTy EntryArray, llvm::StringRef Suffix="", bool Relocatable=false)
Wraps the input device images into the module M as global symbols and registers the images with the O...
std::pair< GlobalVariable *, GlobalVariable * > EntryArrayTy
LLVM_ABI llvm::Error wrapHIPBinary(llvm::Module &M, llvm::ArrayRef< char > Images, EntryArrayTy EntryArray, llvm::StringRef Suffix="", bool EmitSurfacesAndTextures=true)
Wraps the input bundled image into the module M as global symbols and registers the images with the H...
LLVM_ABI llvm::Error wrapCudaBinary(llvm::Module &M, llvm::ArrayRef< char > Images, EntryArrayTy EntryArray, llvm::StringRef Suffix="", bool EmitSurfacesAndTextures=true)
Wraps the input fatbinary image into the module M as global symbols and registers the images with the...
NodeAddr< FuncNode * > Func
Definition RDFGraph.h:393
Context & getContext() const
Definition BasicBlock.h:99
This is an optimization pass for GlobalISel generic memory operations.
Definition Types.h:26
LLVM_ABI file_magic identify_magic(StringRef magic)
Identify the type of a binary file based on how magical it is.
Definition Magic.cpp:33
LLVM_ABI std::error_code inconvertibleErrorCode()
The value returned by this function can be returned from convertToErrorCode for Error values where no...
Definition Error.cpp:94
Error createStringError(std::error_code EC, char const *Fmt, const Ts &... Vals)
Create formatted StringError object.
Definition Error.h:1305
Op::Description Desc
FunctionAddr VTableAddr uintptr_t uintptr_t Version
Definition InstrProf.h:302
class LLVM_GSL_OWNER SmallVector
Forward declaration of SmallVector so that calculateSmallVectorDefaultInlinedElements can reference s...
@ First
Helpers to iterate all locations in the MemoryEffectsBase class.
Definition ModRef.h:74
FunctionAddr VTableAddr uintptr_t uintptr_t Data
Definition InstrProf.h:189
IRBuilder(LLVMContext &, FolderTy, InserterTy, MDNode *, ArrayRef< OperandBundleDef >) -> IRBuilder< FolderTy, InserterTy >
ArrayRef(const T &OneElt) -> ArrayRef< T >
LLVM_ABI void appendToGlobalCtors(Module &M, Function *F, int Priority, Constant *Data=nullptr)
Append F to the list of global ctors of module M with the given Priority.
LLVM_ABI void appendToGlobalDtors(Module &M, Function *F, int Priority, Constant *Data=nullptr)
Same as appendToGlobalCtors(), but for global dtors.
@ Extern
Replace returns with jump to thunk, don't emit thunk.
Definition CodeGen.h:163
This struct is a compact representation of a valid (non-zero power of two) alignment.
Definition Alignment.h:39
@ offload_binary
LLVM offload object file.
Definition Magic.h:58