jhuber6 created this revision. jhuber6 added reviewers: jdoerfert, tianshilei1992, JonChesterfield. Herald added subscribers: ormris, dexonsmith, guansong, hiraditya, yaxunl. Herald added a project: All. jhuber6 requested review of this revision. Herald added subscribers: llvm-commits, cfe-commits, sstefan1, MaskRay. Herald added projects: clang, LLVM.
The previous patch introduced the offloading binary format so we can store some metada along with the binary image. This patch introduces using this inside the linker wrapper and Clang instead of the previous method that embedded the metadata in the section name. Repository: rG LLVM Github Monorepo https://reviews.llvm.org/D122683 Files: clang/include/clang/Basic/CodeGenOptions.h clang/lib/CodeGen/BackendUtil.cpp clang/lib/Driver/ToolChains/Clang.cpp clang/test/Driver/openmp-offload-gpu.c clang/test/Frontend/embed-object.c clang/test/Frontend/embed-object.ll clang/tools/clang-linker-wrapper/ClangLinkerWrapper.cpp llvm/include/llvm/Object/OffloadBinary.h llvm/include/llvm/Transforms/Utils/ModuleUtils.h llvm/lib/CodeGen/TargetLoweringObjectFileImpl.cpp llvm/lib/Transforms/Utils/ModuleUtils.cpp
Index: llvm/lib/Transforms/Utils/ModuleUtils.cpp =================================================================== --- llvm/lib/Transforms/Utils/ModuleUtils.cpp +++ llvm/lib/Transforms/Utils/ModuleUtils.cpp @@ -265,15 +265,15 @@ } void llvm::embedBufferInModule(Module &M, MemoryBufferRef Buf, - StringRef SectionName) { - // Embed the buffer into the module. + StringRef SectionName, Align Alignment) { + // Embed the memory buffer into the module. Constant *ModuleConstant = ConstantDataArray::get( M.getContext(), makeArrayRef(Buf.getBufferStart(), Buf.getBufferSize())); GlobalVariable *GV = new GlobalVariable( - M, ModuleConstant->getType(), true, GlobalValue::ExternalLinkage, - ModuleConstant, SectionName.drop_front()); + M, ModuleConstant->getType(), true, GlobalValue::PrivateLinkage, + ModuleConstant, "llvm.embedded.object"); GV->setSection(SectionName); - GV->setVisibility(GlobalValue::HiddenVisibility); + GV->setAlignment(Alignment); appendToCompilerUsed(M, GV); } Index: llvm/lib/CodeGen/TargetLoweringObjectFileImpl.cpp =================================================================== --- llvm/lib/CodeGen/TargetLoweringObjectFileImpl.cpp +++ llvm/lib/CodeGen/TargetLoweringObjectFileImpl.cpp @@ -447,7 +447,7 @@ Name == getInstrProfSectionName(IPSK_covfun, Triple::ELF, /*AddSegmentInfo=*/false) || Name == ".llvmbc" || Name == ".llvmcmd" || - Name.startswith(".llvm.offloading.")) + Name.startswith(".llvm.offloading")) return SectionKind::getMetadata(); if (Name.empty() || Name[0] != '.') return K; Index: llvm/include/llvm/Transforms/Utils/ModuleUtils.h =================================================================== --- llvm/include/llvm/Transforms/Utils/ModuleUtils.h +++ llvm/include/llvm/Transforms/Utils/ModuleUtils.h @@ -14,6 +14,7 @@ #define LLVM_TRANSFORMS_UTILS_MODULEUTILS_H #include "llvm/ADT/StringRef.h" +#include "llvm/Support/Alignment.h" #include "llvm/Support/MemoryBufferRef.h" #include <utility> // for std::pair @@ -109,7 +110,8 @@ /// Embed the memory buffer \p Buf into the module \p M as a global using the /// specified section name. -void embedBufferInModule(Module &M, MemoryBufferRef Buf, StringRef SectionName); +void embedBufferInModule(Module &M, MemoryBufferRef Buf, StringRef SectionName, + Align Alignment = Align(1)); class CallInst; namespace VFABI { Index: llvm/include/llvm/Object/OffloadBinary.h =================================================================== --- llvm/include/llvm/Object/OffloadBinary.h +++ llvm/include/llvm/Object/OffloadBinary.h @@ -71,6 +71,7 @@ static uint64_t getAlignment() { return alignof(Header); } + uint32_t getVersion() const { return TheHeader->Version; } uint16_t getImageKind() const { return TheEntry->ImageKind; } uint16_t getOffloadKind() const { return TheEntry->OffloadKind; } uint32_t getFlags() const { return TheEntry->Flags; } Index: clang/tools/clang-linker-wrapper/ClangLinkerWrapper.cpp =================================================================== --- clang/tools/clang-linker-wrapper/ClangLinkerWrapper.cpp +++ clang/tools/clang-linker-wrapper/ClangLinkerWrapper.cpp @@ -15,6 +15,7 @@ //===---------------------------------------------------------------------===// #include "OffloadWrapper.h" + #include "clang/Basic/Version.h" #include "llvm/BinaryFormat/Magic.h" #include "llvm/Bitcode/BitcodeWriter.h" @@ -29,6 +30,7 @@ #include "llvm/Object/ArchiveWriter.h" #include "llvm/Object/Binary.h" #include "llvm/Object/ObjectFile.h" +#include "llvm/Object/OffloadBinary.h" #include "llvm/Support/CommandLine.h" #include "llvm/Support/Errc.h" #include "llvm/Support/FileOutputBuffer.h" @@ -47,6 +49,7 @@ #include "llvm/Target/TargetMachine.h" using namespace llvm; +using namespace clang; using namespace llvm::object; static cl::opt<bool> Help("h", cl::desc("Alias for -help"), cl::Hidden); @@ -146,9 +149,10 @@ static codegen::RegisterCodeGenFlags CodeGenFlags; /// Magic section string that marks the existence of offloading data. The -/// section string will be formatted as `.llvm.offloading.<triple>.<arch>`. -#define OFFLOAD_SECTION_MAGIC_STR ".llvm.offloading." +/// section will contain one or more offloading binaries stored contiguously. +#define OFFLOAD_SECTION_MAGIC_STR ".llvm.offloading" +// TODO: Replace all uses of DeviceFile with OffloadFile. /// Information for a device offloading file extracted from the host. struct DeviceFile { DeviceFile(StringRef Kind, StringRef TheTriple, StringRef Arch, @@ -201,16 +205,6 @@ llvm::errs() << *IC << (std::next(IC) != IE ? " " : "\n"); } -static StringRef getDeviceFileExtension(StringRef DeviceTriple, - bool IsBitcode = false) { - Triple TheTriple(DeviceTriple); - if (TheTriple.isAMDGPU() || IsBitcode) - return "bc"; - if (TheTriple.isNVPTX()) - return "cubin"; - return "o"; -} - std::string getMainExecutable(const char *Name) { void *Ptr = (void *)(intptr_t)&getMainExecutable; auto COWPath = sys::fs::getMainExecutable(Name, Ptr); @@ -296,39 +290,58 @@ StringRef Prefix = sys::path::stem(Obj.getFileName()); SmallVector<StringRef, 4> ToBeStripped; - // Extract data from sections of the form `.llvm.offloading.<triple>.<arch>`. + // Extract offloading binaries from sections with the name `.llvm.offloading`. for (const SectionRef &Sec : Obj.sections()) { Expected<StringRef> Name = Sec.getName(); - if (!Name || !Name->startswith(OFFLOAD_SECTION_MAGIC_STR)) + if (!Name || !Name->equals(OFFLOAD_SECTION_MAGIC_STR)) continue; - SmallVector<StringRef, 4> SectionFields; - Name->split(SectionFields, '.'); - StringRef Kind = SectionFields[3]; - StringRef DeviceTriple = SectionFields[4]; - StringRef Arch = SectionFields[5]; + Expected<StringRef> Contents = Sec.getContents(); + if (!Contents) + return Contents.takeError(); + + uint64_t Offset = 0; + // There could be multiple offloading binaries stored at this section. + while (Offset < Contents->size()) { + std::unique_ptr<MemoryBuffer> Buffer = + MemoryBuffer::getMemBuffer(Contents->drop_front(Offset), *Name, + /*RequiresNullTerminator*/ false); + auto BinaryOrErr = OffloadBinary::create(*Buffer); + if (!BinaryOrErr) + return BinaryOrErr.takeError(); + OffloadBinary &Binary = **BinaryOrErr; + + assert(Binary.getVersion() == 1 && "Incompatible device image"); + + StringRef Kind = + getOffloadKindName(static_cast<OffloadKind>(Binary.getOffloadKind())); + StringRef Suffix = + getImageKindName(static_cast<ImageKind>(Binary.getImageKind())); - if (Expected<StringRef> Contents = Sec.getContents()) { SmallString<128> TempFile; - StringRef DeviceExtension = getDeviceFileExtension( - DeviceTriple, identify_magic(*Contents) == file_magic::bitcode); - if (Error Err = createOutputFile(Prefix + "-" + Kind + "-" + - DeviceTriple + "-" + Arch, - DeviceExtension, TempFile)) + if (Error Err = + createOutputFile(Prefix + "-" + Kind + "-" + Binary.getTriple() + + "-" + Binary.getArch(), + Suffix, TempFile)) return std::move(Err); Expected<std::unique_ptr<FileOutputBuffer>> OutputOrErr = - FileOutputBuffer::create(TempFile, Sec.getSize()); + FileOutputBuffer::create(TempFile, Binary.getImage().size()); if (!OutputOrErr) return OutputOrErr.takeError(); std::unique_ptr<FileOutputBuffer> Output = std::move(*OutputOrErr); - std::copy(Contents->begin(), Contents->end(), Output->getBufferStart()); + std::copy(Binary.getImage().bytes_begin(), Binary.getImage().bytes_end(), + Output->getBufferStart()); if (Error E = Output->commit()) return std::move(E); - DeviceFiles.emplace_back(Kind, DeviceTriple, Arch, TempFile); - ToBeStripped.push_back(*Name); + DeviceFiles.emplace_back(Kind, Binary.getTriple(), Binary.getArch(), + TempFile); + + Offset += Binary.getSize(); } + + ToBeStripped.push_back(*Name); } if (ToBeStripped.empty() || !StripSections) @@ -405,42 +418,58 @@ SmallVector<GlobalVariable *, 4> ToBeDeleted; - // Extract data from the global string containing a section of the form - // `.llvm.offloading.<triple>.<arch>`. + // Extract offloading data from globals with the `.llvm.offloading` section + // name. for (GlobalVariable &GV : M->globals()) { - if (!GV.hasSection() || - !GV.getSection().startswith(OFFLOAD_SECTION_MAGIC_STR)) + if (!GV.hasSection() || !GV.getSection().equals(OFFLOAD_SECTION_MAGIC_STR)) continue; auto *CDS = dyn_cast<ConstantDataSequential>(GV.getInitializer()); if (!CDS) continue; - SmallVector<StringRef, 4> SectionFields; - GV.getSection().split(SectionFields, '.'); - StringRef Kind = SectionFields[3]; - StringRef DeviceTriple = SectionFields[4]; - StringRef Arch = SectionFields[5]; - StringRef Contents = CDS->getAsString(); - SmallString<128> TempFile; - StringRef DeviceExtension = getDeviceFileExtension( - DeviceTriple, identify_magic(Contents) == file_magic::bitcode); - if (Error Err = createOutputFile(Prefix + "-" + Kind + "-" + DeviceTriple + - "-" + Arch, - DeviceExtension, TempFile)) - return std::move(Err); - Expected<std::unique_ptr<FileOutputBuffer>> OutputOrErr = - FileOutputBuffer::create(TempFile, Contents.size()); - if (!OutputOrErr) - return OutputOrErr.takeError(); - std::unique_ptr<FileOutputBuffer> Output = std::move(*OutputOrErr); - std::copy(Contents.begin(), Contents.end(), Output->getBufferStart()); - if (Error E = Output->commit()) - return std::move(E); + uint64_t Offset = 0; + // There could be multiple offloading binaries stored at this section. + while (Offset < Contents.size()) { + std::unique_ptr<MemoryBuffer> Buffer = + MemoryBuffer::getMemBuffer(Contents.drop_front(Offset), GV.getName(), + /*RequiresNullTerminator*/ false); + auto BinaryOrErr = OffloadBinary::create(*Buffer); + if (!BinaryOrErr) + return BinaryOrErr.takeError(); + OffloadBinary &Binary = **BinaryOrErr; + + assert(Binary.getVersion() == 1 && "Incompatible device image"); + + StringRef Kind = + getOffloadKindName(static_cast<OffloadKind>(Binary.getOffloadKind())); + StringRef Suffix = + getImageKindName(static_cast<ImageKind>(Binary.getImageKind())); - DeviceFiles.emplace_back(Kind, DeviceTriple, Arch, TempFile); + SmallString<128> TempFile; + if (Error Err = + createOutputFile(Prefix + "-" + Kind + "-" + Binary.getTriple() + + "-" + Binary.getArch(), + Suffix, TempFile)) + return std::move(Err); + + Expected<std::unique_ptr<FileOutputBuffer>> OutputOrErr = + FileOutputBuffer::create(TempFile, Binary.getImage().size()); + if (!OutputOrErr) + return OutputOrErr.takeError(); + std::unique_ptr<FileOutputBuffer> Output = std::move(*OutputOrErr); + std::copy(Binary.getImage().bytes_begin(), Binary.getImage().bytes_end(), + Output->getBufferStart()); + if (Error E = Output->commit()) + return std::move(E); + + DeviceFiles.emplace_back(Kind, Binary.getTriple(), Binary.getArch(), + TempFile); + + Offset += Binary.getSize(); + } ToBeDeleted.push_back(&GV); } Index: clang/test/Frontend/embed-object.ll =================================================================== --- clang/test/Frontend/embed-object.ll +++ clang/test/Frontend/embed-object.ll @@ -1,11 +1,9 @@ ; RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -emit-llvm \ -; RUN: -fembed-offload-object=%S/Inputs/empty.h,section1 \ -; RUN: -fembed-offload-object=%S/Inputs/empty.h,section2 -x ir %s -o - \ +; RUN: -fembed-offload-object=%S/Inputs/empty.h,,, -x ir %s -o - \ ; RUN: | FileCheck %s -check-prefix=CHECK -; CHECK: @[[OBJECT1:.+]] = hidden constant [0 x i8] zeroinitializer, section ".llvm.offloading.section1" -; CHECK: @[[OBJECT2:.+]] = hidden constant [0 x i8] zeroinitializer, section ".llvm.offloading.section2" -; CHECK: @llvm.compiler.used = appending global [3 x i8*] [i8* @x, i8* getelementptr inbounds ([0 x i8], [0 x i8]* @[[OBJECT1]], i32 0, i32 0), i8* getelementptr inbounds ([0 x i8], [0 x i8]* @[[OBJECT2]], i32 0, i32 0)], section "llvm.metadata" +; CHECK: @[[OBJECT:.+]] = private constant [120 x i8] c"\10\FF\10\AD{{.*}}\00", section ".llvm.offloading", align 8 +; CHECK: @llvm.compiler.used = appending global [2 x i8*] [i8* @x, i8* getelementptr inbounds ([120 x i8], [120 x i8]* @[[OBJECT]], i32 0, i32 0)], section "llvm.metadata" @x = private constant i8 1 @llvm.compiler.used = appending global [1 x i8*] [i8* @x], section "llvm.metadata" Index: clang/test/Frontend/embed-object.c =================================================================== --- clang/test/Frontend/embed-object.c +++ clang/test/Frontend/embed-object.c @@ -1,6 +1,6 @@ -// RUN: %clang_cc1 -x c -triple x86_64-unknown-linux-gnu -emit-llvm -fembed-offload-object=%S/Inputs/empty.h,section +// RUN: %clang_cc1 -x c -triple x86_64-unknown-linux-gnu -emit-llvm -fembed-offload-object=%S/Inputs/empty.h,,, -o - | FileCheck %s -// CHECK: @[[OBJECT:.+]] = private constant [0 x i8] zeroinitializer, section ".llvm.offloading.section" -// CHECK: @llvm.compiler.used = appending global [3 x i8*] [i8* getelementptr inbounds ([0 x i8], [0 x i8]* @[[OBJECT1]]], section "llvm.metadata" +// CHECK: @[[OBJECT:.+]] = private constant [120 x i8] c"\10\FF\10\AD\01{{.*}}\00\00", section ".llvm.offloading", align 8 +// CHECK: @llvm.compiler.used = appending global [1 x i8*] [i8* getelementptr inbounds ([120 x i8], [120 x i8]* @[[OBJECT]], i32 0, i32 0)], section "llvm.metadata" void foo(void) {} Index: clang/test/Driver/openmp-offload-gpu.c =================================================================== --- clang/test/Driver/openmp-offload-gpu.c +++ clang/test/Driver/openmp-offload-gpu.c @@ -345,4 +345,4 @@ // RUN: -fopenmp-new-driver -no-canonical-prefixes -nogpulib %s -o openmp-offload-gpu 2>&1 \ // RUN: | FileCheck -check-prefix=NEW_DRIVER_EMBEDDING %s -// NEW_DRIVER_EMBEDDING: -fembed-offload-object=[[CUBIN:.*\.cubin]],openmp.nvptx64-nvidia-cuda.sm_70 +// NEW_DRIVER_EMBEDDING: -fembed-offload-object=[[CUBIN:.*\.cubin]],openmp,nvptx64-nvidia-cuda,sm_70 Index: clang/lib/Driver/ToolChains/Clang.cpp =================================================================== --- clang/lib/Driver/ToolChains/Clang.cpp +++ clang/lib/Driver/ToolChains/Clang.cpp @@ -6993,13 +6993,12 @@ const ArgList &TCArgs = C.getArgsForToolChain(TC, "", Action::OFK_OpenMP); StringRef File = C.getArgs().MakeArgString(TC->getInputFilename(*InputFile)); - StringRef InputName = Clang::getBaseInputStem(Args, Inputs); - CmdArgs.push_back(Args.MakeArgString( - "-fembed-offload-object=" + File + "," + - Action::GetOffloadKindName(Action::OFK_OpenMP) + "." + - TC->getTripleString() + "." + - TCArgs.getLastArgValue(options::OPT_march_EQ) + "." + InputName)); + CmdArgs.push_back( + Args.MakeArgString("-fembed-offload-object=" + File + "," + + Action::GetOffloadKindName(Action::OFK_OpenMP) + + "," + TC->getTripleString() + "," + + TCArgs.getLastArgValue(options::OPT_march_EQ))); } } Index: clang/lib/CodeGen/BackendUtil.cpp =================================================================== --- clang/lib/CodeGen/BackendUtil.cpp +++ clang/lib/CodeGen/BackendUtil.cpp @@ -39,6 +39,7 @@ #include "llvm/MC/MCAsmInfo.h" #include "llvm/MC/SubtargetFeature.h" #include "llvm/MC/TargetRegistry.h" +#include "llvm/Object/OffloadBinary.h" #include "llvm/Passes/PassBuilder.h" #include "llvm/Passes/PassPlugin.h" #include "llvm/Passes/StandardInstrumentations.h" @@ -146,7 +147,7 @@ std::unique_ptr<llvm::ToolOutputFile> openOutputFile(StringRef Path) { std::error_code EC; auto F = std::make_unique<llvm::ToolOutputFile>(Path, EC, - llvm::sys::fs::OF_None); + llvm::sys::fs::OF_None); if (EC) { Diags.Report(diag::err_fe_unable_to_open_output) << Path << EC.message(); F.reset(); @@ -208,19 +209,22 @@ const CodeGenOptions &CGOpts; const LangOptions &LangOpts; }; -} +} // namespace -static void addObjCARCAPElimPass(const PassManagerBuilder &Builder, PassManagerBase &PM) { +static void addObjCARCAPElimPass(const PassManagerBuilder &Builder, + PassManagerBase &PM) { if (Builder.OptLevel > 0) PM.add(createObjCARCAPElimPass()); } -static void addObjCARCExpandPass(const PassManagerBuilder &Builder, PassManagerBase &PM) { +static void addObjCARCExpandPass(const PassManagerBuilder &Builder, + PassManagerBase &PM) { if (Builder.OptLevel > 0) PM.add(createObjCARCExpandPass()); } -static void addObjCARCOptPass(const PassManagerBuilder &Builder, PassManagerBase &PM) { +static void addObjCARCOptPass(const PassManagerBuilder &Builder, + PassManagerBase &PM) { if (Builder.OptLevel > 0) PM.add(createObjCARCOptPass()); } @@ -302,7 +306,7 @@ static void addAddressSanitizerPasses(const PassManagerBuilder &Builder, legacy::PassManagerBase &PM) { const PassManagerBuilderWrapper &BuilderWrapper = - static_cast<const PassManagerBuilderWrapper&>(Builder); + static_cast<const PassManagerBuilderWrapper &>(Builder); const Triple &T = BuilderWrapper.getTargetTriple(); const CodeGenOptions &CGOpts = BuilderWrapper.getCGOpts(); bool Recover = CGOpts.SanitizeRecover.has(SanitizerKind::Address); @@ -330,7 +334,7 @@ } static void addHWAddressSanitizerPasses(const PassManagerBuilder &Builder, - legacy::PassManagerBase &PM) { + legacy::PassManagerBase &PM) { const PassManagerBuilderWrapper &BuilderWrapper = static_cast<const PassManagerBuilderWrapper &>(Builder); const CodeGenOptions &CGOpts = BuilderWrapper.getCGOpts(); @@ -354,7 +358,7 @@ legacy::PassManagerBase &PM, bool CompileKernel) { const PassManagerBuilderWrapper &BuilderWrapper = - static_cast<const PassManagerBuilderWrapper&>(Builder); + static_cast<const PassManagerBuilderWrapper &>(Builder); const CodeGenOptions &CGOpts = BuilderWrapper.getCGOpts(); int TrackOrigins = CGOpts.SanitizeMemoryTrackOrigins; bool Recover = CGOpts.SanitizeRecover.has(SanitizerKind::Memory); @@ -393,7 +397,7 @@ static void addDataFlowSanitizerPass(const PassManagerBuilder &Builder, legacy::PassManagerBase &PM) { const PassManagerBuilderWrapper &BuilderWrapper = - static_cast<const PassManagerBuilderWrapper&>(Builder); + static_cast<const PassManagerBuilderWrapper &>(Builder); const LangOptions &LangOpts = BuilderWrapper.getLangOpts(); PM.add(createDataFlowSanitizerLegacyPassPass(LangOpts.NoSanitizeFiles)); } @@ -418,13 +422,13 @@ TLII->addVectorizableFunctionsFromVecLib(TargetLibraryInfoImpl::Accelerate); break; case CodeGenOptions::LIBMVEC: - switch(TargetTriple.getArch()) { - default: - break; - case llvm::Triple::x86_64: - TLII->addVectorizableFunctionsFromVecLib - (TargetLibraryInfoImpl::LIBMVEC_X86); - break; + switch (TargetTriple.getArch()) { + default: + break; + case llvm::Triple::x86_64: + TLII->addVectorizableFunctionsFromVecLib( + TargetLibraryInfoImpl::LIBMVEC_X86); + break; } break; case CodeGenOptions::MASSV: @@ -930,8 +934,7 @@ // FIXME: The command line parser below is not thread-safe and shares a global // state, so this call might crash or overwrite the options of another Clang // instance in the same process. - llvm::cl::ParseCommandLineOptions(BackendArgs.size() - 1, - BackendArgs.data()); + llvm::cl::ParseCommandLineOptions(BackendArgs.size() - 1, BackendArgs.data()); } void EmitAssemblyHelper::CreateTargetMachine(bool MustCreateTM) { @@ -1053,8 +1056,7 @@ // Emit a module summary by default for Regular LTO except for ld64 // targets bool EmitLTOSummary = - (CodeGenOpts.PrepareForLTO && - !CodeGenOpts.DisableLLVMPasses && + (CodeGenOpts.PrepareForLTO && !CodeGenOpts.DisableLLVMPasses && llvm::Triple(TheModule->getTargetTriple()).getVendor() != llvm::Triple::Apple); if (EmitLTOSummary) { @@ -1360,12 +1362,11 @@ bool IsLTO = CodeGenOpts.PrepareForLTO; if (LangOpts.ObjCAutoRefCount) { - PB.registerPipelineStartEPCallback( - [](ModulePassManager &MPM, OptimizationLevel Level) { - if (Level != OptimizationLevel::O0) - MPM.addPass( - createModuleToFunctionPassAdaptor(ObjCARCExpandPass())); - }); + PB.registerPipelineStartEPCallback([](ModulePassManager &MPM, + OptimizationLevel Level) { + if (Level != OptimizationLevel::O0) + MPM.addPass(createModuleToFunctionPassAdaptor(ObjCARCExpandPass())); + }); PB.registerPipelineEarlySimplificationEPCallback( [](ModulePassManager &MPM, OptimizationLevel Level) { if (Level != OptimizationLevel::O0) @@ -1678,9 +1679,8 @@ const HeaderSearchOptions &HeaderOpts, const CodeGenOptions &CGOpts, const clang::TargetOptions &TOpts, - const LangOptions &LOpts, - StringRef TDesc, Module *M, - BackendAction Action, + const LangOptions &LOpts, StringRef TDesc, + Module *M, BackendAction Action, std::unique_ptr<raw_pwrite_stream> OS) { llvm::TimeTraceScope TimeScope("Backend"); @@ -1697,7 +1697,7 @@ .moveInto(CombinedIndex)) { logAllUnhandledErrors(std::move(E), errs(), "Error loading index file '" + - CGOpts.ThinLTOIndexFile + "': "); + CGOpts.ThinLTOIndexFile + "': "); return; } @@ -1761,22 +1761,33 @@ return; for (StringRef OffloadObject : CGOpts.OffloadObjects) { - if (OffloadObject.count(',') != 1) - Diags.Report(Diags.getCustomDiagID( - DiagnosticsEngine::Error, "Invalid string pair for embedding '%0'")) - << OffloadObject; - auto FilenameAndSection = OffloadObject.split(','); + SmallVector<StringRef, 4> ObjectFields; + OffloadObject.split(ObjectFields, ','); + + if (ObjectFields.size() != 4) { + auto DiagID = Diags.getCustomDiagID( + DiagnosticsEngine::Error, "Expected at least four arguments '%0'"); + Diags.Report(DiagID) << OffloadObject; + return; + } + llvm::ErrorOr<std::unique_ptr<llvm::MemoryBuffer>> ObjectOrErr = - llvm::MemoryBuffer::getFileOrSTDIN(FilenameAndSection.first); + llvm::MemoryBuffer::getFileOrSTDIN(ObjectFields[0]); if (std::error_code EC = ObjectOrErr.getError()) { auto DiagID = Diags.getCustomDiagID(DiagnosticsEngine::Error, "could not open '%0' for embedding"); - Diags.Report(DiagID) << FilenameAndSection.first; + Diags.Report(DiagID) << ObjectFields[0]; return; } - SmallString<128> SectionName( - {".llvm.offloading.", FilenameAndSection.second}); - llvm::embedBufferInModule(*M, **ObjectOrErr, SectionName); + OffloadBinary::OffloadingImage Image{}; + Image.TheImageKind = getImageKind(ObjectFields[0].rsplit(".").second); + Image.TheOffloadKind = getOffloadKind(ObjectFields[1]); + Image.StringData = {{"triple", ObjectFields[2]}, {"arch", ObjectFields[3]}}; + Image.Image = **ObjectOrErr; + + std::unique_ptr<MemoryBuffer> OffloadBuffer = OffloadBinary::write(Image); + llvm::embedBufferInModule(*M, *OffloadBuffer, ".llvm.offloading", + Align(OffloadBinary::getAlignment())); } } Index: clang/include/clang/Basic/CodeGenOptions.h =================================================================== --- clang/include/clang/Basic/CodeGenOptions.h +++ clang/include/clang/Basic/CodeGenOptions.h @@ -276,9 +276,12 @@ /// CUDA runtime back-end for incorporating them into host-side object file. std::string CudaGpuBinaryFileName; - /// List of filenames and section name pairs passed in using the - /// -fembed-offload-object option to embed device-side offloading objects into - /// the host as a named section. Input passed in as '<filename>,<section>' + /// List of filenames and metadata passed in using the -fembed-offload-object + /// option to embed device-side offloading objects into the host as a named + /// section. Input passed in as 'filename,kind,triple,arch'. + /// + /// NOTE: This will need to be expanded whenever we want to pass in more + /// metadata, at some point this should be its own clang tool. std::vector<std::string> OffloadObjects; /// The name of the file to which the backend should save YAML optimization
_______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits