llvm-6502/lib/VMCore/Attributes.cpp
Chandler Carruth d04a8d4b33 Use the new script to sort the includes of every file under lib.
Sooooo many of these had incorrect or strange main module includes.
I have manually inspected all of these, and fixed the main module
include to be the nearest plausible thing I could find. If you own or
care about any of these source files, I encourage you to take some time
and check that these edits were sensible. I can't have broken anything
(I strictly added headers, and reordered them, never removed), but they
may not be the headers you'd really like to identify as containing the
API being implemented.

Many forward declarations and missing includes were added to a header
files to allow them to parse cleanly when included first. The main
module rule does in fact have its merits. =]

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@169131 91177308-0d34-0410-b5e6-96231b3b80d8
2012-12-03 16:50:05 +00:00

548 lines
19 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 Attributes, AttributeImpl, AttrBuilder,
// AttributeListImpl, and AttrListPtr classes.
//
//===----------------------------------------------------------------------===//
#include "llvm/Attributes.h"
#include "AttributesImpl.h"
#include "LLVMContextImpl.h"
#include "llvm/ADT/FoldingSet.h"
#include "llvm/ADT/StringExtras.h"
#include "llvm/Support/Atomic.h"
#include "llvm/Support/Debug.h"
#include "llvm/Support/ManagedStatic.h"
#include "llvm/Support/Mutex.h"
#include "llvm/Support/raw_ostream.h"
#include "llvm/Type.h"
using namespace llvm;
//===----------------------------------------------------------------------===//
// Attributes Implementation
//===----------------------------------------------------------------------===//
Attributes Attributes::get(LLVMContext &Context, ArrayRef<AttrVal> Vals) {
AttrBuilder B;
for (ArrayRef<AttrVal>::iterator I = Vals.begin(), E = Vals.end();
I != E; ++I)
B.addAttribute(*I);
return Attributes::get(Context, B);
}
Attributes Attributes::get(LLVMContext &Context, AttrBuilder &B) {
// If there are no attributes, return an empty Attributes class.
if (!B.hasAttributes())
return Attributes();
// Otherwise, build a key to look up the existing attributes.
LLVMContextImpl *pImpl = Context.pImpl;
FoldingSetNodeID ID;
ID.AddInteger(B.Raw());
void *InsertPoint;
AttributesImpl *PA = pImpl->AttrsSet.FindNodeOrInsertPos(ID, InsertPoint);
if (!PA) {
// If we didn't find any existing attributes of the same shape then create a
// new one and insert it.
PA = new AttributesImpl(B.Raw());
pImpl->AttrsSet.InsertNode(PA, InsertPoint);
}
// Return the AttributesList that we found or created.
return Attributes(PA);
}
bool Attributes::hasAttribute(AttrVal Val) const {
return Attrs && Attrs->hasAttribute(Val);
}
bool Attributes::hasAttributes() const {
return Attrs && Attrs->hasAttributes();
}
bool Attributes::hasAttributes(const Attributes &A) const {
return Attrs && Attrs->hasAttributes(A);
}
/// This returns the alignment field of an attribute as a byte alignment value.
unsigned Attributes::getAlignment() const {
if (!hasAttribute(Attributes::Alignment))
return 0;
return 1U << ((Attrs->getAlignment() >> 16) - 1);
}
/// This returns the stack alignment field of an attribute as a byte alignment
/// value.
unsigned Attributes::getStackAlignment() const {
if (!hasAttribute(Attributes::StackAlignment))
return 0;
return 1U << ((Attrs->getStackAlignment() >> 26) - 1);
}
uint64_t Attributes::Raw() const {
return Attrs ? Attrs->Raw() : 0;
}
Attributes Attributes::typeIncompatible(Type *Ty) {
AttrBuilder Incompatible;
if (!Ty->isIntegerTy())
// Attributes that only apply to integers.
Incompatible.addAttribute(Attributes::SExt)
.addAttribute(Attributes::ZExt);
if (!Ty->isPointerTy())
// Attributes that only apply to pointers.
Incompatible.addAttribute(Attributes::ByVal)
.addAttribute(Attributes::Nest)
.addAttribute(Attributes::NoAlias)
.addAttribute(Attributes::NoCapture)
.addAttribute(Attributes::StructRet);
return Attributes::get(Ty->getContext(), Incompatible);
}
/// encodeLLVMAttributesForBitcode - This returns an integer containing an
/// encoding of all the LLVM attributes found in the given attribute bitset.
/// Any change to this encoding is a breaking change to bitcode compatibility.
uint64_t Attributes::encodeLLVMAttributesForBitcode(Attributes Attrs) {
// FIXME: It doesn't make sense to store the alignment information as an
// expanded out value, we should store it as a log2 value. However, we can't
// just change that here without breaking bitcode compatibility. If this ever
// becomes a problem in practice, we should introduce new tag numbers in the
// bitcode file and have those tags use a more efficiently encoded alignment
// field.
// Store the alignment in the bitcode as a 16-bit raw value instead of a 5-bit
// log2 encoded value. Shift the bits above the alignment up by 11 bits.
uint64_t EncodedAttrs = Attrs.Raw() & 0xffff;
if (Attrs.hasAttribute(Attributes::Alignment))
EncodedAttrs |= Attrs.getAlignment() << 16;
EncodedAttrs |= (Attrs.Raw() & (0xffffULL << 21)) << 11;
return EncodedAttrs;
}
/// decodeLLVMAttributesForBitcode - This returns an attribute bitset containing
/// the LLVM attributes that have been decoded from the given integer. This
/// function must stay in sync with 'encodeLLVMAttributesForBitcode'.
Attributes Attributes::decodeLLVMAttributesForBitcode(LLVMContext &C,
uint64_t EncodedAttrs) {
// The alignment is stored as a 16-bit raw value from bits 31--16. We shift
// the bits above 31 down by 11 bits.
unsigned Alignment = (EncodedAttrs & (0xffffULL << 16)) >> 16;
assert((!Alignment || isPowerOf2_32(Alignment)) &&
"Alignment must be a power of two.");
AttrBuilder B(EncodedAttrs & 0xffff);
if (Alignment)
B.addAlignmentAttr(Alignment);
B.addRawValue((EncodedAttrs & (0xffffULL << 32)) >> 11);
return Attributes::get(C, B);
}
std::string Attributes::getAsString() const {
std::string Result;
if (hasAttribute(Attributes::ZExt))
Result += "zeroext ";
if (hasAttribute(Attributes::SExt))
Result += "signext ";
if (hasAttribute(Attributes::NoReturn))
Result += "noreturn ";
if (hasAttribute(Attributes::NoUnwind))
Result += "nounwind ";
if (hasAttribute(Attributes::UWTable))
Result += "uwtable ";
if (hasAttribute(Attributes::ReturnsTwice))
Result += "returns_twice ";
if (hasAttribute(Attributes::InReg))
Result += "inreg ";
if (hasAttribute(Attributes::NoAlias))
Result += "noalias ";
if (hasAttribute(Attributes::NoCapture))
Result += "nocapture ";
if (hasAttribute(Attributes::StructRet))
Result += "sret ";
if (hasAttribute(Attributes::ByVal))
Result += "byval ";
if (hasAttribute(Attributes::Nest))
Result += "nest ";
if (hasAttribute(Attributes::ReadNone))
Result += "readnone ";
if (hasAttribute(Attributes::ReadOnly))
Result += "readonly ";
if (hasAttribute(Attributes::OptimizeForSize))
Result += "optsize ";
if (hasAttribute(Attributes::NoInline))
Result += "noinline ";
if (hasAttribute(Attributes::InlineHint))
Result += "inlinehint ";
if (hasAttribute(Attributes::AlwaysInline))
Result += "alwaysinline ";
if (hasAttribute(Attributes::StackProtect))
Result += "ssp ";
if (hasAttribute(Attributes::StackProtectReq))
Result += "sspreq ";
if (hasAttribute(Attributes::NoRedZone))
Result += "noredzone ";
if (hasAttribute(Attributes::NoImplicitFloat))
Result += "noimplicitfloat ";
if (hasAttribute(Attributes::Naked))
Result += "naked ";
if (hasAttribute(Attributes::NonLazyBind))
Result += "nonlazybind ";
if (hasAttribute(Attributes::AddressSafety))
Result += "address_safety ";
if (hasAttribute(Attributes::MinSize))
Result += "minsize ";
if (hasAttribute(Attributes::StackAlignment)) {
Result += "alignstack(";
Result += utostr(getStackAlignment());
Result += ") ";
}
if (hasAttribute(Attributes::Alignment)) {
Result += "align ";
Result += utostr(getAlignment());
Result += " ";
}
// Trim the trailing space.
assert(!Result.empty() && "Unknown attribute!");
Result.erase(Result.end()-1);
return Result;
}
//===----------------------------------------------------------------------===//
// AttrBuilder Implementation
//===----------------------------------------------------------------------===//
AttrBuilder &AttrBuilder::addAttribute(Attributes::AttrVal Val){
Bits |= AttributesImpl::getAttrMask(Val);
return *this;
}
AttrBuilder &AttrBuilder::addRawValue(uint64_t Val) {
Bits |= Val;
return *this;
}
AttrBuilder &AttrBuilder::addAlignmentAttr(unsigned Align) {
if (Align == 0) return *this;
assert(isPowerOf2_32(Align) && "Alignment must be a power of two.");
assert(Align <= 0x40000000 && "Alignment too large.");
Bits |= (Log2_32(Align) + 1) << 16;
return *this;
}
AttrBuilder &AttrBuilder::addStackAlignmentAttr(unsigned Align){
// Default alignment, allow the target to define how to align it.
if (Align == 0) return *this;
assert(isPowerOf2_32(Align) && "Alignment must be a power of two.");
assert(Align <= 0x100 && "Alignment too large.");
Bits |= (Log2_32(Align) + 1) << 26;
return *this;
}
AttrBuilder &AttrBuilder::removeAttribute(Attributes::AttrVal Val) {
Bits &= ~AttributesImpl::getAttrMask(Val);
return *this;
}
AttrBuilder &AttrBuilder::addAttributes(const Attributes &A) {
Bits |= A.Raw();
return *this;
}
AttrBuilder &AttrBuilder::removeAttributes(const Attributes &A){
Bits &= ~A.Raw();
return *this;
}
bool AttrBuilder::hasAttribute(Attributes::AttrVal A) const {
return Bits & AttributesImpl::getAttrMask(A);
}
bool AttrBuilder::hasAttributes() const {
return Bits != 0;
}
bool AttrBuilder::hasAttributes(const Attributes &A) const {
return Bits & A.Raw();
}
bool AttrBuilder::hasAlignmentAttr() const {
return Bits & AttributesImpl::getAttrMask(Attributes::Alignment);
}
uint64_t AttrBuilder::getAlignment() const {
if (!hasAlignmentAttr())
return 0;
return 1ULL <<
(((Bits & AttributesImpl::getAttrMask(Attributes::Alignment)) >> 16) - 1);
}
uint64_t AttrBuilder::getStackAlignment() const {
if (!hasAlignmentAttr())
return 0;
return 1ULL <<
(((Bits & AttributesImpl::getAttrMask(Attributes::StackAlignment))>>26)-1);
}
//===----------------------------------------------------------------------===//
// AttributeImpl Definition
//===----------------------------------------------------------------------===//
uint64_t AttributesImpl::getAttrMask(uint64_t Val) {
switch (Val) {
case Attributes::None: return 0;
case Attributes::ZExt: return 1 << 0;
case Attributes::SExt: return 1 << 1;
case Attributes::NoReturn: return 1 << 2;
case Attributes::InReg: return 1 << 3;
case Attributes::StructRet: return 1 << 4;
case Attributes::NoUnwind: return 1 << 5;
case Attributes::NoAlias: return 1 << 6;
case Attributes::ByVal: return 1 << 7;
case Attributes::Nest: return 1 << 8;
case Attributes::ReadNone: return 1 << 9;
case Attributes::ReadOnly: return 1 << 10;
case Attributes::NoInline: return 1 << 11;
case Attributes::AlwaysInline: return 1 << 12;
case Attributes::OptimizeForSize: return 1 << 13;
case Attributes::StackProtect: return 1 << 14;
case Attributes::StackProtectReq: return 1 << 15;
case Attributes::Alignment: return 31 << 16;
case Attributes::NoCapture: return 1 << 21;
case Attributes::NoRedZone: return 1 << 22;
case Attributes::NoImplicitFloat: return 1 << 23;
case Attributes::Naked: return 1 << 24;
case Attributes::InlineHint: return 1 << 25;
case Attributes::StackAlignment: return 7 << 26;
case Attributes::ReturnsTwice: return 1 << 29;
case Attributes::UWTable: return 1 << 30;
case Attributes::NonLazyBind: return 1U << 31;
case Attributes::AddressSafety: return 1ULL << 32;
case Attributes::MinSize: return 1ULL << 33;
}
llvm_unreachable("Unsupported attribute type");
}
bool AttributesImpl::hasAttribute(uint64_t A) const {
return (Bits & getAttrMask(A)) != 0;
}
bool AttributesImpl::hasAttributes() const {
return Bits != 0;
}
bool AttributesImpl::hasAttributes(const Attributes &A) const {
return Bits & A.Raw(); // FIXME: Raw() won't work here in the future.
}
uint64_t AttributesImpl::getAlignment() const {
return Bits & getAttrMask(Attributes::Alignment);
}
uint64_t AttributesImpl::getStackAlignment() const {
return Bits & getAttrMask(Attributes::StackAlignment);
}
//===----------------------------------------------------------------------===//
// AttributeListImpl Definition
//===----------------------------------------------------------------------===//
AttrListPtr AttrListPtr::get(LLVMContext &C,
ArrayRef<AttributeWithIndex> Attrs) {
// If there are no attributes then return a null AttributesList pointer.
if (Attrs.empty())
return AttrListPtr();
#ifndef NDEBUG
for (unsigned i = 0, e = Attrs.size(); i != e; ++i) {
assert(Attrs[i].Attrs.hasAttributes() &&
"Pointless attribute!");
assert((!i || Attrs[i-1].Index < Attrs[i].Index) &&
"Misordered AttributesList!");
}
#endif
// Otherwise, build a key to look up the existing attributes.
LLVMContextImpl *pImpl = C.pImpl;
FoldingSetNodeID ID;
AttributeListImpl::Profile(ID, Attrs);
void *InsertPoint;
AttributeListImpl *PA = pImpl->AttrsLists.FindNodeOrInsertPos(ID,
InsertPoint);
// If we didn't find any existing attributes of the same shape then
// create a new one and insert it.
if (!PA) {
PA = new AttributeListImpl(Attrs);
pImpl->AttrsLists.InsertNode(PA, InsertPoint);
}
// Return the AttributesList that we found or created.
return AttrListPtr(PA);
}
//===----------------------------------------------------------------------===//
// AttrListPtr Method Implementations
//===----------------------------------------------------------------------===//
const AttrListPtr &AttrListPtr::operator=(const AttrListPtr &RHS) {
if (AttrList == RHS.AttrList) return *this;
AttrList = RHS.AttrList;
return *this;
}
/// 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 Attributes();
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 Attributes();
}
/// hasAttrSomewhere - Return true if the specified attribute is set for at
/// least one parameter or for the return value.
bool AttrListPtr::hasAttrSomewhere(Attributes::AttrVal 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.hasAttribute(Attr))
return true;
return false;
}
unsigned AttrListPtr::getNumAttrs() const {
return AttrList ? AttrList->Attrs.size() : 0;
}
Attributes &AttrListPtr::getAttributesAtIndex(unsigned i) const {
assert(AttrList && "Trying to get an attribute from an empty list!");
assert(i < AttrList->Attrs.size() && "Index out of range!");
return AttrList->Attrs[i].Attrs;
}
AttrListPtr AttrListPtr::addAttr(LLVMContext &C, 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.
unsigned OldAlign = OldAttrs.getAlignment();
unsigned NewAlign = Attrs.getAlignment();
assert((!OldAlign || !NewAlign || OldAlign == NewAlign) &&
"Attempt to change alignment!");
#endif
AttrBuilder NewAttrs =
AttrBuilder(OldAttrs).addAttributes(Attrs);
if (NewAttrs == AttrBuilder(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 =
Attributes::get(C, AttrBuilder(Attrs).
addAttributes(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(C, NewAttrList);
}
AttrListPtr AttrListPtr::removeAttr(LLVMContext &C, 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.hasAttribute(Attributes::Alignment) &&
"Attempt to exclude alignment!");
#endif
if (AttrList == 0) return AttrListPtr();
Attributes OldAttrs = getAttributes(Idx);
AttrBuilder NewAttrs =
AttrBuilder(OldAttrs).removeAttributes(Attrs);
if (NewAttrs == AttrBuilder(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 = Attributes::get(C, AttrBuilder(OldAttrList[i].Attrs).
removeAttributes(Attrs));
++i;
if (Attrs.hasAttributes()) // If any attributes left for this param, 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(C, NewAttrList);
}
void AttrListPtr::dump() const {
dbgs() << "PAL[ ";
for (unsigned i = 0; i < getNumSlots(); ++i) {
const AttributeWithIndex &PAWI = getSlot(i);
dbgs() << "{" << PAWI.Index << "," << PAWI.Attrs.getAsString() << "} ";
}
dbgs() << "]\n";
}