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
This commit is contained in:
Bill Wendling 2013-02-11 08:43:33 +00:00
parent d01be8c559
commit f45666e4e9
4 changed files with 90 additions and 19 deletions

View File

@ -171,7 +171,7 @@ public:
/// \brief The Attribute is converted to a string of equivalent mnemonic. This /// \brief The Attribute is converted to a string of equivalent mnemonic. This
/// is, presumably, for writing out the mnemonics for the assembly writer. /// 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. /// \brief Equality and non-equality operators.
bool operator==(Attribute A) const { return pImpl == A.pImpl; } bool operator==(Attribute A) const { return pImpl == A.pImpl; }
@ -317,7 +317,7 @@ public:
unsigned getStackAlignment(unsigned Index) const; unsigned getStackAlignment(unsigned Index) const;
/// \brief Return the attributes at the index as a string. /// \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<Attribute>::iterator iterator; typedef ArrayRef<Attribute>::iterator iterator;

View File

@ -347,6 +347,10 @@ private:
/// mdnMap - Map for MDNodes. /// mdnMap - Map for MDNodes.
DenseMap<const MDNode*, unsigned> mdnMap; DenseMap<const MDNode*, unsigned> mdnMap;
unsigned mdnNext; unsigned mdnNext;
/// asMap - The slot map for attribute sets.
DenseMap<AttributeSet, unsigned> asMap;
unsigned asNext;
public: public:
/// Construct from a module /// Construct from a module
explicit SlotTracker(const Module *M); explicit SlotTracker(const Module *M);
@ -358,6 +362,7 @@ public:
int getLocalSlot(const Value *V); int getLocalSlot(const Value *V);
int getGlobalSlot(const GlobalValue *V); int getGlobalSlot(const GlobalValue *V);
int getMetadataSlot(const MDNode *N); int getMetadataSlot(const MDNode *N);
int getAttributeGroupSlot(AttributeSet AS);
/// If you'd like to deal with a function instead of just a module, use /// If you'd like to deal with a function instead of just a module, use
/// this method to get its data into the SlotTracker. /// this method to get its data into the SlotTracker.
@ -378,6 +383,13 @@ public:
unsigned mdn_size() const { return mdnMap.size(); } unsigned mdn_size() const { return mdnMap.size(); }
bool mdn_empty() const { return mdnMap.empty(); } bool mdn_empty() const { return mdnMap.empty(); }
/// AttributeSet map iterators.
typedef DenseMap<AttributeSet, unsigned>::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. /// This function does the actual initialization.
inline void initialize(); inline void initialize();
@ -392,6 +404,9 @@ private:
/// CreateFunctionSlot - Insert the specified Value* into the slot table. /// CreateFunctionSlot - Insert the specified Value* into the slot table.
void CreateFunctionSlot(const Value *V); 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) /// Add all of the module level global variables (and their initializers)
/// and function declarations, but not the contents of those functions. /// and function declarations, but not the contents of those functions.
void processModule(); void processModule();
@ -446,14 +461,14 @@ static SlotTracker *createSlotTracker(const Value *V) {
// to be added to the slot table. // to be added to the slot table.
SlotTracker::SlotTracker(const Module *M) SlotTracker::SlotTracker(const Module *M)
: TheModule(M), TheFunction(0), FunctionProcessed(false), : 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 level constructor. Causes the contents of the Module and the one
// function provided to be added to the slot table. // function provided to be added to the slot table.
SlotTracker::SlotTracker(const Function *F) SlotTracker::SlotTracker(const Function *F)
: TheModule(F ? F->getParent() : 0), TheFunction(F), FunctionProcessed(false), : 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() { inline void SlotTracker::initialize() {
@ -487,12 +502,18 @@ void SlotTracker::processModule() {
CreateMetadataSlot(NMD->getOperand(i)); CreateMetadataSlot(NMD->getOperand(i));
} }
// Add all the unnamed functions to the table.
for (Module::const_iterator I = TheModule->begin(), E = TheModule->end(); for (Module::const_iterator I = TheModule->begin(), E = TheModule->end();
I != E; ++I) I != E; ++I) {
if (!I->hasName()) if (!I->hasName())
// Add all the unnamed functions to the table.
CreateModuleSlot(I); 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"); ST_DEBUG("end processModule!\n");
} }
@ -589,6 +610,14 @@ int SlotTracker::getLocalSlot(const Value *V) {
return FI == fMap.end() ? -1 : (int)FI->second; 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. /// CreateModuleSlot - Insert the specified GlobalValue* into the slot table.
void SlotTracker::CreateModuleSlot(const GlobalValue *V) { void SlotTracker::CreateModuleSlot(const GlobalValue *V) {
@ -640,6 +669,18 @@ void SlotTracker::CreateMetadataSlot(const MDNode *N) {
CreateMetadataSlot(Op); 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 // AsmWriter Implementation
//===----------------------------------------------------------------------===// //===----------------------------------------------------------------------===//
@ -1201,6 +1242,7 @@ public:
void writeAtomic(AtomicOrdering Ordering, SynchronizationScope SynchScope); void writeAtomic(AtomicOrdering Ordering, SynchronizationScope SynchScope);
void writeAllMDNodes(); void writeAllMDNodes();
void writeAllAttributeGroups();
void printTypeIdentities(); void printTypeIdentities();
void printGlobal(const GlobalVariable *GV); void printGlobal(const GlobalVariable *GV);
@ -1268,6 +1310,8 @@ void AssemblyWriter::writeParamOperand(const Value *Operand,
} }
void AssemblyWriter::printModule(const Module *M) { void AssemblyWriter::printModule(const Module *M) {
Machine.initialize();
if (!M->getModuleIdentifier().empty() && if (!M->getModuleIdentifier().empty() &&
// Don't print the ID if it will start a new line (which would // Don't print the ID if it will start a new line (which would
// require a comment char before it). // 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) for (Module::const_iterator I = M->begin(), E = M->end(); I != E; ++I)
printFunction(I); printFunction(I);
// Output all attribute groups.
if (!Machine.as_empty()) {
Out << '\n';
writeAllAttributeGroups();
}
// Output named metadata. // Output named metadata.
if (!M->named_metadata_empty()) Out << '\n'; if (!M->named_metadata_empty()) Out << '\n';
@ -2063,6 +2113,20 @@ void AssemblyWriter::printMDNodeBody(const MDNode *Node) {
Out << "\n"; Out << "\n";
} }
void AssemblyWriter::writeAllAttributeGroups() {
std::vector<std::pair<AttributeSet, unsigned> > 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<std::pair<AttributeSet, unsigned> >::iterator
I = asVec.begin(), E = asVec.end(); I != E; ++I)
Out << "attributes #" << I->second << " = { "
<< I->first.getAsString(AttributeSet::FunctionIndex, true) << " }\n";
}
//===----------------------------------------------------------------------===// //===----------------------------------------------------------------------===//
// External Interface declarations // External Interface declarations
//===----------------------------------------------------------------------===// //===----------------------------------------------------------------------===//

View File

@ -174,7 +174,7 @@ public:
unsigned getAlignment() const; unsigned getAlignment() const;
unsigned getStackAlignment() const; unsigned getStackAlignment() const;
std::string getAsString() const; std::string getAsString(bool InAttrGrp) const;
typedef SmallVectorImpl<Attribute>::iterator iterator; typedef SmallVectorImpl<Attribute>::iterator iterator;
typedef SmallVectorImpl<Attribute>::const_iterator const_iterator; typedef SmallVectorImpl<Attribute>::const_iterator const_iterator;

View File

@ -150,7 +150,7 @@ unsigned Attribute::getStackAlignment() const {
return pImpl->getValueAsInt(); return pImpl->getValueAsInt();
} }
std::string Attribute::getAsString() const { std::string Attribute::getAsString(bool InAttrGrp) const {
if (!pImpl) return ""; if (!pImpl) return "";
if (hasAttribute(Attribute::AddressSafety)) if (hasAttribute(Attribute::AddressSafety))
@ -221,15 +221,23 @@ std::string Attribute::getAsString() const {
// //
if (hasAttribute(Attribute::Alignment)) { if (hasAttribute(Attribute::Alignment)) {
std::string Result; std::string Result;
Result += "align "; Result += "align";
Result += (InAttrGrp) ? "=" : " ";
Result += utostr(getValueAsInt()); Result += utostr(getValueAsInt());
return Result; return Result;
} }
if (hasAttribute(Attribute::StackAlignment)) { if (hasAttribute(Attribute::StackAlignment)) {
std::string Result; std::string Result;
Result += "alignstack("; Result += "alignstack";
Result += utostr(getValueAsInt()); if (InAttrGrp) {
Result += ")"; Result += "=";
Result += utostr(getValueAsInt());
} else {
Result += "(";
Result += utostr(getValueAsInt());
Result += ")";
}
return Result; return Result;
} }
@ -237,7 +245,6 @@ std::string Attribute::getAsString() const {
// //
// "kind" // "kind"
// "kind" = "value" // "kind" = "value"
// "kind" = ( "value1" "value2" "value3" )
// //
if (isStringAttribute()) { if (isStringAttribute()) {
std::string Result; std::string Result;
@ -246,8 +253,7 @@ std::string Attribute::getAsString() const {
StringRef Val = pImpl->getValueAsString(); StringRef Val = pImpl->getValueAsString();
if (Val.empty()) return Result; if (Val.empty()) return Result;
Result += " = "; Result += "=\"" + Val.str() + '"';
Result += '\"' + Val.str() + '"';
return Result; return Result;
} }
@ -451,11 +457,11 @@ unsigned AttributeSetNode::getStackAlignment() const {
return 0; return 0;
} }
std::string AttributeSetNode::getAsString() const { std::string AttributeSetNode::getAsString(bool InAttrGrp) const {
std::string Str = ""; std::string Str = "";
for (SmallVectorImpl<Attribute>::const_iterator I = AttrList.begin(), for (SmallVectorImpl<Attribute>::const_iterator I = AttrList.begin(),
E = AttrList.end(); I != E; ) { E = AttrList.end(); I != E; ) {
Str += I->getAsString(); Str += I->getAsString(InAttrGrp);
if (++I != E) Str += " "; if (++I != E) Str += " ";
} }
return Str; return Str;
@ -783,9 +789,10 @@ unsigned AttributeSet::getStackAlignment(unsigned Index) const {
return ASN ? ASN->getStackAlignment() : 0; 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); 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. /// \brief The attributes for the specified index are returned.