Skip to content
7 changes: 7 additions & 0 deletions llvm/include/llvm/IR/GlobalVariable.h
Original file line number Diff line number Diff line change
Expand Up @@ -267,6 +267,13 @@ class GlobalVariable : public GlobalObject, public ilist_node<GlobalVariable> {
getAttributes().hasAttribute("rodata-section");
}

MaybeAlign getRequiredGlobalAlignment() {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is an llvm CodeGen detail, not something to expose to IR, and may vary based on the exact target and configuration.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done. Moved to AsmPrinter. LMK if there's a better place.

return isTagged() && getAlign().valueOrOne() < 16 ? MaybeAlign(16)
: std::nullopt;
}

std::optional<uint64_t> getRequiredGlobalSize();

/// Get the custom code model raw value of this global.
///
unsigned getCodeModelRaw() const {
Expand Down
34 changes: 22 additions & 12 deletions llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2398,17 +2398,23 @@ void AsmPrinter::emitRemarksSection(remarks::RemarkStreamer &RS) {
OutStreamer->emitBinaryData(Buf);
}

static void tagGlobalDefinition(Module &M, GlobalVariable *G) {
Constant *Initializer = G->getInitializer();
static uint64_t globalSize(const GlobalVariable &G) {
const Constant *Initializer = G.getInitializer();
uint64_t SizeInBytes =
M.getDataLayout().getTypeAllocSize(Initializer->getType());
G.getParent()->getDataLayout().getTypeAllocSize(Initializer->getType());

uint64_t NewSize = alignTo(SizeInBytes, 16);
if (SizeInBytes != NewSize) {
return SizeInBytes;
}

static void tagGlobalDefinition(GlobalVariable *G) {
Module &M = *G->getParent();
uint64_t SizeInBytes = globalSize(*G);
if (auto NewSize = G->getRequiredGlobalSize()) {
assert(*NewSize > SizeInBytes);
// Pad the initializer out to the next multiple of 16 bytes.
llvm::SmallVector<uint8_t> Init(NewSize - SizeInBytes, 0);
llvm::SmallVector<uint8_t> Init(*NewSize - SizeInBytes, 0);
Constant *Padding = ConstantDataArray::get(M.getContext(), Init);
Initializer = ConstantStruct::getAnon({Initializer, Padding});
auto *Initializer = ConstantStruct::getAnon({G->getInitializer(), Padding});
auto *NewGV = new GlobalVariable(
M, Initializer->getType(), G->isConstant(), G->getLinkage(),
Initializer, "", G, G->getThreadLocalMode(), G->getAddressSpace());
Expand All @@ -2422,8 +2428,10 @@ static void tagGlobalDefinition(Module &M, GlobalVariable *G) {
G = NewGV;
}

if (G->getAlign().valueOrOne() < 16)
G->setAlignment(Align(16));
if (auto Align = G->getRequiredGlobalAlignment()) {
assert(*Align > G->getAlign().valueOrOne());
G->setAlignment(*Align);
}

// Ensure that tagged globals don't get merged by ICF - as they should have
// different tags at runtime.
Expand All @@ -2438,12 +2446,14 @@ bool AsmPrinter::doFinalization(Module &M) {

std::vector<GlobalVariable *> GlobalsToTag;
for (GlobalVariable &G : M.globals()) {
if (G.isDeclaration() || !G.isTagged())
if (G.isDeclaration())
continue;
GlobalsToTag.push_back(&G);
if (G.getRequiredGlobalAlignment().has_value() ||
G.getRequiredGlobalSize().has_value())
GlobalsToTag.push_back(&G);
}
for (GlobalVariable *G : GlobalsToTag)
tagGlobalDefinition(M, G);
tagGlobalDefinition(G);

// Gather all GOT equivalent globals in the module. We really need two
// passes over the globals: one to compute and another to avoid its emission
Expand Down
10 changes: 10 additions & 0 deletions llvm/lib/IR/Globals.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -540,6 +540,16 @@ void GlobalVariable::setCodeModel(CodeModel::Model CM) {
assert(getCodeModel() == CM && "Code model representation error!");
}

std::optional<uint64_t> GlobalVariable::getRequiredGlobalSize() {
if (!isTagged())
return std::nullopt;
Constant *Initializer = getInitializer();
uint64_t SizeInBytes =
getParent()->getDataLayout().getTypeAllocSize(Initializer->getType());
uint64_t Aligned = alignTo(SizeInBytes, 16);
return Aligned != SizeInBytes ? std::optional(Aligned) : std::nullopt;
}

//===----------------------------------------------------------------------===//
// GlobalAlias Implementation
//===----------------------------------------------------------------------===//
Expand Down
Loading