jhuber6 created this revision. jhuber6 added reviewers: jdoerfert, JonChesterfield, ABataev, MaskRay, tianshilei1992. Herald added subscribers: StephenFan, hiraditya. Herald added a project: All. jhuber6 requested review of this revision. Herald added projects: clang, LLVM. Herald added subscribers: llvm-commits, cfe-commits.
Currently we use the `embedBufferInModule` function to store binary strings containing device offloading data inside the host object to create a fatbinary. In the case of LTO, we need to extract this object from the LLVM-IR. This patch adds a metadata node for the embedded objects containing the embedded pointers and the sections they were stored at. This should create a cleaner interface for identifying these values. In the future it may be worthwhile to also encode an `ID` in the metadata corresponding to the object's special section type if relevant. This would allow us to extract the data from an object file and LLVM-IR using the same ID. Repository: rG LLVM Github Monorepo https://reviews.llvm.org/D129033 Files: clang/test/Frontend/embed-object.c clang/test/Frontend/embed-object.ll clang/tools/clang-linker-wrapper/ClangLinkerWrapper.cpp llvm/include/llvm/Transforms/Utils/ModuleUtils.h 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 @@ -275,5 +275,12 @@ GV->setSection(SectionName); GV->setAlignment(Alignment); + LLVMContext &Ctx = M.getContext(); + NamedMDNode *MD = M.getOrInsertNamedMetadata("llvm.embedded.object"); + Metadata *MDVals[] = {ConstantAsMetadata::get(GV), + MDString::get(Ctx, SectionName)}; + + MD->addOperand(llvm::MDNode::get(Ctx, MDVals)); + appendToCompilerUsed(M, GV); } Index: llvm/include/llvm/Transforms/Utils/ModuleUtils.h =================================================================== --- llvm/include/llvm/Transforms/Utils/ModuleUtils.h +++ llvm/include/llvm/Transforms/Utils/ModuleUtils.h @@ -109,7 +109,8 @@ std::string getUniqueModuleId(Module *M); /// Embed the memory buffer \p Buf into the module \p M as a global using the -/// specified section name. +/// specified section name. Also provide metadata entry to identify it in the +/// module using the same section name. void embedBufferInModule(Module &M, MemoryBufferRef Buf, StringRef SectionName, Align Alignment = Align(1)); Index: clang/tools/clang-linker-wrapper/ClangLinkerWrapper.cpp =================================================================== --- clang/tools/clang-linker-wrapper/ClangLinkerWrapper.cpp +++ clang/tools/clang-linker-wrapper/ClangLinkerWrapper.cpp @@ -366,12 +366,23 @@ return createStringError(inconvertibleErrorCode(), "Failed to create module"); - // Extract offloading data from globals with the `.llvm.offloading` section. - for (GlobalVariable &GV : M->globals()) { - if (!GV.hasSection() || !GV.getSection().equals(OFFLOAD_SECTION_MAGIC_STR)) + // Extract offloading data from globals referenced by the + // `llvm.embedded.object` metadata with the `.llvm.offloading` section. + auto MD = M->getNamedMetadata("llvm.embedded.object"); + for (const MDNode *Op : MD->operands()) { + if (Op->getNumOperands() < 2) continue; - auto *CDS = dyn_cast<ConstantDataSequential>(GV.getInitializer()); + MDString *SectionID = dyn_cast<MDString>(Op->getOperand(1)); + if (!SectionID || SectionID->getString() != OFFLOAD_SECTION_MAGIC_STR) + continue; + + GlobalVariable *GV = + mdconst::dyn_extract_or_null<GlobalVariable>(Op->getOperand(0)); + if (!GV) + continue; + + auto *CDS = dyn_cast<ConstantDataSequential>(GV->getInitializer()); if (!CDS) continue; Index: clang/test/Frontend/embed-object.ll =================================================================== --- clang/test/Frontend/embed-object.ll +++ clang/test/Frontend/embed-object.ll @@ -13,3 +13,7 @@ define i32 @foo() { ret i32 0 } + +; CHECK: !llvm.embedded.object = !{![[METADATA_1:[0-9]+]], ![[METADATA_2:[0-9]+]]} +; CHECK: ![[METADATA_1]] = !{ptr @[[OBJECT_1]], !".llvm.offloading"} +; CHECK: ![[METADATA_2]] = !{ptr @[[OBJECT_2]], !".llvm.offloading"} Index: clang/test/Frontend/embed-object.c =================================================================== --- clang/test/Frontend/embed-object.c +++ clang/test/Frontend/embed-object.c @@ -4,3 +4,6 @@ // CHECK: @llvm.compiler.used = appending global [1 x ptr] [ptr @[[OBJECT]]], section "llvm.metadata" void foo(void) {} + +// CHECK: !llvm.embedded.object = !{![[METADATA:[0-9]+]]} +// CHECK: ![[METADATA]] = !{ptr @[[OBJECT]], !".llvm.offloading"}
Index: llvm/lib/Transforms/Utils/ModuleUtils.cpp =================================================================== --- llvm/lib/Transforms/Utils/ModuleUtils.cpp +++ llvm/lib/Transforms/Utils/ModuleUtils.cpp @@ -275,5 +275,12 @@ GV->setSection(SectionName); GV->setAlignment(Alignment); + LLVMContext &Ctx = M.getContext(); + NamedMDNode *MD = M.getOrInsertNamedMetadata("llvm.embedded.object"); + Metadata *MDVals[] = {ConstantAsMetadata::get(GV), + MDString::get(Ctx, SectionName)}; + + MD->addOperand(llvm::MDNode::get(Ctx, MDVals)); + appendToCompilerUsed(M, GV); } Index: llvm/include/llvm/Transforms/Utils/ModuleUtils.h =================================================================== --- llvm/include/llvm/Transforms/Utils/ModuleUtils.h +++ llvm/include/llvm/Transforms/Utils/ModuleUtils.h @@ -109,7 +109,8 @@ std::string getUniqueModuleId(Module *M); /// Embed the memory buffer \p Buf into the module \p M as a global using the -/// specified section name. +/// specified section name. Also provide metadata entry to identify it in the +/// module using the same section name. void embedBufferInModule(Module &M, MemoryBufferRef Buf, StringRef SectionName, Align Alignment = Align(1)); Index: clang/tools/clang-linker-wrapper/ClangLinkerWrapper.cpp =================================================================== --- clang/tools/clang-linker-wrapper/ClangLinkerWrapper.cpp +++ clang/tools/clang-linker-wrapper/ClangLinkerWrapper.cpp @@ -366,12 +366,23 @@ return createStringError(inconvertibleErrorCode(), "Failed to create module"); - // Extract offloading data from globals with the `.llvm.offloading` section. - for (GlobalVariable &GV : M->globals()) { - if (!GV.hasSection() || !GV.getSection().equals(OFFLOAD_SECTION_MAGIC_STR)) + // Extract offloading data from globals referenced by the + // `llvm.embedded.object` metadata with the `.llvm.offloading` section. + auto MD = M->getNamedMetadata("llvm.embedded.object"); + for (const MDNode *Op : MD->operands()) { + if (Op->getNumOperands() < 2) continue; - auto *CDS = dyn_cast<ConstantDataSequential>(GV.getInitializer()); + MDString *SectionID = dyn_cast<MDString>(Op->getOperand(1)); + if (!SectionID || SectionID->getString() != OFFLOAD_SECTION_MAGIC_STR) + continue; + + GlobalVariable *GV = + mdconst::dyn_extract_or_null<GlobalVariable>(Op->getOperand(0)); + if (!GV) + continue; + + auto *CDS = dyn_cast<ConstantDataSequential>(GV->getInitializer()); if (!CDS) continue; Index: clang/test/Frontend/embed-object.ll =================================================================== --- clang/test/Frontend/embed-object.ll +++ clang/test/Frontend/embed-object.ll @@ -13,3 +13,7 @@ define i32 @foo() { ret i32 0 } + +; CHECK: !llvm.embedded.object = !{![[METADATA_1:[0-9]+]], ![[METADATA_2:[0-9]+]]} +; CHECK: ![[METADATA_1]] = !{ptr @[[OBJECT_1]], !".llvm.offloading"} +; CHECK: ![[METADATA_2]] = !{ptr @[[OBJECT_2]], !".llvm.offloading"} Index: clang/test/Frontend/embed-object.c =================================================================== --- clang/test/Frontend/embed-object.c +++ clang/test/Frontend/embed-object.c @@ -4,3 +4,6 @@ // CHECK: @llvm.compiler.used = appending global [1 x ptr] [ptr @[[OBJECT]]], section "llvm.metadata" void foo(void) {} + +// CHECK: !llvm.embedded.object = !{![[METADATA:[0-9]+]]} +// CHECK: ![[METADATA]] = !{ptr @[[OBJECT]], !".llvm.offloading"}
_______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits