Add support for emitting a string attribute.
[oota-llvm.git] / lib / IR / Attributes.cpp
index 59e86f02a0e42422bdadf468255881785c2f85e9..5608cbd47fa1c51bdc073a8596b5b3edaced0e59 100644 (file)
@@ -30,15 +30,24 @@ using namespace llvm;
 // Attribute Construction Methods
 //===----------------------------------------------------------------------===//
 
-Attribute Attribute::get(LLVMContext &Context, AttrKind Kind,
-                         Constant *Val) {
-  if (Kind == None) return Attribute();
+Attribute Attribute::get(LLVMContext &Context, AttrKind Kind) {
+  AttrBuilder B;
+  return Attribute::get(Context, B.addAttribute(Kind));
+}
+
+Attribute Attribute::get(LLVMContext &Context, AttrBuilder &B) {
+  // If there are no attributes, return an empty Attribute class.
+  if (!B.hasAttributes())
+    return Attribute();
+
+  assert(std::distance(B.begin(), B.end()) == 1 &&
+         "The Attribute object should represent one attribute only!");
 
   // Otherwise, build a key to look up the existing attributes.
   LLVMContextImpl *pImpl = Context.pImpl;
   FoldingSetNodeID ID;
-  ID.AddInteger(Kind);
-  ID.AddPointer(Val);
+  ConstantInt *CI = ConstantInt::get(Type::getInt64Ty(Context), B.Raw());
+  ID.AddPointer(CI);
 
   void *InsertPoint;
   AttributeImpl *PA = pImpl->AttrsSet.FindNodeOrInsertPos(ID, InsertPoint);
@@ -46,9 +55,7 @@ Attribute Attribute::get(LLVMContext &Context, AttrKind Kind,
   if (!PA) {
     // If we didn't find any existing attributes of the same shape then create a
     // new one and insert it.
-    PA = (!Val) ?
-      new AttributeImpl(Context, Kind) :
-      new AttributeImpl(Context, Kind, Val);
+    PA = new AttributeImpl(Context, CI);
     pImpl->AttrsSet.InsertNode(PA, InsertPoint);
   }
 
@@ -57,14 +64,14 @@ Attribute Attribute::get(LLVMContext &Context, AttrKind Kind,
 }
 
 Attribute Attribute::getWithAlignment(LLVMContext &Context, uint64_t Align) {
-  return get(Context, Attribute::Alignment,
-             ConstantInt::get(Type::getInt64Ty(Context), Align));
+  AttrBuilder B;
+  return get(Context, B.addAlignmentAttr(Align));
 }
 
 Attribute Attribute::getWithStackAlignment(LLVMContext &Context,
                                            uint64_t Align) {
-  return get(Context, Attribute::StackAlignment,
-             ConstantInt::get(Type::getInt64Ty(Context), Align));
+  AttrBuilder B;
+  return get(Context, B.addStackAlignmentAttr(Align));
 }
 
 //===----------------------------------------------------------------------===//
@@ -75,10 +82,6 @@ bool Attribute::hasAttribute(AttrKind Val) const {
   return pImpl && pImpl->hasAttribute(Val);
 }
 
-bool Attribute::hasAttributes() const {
-  return pImpl && pImpl->hasAttributes();
-}
-
 Constant *Attribute::getAttributeKind() const {
   return pImpl ? pImpl->getAttributeKind() : 0;
 }
@@ -103,60 +106,70 @@ unsigned Attribute::getStackAlignment() const {
 }
 
 std::string Attribute::getAsString() const {
-  if (hasAttribute(Attribute::ZExt))
-    return "zeroext";
-  if (hasAttribute(Attribute::SExt))
-    return "signext";
-  if (hasAttribute(Attribute::NoReturn))
-    return "noreturn";
-  if (hasAttribute(Attribute::NoUnwind))
-    return "nounwind";
-  if (hasAttribute(Attribute::UWTable))
-    return "uwtable";
-  if (hasAttribute(Attribute::ReturnsTwice))
-    return "returns_twice";
+  if (!pImpl) return "";
+
+  if (hasAttribute(Attribute::AddressSafety))
+    return "address_safety";
+  if (hasAttribute(Attribute::AlwaysInline))
+    return "alwaysinline";
+  if (hasAttribute(Attribute::ByVal))
+    return "byval";
+  if (hasAttribute(Attribute::InlineHint))
+    return "inlinehint";
   if (hasAttribute(Attribute::InReg))
     return "inreg";
+  if (hasAttribute(Attribute::MinSize))
+    return "minsize";
+  if (hasAttribute(Attribute::Naked))
+    return "naked";
+  if (hasAttribute(Attribute::Nest))
+    return "nest";
   if (hasAttribute(Attribute::NoAlias))
     return "noalias";
   if (hasAttribute(Attribute::NoCapture))
     return "nocapture";
-  if (hasAttribute(Attribute::StructRet))
-    return "sret";
-  if (hasAttribute(Attribute::ByVal))
-    return "byval";
-  if (hasAttribute(Attribute::Nest))
-    return "nest";
+  if (hasAttribute(Attribute::NoDuplicate))
+    return "noduplicate";
+  if (hasAttribute(Attribute::NoImplicitFloat))
+    return "noimplicitfloat";
+  if (hasAttribute(Attribute::NoInline))
+    return "noinline";
+  if (hasAttribute(Attribute::NonLazyBind))
+    return "nonlazybind";
+  if (hasAttribute(Attribute::NoRedZone))
+    return "noredzone";
+  if (hasAttribute(Attribute::NoReturn))
+    return "noreturn";
+  if (hasAttribute(Attribute::NoUnwind))
+    return "nounwind";
+  if (hasAttribute(Attribute::OptimizeForSize))
+    return "optsize";
   if (hasAttribute(Attribute::ReadNone))
     return "readnone";
   if (hasAttribute(Attribute::ReadOnly))
     return "readonly";
-  if (hasAttribute(Attribute::OptimizeForSize))
-    return "optsize";
-  if (hasAttribute(Attribute::NoInline))
-    return "noinline";
-  if (hasAttribute(Attribute::InlineHint))
-    return "inlinehint";
-  if (hasAttribute(Attribute::AlwaysInline))
-    return "alwaysinline";
+  if (hasAttribute(Attribute::ReturnsTwice))
+    return "returns_twice";
+  if (hasAttribute(Attribute::SExt))
+    return "signext";
   if (hasAttribute(Attribute::StackProtect))
     return "ssp";
   if (hasAttribute(Attribute::StackProtectReq))
     return "sspreq";
   if (hasAttribute(Attribute::StackProtectStrong))
     return "sspstrong";
-  if (hasAttribute(Attribute::NoRedZone))
-    return "noredzone";
-  if (hasAttribute(Attribute::NoImplicitFloat))
-    return "noimplicitfloat";
-  if (hasAttribute(Attribute::Naked))
-    return "naked";
-  if (hasAttribute(Attribute::NonLazyBind))
-    return "nonlazybind";
-  if (hasAttribute(Attribute::AddressSafety))
-    return "address_safety";
-  if (hasAttribute(Attribute::MinSize))
-    return "minsize";
+  if (hasAttribute(Attribute::StructRet))
+    return "sret";
+  if (hasAttribute(Attribute::UWTable))
+    return "uwtable";
+  if (hasAttribute(Attribute::ZExt))
+    return "zeroext";
+
+  // FIXME: These should be output like this:
+  //
+  //   align=4
+  //   alignstack=8
+  //
   if (hasAttribute(Attribute::StackAlignment)) {
     std::string Result;
     Result += "alignstack(";
@@ -168,17 +181,38 @@ std::string Attribute::getAsString() const {
     std::string Result;
     Result += "align ";
     Result += utostr(getAlignment());
-    Result += "";
     return Result;
   }
-  if (hasAttribute(Attribute::NoDuplicate))
-    return "noduplicate";
+
+  // Convert target-dependent attributes to strings of the form:
+  //
+  //   "kind"
+  //   "kind" = "value"
+  //   "kind" = ("value1" "value2" "value3" )
+  //
+  if (ConstantDataArray *CDA =
+      dyn_cast<ConstantDataArray>(pImpl->getAttributeKind())) {
+    std::string Result;
+    Result += '\"' + CDA->getAsString().str() + '"';
+
+    ArrayRef<Constant*> Vals = pImpl->getAttributeValues();
+    if (Vals.empty()) return Result;
+    Result += " = ";
+    if (Vals.size() > 1) Result += '(';
+    for (ArrayRef<Constant*>::iterator I = Vals.begin(), E = Vals.end();
+         I != E; ) {
+      ConstantDataArray *CDA = cast<ConstantDataArray>(*I++);
+      Result += '\"' + CDA->getAsString().str() + '"';
+      if (I != E) Result += ' ';
+    }
+    if (Vals.size() > 1) Result += ')';
+  }
 
   llvm_unreachable("Unknown attribute");
 }
 
 bool Attribute::operator==(AttrKind K) const {
-  return pImpl && *pImpl == K;
+  return (pImpl && *pImpl == K) || (!pImpl && K == None);
 }
 bool Attribute::operator!=(AttrKind K) const {
   return !(*this == K);
@@ -219,10 +253,6 @@ bool AttributeImpl::hasAttribute(Attribute::AttrKind A) const {
   return (Raw() & getAttrMask(A)) != 0;
 }
 
-bool AttributeImpl::hasAttributes() const {
-  return Raw() != 0;
-}
-
 uint64_t AttributeImpl::getAlignment() const {
   uint64_t Mask = Raw() & getAttrMask(Attribute::Alignment);
   return 1ULL << ((Mask >> 16) - 1);
@@ -447,7 +477,7 @@ AttributeSet AttributeSet::get(LLVMContext &C,
   for (unsigned i = 0, e = Attrs.size(); i != e; ++i) {
     assert((!i || Attrs[i-1].first <= Attrs[i].first) &&
            "Misordered Attributes list!");
-    assert(Attrs[i].second.hasAttributes() &&
+    assert(Attrs[i].second != Attribute::None &&
            "Pointless attribute!");
   }
 #endif