From f45666e4e99eb1bd4a70b12941e7372186d88066 Mon Sep 17 00:00:00 2001 From: Bill Wendling Date: Mon, 11 Feb 2013 08:43:33 +0000 Subject: [PATCH] Add support for printing out the attribute groups. This emits the attribute groups that are used by the functions. (It currently doesn't print out return type or parameter attributes within attribute groups.) Note: The functions still retrieve their attributes from the "old" bitcode format (using the deprecated 'Raw()' method). This means that string attributes within an attribute group will not show up during a disassembly. This will be addressed in a future commit. llvm-svn: 174867 --- include/llvm/IR/Attributes.h | 4 +- lib/IR/AsmWriter.cpp | 72 ++++++++++++++++++++++++++++++++++-- lib/IR/AttributeImpl.h | 2 +- lib/IR/Attributes.cpp | 31 ++++++++++------ 4 files changed, 90 insertions(+), 19 deletions(-) diff --git a/include/llvm/IR/Attributes.h b/include/llvm/IR/Attributes.h index d4836ee30e2..d064e7e2ad3 100644 --- a/include/llvm/IR/Attributes.h +++ b/include/llvm/IR/Attributes.h @@ -171,7 +171,7 @@ public: /// \brief The Attribute is converted to a string of equivalent mnemonic. This /// is, presumably, for writing out the mnemonics for the assembly writer. - std::string getAsString() const; + std::string getAsString(bool InAttrGrp = false) const; /// \brief Equality and non-equality operators. bool operator==(Attribute A) const { return pImpl == A.pImpl; } @@ -317,7 +317,7 @@ public: unsigned getStackAlignment(unsigned Index) const; /// \brief Return the attributes at the index as a string. - std::string getAsString(unsigned Index) const; + std::string getAsString(unsigned Index, bool InAttrGrp = false) const; typedef ArrayRef::iterator iterator; diff --git a/lib/IR/AsmWriter.cpp b/lib/IR/AsmWriter.cpp index d3736a1bb4b..bf893e855e5 100644 --- a/lib/IR/AsmWriter.cpp +++ b/lib/IR/AsmWriter.cpp @@ -347,6 +347,10 @@ private: /// mdnMap - Map for MDNodes. DenseMap mdnMap; unsigned mdnNext; + + /// asMap - The slot map for attribute sets. + DenseMap asMap; + unsigned asNext; public: /// Construct from a module explicit SlotTracker(const Module *M); @@ -358,6 +362,7 @@ public: int getLocalSlot(const Value *V); int getGlobalSlot(const GlobalValue *V); int getMetadataSlot(const MDNode *N); + int getAttributeGroupSlot(AttributeSet AS); /// If you'd like to deal with a function instead of just a module, use /// this method to get its data into the SlotTracker. @@ -378,6 +383,13 @@ public: unsigned mdn_size() const { return mdnMap.size(); } bool mdn_empty() const { return mdnMap.empty(); } + /// AttributeSet map iterators. + typedef DenseMap::iterator as_iterator; + as_iterator as_begin() { return asMap.begin(); } + as_iterator as_end() { return asMap.end(); } + unsigned as_size() const { return asMap.size(); } + bool as_empty() const { return asMap.empty(); } + /// This function does the actual initialization. inline void initialize(); @@ -392,6 +404,9 @@ private: /// CreateFunctionSlot - Insert the specified Value* into the slot table. void CreateFunctionSlot(const Value *V); + /// \brief Insert the specified AttributeSet into the slot table. + void CreateAttributeSetSlot(AttributeSet AS); + /// Add all of the module level global variables (and their initializers) /// and function declarations, but not the contents of those functions. void processModule(); @@ -446,14 +461,14 @@ static SlotTracker *createSlotTracker(const Value *V) { // to be added to the slot table. SlotTracker::SlotTracker(const Module *M) : TheModule(M), TheFunction(0), FunctionProcessed(false), - mNext(0), fNext(0), mdnNext(0) { + mNext(0), fNext(0), mdnNext(0), asNext(0) { } // Function level constructor. Causes the contents of the Module and the one // function provided to be added to the slot table. SlotTracker::SlotTracker(const Function *F) : TheModule(F ? F->getParent() : 0), TheFunction(F), FunctionProcessed(false), - mNext(0), fNext(0), mdnNext(0) { + mNext(0), fNext(0), mdnNext(0), asNext(0) { } inline void SlotTracker::initialize() { @@ -487,12 +502,18 @@ void SlotTracker::processModule() { CreateMetadataSlot(NMD->getOperand(i)); } - // Add all the unnamed functions to the table. for (Module::const_iterator I = TheModule->begin(), E = TheModule->end(); - I != E; ++I) + I != E; ++I) { if (!I->hasName()) + // Add all the unnamed functions to the table. CreateModuleSlot(I); + // Add all the function attributes to the table. + AttributeSet FnAttrs = I->getAttributes().getFnAttributes(); + if (FnAttrs.hasAttributes(AttributeSet::FunctionIndex)) + CreateAttributeSetSlot(FnAttrs); + } + ST_DEBUG("end processModule!\n"); } @@ -589,6 +610,14 @@ int SlotTracker::getLocalSlot(const Value *V) { return FI == fMap.end() ? -1 : (int)FI->second; } +int SlotTracker::getAttributeGroupSlot(AttributeSet AS) { + // Check for uninitialized state and do lazy initialization. + initialize(); + + // Find the AttributeSet in the module map. + as_iterator AI = asMap.find(AS); + return AI == asMap.end() ? -1 : (int)AI->second; +} /// CreateModuleSlot - Insert the specified GlobalValue* into the slot table. void SlotTracker::CreateModuleSlot(const GlobalValue *V) { @@ -640,6 +669,18 @@ void SlotTracker::CreateMetadataSlot(const MDNode *N) { CreateMetadataSlot(Op); } +void SlotTracker::CreateAttributeSetSlot(AttributeSet AS) { + assert(AS.hasAttributes(AttributeSet::FunctionIndex) && + "Doesn't need a slot!"); + + as_iterator I = asMap.find(AS); + if (I != asMap.end()) + return; + + unsigned DestSlot = asNext++; + asMap[AS] = DestSlot; +} + //===----------------------------------------------------------------------===// // AsmWriter Implementation //===----------------------------------------------------------------------===// @@ -1201,6 +1242,7 @@ public: void writeAtomic(AtomicOrdering Ordering, SynchronizationScope SynchScope); void writeAllMDNodes(); + void writeAllAttributeGroups(); void printTypeIdentities(); void printGlobal(const GlobalVariable *GV); @@ -1268,6 +1310,8 @@ void AssemblyWriter::writeParamOperand(const Value *Operand, } void AssemblyWriter::printModule(const Module *M) { + Machine.initialize(); + if (!M->getModuleIdentifier().empty() && // Don't print the ID if it will start a new line (which would // require a comment char before it). @@ -1322,6 +1366,12 @@ void AssemblyWriter::printModule(const Module *M) { for (Module::const_iterator I = M->begin(), E = M->end(); I != E; ++I) printFunction(I); + // Output all attribute groups. + if (!Machine.as_empty()) { + Out << '\n'; + writeAllAttributeGroups(); + } + // Output named metadata. if (!M->named_metadata_empty()) Out << '\n'; @@ -2063,6 +2113,20 @@ void AssemblyWriter::printMDNodeBody(const MDNode *Node) { Out << "\n"; } +void AssemblyWriter::writeAllAttributeGroups() { + std::vector > asVec; + asVec.resize(Machine.as_size()); + + for (SlotTracker::as_iterator I = Machine.as_begin(), E = Machine.as_end(); + I != E; ++I) + asVec[I->second] = *I; + + for (std::vector >::iterator + I = asVec.begin(), E = asVec.end(); I != E; ++I) + Out << "attributes #" << I->second << " = { " + << I->first.getAsString(AttributeSet::FunctionIndex, true) << " }\n"; +} + //===----------------------------------------------------------------------===// // External Interface declarations //===----------------------------------------------------------------------===// diff --git a/lib/IR/AttributeImpl.h b/lib/IR/AttributeImpl.h index 84f472d033b..7bb1fccba0a 100644 --- a/lib/IR/AttributeImpl.h +++ b/lib/IR/AttributeImpl.h @@ -174,7 +174,7 @@ public: unsigned getAlignment() const; unsigned getStackAlignment() const; - std::string getAsString() const; + std::string getAsString(bool InAttrGrp) const; typedef SmallVectorImpl::iterator iterator; typedef SmallVectorImpl::const_iterator const_iterator; diff --git a/lib/IR/Attributes.cpp b/lib/IR/Attributes.cpp index 267c1aa8932..d338d6538e8 100644 --- a/lib/IR/Attributes.cpp +++ b/lib/IR/Attributes.cpp @@ -150,7 +150,7 @@ unsigned Attribute::getStackAlignment() const { return pImpl->getValueAsInt(); } -std::string Attribute::getAsString() const { +std::string Attribute::getAsString(bool InAttrGrp) const { if (!pImpl) return ""; if (hasAttribute(Attribute::AddressSafety)) @@ -221,15 +221,23 @@ std::string Attribute::getAsString() const { // if (hasAttribute(Attribute::Alignment)) { std::string Result; - Result += "align "; + Result += "align"; + Result += (InAttrGrp) ? "=" : " "; Result += utostr(getValueAsInt()); return Result; } + if (hasAttribute(Attribute::StackAlignment)) { std::string Result; - Result += "alignstack("; - Result += utostr(getValueAsInt()); - Result += ")"; + Result += "alignstack"; + if (InAttrGrp) { + Result += "="; + Result += utostr(getValueAsInt()); + } else { + Result += "("; + Result += utostr(getValueAsInt()); + Result += ")"; + } return Result; } @@ -237,7 +245,6 @@ std::string Attribute::getAsString() const { // // "kind" // "kind" = "value" - // "kind" = ( "value1" "value2" "value3" ) // if (isStringAttribute()) { std::string Result; @@ -246,8 +253,7 @@ std::string Attribute::getAsString() const { StringRef Val = pImpl->getValueAsString(); if (Val.empty()) return Result; - Result += " = "; - Result += '\"' + Val.str() + '"'; + Result += "=\"" + Val.str() + '"'; return Result; } @@ -451,11 +457,11 @@ unsigned AttributeSetNode::getStackAlignment() const { return 0; } -std::string AttributeSetNode::getAsString() const { +std::string AttributeSetNode::getAsString(bool InAttrGrp) const { std::string Str = ""; for (SmallVectorImpl::const_iterator I = AttrList.begin(), E = AttrList.end(); I != E; ) { - Str += I->getAsString(); + Str += I->getAsString(InAttrGrp); if (++I != E) Str += " "; } return Str; @@ -783,9 +789,10 @@ unsigned AttributeSet::getStackAlignment(unsigned Index) const { return ASN ? ASN->getStackAlignment() : 0; } -std::string AttributeSet::getAsString(unsigned Index) const { +std::string AttributeSet::getAsString(unsigned Index, + bool InAttrGrp) const { AttributeSetNode *ASN = getAttributes(Index); - return ASN ? ASN->getAsString() : std::string(""); + return ASN ? ASN->getAsString(InAttrGrp) : std::string(""); } /// \brief The attributes for the specified index are returned.