Add support for metadata attachments for global variables.

This patch adds an IR, assembly and bitcode representation for metadata
attachments for globals. Future patches will port existing features to use
these new attachments.

Differential Revision: http://reviews.llvm.org/D20074

llvm-svn: 271348
This commit is contained in:
Peter Collingbourne 2016-05-31 23:01:54 +00:00
parent 81fbadb63f
commit cceae7feda
18 changed files with 217 additions and 110 deletions

View File

@ -856,6 +856,16 @@ be one ``GCNAME`` record for each garbage collector name referenced in function
``gc`` attributes within the module. These records can be referenced by 1-based
index in the *gc* fields of ``FUNCTION`` records.
MODULE_CODE_GLOBALVAR_ATTACHMENT Record
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
``[GLOBALVAR_ATTACHMENT, valueid, n x [id, mdnode]]``
The ``GLOBALVAR_ATTACHMENT`` record (code 19) describes the metadata
attachments for a global variable. The ``valueid`` is the value index for
the global variable, and the remaining fields are pairs of metadata name
indices and metadata node indices.
.. _PARAMATTR_BLOCK:
PARAMATTR_BLOCK Contents

View File

@ -619,7 +619,8 @@ assume that the globals are densely packed in their section and try to
iterate over them as an array, alignment padding would break this
iteration. The maximum alignment is ``1 << 29``.
Globals can also have a :ref:`DLL storage class <dllstorageclass>`.
Globals can also have a :ref:`DLL storage class <dllstorageclass>` and
an optional list of attached :ref:`metadata <metadata>`,
Variables and aliases can have a
:ref:`Thread Local Storage Model <tls_model>`.
@ -630,7 +631,7 @@ Syntax::
[unnamed_addr] [AddrSpace] [ExternallyInitialized]
<global | constant> <Type> [<InitializerConstant>]
[, section "name"] [, comdat [($name)]]
[, align <Alignment>]
[, align <Alignment>] (, !name !N)*
For example, the following defines a global in a numbered address space
with an initializer, section, and alignment:

View File

@ -113,6 +113,9 @@ enum ModuleCodes {
// IFUNC: [ifunc value type, addrspace, resolver val#, linkage, visibility]
MODULE_CODE_IFUNC = 18,
// GLOBALVAR_ATTACHMENT: [valueid, n x [id, mdnode]]
MODULE_CODE_GLOBALVAR_ATTACHMENT = 19,
};
/// PARAMATTR blocks have code for defining a parameter attribute set.

View File

@ -72,13 +72,8 @@ private:
/// Bits from GlobalObject::GlobalObjectSubclassData.
enum {
/// Whether this function is materializable.
IsMaterializableBit = 1 << 0,
HasMetadataHashEntryBit = 1 << 1
IsMaterializableBit = 0,
};
void setGlobalObjectBit(unsigned Mask, bool Value) {
setGlobalObjectSubClassData((~Mask & getGlobalObjectSubClassData()) |
(Value ? Mask : 0u));
}
friend class SymbolTableListTraits<Function>;
@ -614,35 +609,6 @@ public:
/// setjmp or other function that gcc recognizes as "returning twice".
bool callsFunctionThatReturnsTwice() const;
/// \brief Check if this has any metadata.
bool hasMetadata() const { return hasMetadataHashEntry(); }
/// \brief Get the current metadata attachment, if any.
///
/// Returns \c nullptr if such an attachment is missing.
/// @{
MDNode *getMetadata(unsigned KindID) const;
MDNode *getMetadata(StringRef Kind) const;
/// @}
/// \brief Set a particular kind of metadata attachment.
///
/// Sets the given attachment to \c MD, erasing it if \c MD is \c nullptr or
/// replacing it if it already exists.
/// @{
void setMetadata(unsigned KindID, MDNode *MD);
void setMetadata(StringRef Kind, MDNode *MD);
/// @}
/// \brief Get all current metadata attachments.
void
getAllMetadata(SmallVectorImpl<std::pair<unsigned, MDNode *>> &MDs) const;
/// \brief Drop metadata not in the given list.
///
/// Drop all metadata from \c this not included in \c KnownIDs.
void dropUnknownMetadata(ArrayRef<unsigned> KnownIDs);
/// \brief Set the attached subprogram.
///
/// Calls \a setMetadata() with \a LLVMContext::MD_dbg.
@ -664,15 +630,6 @@ private:
Value::setValueSubclassData(D);
}
void setValueSubclassDataBit(unsigned Bit, bool On);
bool hasMetadataHashEntry() const {
return getGlobalObjectSubClassData() & HasMetadataHashEntryBit;
}
void setHasMetadataHashEntry(bool HasEntry) {
setGlobalObjectBit(HasMetadataHashEntryBit, HasEntry);
}
void clearMetadata();
};
template <>

View File

@ -20,6 +20,7 @@
namespace llvm {
class Comdat;
class MDNode;
class Module;
class GlobalObject : public GlobalValue {
@ -36,12 +37,19 @@ protected:
std::string Section; // Section to emit this into, empty means default
Comdat *ObjComdat;
static const unsigned AlignmentBits = 5;
enum {
LastAlignmentBit = 4,
HasMetadataHashEntryBit,
GlobalObjectBits,
};
static const unsigned GlobalObjectSubClassDataBits =
GlobalValueSubClassDataBits - AlignmentBits;
GlobalValueSubClassDataBits - GlobalObjectBits;
private:
static const unsigned AlignmentBits = LastAlignmentBit + 1;
static const unsigned AlignmentMask = (1 << AlignmentBits) - 1;
static const unsigned GlobalObjectMask = (1 << GlobalObjectBits) - 1;
public:
unsigned getAlignment() const {
@ -63,6 +71,35 @@ public:
Comdat *getComdat() { return ObjComdat; }
void setComdat(Comdat *C) { ObjComdat = C; }
/// Check if this has any metadata.
bool hasMetadata() const { return hasMetadataHashEntry(); }
/// Get the current metadata attachment, if any.
///
/// Returns \c nullptr if such an attachment is missing.
/// @{
MDNode *getMetadata(unsigned KindID) const;
MDNode *getMetadata(StringRef Kind) const;
/// @}
/// Set a particular kind of metadata attachment.
///
/// Sets the given attachment to \c MD, erasing it if \c MD is \c nullptr or
/// replacing it if it already exists.
/// @{
void setMetadata(unsigned KindID, MDNode *MD);
void setMetadata(StringRef Kind, MDNode *MD);
/// @}
/// Get all current metadata attachments.
void
getAllMetadata(SmallVectorImpl<std::pair<unsigned, MDNode *>> &MDs) const;
/// Drop metadata not in the given list.
///
/// Drop all metadata from \c this not included in \c KnownIDs.
void dropUnknownMetadata(ArrayRef<unsigned> KnownIDs);
void copyAttributesFrom(const GlobalValue *Src) override;
// Methods for support type inquiry through isa, cast, and dyn_cast:
@ -70,6 +107,19 @@ public:
return V->getValueID() == Value::FunctionVal ||
V->getValueID() == Value::GlobalVariableVal;
}
protected:
void clearMetadata();
private:
bool hasMetadataHashEntry() const {
return getGlobalValueSubClassData() & (1 << HasMetadataHashEntryBit);
}
void setHasMetadataHashEntry(bool HasEntry) {
unsigned Mask = 1 << HasMetadataHashEntryBit;
setGlobalValueSubClassData((~Mask & getGlobalValueSubClassData()) |
(HasEntry ? Mask : 0u));
}
};
} // End llvm namespace

View File

@ -159,6 +159,10 @@ public:
///
void eraseFromParent() override;
/// Drop all references in preparation to destroy the GlobalVariable. This
/// drops not only the reference to the initializer but also to any metadata.
void dropAllReferences();
// Methods for support type inquiry through isa, cast, and dyn_cast:
static inline bool classof(const Value *V) {
return V->getValueID() == Value::GlobalVariableVal;

View File

@ -891,6 +891,9 @@ bool LLParser::ParseGlobal(const std::string &Name, LocTy NameLoc,
unsigned Alignment;
if (ParseOptionalAlignment(Alignment)) return true;
GV->setAlignment(Alignment);
} else if (Lex.getKind() == lltok::MetadataVar) {
if (ParseGlobalObjectMetadataAttachment(*GV))
return true;
} else {
Comdat *C;
if (parseOptionalComdat(Name, C))
@ -1708,17 +1711,24 @@ bool LLParser::ParseInstructionMetadata(Instruction &Inst) {
return false;
}
/// ParseGlobalObjectMetadataAttachment
/// ::= !dbg !57
bool LLParser::ParseGlobalObjectMetadataAttachment(GlobalObject &GO) {
unsigned MDK;
MDNode *N;
if (ParseMetadataAttachment(MDK, N))
return true;
GO.setMetadata(MDK, N);
return false;
}
/// ParseOptionalFunctionMetadata
/// ::= (!dbg !57)*
bool LLParser::ParseOptionalFunctionMetadata(Function &F) {
while (Lex.getKind() == lltok::MetadataVar) {
unsigned MDK;
MDNode *N;
if (ParseMetadataAttachment(MDK, N))
while (Lex.getKind() == lltok::MetadataVar)
if (ParseGlobalObjectMetadataAttachment(F))
return true;
F.setMetadata(MDK, N);
}
return false;
}

View File

@ -424,6 +424,7 @@ namespace llvm {
bool ParseMDNodeVector(SmallVectorImpl<Metadata *> &MDs);
bool ParseMetadataAttachment(unsigned &Kind, MDNode *&MD);
bool ParseInstructionMetadata(Instruction &Inst);
bool ParseGlobalObjectMetadataAttachment(GlobalObject &GO);
bool ParseOptionalFunctionMetadata(Function &F);
template <class FieldTy>

View File

@ -443,6 +443,9 @@ private:
unsigned &NextMetadataNo);
std::error_code parseMetadataKinds();
std::error_code parseMetadataKindRecord(SmallVectorImpl<uint64_t> &Record);
std::error_code
parseGlobalObjectAttachment(GlobalObject &GO,
ArrayRef<uint64_t> Record);
std::error_code parseMetadataAttachment(Function &F);
ErrorOr<std::string> parseModuleTriple();
std::error_code parseUseLists();
@ -3820,6 +3823,16 @@ std::error_code BitcodeReader::parseModule(uint64_t ResumeBit,
}
break;
}
case bitc::MODULE_CODE_GLOBALVAR_ATTACHMENT: {
if (Record.size() % 2 == 0)
return error("Invalid record");
unsigned ValueID = Record[0];
if (ValueID >= ValueList.size())
return error("Invalid record");
if (auto *GV = dyn_cast<GlobalVariable>(ValueList[ValueID]))
parseGlobalObjectAttachment(*GV, ArrayRef<uint64_t>(Record).slice(1));
break;
}
// FUNCTION: [type, callingconv, isproto, linkage, paramattr,
// alignment, section, visibility, gc, unnamed_addr,
// prologuedata, dllstorageclass, comdat, prefixdata]
@ -4144,6 +4157,21 @@ ErrorOr<std::string> BitcodeReader::parseIdentificationBlock() {
}
}
std::error_code BitcodeReader::parseGlobalObjectAttachment(
GlobalObject &GO, ArrayRef<uint64_t> Record) {
assert(Record.size() % 2 == 0);
for (unsigned I = 0, E = Record.size(); I != E; I += 2) {
auto K = MDKindMap.find(Record[I]);
if (K == MDKindMap.end())
return error("Invalid ID");
MDNode *MD = MetadataList.getMDNodeFwdRefOrNull(Record[I + 1]);
if (!MD)
return error("Invalid metadata attachment");
GO.setMetadata(K->second, MD);
}
return std::error_code();
}
/// Parse metadata attachments.
std::error_code BitcodeReader::parseMetadataAttachment(Function &F) {
if (Stream.EnterSubBlock(bitc::METADATA_ATTACHMENT_ID))
@ -4175,15 +4203,8 @@ std::error_code BitcodeReader::parseMetadataAttachment(Function &F) {
return error("Invalid record");
if (RecordLength % 2 == 0) {
// A function attachment.
for (unsigned I = 0; I != RecordLength; I += 2) {
auto K = MDKindMap.find(Record[I]);
if (K == MDKindMap.end())
return error("Invalid ID");
MDNode *MD = MetadataList.getMDNodeFwdRefOrNull(Record[I + 1]);
if (!MD)
return error("Invalid metadata attachment");
F.setMetadata(K->second, MD);
}
if (std::error_code EC = parseGlobalObjectAttachment(F, Record))
return EC;
continue;
}

View File

@ -223,7 +223,10 @@ private:
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);
@ -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();
@ -2894,7 +2904,7 @@ void ModuleBitcodeWriter::writeFunction(
writeValueSymbolTable(F.getValueSymbolTable());
if (NeedsMetadataAttachment)
writeMetadataAttachment(F);
writeFunctionMetadataAttachment(F);
if (VE.shouldPreserveUseListOrder())
writeUseListBlock(&F);
VE.purgeFunction();
@ -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);
}

View File

@ -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) {
@ -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(

View File

@ -255,7 +255,7 @@ private:
/// 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.
///
@ -272,7 +272,7 @@ private:
/// \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);
///}

View File

@ -681,6 +681,9 @@ private:
/// 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);
@ -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()) {
@ -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);
@ -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);
}

View File

@ -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 {

View File

@ -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");
}
@ -301,6 +301,10 @@ void GlobalVariable::copyAttributesFrom(const GlobalValue *Src) {
}
}
void GlobalVariable::dropAllReferences() {
User::dropAllReferences();
clearMetadata();
}
//===----------------------------------------------------------------------===//
// GlobalIndirectSymbol Implementation

View File

@ -1107,8 +1107,8 @@ public:
/// 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

View File

@ -1281,24 +1281,24 @@ 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;
}
@ -1306,29 +1306,29 @@ void Function::setMetadata(unsigned KindID, MDNode *MD) {
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()) {
@ -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) {
@ -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);
}

View File

@ -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
@ -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)