diff --git a/clang/test/Frontend/embed-object.c b/clang/test/Frontend/embed-object.c --- a/clang/test/Frontend/embed-object.c +++ b/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.objects = !{![[METADATA:[0-9]+]]} +// CHECK: ![[METADATA]] = !{ptr @[[OBJECT]], !".llvm.offloading"} diff --git a/clang/test/Frontend/embed-object.ll b/clang/test/Frontend/embed-object.ll --- a/clang/test/Frontend/embed-object.ll +++ b/clang/test/Frontend/embed-object.ll @@ -13,3 +13,7 @@ define i32 @foo() { ret i32 0 } + +; CHECK: !llvm.embedded.objects = !{![[METADATA_1:[0-9]+]], ![[METADATA_2:[0-9]+]]} +; CHECK: ![[METADATA_1]] = !{ptr @[[OBJECT_1]], !".llvm.offloading"} +; CHECK: ![[METADATA_2]] = !{ptr @[[OBJECT_2]], !".llvm.offloading"} diff --git a/clang/tools/clang-linker-wrapper/ClangLinkerWrapper.cpp b/clang/tools/clang-linker-wrapper/ClangLinkerWrapper.cpp --- a/clang/tools/clang-linker-wrapper/ClangLinkerWrapper.cpp +++ b/clang/tools/clang-linker-wrapper/ClangLinkerWrapper.cpp @@ -366,12 +366,26 @@ 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"); + if (!MD) + return Error::success(); + + for (const MDNode *Op : MD->operands()) { + if (Op->getNumOperands() < 2) + continue; + + MDString *SectionID = dyn_cast(Op->getOperand(1)); + if (!SectionID || SectionID->getString() != OFFLOAD_SECTION_MAGIC_STR) + continue; + + GlobalVariable *GV = + mdconst::dyn_extract_or_null(Op->getOperand(0)); + if (!GV) continue; - auto *CDS = dyn_cast(GV.getInitializer()); + auto *CDS = dyn_cast(GV->getInitializer()); if (!CDS) continue; diff --git a/llvm/docs/LangRef.rst b/llvm/docs/LangRef.rst --- a/llvm/docs/LangRef.rst +++ b/llvm/docs/LangRef.rst @@ -7429,6 +7429,19 @@ module. This is represented by the ``LTOPostLink`` module flags metadata, which will be created with a value of ``1`` when LTO linking occurs. +Embedded Objects Names Metadata +=============================== + +Offloading compilations need to embed device code into the host section table to +create a fat binary. This metadata node references each global that will be +embedded in the module. The primary use for this is to make referencing these +globals more efficient in the IR. The metadata references nodes containing +pointers to the global to be embedded followed by the section name it will be +stored at:: + + !llvm.embedded.objects = !{!0} + !0 = !{ptr @object, !".section"} + Automatic Linker Flags Named Metadata ===================================== diff --git a/llvm/include/llvm/Transforms/Utils/ModuleUtils.h b/llvm/include/llvm/Transforms/Utils/ModuleUtils.h --- a/llvm/include/llvm/Transforms/Utils/ModuleUtils.h +++ b/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 a 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)); diff --git a/llvm/lib/Transforms/Utils/ModuleUtils.cpp b/llvm/lib/Transforms/Utils/ModuleUtils.cpp --- a/llvm/lib/Transforms/Utils/ModuleUtils.cpp +++ b/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.objects"); + Metadata *MDVals[] = {ConstantAsMetadata::get(GV), + MDString::get(Ctx, SectionName)}; + + MD->addOperand(llvm::MDNode::get(Ctx, MDVals)); + appendToCompilerUsed(M, GV); }