42 changes: 30 additions & 12 deletions llvm/lib/Bitcode/Writer/BitcodeWriter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -223,7 +223,10 @@ class ModuleBitcodeWriter : public BitcodeWriter {
SmallVectorImpl<uint64_t> &Record);
void writeModuleMetadata();
void writeFunctionMetadata(const Function &F);
void writeMetadataAttachment(const Function &F);
void writeFunctionMetadataAttachment(const Function &F);
void writeGlobalVariableMetadataAttachment(const GlobalVariable &GV);
void pushGlobalMetadataAttachment(SmallVectorImpl<uint64_t> &Record,
const GlobalObject &GO);
void writeModuleMetadataStore();
void writeOperandBundleTags();
void writeConstants(unsigned FirstVal, unsigned LastVal, bool isGlobal);
Expand Down Expand Up @@ -1831,24 +1834,31 @@ void ModuleBitcodeWriter::writeFunctionMetadata(const Function &F) {
Stream.ExitBlock();
}

void ModuleBitcodeWriter::writeMetadataAttachment(const Function &F) {
void ModuleBitcodeWriter::pushGlobalMetadataAttachment(
SmallVectorImpl<uint64_t> &Record, const GlobalObject &GO) {
// [n x [id, mdnode]]
SmallVector<std::pair<unsigned, MDNode *>, 4> MDs;
GO.getAllMetadata(MDs);
for (const auto &I : MDs) {
Record.push_back(I.first);
Record.push_back(VE.getMetadataID(I.second));
}
}

void ModuleBitcodeWriter::writeFunctionMetadataAttachment(const Function &F) {
Stream.EnterSubblock(bitc::METADATA_ATTACHMENT_ID, 3);

SmallVector<uint64_t, 64> Record;

// Write metadata attachments
// METADATA_ATTACHMENT - [m x [value, [n x [id, mdnode]]]
SmallVector<std::pair<unsigned, MDNode *>, 4> MDs;
F.getAllMetadata(MDs);
if (!MDs.empty()) {
for (const auto &I : MDs) {
Record.push_back(I.first);
Record.push_back(VE.getMetadataID(I.second));
}
if (F.hasMetadata()) {
pushGlobalMetadataAttachment(Record, F);
Stream.EmitRecord(bitc::METADATA_ATTACHMENT, Record, 0);
Record.clear();
}

// Write metadata attachments
// METADATA_ATTACHMENT - [m x [value, [n x [id, mdnode]]]
SmallVector<std::pair<unsigned, MDNode *>, 4> MDs;
for (const BasicBlock &BB : F)
for (const Instruction &I : BB) {
MDs.clear();
Expand Down Expand Up @@ -2894,7 +2904,7 @@ void ModuleBitcodeWriter::writeFunction(
writeValueSymbolTable(F.getValueSymbolTable());

if (NeedsMetadataAttachment)
writeMetadataAttachment(F);
writeFunctionMetadataAttachment(F);
if (VE.shouldPreserveUseListOrder())
writeUseListBlock(&F);
VE.purgeFunction();
Expand Down Expand Up @@ -3597,6 +3607,14 @@ void ModuleBitcodeWriter::writeModule() {
writeValueSymbolTable(M.getValueSymbolTable(),
/* IsModuleLevel */ true, &FunctionToBitcodeIndex);

for (const GlobalVariable &GV : M.globals())
if (GV.hasMetadata()) {
SmallVector<uint64_t, 4> Record;
Record.push_back(VE.getValueID(&GV));
pushGlobalMetadataAttachment(Record, GV);
Stream.EmitRecord(bitc::MODULE_CODE_GLOBALVAR_ATTACHMENT, Record);
}

if (GenerateHash) {
writeModuleHash(BlockStartPos);
}
Expand Down
16 changes: 11 additions & 5 deletions llvm/lib/Bitcode/Writer/ValueEnumerator.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -344,6 +344,11 @@ ValueEnumerator::ValueEnumerator(const Module &M,
EnumerateNamedMetadata(M);

SmallVector<std::pair<unsigned, MDNode *>, 8> MDs;
for (const GlobalVariable &GV : M.globals()) {
GV.getAllMetadata(MDs);
for (const auto &I : MDs)
EnumerateMetadata(&GV, I.second);
}

// Enumerate types used by function bodies and argument lists.
for (const Function &F : M) {
Expand Down Expand Up @@ -523,17 +528,18 @@ void ValueEnumerator::EnumerateNamedMDNode(const NamedMDNode *MD) {
EnumerateMetadata(nullptr, MD->getOperand(i));
}

unsigned ValueEnumerator::getMetadataFunctionID(const Function *F) const {
return F ? getValueID(F) + 1 : 0;
unsigned ValueEnumerator::getMetadataGlobalID(const GlobalObject *GO) const {
return GO ? getValueID(GO) + 1 : 0;
}

void ValueEnumerator::EnumerateMetadata(const Function *F, const Metadata *MD) {
EnumerateMetadata(getMetadataFunctionID(F), MD);
void ValueEnumerator::EnumerateMetadata(const GlobalObject *GO,
const Metadata *MD) {
EnumerateMetadata(getMetadataGlobalID(GO), MD);
}

void ValueEnumerator::EnumerateFunctionLocalMetadata(
const Function &F, const LocalAsMetadata *Local) {
EnumerateFunctionLocalMetadata(getMetadataFunctionID(&F), Local);
EnumerateFunctionLocalMetadata(getMetadataGlobalID(&F), Local);
}

void ValueEnumerator::dropFunctionFromMetadata(
Expand Down
4 changes: 2 additions & 2 deletions llvm/lib/Bitcode/Writer/ValueEnumerator.h
Original file line number Diff line number Diff line change
Expand Up @@ -255,7 +255,7 @@ class ValueEnumerator {
/// it's an \a MDNode.
const MDNode *enumerateMetadataImpl(unsigned F, const Metadata *MD);

unsigned getMetadataFunctionID(const Function *F) const;
unsigned getMetadataGlobalID(const GlobalObject *GO) const;

/// Enumerate reachable metadata in (almost) post-order.
///
Expand All @@ -272,7 +272,7 @@ class ValueEnumerator {
/// \a organizeMetadata() will later partition distinct nodes ahead of
/// uniqued ones.
///{
void EnumerateMetadata(const Function *F, const Metadata *MD);
void EnumerateMetadata(const GlobalObject *GO, const Metadata *MD);
void EnumerateMetadata(unsigned F, const Metadata *MD);
///}

Expand Down
15 changes: 13 additions & 2 deletions llvm/lib/IR/AsmWriter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -681,6 +681,9 @@ class SlotTracker {
/// Add all of the functions arguments, basic blocks, and instructions.
void processFunction();

/// Add the metadata directly attached to a GlobalObject.
void processGlobalObjectMetadata(const GlobalObject &GO);

/// Add all of the metadata from a function.
void processFunctionMetadata(const Function &F);

Expand Down Expand Up @@ -799,6 +802,7 @@ void SlotTracker::processModule() {
for (const GlobalVariable &Var : TheModule->globals()) {
if (!Var.hasName())
CreateModuleSlot(&Var);
processGlobalObjectMetadata(Var);
}

for (const GlobalAlias &A : TheModule->aliases()) {
Expand Down Expand Up @@ -882,12 +886,15 @@ void SlotTracker::processFunction() {
ST_DEBUG("end processFunction!\n");
}

void SlotTracker::processFunctionMetadata(const Function &F) {
void SlotTracker::processGlobalObjectMetadata(const GlobalObject &GO) {
SmallVector<std::pair<unsigned, MDNode *>, 4> MDs;
F.getAllMetadata(MDs);
GO.getAllMetadata(MDs);
for (auto &MD : MDs)
CreateMetadataSlot(MD.second);
}

void SlotTracker::processFunctionMetadata(const Function &F) {
processGlobalObjectMetadata(F);
for (auto &BB : F) {
for (auto &I : BB)
processInstructionMetadata(I);
Expand Down Expand Up @@ -2473,6 +2480,10 @@ void AssemblyWriter::printGlobal(const GlobalVariable *GV) {
if (GV->getAlignment())
Out << ", align " << GV->getAlignment();

SmallVector<std::pair<unsigned, MDNode *>, 4> MDs;
GV->getAllMetadata(MDs);
printMetadataAttachments(MDs, ", ");

printInfoComment(*GV);
}

Expand Down
6 changes: 4 additions & 2 deletions llvm/lib/IR/Function.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -218,11 +218,13 @@ bool Argument::hasAttribute(Attribute::AttrKind Kind) const {
//===----------------------------------------------------------------------===//

bool Function::isMaterializable() const {
return getGlobalObjectSubClassData() & IsMaterializableBit;
return getGlobalObjectSubClassData() & (1 << IsMaterializableBit);
}

void Function::setIsMaterializable(bool V) {
setGlobalObjectBit(IsMaterializableBit, V);
unsigned Mask = 1 << IsMaterializableBit;
setGlobalObjectSubClassData((~Mask & getGlobalObjectSubClassData()) |
(V ? Mask : 0u));
}

LLVMContext &Function::getContext() const {
Expand Down
10 changes: 7 additions & 3 deletions llvm/lib/IR/Globals.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -81,13 +81,13 @@ void GlobalObject::setAlignment(unsigned Align) {

unsigned GlobalObject::getGlobalObjectSubClassData() const {
unsigned ValueData = getGlobalValueSubClassData();
return ValueData >> AlignmentBits;
return ValueData >> GlobalObjectBits;
}

void GlobalObject::setGlobalObjectSubClassData(unsigned Val) {
unsigned OldData = getGlobalValueSubClassData();
setGlobalValueSubClassData((OldData & AlignmentMask) |
(Val << AlignmentBits));
setGlobalValueSubClassData((OldData & GlobalObjectMask) |
(Val << GlobalObjectBits));
assert(getGlobalObjectSubClassData() == Val && "representation error");
}

Expand Down Expand Up @@ -301,6 +301,10 @@ void GlobalVariable::copyAttributesFrom(const GlobalValue *Src) {
}
}

void GlobalVariable::dropAllReferences() {
User::dropAllReferences();
clearMetadata();
}

//===----------------------------------------------------------------------===//
// GlobalIndirectSymbol Implementation
Expand Down
4 changes: 2 additions & 2 deletions llvm/lib/IR/LLVMContextImpl.h
Original file line number Diff line number Diff line change
Expand Up @@ -1107,8 +1107,8 @@ class LLVMContextImpl {
/// Collection of per-instruction metadata used in this context.
DenseMap<const Instruction *, MDAttachmentMap> InstructionMetadata;

/// Collection of per-function metadata used in this context.
DenseMap<const Function *, MDAttachmentMap> FunctionMetadata;
/// Collection of per-GlobalObject metadata used in this context.
DenseMap<const GlobalObject *, MDAttachmentMap> GlobalObjectMetadata;

/// DiscriminatorTable - This table maps file:line locations to an
/// integer representing the next DWARF path discriminator to assign to
Expand Down
26 changes: 13 additions & 13 deletions llvm/lib/IR/Metadata.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1281,54 +1281,54 @@ void Instruction::clearMetadataHashEntries() {
setHasMetadataHashEntry(false);
}

MDNode *Function::getMetadata(unsigned KindID) const {
MDNode *GlobalObject::getMetadata(unsigned KindID) const {
if (!hasMetadata())
return nullptr;
return getContext().pImpl->FunctionMetadata[this].lookup(KindID);
return getContext().pImpl->GlobalObjectMetadata[this].lookup(KindID);
}

MDNode *Function::getMetadata(StringRef Kind) const {
MDNode *GlobalObject::getMetadata(StringRef Kind) const {
if (!hasMetadata())
return nullptr;
return getMetadata(getContext().getMDKindID(Kind));
}

void Function::setMetadata(unsigned KindID, MDNode *MD) {
void GlobalObject::setMetadata(unsigned KindID, MDNode *MD) {
if (MD) {
if (!hasMetadata())
setHasMetadataHashEntry(true);

getContext().pImpl->FunctionMetadata[this].set(KindID, *MD);
getContext().pImpl->GlobalObjectMetadata[this].set(KindID, *MD);
return;
}

// Nothing to unset.
if (!hasMetadata())
return;

auto &Store = getContext().pImpl->FunctionMetadata[this];
auto &Store = getContext().pImpl->GlobalObjectMetadata[this];
Store.erase(KindID);
if (Store.empty())
clearMetadata();
}

void Function::setMetadata(StringRef Kind, MDNode *MD) {
void GlobalObject::setMetadata(StringRef Kind, MDNode *MD) {
if (!MD && !hasMetadata())
return;
setMetadata(getContext().getMDKindID(Kind), MD);
}

void Function::getAllMetadata(
void GlobalObject::getAllMetadata(
SmallVectorImpl<std::pair<unsigned, MDNode *>> &MDs) const {
MDs.clear();

if (!hasMetadata())
return;

getContext().pImpl->FunctionMetadata[this].getAll(MDs);
getContext().pImpl->GlobalObjectMetadata[this].getAll(MDs);
}

void Function::dropUnknownMetadata(ArrayRef<unsigned> KnownIDs) {
void GlobalObject::dropUnknownMetadata(ArrayRef<unsigned> KnownIDs) {
if (!hasMetadata())
return;
if (KnownIDs.empty()) {
Expand All @@ -1339,7 +1339,7 @@ void Function::dropUnknownMetadata(ArrayRef<unsigned> KnownIDs) {
SmallSet<unsigned, 5> KnownSet;
KnownSet.insert(KnownIDs.begin(), KnownIDs.end());

auto &Store = getContext().pImpl->FunctionMetadata[this];
auto &Store = getContext().pImpl->GlobalObjectMetadata[this];
assert(!Store.empty());

Store.remove_if([&KnownSet](const std::pair<unsigned, TrackingMDNodeRef> &I) {
Expand All @@ -1350,10 +1350,10 @@ void Function::dropUnknownMetadata(ArrayRef<unsigned> KnownIDs) {
clearMetadata();
}

void Function::clearMetadata() {
void GlobalObject::clearMetadata() {
if (!hasMetadata())
return;
getContext().pImpl->FunctionMetadata.erase(this);
getContext().pImpl->GlobalObjectMetadata.erase(this);
setHasMetadataHashEntry(false);
}

Expand Down
19 changes: 14 additions & 5 deletions llvm/test/Assembler/metadata.ll
Original file line number Diff line number Diff line change
@@ -1,8 +1,11 @@
; RUN: llvm-as < %s | llvm-dis | llvm-as | llvm-dis | FileCheck %s
; RUN: verify-uselistorder %s

; CHECK: @global = global i32 0, !foo [[M2:![0-9]+]], !baz [[M3:![0-9]+]]
@global = global i32 0, !foo !2, !baz !3

; CHECK-LABEL: @test
; CHECK: ret void, !bar !4, !foo !3
; CHECK: ret void, !foo [[M0:![0-9]+]], !bar [[M1:![0-9]+]]
define void @test() !dbg !1 {
add i32 2, 1, !bar !0
add i32 1, 2, !foo !1
Expand All @@ -11,24 +14,30 @@ define void @test() !dbg !1 {
ret void, !foo !0, !bar !1
}

; CHECK-LABEL: define void @test2() !foo !5 !baz !6
; CHECK: define void @test2() !foo [[M2]] !baz [[M3]]
define void @test2() !foo !2 !baz !3 {
unreachable
}

; CHECK-LABEL: define void @test3() !bar !6
; CHECK: unreachable, !bar !7
; CHECK: define void @test3() !bar [[M3]]
; CHECK: unreachable, !bar [[M4:![0-9]+]]
define void @test3() !bar !3 {
unreachable, !bar !4
}

; CHECK-LABEL: define void @test_attachment_name() {
; CHECK: unreachable, !\342abc !7
; CHECK: unreachable, !\342abc [[M4]]
define void @test_attachment_name() {
;; Escape the first character when printing text IR, since it's a digit
unreachable, !\34\32abc !4
}

; CHECK: [[M2]] = distinct !{}
; CHECK: [[M3]] = distinct !{}
; CHECK: [[M0]] = !DILocation
; CHECK: [[M1]] = distinct !DISubprogram
; CHECK: [[M4]] = distinct !{}

!llvm.module.flags = !{!7}
!llvm.dbg.cu = !{!5}
!0 = !DILocation(line: 662302, column: 26, scope: !1)
Expand Down