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
/// 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<Attribute>::iterator iterator;

View File

@ -347,6 +347,10 @@ private:
/// mdnMap - Map for MDNodes.
DenseMap<const MDNode*, unsigned> mdnMap;
unsigned mdnNext;
/// asMap - The slot map for attribute sets.
DenseMap<AttributeSet, unsigned> 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<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.
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<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
//===----------------------------------------------------------------------===//

View File

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

View File

@ -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<Attribute>::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.