mirror of
https://github.com/RPCS3/llvm-mirror.git
synced 2024-11-26 04:32:44 +01:00
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:
parent
3c1133f753
commit
fa4e4af5c9
@ -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
|
||||
|
@ -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:
|
||||
|
@ -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.
|
||||
|
@ -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 <>
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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>
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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(
|
||||
|
@ -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);
|
||||
///}
|
||||
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
|
@ -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 {
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
|
@ -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)
|
||||
|
Loading…
Reference in New Issue
Block a user