[Clang] Use metadata to make identifying embedded objects easier

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.

Reviewed By: jdoerfert

Differential Revision: https://reviews.llvm.org/D129033
This commit is contained in:
Joseph Huber 2022-07-01 22:40:41 -04:00
parent 23f56132da
commit ed801ad5e5
6 changed files with 47 additions and 5 deletions

View File

@ -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"}

View File

@ -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"}

View File

@ -366,12 +366,26 @@ Error extractFromBitcode(std::unique_ptr<MemoryBuffer> Buffer,
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;
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;

View File

@ -7429,6 +7429,19 @@ Some optimisations are only when the entire LTO unit is present in the current
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
=====================================

View File

@ -109,7 +109,8 @@ void filterDeadComdatFunctions(
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));

View File

@ -275,5 +275,12 @@ void llvm::embedBufferInModule(Module &M, MemoryBufferRef Buf,
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);
}