[llvm] r265189 - Swift Calling Convention: add swifterror attribute.

Manman Ren via llvm-commits llvm-commits at lists.llvm.org
Fri Apr 1 14:41:16 PDT 2016


Author: mren
Date: Fri Apr  1 16:41:15 2016
New Revision: 265189

URL: http://llvm.org/viewvc/llvm-project?rev=265189&view=rev
Log:
Swift Calling Convention: add swifterror attribute.

A ``swifterror`` attribute can be applied to a function parameter or an
AllocaInst.

This commit does not include any target-specific change. The target-specific
optimization will come as a follow-up patch.

Differential Revision: http://reviews.llvm.org/D18092

Added:
    llvm/trunk/test/Verifier/swifterror.ll
    llvm/trunk/test/Verifier/swifterror2.ll
    llvm/trunk/test/Verifier/swifterror3.ll
Modified:
    llvm/trunk/docs/LangRef.rst
    llvm/trunk/include/llvm-c/Core.h
    llvm/trunk/include/llvm/CodeGen/FastISel.h
    llvm/trunk/include/llvm/IR/Argument.h
    llvm/trunk/include/llvm/IR/Attributes.td
    llvm/trunk/include/llvm/IR/Instructions.h
    llvm/trunk/include/llvm/Target/TargetCallingConv.h
    llvm/trunk/include/llvm/Target/TargetCallingConv.td
    llvm/trunk/include/llvm/Target/TargetLowering.h
    llvm/trunk/lib/AsmParser/LLLexer.cpp
    llvm/trunk/lib/AsmParser/LLParser.cpp
    llvm/trunk/lib/AsmParser/LLToken.h
    llvm/trunk/lib/Bitcode/Reader/BitcodeReader.cpp
    llvm/trunk/lib/Bitcode/Writer/BitcodeWriter.cpp
    llvm/trunk/lib/CodeGen/SelectionDAG/FastISel.cpp
    llvm/trunk/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp
    llvm/trunk/lib/CodeGen/SelectionDAG/TargetLowering.cpp
    llvm/trunk/lib/IR/AsmWriter.cpp
    llvm/trunk/lib/IR/Attributes.cpp
    llvm/trunk/lib/IR/Function.cpp
    llvm/trunk/lib/IR/Instructions.cpp
    llvm/trunk/lib/IR/Verifier.cpp
    llvm/trunk/test/Bitcode/attributes.ll

Modified: llvm/trunk/docs/LangRef.rst
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/docs/LangRef.rst?rev=265189&r1=265188&r2=265189&view=diff
==============================================================================
--- llvm/trunk/docs/LangRef.rst (original)
+++ llvm/trunk/docs/LangRef.rst Fri Apr  1 16:41:15 2016
@@ -1063,6 +1063,25 @@ Currently, only the following parameter
     a valid attribute for return values and can only be applied to one
     parameter.
 
+``swifterror``
+    This attribute is motivated to model and optimize Swift error handling. It
+    can be applied to a parameter with pointer to pointer type or a
+    pointer-sized alloca. At the call site, the actual argument that corresponds
+    to a ``swifterror`` parameter has to come from a ``swifterror`` alloca. A
+    ``swifterror`` value (either the parameter or the alloca) can only be loaded
+    and stored from, or used as a ``swifterror`` argument. This is not a valid
+    attribute for return values and can only be applied to one parameter.
+
+    These constraints allow the calling convention to optimize access to
+    ``swifterror`` variables by associating them with a specific register at
+    call boundaries rather than placing them in memory. Since this does change
+    the calling convention, a function which uses the ``swifterror`` attribute
+    on a parameter is not ABI-compatible with one which does not.
+
+    These constraints also allow LLVM to assume that a ``swifterror`` argument
+    does not alias any other memory visible within a function and that a
+    ``swifterror`` alloca passed as an argument does not escape.
+
 .. _gc:
 
 Garbage Collector Strategy Names

Modified: llvm/trunk/include/llvm-c/Core.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm-c/Core.h?rev=265189&r1=265188&r2=265189&view=diff
==============================================================================
--- llvm/trunk/include/llvm-c/Core.h (original)
+++ llvm/trunk/include/llvm-c/Core.h Fri Apr  1 16:41:15 2016
@@ -95,6 +95,7 @@ typedef enum {
     LLVMConvergentAttribute = 1ULL << 46,
     LLVMSafeStackAttribute = 1ULL << 47,
     LLVMSwiftSelfAttribute = 1ULL << 48,
+    LLVMSwiftErrorAttribute = 1ULL << 49,
     */
 } LLVMAttribute;
 

Modified: llvm/trunk/include/llvm/CodeGen/FastISel.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/CodeGen/FastISel.h?rev=265189&r1=265188&r2=265189&view=diff
==============================================================================
--- llvm/trunk/include/llvm/CodeGen/FastISel.h (original)
+++ llvm/trunk/include/llvm/CodeGen/FastISel.h Fri Apr  1 16:41:15 2016
@@ -42,13 +42,14 @@ public:
     bool IsInAlloca : 1;
     bool IsReturned : 1;
     bool IsSwiftSelf : 1;
+    bool IsSwiftError : 1;
     uint16_t Alignment;
 
     ArgListEntry()
         : Val(nullptr), Ty(nullptr), IsSExt(false), IsZExt(false),
           IsInReg(false), IsSRet(false), IsNest(false), IsByVal(false),
           IsInAlloca(false), IsReturned(false), IsSwiftSelf(false),
-          Alignment(0) {}
+          IsSwiftError(false), Alignment(0) {}
 
     /// \brief Set CallLoweringInfo attribute flags based on a call instruction
     /// and called function attributes.

Modified: llvm/trunk/include/llvm/IR/Argument.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/IR/Argument.h?rev=265189&r1=265188&r2=265189&view=diff
==============================================================================
--- llvm/trunk/include/llvm/IR/Argument.h (original)
+++ llvm/trunk/include/llvm/IR/Argument.h Fri Apr  1 16:41:15 2016
@@ -76,6 +76,9 @@ public:
   /// \brief Return true if this argument has the swiftself attribute.
   bool hasSwiftSelfAttr() const;
 
+  /// \brief Return true if this argument has the swifterror attribute.
+  bool hasSwiftErrorAttr() const;
+
   /// \brief Return true if this argument has the byval attribute or inalloca
   /// attribute on it in its containing function.  These attributes both
   /// represent arguments being passed by value.

Modified: llvm/trunk/include/llvm/IR/Attributes.td
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/IR/Attributes.td?rev=265189&r1=265188&r2=265189&view=diff
==============================================================================
--- llvm/trunk/include/llvm/IR/Attributes.td (original)
+++ llvm/trunk/include/llvm/IR/Attributes.td Fri Apr  1 16:41:15 2016
@@ -154,6 +154,9 @@ def SanitizeThread : EnumAttr<"sanitize_
 /// MemorySanitizer is on.
 def SanitizeMemory : EnumAttr<"sanitize_memory">;
 
+/// Argument is swift error.
+def SwiftError : EnumAttr<"swifterror">;
+
 /// Argument is swift self/context.
 def SwiftSelf : EnumAttr<"swiftself">;
 

Modified: llvm/trunk/include/llvm/IR/Instructions.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/IR/Instructions.h?rev=265189&r1=265188&r2=265189&view=diff
==============================================================================
--- llvm/trunk/include/llvm/IR/Instructions.h (original)
+++ llvm/trunk/include/llvm/IR/Instructions.h Fri Apr  1 16:41:15 2016
@@ -152,6 +152,18 @@ public:
                                (V ? 32 : 0));
   }
 
+  /// \brief Return true if this alloca is used as a swifterror argument to a
+  /// call.
+  bool isSwiftError() const {
+    return getSubclassDataFromInstruction() & 64;
+  }
+
+  /// \brief Specify whether this alloca is used to represent a swifterror.
+  void setSwiftError(bool V) {
+    setInstructionSubclassData((getSubclassDataFromInstruction() & ~64) |
+                               (V ? 64 : 0));
+  }
+
   // Methods for support type inquiry through isa, cast, and dyn_cast:
   static inline bool classof(const Instruction *I) {
     return (I->getOpcode() == Instruction::Alloca);

Modified: llvm/trunk/include/llvm/Target/TargetCallingConv.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/Target/TargetCallingConv.h?rev=265189&r1=265188&r2=265189&view=diff
==============================================================================
--- llvm/trunk/include/llvm/Target/TargetCallingConv.h (original)
+++ llvm/trunk/include/llvm/Target/TargetCallingConv.h Fri Apr  1 16:41:15 2016
@@ -50,6 +50,8 @@ namespace ISD {
     static const uint64_t SplitEndOffs   = 13;
     static const uint64_t SwiftSelf      = 1ULL<<14; ///< Swift self parameter
     static const uint64_t SwiftSelfOffs  = 14;
+    static const uint64_t SwiftError     = 1ULL<<15; ///< Swift error parameter
+    static const uint64_t SwiftErrorOffs = 15;
     static const uint64_t OrigAlign      = 0x1FULL<<27;
     static const uint64_t OrigAlignOffs  = 27;
     static const uint64_t ByValSize      = 0x3fffffffULL<<32; ///< Struct size
@@ -87,6 +89,9 @@ namespace ISD {
     bool isSwiftSelf() const { return Flags & SwiftSelf; }
     void setSwiftSelf() { Flags |= One << SwiftSelfOffs; }
 
+    bool isSwiftError() const { return Flags & SwiftError; }
+    void setSwiftError() { Flags |= One << SwiftErrorOffs; }
+
     bool isNest()      const { return Flags & Nest; }
     void setNest()     { Flags |= One << NestOffs; }
 

Modified: llvm/trunk/include/llvm/Target/TargetCallingConv.td
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/Target/TargetCallingConv.td?rev=265189&r1=265188&r2=265189&view=diff
==============================================================================
--- llvm/trunk/include/llvm/Target/TargetCallingConv.td (original)
+++ llvm/trunk/include/llvm/Target/TargetCallingConv.td Fri Apr  1 16:41:15 2016
@@ -47,6 +47,11 @@ class CCIfByVal<CCAction A> : CCIf<"ArgF
 class CCIfSwiftSelf<CCAction A> : CCIf<"ArgFlags.isSwiftSelf()", A> {
 }
 
+/// CCIfSwiftError - If the current argument has swifterror parameter attribute,
+/// apply Action A.
+class CCIfSwiftError<CCAction A> : CCIf<"ArgFlags.isSwiftError()", A> {
+}
+
 /// CCIfConsecutiveRegs - If the current argument has InConsecutiveRegs
 /// parameter attribute, apply Action A.
 class CCIfConsecutiveRegs<CCAction A> : CCIf<"ArgFlags.isInConsecutiveRegs()", A> {

Modified: llvm/trunk/include/llvm/Target/TargetLowering.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/Target/TargetLowering.h?rev=265189&r1=265188&r2=265189&view=diff
==============================================================================
--- llvm/trunk/include/llvm/Target/TargetLowering.h (original)
+++ llvm/trunk/include/llvm/Target/TargetLowering.h Fri Apr  1 16:41:15 2016
@@ -2327,11 +2327,13 @@ public:
     bool isInAlloca : 1;
     bool isReturned : 1;
     bool isSwiftSelf : 1;
+    bool isSwiftError : 1;
     uint16_t Alignment;
 
     ArgListEntry() : isSExt(false), isZExt(false), isInReg(false),
       isSRet(false), isNest(false), isByVal(false), isInAlloca(false),
-      isReturned(false), isSwiftSelf(false), Alignment(0) { }
+      isReturned(false), isSwiftSelf(false), isSwiftError(false),
+      Alignment(0) { }
 
     void setAttributes(ImmutableCallSite *CS, unsigned AttrIdx);
   };

Modified: llvm/trunk/lib/AsmParser/LLLexer.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/AsmParser/LLLexer.cpp?rev=265189&r1=265188&r2=265189&view=diff
==============================================================================
--- llvm/trunk/lib/AsmParser/LLLexer.cpp (original)
+++ llvm/trunk/lib/AsmParser/LLLexer.cpp Fri Apr  1 16:41:15 2016
@@ -648,6 +648,7 @@ lltok::Kind LLLexer::LexIdentifier() {
   KEYWORD(sanitize_address);
   KEYWORD(sanitize_thread);
   KEYWORD(sanitize_memory);
+  KEYWORD(swifterror);
   KEYWORD(swiftself);
   KEYWORD(uwtable);
   KEYWORD(zeroext);

Modified: llvm/trunk/lib/AsmParser/LLParser.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/AsmParser/LLParser.cpp?rev=265189&r1=265188&r2=265189&view=diff
==============================================================================
--- llvm/trunk/lib/AsmParser/LLParser.cpp (original)
+++ llvm/trunk/lib/AsmParser/LLParser.cpp Fri Apr  1 16:41:15 2016
@@ -1088,6 +1088,7 @@ bool LLParser::ParseFnAttributeValuePair
     case lltok::kw_nonnull:
     case lltok::kw_returned:
     case lltok::kw_sret:
+    case lltok::kw_swifterror:
     case lltok::kw_swiftself:
       HaveError |=
         Error(Lex.getLoc(),
@@ -1362,6 +1363,7 @@ bool LLParser::ParseOptionalParamAttrs(A
     case lltok::kw_returned:        B.addAttribute(Attribute::Returned); break;
     case lltok::kw_signext:         B.addAttribute(Attribute::SExt); break;
     case lltok::kw_sret:            B.addAttribute(Attribute::StructRet); break;
+    case lltok::kw_swifterror:      B.addAttribute(Attribute::SwiftError); break;
     case lltok::kw_swiftself:       B.addAttribute(Attribute::SwiftSelf); break;
     case lltok::kw_zeroext:         B.addAttribute(Attribute::ZExt); break;
 
@@ -1450,6 +1452,7 @@ bool LLParser::ParseOptionalReturnAttrs(
     case lltok::kw_nocapture:
     case lltok::kw_returned:
     case lltok::kw_sret:
+    case lltok::kw_swifterror:
     case lltok::kw_swiftself:
       HaveError |= Error(Lex.getLoc(), "invalid use of parameter-only attribute");
       break;
@@ -5802,7 +5805,8 @@ bool LLParser::ParseCall(Instruction *&I
 //===----------------------------------------------------------------------===//
 
 /// ParseAlloc
-///   ::= 'alloca' 'inalloca'? Type (',' TypeAndValue)? (',' 'align' i32)?
+///   ::= 'alloca' 'inalloca'? 'swifterror'? Type (',' TypeAndValue)?
+///       (',' 'align' i32)?
 int LLParser::ParseAlloc(Instruction *&Inst, PerFunctionState &PFS) {
   Value *Size = nullptr;
   LocTy SizeLoc, TyLoc;
@@ -5810,6 +5814,7 @@ int LLParser::ParseAlloc(Instruction *&I
   Type *Ty = nullptr;
 
   bool IsInAlloca = EatIfPresent(lltok::kw_inalloca);
+  bool IsSwiftError = EatIfPresent(lltok::kw_swifterror);
 
   if (ParseType(Ty, TyLoc)) return true;
 
@@ -5834,6 +5839,7 @@ int LLParser::ParseAlloc(Instruction *&I
 
   AllocaInst *AI = new AllocaInst(Ty, Size, Alignment);
   AI->setUsedWithInAlloca(IsInAlloca);
+  AI->setSwiftError(IsSwiftError);
   Inst = AI;
   return AteExtraComma ? InstExtraComma : InstNormal;
 }

Modified: llvm/trunk/lib/AsmParser/LLToken.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/AsmParser/LLToken.h?rev=265189&r1=265188&r2=265189&view=diff
==============================================================================
--- llvm/trunk/lib/AsmParser/LLToken.h (original)
+++ llvm/trunk/lib/AsmParser/LLToken.h Fri Apr  1 16:41:15 2016
@@ -152,6 +152,7 @@ namespace lltok {
     kw_sret,
     kw_sanitize_thread,
     kw_sanitize_memory,
+    kw_swifterror,
     kw_swiftself,
     kw_uwtable,
     kw_zeroext,

Modified: llvm/trunk/lib/Bitcode/Reader/BitcodeReader.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Bitcode/Reader/BitcodeReader.cpp?rev=265189&r1=265188&r2=265189&view=diff
==============================================================================
--- llvm/trunk/lib/Bitcode/Reader/BitcodeReader.cpp (original)
+++ llvm/trunk/lib/Bitcode/Reader/BitcodeReader.cpp Fri Apr  1 16:41:15 2016
@@ -1317,6 +1317,8 @@ static Attribute::AttrKind getAttrFromCo
     return Attribute::SanitizeThread;
   case bitc::ATTR_KIND_SANITIZE_MEMORY:
     return Attribute::SanitizeMemory;
+  case bitc::ATTR_KIND_SWIFT_ERROR:
+    return Attribute::SwiftError;
   case bitc::ATTR_KIND_SWIFT_SELF:
     return Attribute::SwiftSelf;
   case bitc::ATTR_KIND_UW_TABLE:
@@ -4843,10 +4845,11 @@ std::error_code BitcodeReader::parseFunc
       uint64_t AlignRecord = Record[3];
       const uint64_t InAllocaMask = uint64_t(1) << 5;
       const uint64_t ExplicitTypeMask = uint64_t(1) << 6;
-      // Reserve bit 7 for SwiftError flag.
-      // const uint64_t SwiftErrorMask = uint64_t(1) << 7;
-      const uint64_t FlagMask = InAllocaMask | ExplicitTypeMask;
+      const uint64_t SwiftErrorMask = uint64_t(1) << 7;
+      const uint64_t FlagMask = InAllocaMask | ExplicitTypeMask |
+                                SwiftErrorMask;
       bool InAlloca = AlignRecord & InAllocaMask;
+      bool SwiftError = AlignRecord & SwiftErrorMask;
       Type *Ty = getTypeByID(Record[0]);
       if ((AlignRecord & ExplicitTypeMask) == 0) {
         auto *PTy = dyn_cast_or_null<PointerType>(Ty);
@@ -4865,6 +4868,7 @@ std::error_code BitcodeReader::parseFunc
         return error("Invalid record");
       AllocaInst *AI = new AllocaInst(Ty, Size, Align);
       AI->setUsedWithInAlloca(InAlloca);
+      AI->setSwiftError(SwiftError);
       I = AI;
       InstructionList.push_back(I);
       break;

Modified: llvm/trunk/lib/Bitcode/Writer/BitcodeWriter.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Bitcode/Writer/BitcodeWriter.cpp?rev=265189&r1=265188&r2=265189&view=diff
==============================================================================
--- llvm/trunk/lib/Bitcode/Writer/BitcodeWriter.cpp (original)
+++ llvm/trunk/lib/Bitcode/Writer/BitcodeWriter.cpp Fri Apr  1 16:41:15 2016
@@ -261,6 +261,8 @@ static uint64_t getAttrKindEncoding(Attr
     return bitc::ATTR_KIND_SANITIZE_THREAD;
   case Attribute::SanitizeMemory:
     return bitc::ATTR_KIND_SANITIZE_MEMORY;
+  case Attribute::SwiftError:
+    return bitc::ATTR_KIND_SWIFT_ERROR;
   case Attribute::SwiftSelf:
     return bitc::ATTR_KIND_SWIFT_SELF;
   case Attribute::UWTable:
@@ -2142,8 +2144,7 @@ static void WriteInstruction(const Instr
     assert(AlignRecord < 1 << 5 && "alignment greater than 1 << 64");
     AlignRecord |= AI.isUsedWithInAlloca() << 5;
     AlignRecord |= 1 << 6;
-    // Reserve bit 7 for SwiftError flag.
-    // AlignRecord |= AI.isSwiftError() << 7;
+    AlignRecord |= AI.isSwiftError() << 7;
     Vals.push_back(AlignRecord);
     break;
   }

Modified: llvm/trunk/lib/CodeGen/SelectionDAG/FastISel.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/CodeGen/SelectionDAG/FastISel.cpp?rev=265189&r1=265188&r2=265189&view=diff
==============================================================================
--- llvm/trunk/lib/CodeGen/SelectionDAG/FastISel.cpp (original)
+++ llvm/trunk/lib/CodeGen/SelectionDAG/FastISel.cpp Fri Apr  1 16:41:15 2016
@@ -90,6 +90,7 @@ void FastISel::ArgListEntry::setAttribut
   IsInAlloca = CS->paramHasAttr(AttrIdx, Attribute::InAlloca);
   IsReturned = CS->paramHasAttr(AttrIdx, Attribute::Returned);
   IsSwiftSelf = CS->paramHasAttr(AttrIdx, Attribute::SwiftSelf);
+  IsSwiftError = CS->paramHasAttr(AttrIdx, Attribute::SwiftError);
   Alignment = CS->getParamAlignment(AttrIdx);
 }
 
@@ -960,6 +961,8 @@ bool FastISel::lowerCallTo(CallLoweringI
       Flags.setSRet();
     if (Arg.IsSwiftSelf)
       Flags.setSwiftSelf();
+    if (Arg.IsSwiftError)
+      Flags.setSwiftError();
     if (Arg.IsByVal)
       Flags.setByVal();
     if (Arg.IsInAlloca) {

Modified: llvm/trunk/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp?rev=265189&r1=265188&r2=265189&view=diff
==============================================================================
--- llvm/trunk/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp (original)
+++ llvm/trunk/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp Fri Apr  1 16:41:15 2016
@@ -7282,6 +7282,7 @@ TargetLowering::LowerCallTo(TargetLoweri
     Entry.isByVal = false;
     Entry.isReturned = false;
     Entry.isSwiftSelf = false;
+    Entry.isSwiftError = false;
     Entry.Alignment = Align;
     CLI.getArgs().insert(CLI.getArgs().begin(), Entry);
     CLI.RetTy = Type::getVoidTy(CLI.RetTy->getContext());
@@ -7341,6 +7342,8 @@ TargetLowering::LowerCallTo(TargetLoweri
         Flags.setSRet();
       if (Args[i].isSwiftSelf)
         Flags.setSwiftSelf();
+      if (Args[i].isSwiftError)
+        Flags.setSwiftError();
       if (Args[i].isByVal)
         Flags.setByVal();
       if (Args[i].isInAlloca) {
@@ -7623,6 +7626,8 @@ void SelectionDAGISel::LowerArguments(co
         Flags.setSRet();
       if (F.getAttributes().hasAttribute(Idx, Attribute::SwiftSelf))
         Flags.setSwiftSelf();
+      if (F.getAttributes().hasAttribute(Idx, Attribute::SwiftError))
+        Flags.setSwiftError();
       if (F.getAttributes().hasAttribute(Idx, Attribute::ByVal))
         Flags.setByVal();
       if (F.getAttributes().hasAttribute(Idx, Attribute::InAlloca)) {

Modified: llvm/trunk/lib/CodeGen/SelectionDAG/TargetLowering.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/CodeGen/SelectionDAG/TargetLowering.cpp?rev=265189&r1=265188&r2=265189&view=diff
==============================================================================
--- llvm/trunk/lib/CodeGen/SelectionDAG/TargetLowering.cpp (original)
+++ llvm/trunk/lib/CodeGen/SelectionDAG/TargetLowering.cpp Fri Apr  1 16:41:15 2016
@@ -78,6 +78,7 @@ void TargetLowering::ArgListEntry::setAt
   isInAlloca = CS->paramHasAttr(AttrIdx, Attribute::InAlloca);
   isReturned = CS->paramHasAttr(AttrIdx, Attribute::Returned);
   isSwiftSelf = CS->paramHasAttr(AttrIdx, Attribute::SwiftSelf);
+  isSwiftError = CS->paramHasAttr(AttrIdx, Attribute::SwiftError);
   Alignment  = CS->getParamAlignment(AttrIdx);
 }
 

Modified: llvm/trunk/lib/IR/AsmWriter.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/IR/AsmWriter.cpp?rev=265189&r1=265188&r2=265189&view=diff
==============================================================================
--- llvm/trunk/lib/IR/AsmWriter.cpp (original)
+++ llvm/trunk/lib/IR/AsmWriter.cpp Fri Apr  1 16:41:15 2016
@@ -3028,6 +3028,8 @@ void AssemblyWriter::printInstruction(co
     Out << ' ';
     if (AI->isUsedWithInAlloca())
       Out << "inalloca ";
+    if (AI->isSwiftError())
+      Out << "swifterror ";
     TypePrinter.print(AI->getAllocatedType(), Out);
 
     // Explicitly write the array size if the code is broken, if it's an array

Modified: llvm/trunk/lib/IR/Attributes.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/IR/Attributes.cpp?rev=265189&r1=265188&r2=265189&view=diff
==============================================================================
--- llvm/trunk/lib/IR/Attributes.cpp (original)
+++ llvm/trunk/lib/IR/Attributes.cpp Fri Apr  1 16:41:15 2016
@@ -195,6 +195,8 @@ std::string Attribute::getAsString(bool
     return "byval";
   if (hasAttribute(Attribute::Convergent))
     return "convergent";
+  if (hasAttribute(Attribute::SwiftError))
+    return "swifterror";
   if (hasAttribute(Attribute::SwiftSelf))
     return "swiftself";
   if (hasAttribute(Attribute::InaccessibleMemOnly))
@@ -451,6 +453,7 @@ uint64_t AttributeImpl::getAttrMask(Attr
   case Attribute::InaccessibleMemOnly:         return 1ULL << 49;
   case Attribute::InaccessibleMemOrArgMemOnly: return 1ULL << 50;
   case Attribute::SwiftSelf:       return 1ULL << 51;
+  case Attribute::SwiftError:      return 1ULL << 52;
   case Attribute::Dereferenceable:
     llvm_unreachable("dereferenceable attribute not supported in raw format");
     break;

Modified: llvm/trunk/lib/IR/Function.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/IR/Function.cpp?rev=265189&r1=265188&r2=265189&view=diff
==============================================================================
--- llvm/trunk/lib/IR/Function.cpp (original)
+++ llvm/trunk/lib/IR/Function.cpp Fri Apr  1 16:41:15 2016
@@ -97,6 +97,11 @@ bool Argument::hasSwiftSelfAttr() const
     hasAttribute(getArgNo()+1, Attribute::SwiftSelf);
 }
 
+bool Argument::hasSwiftErrorAttr() const {
+  return getParent()->getAttributes().
+    hasAttribute(getArgNo()+1, Attribute::SwiftError);
+}
+
 /// \brief Return true if this argument has the inalloca attribute on it in
 /// its containing function.
 bool Argument::hasInAllocaAttr() const {

Modified: llvm/trunk/lib/IR/Instructions.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/IR/Instructions.cpp?rev=265189&r1=265188&r2=265189&view=diff
==============================================================================
--- llvm/trunk/lib/IR/Instructions.cpp (original)
+++ llvm/trunk/lib/IR/Instructions.cpp Fri Apr  1 16:41:15 2016
@@ -3811,6 +3811,7 @@ AllocaInst *AllocaInst::cloneImpl() cons
   AllocaInst *Result = new AllocaInst(getAllocatedType(),
                                       (Value *)getOperand(0), getAlignment());
   Result->setUsedWithInAlloca(isUsedWithInAlloca());
+  Result->setSwiftError(isSwiftError());
   return Result;
 }
 

Modified: llvm/trunk/lib/IR/Verifier.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/IR/Verifier.cpp?rev=265189&r1=265188&r2=265189&view=diff
==============================================================================
--- llvm/trunk/lib/IR/Verifier.cpp (original)
+++ llvm/trunk/lib/IR/Verifier.cpp Fri Apr  1 16:41:15 2016
@@ -426,6 +426,8 @@ private:
   void visitCleanupReturnInst(CleanupReturnInst &CRI);
 
   void verifyCallSite(CallSite CS);
+  void verifySwiftErrorCallSite(CallSite CS, const Value *SwiftErrorVal);
+  void verifySwiftErrorValue(const Value *SwiftErrorVal);
   void verifyMustTailCall(CallInst &CI);
   bool performTypeCheck(Intrinsic::ID ID, Function *F, Type *Ty, int VT,
                         unsigned ArgNo, std::string &Suffix);
@@ -1348,9 +1350,10 @@ void Verifier::verifyParameterAttrs(Attr
                !Attrs.hasAttribute(Idx, Attribute::NoCapture) &&
                !Attrs.hasAttribute(Idx, Attribute::Returned) &&
                !Attrs.hasAttribute(Idx, Attribute::InAlloca) &&
-               !Attrs.hasAttribute(Idx, Attribute::SwiftSelf),
+               !Attrs.hasAttribute(Idx, Attribute::SwiftSelf) &&
+               !Attrs.hasAttribute(Idx, Attribute::SwiftError),
            "Attributes 'byval', 'inalloca', 'nest', 'sret', 'nocapture', "
-           "'returned', and 'swiftself' do not apply to return "
+           "'returned', 'swiftself', and 'swifterror' do not apply to return "
            "values!",
            V);
 
@@ -1411,10 +1414,19 @@ void Verifier::verifyParameterAttrs(Attr
              "Attributes 'byval' and 'inalloca' do not support unsized types!",
              V);
     }
+    if (!isa<PointerType>(PTy->getElementType()))
+      Assert(!Attrs.hasAttribute(Idx, Attribute::SwiftError),
+             "Attribute 'swifterror' only applies to parameters "
+             "with pointer to pointer type!",
+             V);
   } else {
     Assert(!Attrs.hasAttribute(Idx, Attribute::ByVal),
            "Attribute 'byval' only applies to parameters with pointer type!",
            V);
+    Assert(!Attrs.hasAttribute(Idx, Attribute::SwiftError),
+           "Attribute 'swifterror' only applies to parameters "
+           "with pointer type!",
+           V);
   }
 }
 
@@ -1429,6 +1441,7 @@ void Verifier::verifyFunctionAttrs(Funct
   bool SawReturned = false;
   bool SawSRet = false;
   bool SawSwiftSelf = false;
+  bool SawSwiftError = false;
 
   for (unsigned i = 0, e = Attrs.getNumSlots(); i != e; ++i) {
     unsigned Idx = Attrs.getSlotIndex(i);
@@ -1473,6 +1486,12 @@ void Verifier::verifyFunctionAttrs(Funct
       SawSwiftSelf = true;
     }
 
+    if (Attrs.hasAttribute(Idx, Attribute::SwiftError)) {
+      Assert(!SawSwiftError, "Cannot have multiple 'swifterror' parameters!",
+             V);
+      SawSwiftError = true;
+    }
+
     if (Attrs.hasAttribute(Idx, Attribute::InAlloca)) {
       Assert(Idx == FT->getNumParams(), "inalloca isn't on the last parameter!",
              V);
@@ -1886,6 +1905,11 @@ void Verifier::visitFunction(const Funct
       Assert(!Arg.getType()->isTokenTy(),
              "Function takes token but isn't an intrinsic", &Arg, &F);
     }
+
+    // Check that swifterror argument is only used by loads and stores.
+    if (Attrs.hasAttribute(i+1, Attribute::SwiftError)) {
+      verifySwiftErrorValue(&Arg);
+    }
     ++i;
   }
 
@@ -2462,6 +2486,18 @@ void Verifier::verifyCallSite(CallSite C
              "inalloca argument for call has mismatched alloca", AI, I);
   }
 
+  // For each argument of the callsite, if it has the swifterror argument,
+  // make sure the underlying alloca has swifterror as well.
+  for (unsigned i = 0, e = FTy->getNumParams(); i != e; ++i)
+    if (CS.paramHasAttr(i+1, Attribute::SwiftError)) {
+      Value *SwiftErrorArg = CS.getArgument(i);
+      auto AI = dyn_cast<AllocaInst>(SwiftErrorArg->stripInBoundsOffsets());
+      Assert(AI, "swifterror argument should come from alloca", AI, I);
+      if (AI)
+        Assert(AI->isSwiftError(),
+               "swifterror argument for call has mismatched alloca", AI, I);
+    }
+
   if (FTy->isVarArg()) {
     // FIXME? is 'nest' even legal here?
     bool SawNest = false;
@@ -2565,7 +2601,8 @@ static bool isTypeCongruent(Type *L, Typ
 static AttrBuilder getParameterABIAttributes(int I, AttributeSet Attrs) {
   static const Attribute::AttrKind ABIAttrs[] = {
       Attribute::StructRet, Attribute::ByVal, Attribute::InAlloca,
-      Attribute::InReg, Attribute::Returned, Attribute::SwiftSelf};
+      Attribute::InReg, Attribute::Returned, Attribute::SwiftSelf,
+      Attribute::SwiftError};
   AttrBuilder Copy;
   for (auto AK : ABIAttrs) {
     if (Attrs.hasAttribute(I + 1, AK))
@@ -2924,6 +2961,42 @@ void Verifier::visitStoreInst(StoreInst
   visitInstruction(SI);
 }
 
+/// Check that SwiftErrorVal is used as a swifterror argument in CS.
+void Verifier::verifySwiftErrorCallSite(CallSite CS,
+                                        const Value *SwiftErrorVal) {
+  unsigned Idx = 0;
+  for (CallSite::arg_iterator I = CS.arg_begin(), E = CS.arg_end();
+       I != E; ++I, ++Idx) {
+    if (*I == SwiftErrorVal) {
+      Assert(CS.paramHasAttr(Idx+1, Attribute::SwiftError),
+             "swifterror value when used in a callsite should be marked "
+             "with swifterror attribute",
+              SwiftErrorVal, CS);
+    }
+  }
+}
+
+void Verifier::verifySwiftErrorValue(const Value *SwiftErrorVal) {
+  // Check that swifterror value is only used by loads, stores, or as
+  // a swifterror argument.
+  for (const User *U : SwiftErrorVal->users()) {
+    Assert(isa<LoadInst>(U) || isa<StoreInst>(U) || isa<CallInst>(U) ||
+           isa<InvokeInst>(U),
+           "swifterror value can only be loaded and stored from, or "
+           "as a swifterror argument!",
+           SwiftErrorVal, U);
+    // If it is used by a store, check it is the second operand.
+    if (auto StoreI = dyn_cast<StoreInst>(U))
+      Assert(StoreI->getOperand(1) == SwiftErrorVal,
+             "swifterror value should be the second operand when used "
+             "by stores", SwiftErrorVal, U);
+    if (auto CallI = dyn_cast<CallInst>(U))
+      verifySwiftErrorCallSite(const_cast<CallInst*>(CallI), SwiftErrorVal);
+    if (auto II = dyn_cast<InvokeInst>(U))
+      verifySwiftErrorCallSite(const_cast<InvokeInst*>(II), SwiftErrorVal);
+  }
+}
+
 void Verifier::visitAllocaInst(AllocaInst &AI) {
   SmallPtrSet<Type*, 4> Visited;
   PointerType *PTy = AI.getType();
@@ -2937,6 +3010,10 @@ void Verifier::visitAllocaInst(AllocaIns
   Assert(AI.getAlignment() <= Value::MaximumAlignment,
          "huge alignment values are unsupported", &AI);
 
+  if (AI.isSwiftError()) {
+    verifySwiftErrorValue(&AI);
+  }
+
   visitInstruction(AI);
 }
 

Modified: llvm/trunk/test/Bitcode/attributes.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Bitcode/attributes.ll?rev=265189&r1=265188&r2=265189&view=diff
==============================================================================
--- llvm/trunk/test/Bitcode/attributes.ll (original)
+++ llvm/trunk/test/Bitcode/attributes.ll Fri Apr  1 16:41:15 2016
@@ -293,6 +293,31 @@ define void @f50(i8* swiftself)
   ret void;
 }
 
+; CHECK: define i32 @f51(i8** swifterror)
+define i32 @f51(i8** swifterror)
+{
+  ret i32 0
+}
+
+; CHECK: define i32 @f52(i32, i8** swifterror)
+define i32 @f52(i32, i8** swifterror)
+{
+  ret i32 0
+}
+
+%swift_error = type {i64, i8}
+declare float @foo(%swift_error** swifterror %error_ptr_ref)
+
+; CHECK: define float @f53
+; CHECK: alloca swifterror
+define float @f53(i8* %error_ref) {
+entry:
+  %error_ptr_ref = alloca swifterror %swift_error*
+  store %swift_error* null, %swift_error** %error_ptr_ref
+  %call = call float @foo(%swift_error** swifterror %error_ptr_ref)
+  ret float 1.0
+}
+
 ; CHECK: attributes #0 = { noreturn }
 ; CHECK: attributes #1 = { nounwind }
 ; CHECK: attributes #2 = { readnone }

Added: llvm/trunk/test/Verifier/swifterror.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Verifier/swifterror.ll?rev=265189&view=auto
==============================================================================
--- llvm/trunk/test/Verifier/swifterror.ll (added)
+++ llvm/trunk/test/Verifier/swifterror.ll Fri Apr  1 16:41:15 2016
@@ -0,0 +1,31 @@
+; RUN: not llvm-as %s -o /dev/null 2>&1 | FileCheck %s
+
+%swift_error = type {i64, i8}
+
+; CHECK: swifterror value can only be loaded and stored from, or as a swifterror argument!
+; CHECK: %swift_error** %error_ptr_ref
+; CHECK: %t = getelementptr inbounds %swift_error*, %swift_error** %error_ptr_ref, i64 1
+define float @foo(%swift_error** swifterror %error_ptr_ref) {
+  %t = getelementptr inbounds %swift_error*, %swift_error** %error_ptr_ref, i64 1
+  ret float 1.0
+}
+
+; CHECK: swifterror argument for call has mismatched alloca
+; CHECK: %error_ptr_ref = alloca %swift_error*
+; CHECK: %call = call float @foo(%swift_error** swifterror %error_ptr_ref)
+define float @caller(i8* %error_ref) {
+entry:
+  %error_ptr_ref = alloca %swift_error*
+  store %swift_error* null, %swift_error** %error_ptr_ref
+  %call = call float @foo(%swift_error** swifterror %error_ptr_ref)
+  ret float 1.0
+}
+
+; CHECK: Cannot have multiple 'swifterror' parameters!
+declare void @a(i32** swifterror %a, i32** swifterror %b)
+
+; CHECK: Attribute 'swifterror' only applies to parameters with pointer type!
+declare void @b(i32 swifterror %a)
+
+; CHECK: Attribute 'swifterror' only applies to parameters with pointer to pointer type!
+declare void @c(i32* swifterror %a)

Added: llvm/trunk/test/Verifier/swifterror2.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Verifier/swifterror2.ll?rev=265189&view=auto
==============================================================================
--- llvm/trunk/test/Verifier/swifterror2.ll (added)
+++ llvm/trunk/test/Verifier/swifterror2.ll Fri Apr  1 16:41:15 2016
@@ -0,0 +1,4 @@
+; RUN: not llvm-as %s -o /dev/null 2>&1 | FileCheck %s
+
+; CHECK: invalid use of parameter-only attribute
+declare swifterror void @c(i32** swifterror %a)

Added: llvm/trunk/test/Verifier/swifterror3.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Verifier/swifterror3.ll?rev=265189&view=auto
==============================================================================
--- llvm/trunk/test/Verifier/swifterror3.ll (added)
+++ llvm/trunk/test/Verifier/swifterror3.ll Fri Apr  1 16:41:15 2016
@@ -0,0 +1,4 @@
+; RUN: not llvm-as %s -o /dev/null 2>&1 | FileCheck %s
+
+; CHECK: expected type
+declare void @c(swifterror i32* %a)




More information about the llvm-commits mailing list