summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--include/llvm/Attributes.h209
-rw-r--r--lib/VMCore/Attributes.cpp32
-rw-r--r--lib/VMCore/AttributesImpl.h40
-rw-r--r--lib/VMCore/LLVMContextImpl.cpp7
-rw-r--r--lib/VMCore/LLVMContextImpl.h6
5 files changed, 239 insertions, 55 deletions
diff --git a/include/llvm/Attributes.h b/include/llvm/Attributes.h
index 3a204b949e..d36e10d658 100644
--- a/include/llvm/Attributes.h
+++ b/include/llvm/Attributes.h
@@ -22,6 +22,7 @@
namespace llvm {
+class LLVMContext;
class Type;
namespace Attribute {
@@ -134,14 +135,125 @@ const AttrConst MutuallyIncompatible[5] = {
} // namespace Attribute
+/// AttributeImpl - The internal representation of the Attributes class. This is
+/// uniquified.
+class AttributesImpl;
+
/// Attributes - A bitset of attributes.
class Attributes {
// Currently, we need less than 64 bits.
uint64_t Bits;
+
+ explicit Attributes(AttributesImpl *A);
public:
- Attributes() : Bits(0) { }
- explicit Attributes(uint64_t Val) : Bits(Val) { }
- /*implicit*/ Attributes(Attribute::AttrConst Val) : Bits(Val.v) { }
+ Attributes() : Bits(0) {}
+ explicit Attributes(uint64_t Val) : Bits(Val) {}
+ /*implicit*/ Attributes(Attribute::AttrConst Val) : Bits(Val.v) {}
+
+ class Builder {
+ friend class Attributes;
+ uint64_t Bits;
+ public:
+ void addZExtAttr() {
+ Bits |= Attribute::ZExt_i;
+ }
+ void addSExtAttr() {
+ Bits |= Attribute::SExt_i;
+ }
+ void addNoReturnAttr() {
+ Bits |= Attribute::NoReturn_i;
+ }
+ void addInRegAttr() {
+ Bits |= Attribute::InReg_i;
+ }
+ void addStructRetAttr() {
+ Bits |= Attribute::StructRet_i;
+ }
+ void addNoUnwindAttr() {
+ Bits |= Attribute::NoUnwind_i;
+ }
+ void addNoAliasAttr() {
+ Bits |= Attribute::NoAlias_i;
+ }
+ void addByValAttr() {
+ Bits |= Attribute::ByVal_i;
+ }
+ void addNestAttr() {
+ Bits |= Attribute::Nest_i;
+ }
+ void addReadNoneAttr() {
+ Bits |= Attribute::ReadNone_i;
+ }
+ void addReadOnlyAttr() {
+ Bits |= Attribute::ReadOnly_i;
+ }
+ void addNoInlineAttr() {
+ Bits |= Attribute::NoInline_i;
+ }
+ void addAlwaysInlineAttr() {
+ Bits |= Attribute::AlwaysInline_i;
+ }
+ void addOptimizeForSizeAttr() {
+ Bits |= Attribute::OptimizeForSize_i;
+ }
+ void addStackProtectAttr() {
+ Bits |= Attribute::StackProtect_i;
+ }
+ void addStackProtectReqAttr() {
+ Bits |= Attribute::StackProtectReq_i;
+ }
+ void addAlignmentAttr() {
+ Bits |= Attribute::Alignment_i;
+ }
+ void addNoCaptureAttr() {
+ Bits |= Attribute::NoCapture_i;
+ }
+ void addNoRedZoneAttr() {
+ Bits |= Attribute::NoRedZone_i;
+ }
+ void addNoImplicitFloatAttr() {
+ Bits |= Attribute::NoImplicitFloat_i;
+ }
+ void addNakedAttr() {
+ Bits |= Attribute::Naked_i;
+ }
+ void addInlineHintAttr() {
+ Bits |= Attribute::InlineHint_i;
+ }
+ void addReturnsTwiceAttr() {
+ Bits |= Attribute::ReturnsTwice_i;
+ }
+ void addStackAlignmentAttr() {
+ Bits |= Attribute::StackAlignment_i;
+ }
+ void addUWTableAttr() {
+ Bits |= Attribute::UWTable_i;
+ }
+ void addNonLazyBindAttr() {
+ Bits |= Attribute::NonLazyBind_i;
+ }
+ void addAddressSafetyAttr() {
+ Bits |= Attribute::AddressSafety_i;
+ }
+ void addAlignmentAttr(unsigned Align) {
+ if (Align == 0) return;
+ assert(isPowerOf2_32(Align) && "Alignment must be a power of two.");
+ assert(Align <= 0x40000000 && "Alignment too large.");
+ Bits |= (Log2_32(Align) + 1) << 16;
+ }
+ void addStackAlignment(unsigned Align) {
+ // Default alignment, allow the target to define how to align it.
+ if (Align == 0) return;
+
+ assert(isPowerOf2_32(Align) && "Alignment must be a power of two.");
+ assert(Align <= 0x100 && "Alignment too large.");
+ Bits |= (Log2_32(Align) + 1) << 26;
+ }
+ };
+
+ /// get - Return a uniquified Attributes object. This takes the uniquified
+ /// value from the Builder and wraps it in the Attributes class.
+ static Attributes get(LLVMContext &Context, Builder &B);
// Attribute query methods.
// FIXME: StackAlignment & Alignment attributes have no predicate methods.
@@ -234,20 +346,12 @@ public:
return Bits & Attribute::AddressSafety_i;
}
- uint64_t getRawAlignment() const {
- return Bits & Attribute::Alignment_i;
- }
- uint64_t getRawStackAlignment() const {
- return Bits & Attribute::StackAlignment_i;
- }
-
/// This returns the alignment field of an attribute as a byte alignment
/// value.
unsigned getAlignment() const {
if (!hasAlignmentAttr())
return 0;
-
- return 1U << ((getRawAlignment() >> 16) - 1);
+ return 1U << (((Bits & Attribute::Alignment_i) >> 16) - 1);
}
/// This returns the stack alignment field of an attribute as a byte alignment
@@ -255,32 +359,7 @@ public:
unsigned getStackAlignment() const {
if (!hasStackAlignmentAttr())
return 0;
-
- return 1U << ((getRawStackAlignment() >> 26) - 1);
- }
-
- /// This turns an int alignment (a power of 2, normally) into the form used
- /// internally in Attributes.
- static Attributes constructAlignmentFromInt(unsigned i) {
- // Default alignment, allow the target to define how to align it.
- if (i == 0)
- return Attribute::None;
-
- assert(isPowerOf2_32(i) && "Alignment must be a power of two.");
- assert(i <= 0x40000000 && "Alignment too large.");
- return Attributes((Log2_32(i)+1) << 16);
- }
-
- /// This turns an int stack alignment (which must be a power of 2) into the
- /// form used internally in Attributes.
- static Attributes constructStackAlignmentFromInt(unsigned i) {
- // Default alignment, allow the target to define how to align it.
- if (i == 0)
- return Attribute::None;
-
- assert(isPowerOf2_32(i) && "Alignment must be a power of two.");
- assert(i <= 0x100 && "Alignment too large.");
- return Attributes((Log2_32(i)+1) << 26);
+ return 1U << (((Bits & Attribute::StackAlignment_i) >> 26) - 1);
}
// This is a "safe bool() operator".
@@ -312,11 +391,29 @@ public:
Attributes operator ~ () const { return Attributes(~Bits); }
uint64_t Raw() const { return Bits; }
- /// The set of Attributes set in Attributes is converted to a string of
- /// equivalent mnemonics. This is, presumably, for writing out the mnemonics
- /// for the assembly writer.
- /// @brief Convert attribute bits to text
- std::string getAsString() const;
+ /// This turns an int alignment (a power of 2, normally) into the form used
+ /// internally in Attributes.
+ static Attributes constructAlignmentFromInt(unsigned i) {
+ // Default alignment, allow the target to define how to align it.
+ if (i == 0)
+ return Attribute::None;
+
+ assert(isPowerOf2_32(i) && "Alignment must be a power of two.");
+ assert(i <= 0x40000000 && "Alignment too large.");
+ return Attributes((Log2_32(i)+1) << 16);
+ }
+
+ /// This turns an int stack alignment (which must be a power of 2) into the
+ /// form used internally in Attributes.
+ static Attributes constructStackAlignmentFromInt(unsigned i) {
+ // Default alignment, allow the target to define how to align it.
+ if (i == 0)
+ return Attribute::None;
+
+ assert(isPowerOf2_32(i) && "Alignment must be a power of two.");
+ assert(i <= 0x100 && "Alignment too large.");
+ return Attributes((Log2_32(i)+1) << 26);
+ }
/// @brief Which attributes cannot be applied to a type.
static Attributes typeIncompatible(Type *Ty);
@@ -337,10 +434,9 @@ public:
// bits.
uint64_t EncodedAttrs = Attrs.Raw() & 0xffff;
if (Attrs.hasAlignmentAttr())
- EncodedAttrs |= (1ull << 16) <<
- ((Attrs.getRawAlignment() - 1) >> 16);
- EncodedAttrs |= (Attrs.Raw() & (0xfffull << 21)) << 11;
-
+ EncodedAttrs |= (1ULL << 16) <<
+ (((Attrs.Bits & Attribute::Alignment_i) - 1) >> 16);
+ EncodedAttrs |= (Attrs.Raw() & (0xfffULL << 21)) << 11;
return EncodedAttrs;
}
@@ -350,26 +446,31 @@ public:
static Attributes decodeLLVMAttributesForBitcode(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;
+ unsigned Alignment = (EncodedAttrs & (0xffffULL << 16)) >> 16;
assert((!Alignment || isPowerOf2_32(Alignment)) &&
"Alignment must be a power of two.");
Attributes Attrs(EncodedAttrs & 0xffff);
if (Alignment)
Attrs |= Attributes::constructAlignmentFromInt(Alignment);
- Attrs |= Attributes((EncodedAttrs & (0xfffull << 32)) >> 11);
-
+ Attrs |= Attributes((EncodedAttrs & (0xfffULL << 32)) >> 11);
return Attrs;
}
+
+ /// The set of Attributes set in Attributes is converted to a string of
+ /// equivalent mnemonics. This is, presumably, for writing out the mnemonics
+ /// for the assembly writer.
+ /// @brief Convert attribute bits to text
+ std::string getAsString() const;
};
/// This is just a pair of values to associate a set of attributes
/// with an index.
struct AttributeWithIndex {
- Attributes Attrs; ///< The attributes that are set, or'd together.
- unsigned Index; ///< Index of the parameter for which the attributes apply.
- ///< Index 0 is used for return value attributes.
- ///< Index ~0U is used for function attributes.
+ Attributes Attrs; ///< The attributes that are set, or'd together.
+ unsigned Index; ///< Index of the parameter for which the attributes apply.
+ ///< Index 0 is used for return value attributes.
+ ///< Index ~0U is used for function attributes.
static AttributeWithIndex get(unsigned Idx, Attributes Attrs) {
AttributeWithIndex P;
diff --git a/lib/VMCore/Attributes.cpp b/lib/VMCore/Attributes.cpp
index 453190bbaf..7d3197cb0d 100644
--- a/lib/VMCore/Attributes.cpp
+++ b/lib/VMCore/Attributes.cpp
@@ -12,6 +12,8 @@
//===----------------------------------------------------------------------===//
#include "llvm/Attributes.h"
+#include "AttributesImpl.h"
+#include "LLVMContextImpl.h"
#include "llvm/Type.h"
#include "llvm/ADT/StringExtras.h"
#include "llvm/ADT/FoldingSet.h"
@@ -110,6 +112,36 @@ Attributes Attributes::typeIncompatible(Type *Ty) {
}
//===----------------------------------------------------------------------===//
+// AttributeImpl Definition
+//===----------------------------------------------------------------------===//
+
+Attributes::Attributes(AttributesImpl *A) : Bits(0) {}
+
+Attributes Attributes::get(LLVMContext &Context, Attributes::Builder &B) {
+ // If there are no attributes, return an empty Attributes class.
+ if (B.Bits == 0)
+ return Attributes();
+
+ // Otherwise, build a key to look up the existing attributes.
+ LLVMContextImpl *pImpl = Context.pImpl;
+ FoldingSetNodeID ID;
+ ID.AddInteger(B.Bits);
+
+ 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.Bits);
+ pImpl->AttrsSet.InsertNode(PA, InsertPoint);
+ }
+
+ // Return the AttributesList that we found or created.
+ return Attributes(PA);
+}
+
+//===----------------------------------------------------------------------===//
// AttributeListImpl Definition
//===----------------------------------------------------------------------===//
diff --git a/lib/VMCore/AttributesImpl.h b/lib/VMCore/AttributesImpl.h
new file mode 100644
index 0000000000..90890a14c3
--- /dev/null
+++ b/lib/VMCore/AttributesImpl.h
@@ -0,0 +1,40 @@
+//===-- AttributesImpl.h - Attributes Internals -----------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file defines various helper methods and classes used by LLVMContextImpl
+// for creating and managing attributes.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_ATTRIBUTESIMPL_H
+#define LLVM_ATTRIBUTESIMPL_H
+
+#include "llvm/ADT/FoldingSet.h"
+
+namespace llvm {
+
+class AttributesImpl : public FoldingSetNode {
+ uint64_t Bits; // FIXME: We will be expanding this.
+
+ void operator=(const AttributesImpl &) LLVM_DELETED_FUNCTION;
+ AttributesImpl(const AttributesImpl &) LLVM_DELETED_FUNCTION;
+public:
+ AttributesImpl(uint64_t bits) : Bits(bits) {}
+
+ void Profile(FoldingSetNodeID &ID) const {
+ Profile(ID, Bits);
+ }
+ static void Profile(FoldingSetNodeID &ID, uint64_t Bits) {
+ ID.AddInteger(Bits);
+ }
+};
+
+} // end llvm namespace
+
+#endif
diff --git a/lib/VMCore/LLVMContextImpl.cpp b/lib/VMCore/LLVMContextImpl.cpp
index 6279bb823d..a86363b632 100644
--- a/lib/VMCore/LLVMContextImpl.cpp
+++ b/lib/VMCore/LLVMContextImpl.cpp
@@ -12,6 +12,7 @@
//===----------------------------------------------------------------------===//
#include "LLVMContextImpl.h"
+#include "llvm/Attributes.h"
#include "llvm/Module.h"
#include "llvm/ADT/STLExtras.h"
#include <algorithm>
@@ -93,6 +94,11 @@ LLVMContextImpl::~LLVMContextImpl() {
E = CDSConstants.end(); I != E; ++I)
delete I->second;
CDSConstants.clear();
+
+ // Destroy attributes.
+ for (FoldingSetIterator<AttributesImpl> I = AttrsSet.begin(),
+ E = AttrsSet.end(); I != E; ++I)
+ delete &*I;
// Destroy MDNodes. ~MDNode can move and remove nodes between the MDNodeSet
// and the NonUniquedMDNodes sets, so copy the values out first.
@@ -107,6 +113,7 @@ LLVMContextImpl::~LLVMContextImpl() {
(*I)->destroy();
assert(MDNodeSet.empty() && NonUniquedMDNodes.empty() &&
"Destroying all MDNodes didn't empty the Context's sets.");
+
// Destroy MDStrings.
DeleteContainerSeconds(MDStringCache);
}
diff --git a/lib/VMCore/LLVMContextImpl.h b/lib/VMCore/LLVMContextImpl.h
index 2252028b15..ee31814c05 100644
--- a/lib/VMCore/LLVMContextImpl.h
+++ b/lib/VMCore/LLVMContextImpl.h
@@ -16,6 +16,7 @@
#define LLVM_LLVMCONTEXT_IMPL_H
#include "llvm/LLVMContext.h"
+#include "AttributesImpl.h"
#include "ConstantsContext.h"
#include "LeaksContext.h"
#include "llvm/Constants.h"
@@ -253,10 +254,13 @@ public:
typedef DenseMap<DenseMapAPFloatKeyInfo::KeyTy, ConstantFP*,
DenseMapAPFloatKeyInfo> FPMapTy;
FPMapTy FPConstants;
+
+ FoldingSet<AttributesImpl> AttrsSet;
StringMap<Value*> MDStringCache;
-
+
FoldingSet<MDNode> MDNodeSet;
+
// MDNodes may be uniqued or not uniqued. When they're not uniqued, they
// aren't in the MDNodeSet, but they're still shared between objects, so no
// one object can destroy them. This set allows us to at least destroy them