llvm-6502/lib/VMCore/Attributes.cpp
Charles Davis 1e063d14df Add a new function attribute, 'alignstack'. It will indicate (when the backends
implement support for it) that the stack should be forcibly realigned in the
prologue (and the process reversed in the epilogue).


git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@95945 91177308-0d34-0410-b5e6-96231b3b80d8
2010-02-12 00:31:15 +00:00

335 lines
11 KiB
C++

//===-- Attributes.cpp - Implement AttributesList -------------------------===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file implements the AttributesList class and Attribute utilities.
//
//===----------------------------------------------------------------------===//
#include "llvm/Attributes.h"
#include "llvm/Type.h"
#include "llvm/ADT/StringExtras.h"
#include "llvm/ADT/FoldingSet.h"
#include "llvm/System/Atomic.h"
#include "llvm/System/Mutex.h"
#include "llvm/Support/Debug.h"
#include "llvm/Support/ManagedStatic.h"
#include "llvm/Support/raw_ostream.h"
using namespace llvm;
//===----------------------------------------------------------------------===//
// Attribute Function Definitions
//===----------------------------------------------------------------------===//
std::string Attribute::getAsString(Attributes Attrs) {
std::string Result;
if (Attrs & Attribute::ZExt)
Result += "zeroext ";
if (Attrs & Attribute::SExt)
Result += "signext ";
if (Attrs & Attribute::NoReturn)
Result += "noreturn ";
if (Attrs & Attribute::NoUnwind)
Result += "nounwind ";
if (Attrs & Attribute::InReg)
Result += "inreg ";
if (Attrs & Attribute::NoAlias)
Result += "noalias ";
if (Attrs & Attribute::NoCapture)
Result += "nocapture ";
if (Attrs & Attribute::StructRet)
Result += "sret ";
if (Attrs & Attribute::ByVal)
Result += "byval ";
if (Attrs & Attribute::Nest)
Result += "nest ";
if (Attrs & Attribute::ReadNone)
Result += "readnone ";
if (Attrs & Attribute::ReadOnly)
Result += "readonly ";
if (Attrs & Attribute::OptimizeForSize)
Result += "optsize ";
if (Attrs & Attribute::NoInline)
Result += "noinline ";
if (Attrs & Attribute::InlineHint)
Result += "inlinehint ";
if (Attrs & Attribute::AlwaysInline)
Result += "alwaysinline ";
if (Attrs & Attribute::StackProtect)
Result += "ssp ";
if (Attrs & Attribute::StackProtectReq)
Result += "sspreq ";
if (Attrs & Attribute::NoRedZone)
Result += "noredzone ";
if (Attrs & Attribute::NoImplicitFloat)
Result += "noimplicitfloat ";
if (Attrs & Attribute::Naked)
Result += "naked ";
if (Attrs & Attribute::StackAlignment) {
Result += "alignstack(";
Result += utostr(Attribute::getStackAlignmentFromAttrs(Attrs));
Result += ") ";
}
if (Attrs & Attribute::Alignment) {
Result += "align ";
Result += utostr(Attribute::getAlignmentFromAttrs(Attrs));
Result += " ";
}
// Trim the trailing space.
assert(!Result.empty() && "Unknown attribute!");
Result.erase(Result.end()-1);
return Result;
}
Attributes Attribute::typeIncompatible(const Type *Ty) {
Attributes Incompatible = None;
if (!Ty->isInteger())
// Attributes that only apply to integers.
Incompatible |= SExt | ZExt;
if (!isa<PointerType>(Ty))
// Attributes that only apply to pointers.
Incompatible |= ByVal | Nest | NoAlias | StructRet | NoCapture;
return Incompatible;
}
//===----------------------------------------------------------------------===//
// AttributeListImpl Definition
//===----------------------------------------------------------------------===//
namespace llvm {
class AttributeListImpl : public FoldingSetNode {
sys::cas_flag RefCount;
// AttributesList is uniqued, these should not be publicly available.
void operator=(const AttributeListImpl &); // Do not implement
AttributeListImpl(const AttributeListImpl &); // Do not implement
~AttributeListImpl(); // Private implementation
public:
SmallVector<AttributeWithIndex, 4> Attrs;
AttributeListImpl(const AttributeWithIndex *Attr, unsigned NumAttrs)
: Attrs(Attr, Attr+NumAttrs) {
RefCount = 0;
}
void AddRef() { sys::AtomicIncrement(&RefCount); }
void DropRef() {
sys::cas_flag old = sys::AtomicDecrement(&RefCount);
if (old == 0) delete this;
}
void Profile(FoldingSetNodeID &ID) const {
Profile(ID, Attrs.data(), Attrs.size());
}
static void Profile(FoldingSetNodeID &ID, const AttributeWithIndex *Attr,
unsigned NumAttrs) {
for (unsigned i = 0; i != NumAttrs; ++i)
ID.AddInteger(uint64_t(Attr[i].Attrs) << 32 | unsigned(Attr[i].Index));
}
};
}
static ManagedStatic<sys::SmartMutex<true> > ALMutex;
static ManagedStatic<FoldingSet<AttributeListImpl> > AttributesLists;
AttributeListImpl::~AttributeListImpl() {
sys::SmartScopedLock<true> Lock(*ALMutex);
AttributesLists->RemoveNode(this);
}
AttrListPtr AttrListPtr::get(const AttributeWithIndex *Attrs, unsigned NumAttrs) {
// If there are no attributes then return a null AttributesList pointer.
if (NumAttrs == 0)
return AttrListPtr();
#ifndef NDEBUG
for (unsigned i = 0; i != NumAttrs; ++i) {
assert(Attrs[i].Attrs != Attribute::None &&
"Pointless attribute!");
assert((!i || Attrs[i-1].Index < Attrs[i].Index) &&
"Misordered AttributesList!");
}
#endif
// Otherwise, build a key to look up the existing attributes.
FoldingSetNodeID ID;
AttributeListImpl::Profile(ID, Attrs, NumAttrs);
void *InsertPos;
sys::SmartScopedLock<true> Lock(*ALMutex);
AttributeListImpl *PAL =
AttributesLists->FindNodeOrInsertPos(ID, InsertPos);
// If we didn't find any existing attributes of the same shape then
// create a new one and insert it.
if (!PAL) {
PAL = new AttributeListImpl(Attrs, NumAttrs);
AttributesLists->InsertNode(PAL, InsertPos);
}
// Return the AttributesList that we found or created.
return AttrListPtr(PAL);
}
//===----------------------------------------------------------------------===//
// AttrListPtr Method Implementations
//===----------------------------------------------------------------------===//
AttrListPtr::AttrListPtr(AttributeListImpl *LI) : AttrList(LI) {
if (LI) LI->AddRef();
}
AttrListPtr::AttrListPtr(const AttrListPtr &P) : AttrList(P.AttrList) {
if (AttrList) AttrList->AddRef();
}
const AttrListPtr &AttrListPtr::operator=(const AttrListPtr &RHS) {
if (AttrList == RHS.AttrList) return *this;
if (AttrList) AttrList->DropRef();
AttrList = RHS.AttrList;
if (AttrList) AttrList->AddRef();
return *this;
}
AttrListPtr::~AttrListPtr() {
if (AttrList) AttrList->DropRef();
}
/// getNumSlots - Return the number of slots used in this attribute list.
/// This is the number of arguments that have an attribute set on them
/// (including the function itself).
unsigned AttrListPtr::getNumSlots() const {
return AttrList ? AttrList->Attrs.size() : 0;
}
/// getSlot - Return the AttributeWithIndex at the specified slot. This
/// holds a number plus a set of attributes.
const AttributeWithIndex &AttrListPtr::getSlot(unsigned Slot) const {
assert(AttrList && Slot < AttrList->Attrs.size() && "Slot # out of range!");
return AttrList->Attrs[Slot];
}
/// getAttributes - The attributes for the specified index are
/// returned. Attributes for the result are denoted with Idx = 0.
/// Function notes are denoted with idx = ~0.
Attributes AttrListPtr::getAttributes(unsigned Idx) const {
if (AttrList == 0) return Attribute::None;
const SmallVector<AttributeWithIndex, 4> &Attrs = AttrList->Attrs;
for (unsigned i = 0, e = Attrs.size(); i != e && Attrs[i].Index <= Idx; ++i)
if (Attrs[i].Index == Idx)
return Attrs[i].Attrs;
return Attribute::None;
}
/// hasAttrSomewhere - Return true if the specified attribute is set for at
/// least one parameter or for the return value.
bool AttrListPtr::hasAttrSomewhere(Attributes Attr) const {
if (AttrList == 0) return false;
const SmallVector<AttributeWithIndex, 4> &Attrs = AttrList->Attrs;
for (unsigned i = 0, e = Attrs.size(); i != e; ++i)
if (Attrs[i].Attrs & Attr)
return true;
return false;
}
AttrListPtr AttrListPtr::addAttr(unsigned Idx, Attributes Attrs) const {
Attributes OldAttrs = getAttributes(Idx);
#ifndef NDEBUG
// FIXME it is not obvious how this should work for alignment.
// For now, say we can't change a known alignment.
Attributes OldAlign = OldAttrs & Attribute::Alignment;
Attributes NewAlign = Attrs & Attribute::Alignment;
assert((!OldAlign || !NewAlign || OldAlign == NewAlign) &&
"Attempt to change alignment!");
#endif
Attributes NewAttrs = OldAttrs | Attrs;
if (NewAttrs == OldAttrs)
return *this;
SmallVector<AttributeWithIndex, 8> NewAttrList;
if (AttrList == 0)
NewAttrList.push_back(AttributeWithIndex::get(Idx, Attrs));
else {
const SmallVector<AttributeWithIndex, 4> &OldAttrList = AttrList->Attrs;
unsigned i = 0, e = OldAttrList.size();
// Copy attributes for arguments before this one.
for (; i != e && OldAttrList[i].Index < Idx; ++i)
NewAttrList.push_back(OldAttrList[i]);
// If there are attributes already at this index, merge them in.
if (i != e && OldAttrList[i].Index == Idx) {
Attrs |= OldAttrList[i].Attrs;
++i;
}
NewAttrList.push_back(AttributeWithIndex::get(Idx, Attrs));
// Copy attributes for arguments after this one.
NewAttrList.insert(NewAttrList.end(),
OldAttrList.begin()+i, OldAttrList.end());
}
return get(NewAttrList.data(), NewAttrList.size());
}
AttrListPtr AttrListPtr::removeAttr(unsigned Idx, Attributes Attrs) const {
#ifndef NDEBUG
// FIXME it is not obvious how this should work for alignment.
// For now, say we can't pass in alignment, which no current use does.
assert(!(Attrs & Attribute::Alignment) && "Attempt to exclude alignment!");
#endif
if (AttrList == 0) return AttrListPtr();
Attributes OldAttrs = getAttributes(Idx);
Attributes NewAttrs = OldAttrs & ~Attrs;
if (NewAttrs == OldAttrs)
return *this;
SmallVector<AttributeWithIndex, 8> NewAttrList;
const SmallVector<AttributeWithIndex, 4> &OldAttrList = AttrList->Attrs;
unsigned i = 0, e = OldAttrList.size();
// Copy attributes for arguments before this one.
for (; i != e && OldAttrList[i].Index < Idx; ++i)
NewAttrList.push_back(OldAttrList[i]);
// If there are attributes already at this index, merge them in.
assert(OldAttrList[i].Index == Idx && "Attribute isn't set?");
Attrs = OldAttrList[i].Attrs & ~Attrs;
++i;
if (Attrs) // If any attributes left for this parameter, add them.
NewAttrList.push_back(AttributeWithIndex::get(Idx, Attrs));
// Copy attributes for arguments after this one.
NewAttrList.insert(NewAttrList.end(),
OldAttrList.begin()+i, OldAttrList.end());
return get(NewAttrList.data(), NewAttrList.size());
}
void AttrListPtr::dump() const {
dbgs() << "PAL[ ";
for (unsigned i = 0; i < getNumSlots(); ++i) {
const AttributeWithIndex &PAWI = getSlot(i);
dbgs() << "{" << PAWI.Index << "," << PAWI.Attrs << "} ";
}
dbgs() << "]\n";
}