diff --git a/clang/lib/CodeGen/CGOpenMPRuntime.h b/clang/lib/CodeGen/CGOpenMPRuntime.h --- a/clang/lib/CodeGen/CGOpenMPRuntime.h +++ b/clang/lib/CodeGen/CGOpenMPRuntime.h @@ -518,15 +518,6 @@ /// kmp_int64 st; // stride /// }; QualType KmpDimTy; - /// Type struct __tgt_offload_entry{ - /// void *addr; // Pointer to the offload entry info. - /// // (function or global) - /// char *name; // Name of the function or global. - /// size_t size; // Size of the entry info (0 if it a function). - /// int32_t flags; - /// int32_t reserved; - /// }; - QualType TgtOffloadEntryQTy; /// Entity that registers the offloading constants that were emitted so /// far. class OffloadEntriesInfoManagerTy { @@ -782,9 +773,6 @@ /// metadata. void loadOffloadInfoMetadata(); - /// Returns __tgt_offload_entry type. - QualType getTgtOffloadEntryQTy(); - /// Start scanning from statement \a S and and emit all target regions /// found along the way. /// \param S Starting statement. diff --git a/clang/lib/CodeGen/CGOpenMPRuntime.cpp b/clang/lib/CodeGen/CGOpenMPRuntime.cpp --- a/clang/lib/CodeGen/CGOpenMPRuntime.cpp +++ b/clang/lib/CodeGen/CGOpenMPRuntime.cpp @@ -1329,51 +1329,6 @@ return Res; } -static void buildStructValue(ConstantStructBuilder &Fields, CodeGenModule &CGM, - const RecordDecl *RD, const CGRecordLayout &RL, - ArrayRef Data) { - llvm::StructType *StructTy = RL.getLLVMType(); - unsigned PrevIdx = 0; - ConstantInitBuilder CIBuilder(CGM); - const auto *DI = Data.begin(); - for (const FieldDecl *FD : RD->fields()) { - unsigned Idx = RL.getLLVMFieldNo(FD); - // Fill the alignment. - for (unsigned I = PrevIdx; I < Idx; ++I) - Fields.add(llvm::Constant::getNullValue(StructTy->getElementType(I))); - PrevIdx = Idx + 1; - Fields.add(*DI); - ++DI; - } -} - -template -static llvm::GlobalVariable * -createGlobalStruct(CodeGenModule &CGM, QualType Ty, bool IsConstant, - ArrayRef Data, const Twine &Name, - As &&... Args) { - const auto *RD = cast(Ty->getAsTagDecl()); - const CGRecordLayout &RL = CGM.getTypes().getCGRecordLayout(RD); - ConstantInitBuilder CIBuilder(CGM); - ConstantStructBuilder Fields = CIBuilder.beginStruct(RL.getLLVMType()); - buildStructValue(Fields, CGM, RD, RL, Data); - return Fields.finishAndCreateGlobal( - Name, CGM.getContext().getAlignOfGlobalVarInChars(Ty), IsConstant, - std::forward(Args)...); -} - -template -static void -createConstantGlobalStructAndAddToParent(CodeGenModule &CGM, QualType Ty, - ArrayRef Data, - T &Parent) { - const auto *RD = cast(Ty->getAsTagDecl()); - const CGRecordLayout &RL = CGM.getTypes().getCGRecordLayout(RD); - ConstantStructBuilder Fields = Parent.beginStruct(RL.getLLVMType()); - buildStructValue(Fields, CGM, RD, RL, Data); - Fields.finishAndAddTo(Parent); -} - void CGOpenMPRuntime::setLocThreadIdInsertPt(CodeGenFunction &CGF, bool AtCurrentPoint) { auto &Elem = OpenMPLocThreadIDMap.FindAndConstruct(CGF.CurFn); @@ -3136,32 +3091,7 @@ void CGOpenMPRuntime::createOffloadEntry( llvm::Constant *ID, llvm::Constant *Addr, uint64_t Size, int32_t Flags, llvm::GlobalValue::LinkageTypes Linkage) { - StringRef Name = Addr->getName(); - llvm::Module &M = CGM.getModule(); - llvm::LLVMContext &C = M.getContext(); - - // Create constant string with the name. - llvm::Constant *StrPtrInit = llvm::ConstantDataArray::getString(C, Name); - - std::string StringName = getName({"omp_offloading", "entry_name"}); - auto *Str = new llvm::GlobalVariable( - M, StrPtrInit->getType(), /*isConstant=*/true, - llvm::GlobalValue::InternalLinkage, StrPtrInit, StringName); - Str->setUnnamedAddr(llvm::GlobalValue::UnnamedAddr::Global); - - llvm::Constant *Data[] = { - llvm::ConstantExpr::getPointerBitCastOrAddrSpaceCast(ID, CGM.VoidPtrTy), - llvm::ConstantExpr::getPointerBitCastOrAddrSpaceCast(Str, CGM.Int8PtrTy), - llvm::ConstantInt::get(CGM.SizeTy, Size), - llvm::ConstantInt::get(CGM.Int32Ty, Flags), - llvm::ConstantInt::get(CGM.Int32Ty, 0)}; - std::string EntryName = getName({"omp_offloading", "entry", ""}); - llvm::GlobalVariable *Entry = createGlobalStruct( - CGM, getTgtOffloadEntryQTy(), /*IsConstant=*/true, Data, - Twine(EntryName).concat(Name), llvm::GlobalValue::WeakAnyLinkage); - - // The entry has to be created in the section the linker expects it to be. - Entry->setSection("omp_offloading_entries"); + OMPBuilder.emitOffloadingEntry(ID, Addr->getName(), Size, Flags); } void CGOpenMPRuntime::createOffloadEntriesAndInfoMetadata() { @@ -3426,35 +3356,6 @@ } } -QualType CGOpenMPRuntime::getTgtOffloadEntryQTy() { - // Make sure the type of the entry is already created. This is the type we - // have to create: - // struct __tgt_offload_entry{ - // void *addr; // Pointer to the offload entry info. - // // (function or global) - // char *name; // Name of the function or global. - // size_t size; // Size of the entry info (0 if it a function). - // int32_t flags; // Flags associated with the entry, e.g. 'link'. - // int32_t reserved; // Reserved, to use by the runtime library. - // }; - if (TgtOffloadEntryQTy.isNull()) { - ASTContext &C = CGM.getContext(); - RecordDecl *RD = C.buildImplicitRecord("__tgt_offload_entry"); - RD->startDefinition(); - addFieldToRecordDecl(C, RD, C.VoidPtrTy); - addFieldToRecordDecl(C, RD, C.getPointerType(C.CharTy)); - addFieldToRecordDecl(C, RD, C.getSizeType()); - addFieldToRecordDecl( - C, RD, C.getIntTypeForBitwidth(/*DestWidth=*/32, /*Signed=*/true)); - addFieldToRecordDecl( - C, RD, C.getIntTypeForBitwidth(/*DestWidth=*/32, /*Signed=*/true)); - RD->completeDefinition(); - RD->addAttr(PackedAttr::CreateImplicit(C)); - TgtOffloadEntryQTy = C.getRecordType(RD); - } - return TgtOffloadEntryQTy; -} - namespace { struct PrivateHelpersTy { PrivateHelpersTy(const Expr *OriginalRef, const VarDecl *Original, diff --git a/llvm/include/llvm/Frontend/OpenMP/OMPIRBuilder.h b/llvm/include/llvm/Frontend/OpenMP/OMPIRBuilder.h --- a/llvm/include/llvm/Frontend/OpenMP/OMPIRBuilder.h +++ b/llvm/include/llvm/Frontend/OpenMP/OMPIRBuilder.h @@ -779,6 +779,27 @@ /// Value. GlobalValue *createGlobalFlag(unsigned Value, StringRef Name); + /// Create an offloading section struct used to register this global at + /// runtime. + /// + /// Type struct __tgt_offload_entry{ + /// void *addr; // Pointer to the offload entry info. + /// // (function or global) + /// char *name; // Name of the function or global. + /// size_t size; // Size of the entry info (0 if it a function). + /// int32_t flags; + /// int32_t reserved; + /// }; + /// + /// \param Addr The pointer to the global being registered. + /// \param Name The symbol name associated with the global. + /// \param Size The size in bytes of the global (0 for functions). + /// \param Flags Flags associated with the entry. + /// \param SectionName The section this entry will be placed at. + void emitOffloadingEntry(Constant *Addr, StringRef Name, uint64_t Size, + int32_t Flags, + StringRef SectionName = "omp_offloading_entries"); + /// Generate control flow and cleanup for cancellation. /// /// \param CancelFlag Flag indicating if the cancellation is performed. diff --git a/llvm/include/llvm/Frontend/OpenMP/OMPKinds.def b/llvm/include/llvm/Frontend/OpenMP/OMPKinds.def --- a/llvm/include/llvm/Frontend/OpenMP/OMPKinds.def +++ b/llvm/include/llvm/Frontend/OpenMP/OMPKinds.def @@ -86,6 +86,8 @@ OMP_STRUCT_TYPE(VarName, "struct." #Name, __VA_ARGS__) __OMP_STRUCT_TYPE(Ident, ident_t, Int32, Int32, Int32, Int32, Int8Ptr) +__OMP_STRUCT_TYPE(OffloadEntry, __tgt_offload_entry, Int8Ptr, Int8Ptr, SizeTy, + Int32, Int32) __OMP_STRUCT_TYPE(AsyncInfo, __tgt_async_info, Int8Ptr) #undef __OMP_STRUCT_TYPE diff --git a/llvm/lib/Frontend/OpenMP/OMPIRBuilder.cpp b/llvm/lib/Frontend/OpenMP/OMPIRBuilder.cpp --- a/llvm/lib/Frontend/OpenMP/OMPIRBuilder.cpp +++ b/llvm/lib/Frontend/OpenMP/OMPIRBuilder.cpp @@ -753,6 +753,44 @@ return Builder.saveIP(); } +void OpenMPIRBuilder::emitOffloadingEntry(Constant *Addr, StringRef Name, + uint64_t Size, int32_t Flags, + StringRef SectionName) { + Type *Int8PtrTy = Type::getInt8PtrTy(M.getContext()); + Type *Int32Ty = Type::getInt32Ty(M.getContext()); + Type *SizeTy = M.getDataLayout().getIntPtrType(M.getContext()); + + Constant *AddrName = ConstantDataArray::getString(M.getContext(), Name); + + // Create the constant string used to look up the symbol in the device. + auto *Str = + new llvm::GlobalVariable(M, AddrName->getType(), /*isConstant=*/true, + llvm::GlobalValue::InternalLinkage, AddrName, + ".omp_offloading.entry_name"); + Str->setUnnamedAddr(llvm::GlobalValue::UnnamedAddr::Global); + + // Construct the offloading entry. + Constant *EntryData[] = { + ConstantExpr::getPointerBitCastOrAddrSpaceCast(Addr, Int8PtrTy), + ConstantExpr::getPointerBitCastOrAddrSpaceCast(Str, Int8PtrTy), + ConstantInt::get(SizeTy, Size), + ConstantInt::get(Int32Ty, Flags), + ConstantInt::get(Int32Ty, 0), + }; + Constant *EntryInitializer = + ConstantStruct::get(OpenMPIRBuilder::OffloadEntry, EntryData); + + auto *Entry = new GlobalVariable( + M, OpenMPIRBuilder::OffloadEntry, + /* isConstant = */ true, GlobalValue::WeakAnyLinkage, EntryInitializer, + ".omp_offloading.entry." + Name, nullptr, GlobalValue::NotThreadLocal, + M.getDataLayout().getDefaultGlobalsAddressSpace()); + + // The entry has to be created in the section the linker expects it to be. + Entry->setSection(SectionName); + Entry->setAlignment(Align(1)); +} + void OpenMPIRBuilder::emitCancelationCheckImpl(Value *CancelFlag, omp::Directive CanceledDirective, FinalizeCallbackTy ExitCB) {