From 772fe17a6d07304ae2e6b3052bbb24ebb751f0f3 Mon Sep 17 00:00:00 2001 From: Bill Wendling Date: Wed, 27 Jul 2011 20:18:04 +0000 Subject: Merge the contents from exception-handling-rewrite to the mainline. This adds the new instructions 'landingpad' and 'resume'. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@136253 91177308-0d34-0410-b5e6-96231b3b80d8 --- docs/LangRef.html | 35 ++++- include/llvm-c/Core.h | 111 ++++++++------- include/llvm/Bitcode/LLVMBitCodes.h | 5 +- include/llvm/Instruction.def | 63 ++++----- include/llvm/Instructions.h | 163 +++++++++++++++++++++++ include/llvm/Support/IRBuilder.h | 9 ++ include/llvm/Support/InstVisitor.h | 2 + lib/AsmParser/LLLexer.cpp | 8 +- lib/AsmParser/LLParser.cpp | 63 +++++++++ lib/AsmParser/LLParser.h | 2 + lib/AsmParser/LLToken.h | 8 +- lib/Bitcode/Reader/BitcodeReader.cpp | 39 ++++++ lib/Bitcode/Writer/BitcodeWriter.cpp | 18 +++ lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp | 8 ++ lib/CodeGen/SelectionDAG/SelectionDAGBuilder.h | 2 + lib/CodeGen/ShadowStackGC.cpp | 6 +- lib/Target/CBackend/CBackend.cpp | 4 +- lib/Target/CppBackend/CPPBackend.cpp | 8 ++ lib/Transforms/IPO/GlobalOpt.cpp | 2 +- lib/Transforms/InstCombine/InstCombineCalls.cpp | 8 +- lib/Transforms/Scalar/SCCP.cpp | 2 + lib/VMCore/AsmWriter.cpp | 30 +++++ lib/VMCore/Core.cpp | 22 +++ lib/VMCore/Instruction.cpp | 2 + lib/VMCore/Instructions.cpp | 105 ++++++++++++++- lib/VMCore/Verifier.cpp | 69 ++++++++-- test/Feature/exceptionhandling.ll | 54 ++++++++ 27 files changed, 742 insertions(+), 106 deletions(-) create mode 100644 test/Feature/exceptionhandling.ll diff --git a/docs/LangRef.html b/docs/LangRef.html index ab98d3d835..40affb7e91 100644 --- a/docs/LangRef.html +++ b/docs/LangRef.html @@ -123,6 +123,7 @@
  • 'indirectbr' Instruction
  • 'invoke' Instruction
  • 'unwind' Instruction
  • +
  • 'resume' Instruction
  • 'unreachable' Instruction
  • @@ -2942,13 +2943,14 @@ should not be exposed to source languages.

    control flow, not values (the one exception being the 'invoke' instruction).

    -

    There are seven different terminator instructions: the +

    There are eight different terminator instructions: the 'ret' instruction, the 'br' instruction, the 'switch' instruction, the ''indirectbr' Instruction, the 'invoke' instruction, the - 'unwind' instruction, and the + 'unwind' instruction, the + 'resume' instruction, and the 'unreachable' instruction.

    @@ -3271,6 +3273,35 @@ that the invoke/unwind semantics are likely to change in future versions.

    +

    + 'resume' Instruction +

    + +
    + +
    Syntax:
    +
    +  resume <type> <value>
    +
    + +
    Overview:
    +

    The 'resume' instruction is a terminator instruction that has no + successors. Its operand must have the same type as the result of any + 'landingpad' instruction in the same function.

    + +
    Semantics:
    +

    The 'resume' instruction resumes propagation of an existing + (in-flight) exception.

    + +
    Example:
    +
    + resume { i8*, i32 } %exn
    +
    + +
    + + +

    'unreachable' Instruction

    diff --git a/include/llvm-c/Core.h b/include/llvm-c/Core.h index c9522a6666..3019d9231d 100644 --- a/include/llvm-c/Core.h +++ b/include/llvm-c/Core.h @@ -126,67 +126,69 @@ typedef enum { LLVMIndirectBr = 4, LLVMInvoke = 5, LLVMUnwind = 6, - LLVMUnreachable = 7, + LLVMResume = 7, + LLVMUnreachable = 8, /* Standard Binary Operators */ - LLVMAdd = 8, - LLVMFAdd = 9, - LLVMSub = 10, - LLVMFSub = 11, - LLVMMul = 12, - LLVMFMul = 13, - LLVMUDiv = 14, - LLVMSDiv = 15, - LLVMFDiv = 16, - LLVMURem = 17, - LLVMSRem = 18, - LLVMFRem = 19, + LLVMAdd = 9, + LLVMFAdd = 10, + LLVMSub = 11, + LLVMFSub = 12, + LLVMMul = 13, + LLVMFMul = 14, + LLVMUDiv = 15, + LLVMSDiv = 16, + LLVMFDiv = 17, + LLVMURem = 18, + LLVMSRem = 19, + LLVMFRem = 20, /* Logical Operators */ - LLVMShl = 20, - LLVMLShr = 21, - LLVMAShr = 22, - LLVMAnd = 23, - LLVMOr = 24, - LLVMXor = 25, + LLVMShl = 21, + LLVMLShr = 22, + LLVMAShr = 23, + LLVMAnd = 24, + LLVMOr = 25, + LLVMXor = 26, /* Memory Operators */ - LLVMAlloca = 26, - LLVMLoad = 27, - LLVMStore = 28, - LLVMGetElementPtr = 29, + LLVMAlloca = 27, + LLVMLoad = 28, + LLVMStore = 29, + LLVMGetElementPtr = 30, /* Cast Operators */ - LLVMTrunc = 30, - LLVMZExt = 31, - LLVMSExt = 32, - LLVMFPToUI = 33, - LLVMFPToSI = 34, - LLVMUIToFP = 35, - LLVMSIToFP = 36, - LLVMFPTrunc = 37, - LLVMFPExt = 38, - LLVMPtrToInt = 39, - LLVMIntToPtr = 40, - LLVMBitCast = 41, + LLVMTrunc = 31, + LLVMZExt = 32, + LLVMSExt = 33, + LLVMFPToUI = 34, + LLVMFPToSI = 35, + LLVMUIToFP = 36, + LLVMSIToFP = 37, + LLVMFPTrunc = 38, + LLVMFPExt = 39, + LLVMPtrToInt = 40, + LLVMIntToPtr = 41, + LLVMBitCast = 42, /* Other Operators */ - LLVMICmp = 42, - LLVMFCmp = 43, - LLVMPHI = 44, - LLVMCall = 45, - LLVMSelect = 46, + LLVMICmp = 43, + LLVMFCmp = 44, + LLVMPHI = 45, + LLVMCall = 46, + LLVMSelect = 47, /* UserOp1 */ /* UserOp2 */ - LLVMVAArg = 49, - LLVMExtractElement = 50, - LLVMInsertElement = 51, - LLVMShuffleVector = 52, - LLVMExtractValue = 53, - LLVMInsertValue = 54, + LLVMVAArg = 50, + LLVMExtractElement = 51, + LLVMInsertElement = 52, + LLVMShuffleVector = 53, + LLVMExtractValue = 54, + LLVMInsertValue = 55, + LLVMLandingPad = 56, /* Atomic operators */ - LLVMFence = 55 + LLVMFence = 57 } LLVMOpcode; typedef enum { @@ -277,6 +279,11 @@ typedef enum { LLVMRealPredicateTrue /**< Always true (always folded) */ } LLVMRealPredicate; +typedef enum { + LLVMCatch, /**< A catch clause */ + LLVMFilter /**< A filter clause */ +} LLVMLandingPadClauseTy; + void LLVMInitializeCore(LLVMPassRegistryRef R); @@ -463,6 +470,7 @@ LLVMTypeRef LLVMX86MMXType(void); macro(GetElementPtrInst) \ macro(InsertElementInst) \ macro(InsertValueInst) \ + macro(LandingPadInst) \ macro(PHINode) \ macro(SelectInst) \ macro(ShuffleVectorInst) \ @@ -474,6 +482,7 @@ LLVMTypeRef LLVMX86MMXType(void); macro(SwitchInst) \ macro(UnreachableInst) \ macro(UnwindInst) \ + macro(ResumeInst) \ macro(UnaryInstruction) \ macro(AllocaInst) \ macro(CastInst) \ @@ -822,6 +831,7 @@ LLVMValueRef LLVMBuildInvoke(LLVMBuilderRef, LLVMValueRef Fn, LLVMBasicBlockRef Then, LLVMBasicBlockRef Catch, const char *Name); LLVMValueRef LLVMBuildUnwind(LLVMBuilderRef); +LLVMValueRef LLVMBuildResume(LLVMBuilderRef B, LLVMValueRef Exn); LLVMValueRef LLVMBuildUnreachable(LLVMBuilderRef); /* Add a case to the switch instruction */ @@ -831,6 +841,13 @@ void LLVMAddCase(LLVMValueRef Switch, LLVMValueRef OnVal, /* Add a destination to the indirectbr instruction */ void LLVMAddDestination(LLVMValueRef IndirectBr, LLVMBasicBlockRef Dest); +/* Add a clause to the landingpad instruction */ +void LLVMAddClause(LLVMValueRef LandingPad, LLVMLandingPadClauseTy ClauseTy, + LLVMValueRef ClauseVal); + +/* Set the 'cleanup' flag in the landingpad instruction */ +void LLVMSetCleanup(LLVMValueRef LandingPad, LLVMBool Val); + /* Arithmetic */ LLVMValueRef LLVMBuildAdd(LLVMBuilderRef, LLVMValueRef LHS, LLVMValueRef RHS, const char *Name); diff --git a/include/llvm/Bitcode/LLVMBitCodes.h b/include/llvm/Bitcode/LLVMBitCodes.h index 503a867ed2..0f74f633ea 100644 --- a/include/llvm/Bitcode/LLVMBitCodes.h +++ b/include/llvm/Bitcode/LLVMBitCodes.h @@ -257,7 +257,7 @@ namespace bitc { FUNC_CODE_INST_UNREACHABLE = 15, // UNREACHABLE FUNC_CODE_INST_PHI = 16, // PHI: [ty, val0,bb0, ...] - // 17 is unused. + FUNC_CODE_INST_RESUME = 17, // RESUME: [opval] // 18 is unused. FUNC_CODE_INST_ALLOCA = 19, // ALLOCA: [instty, op, align] FUNC_CODE_INST_LOAD = 20, // LOAD: [opty, op, align, vol] @@ -284,7 +284,8 @@ namespace bitc { FUNC_CODE_INST_CALL = 34, // CALL: [attr, fnty, fnid, args...] FUNC_CODE_DEBUG_LOC = 35, // DEBUG_LOC: [Line,Col,ScopeVal, IAVal] - FUNC_CODE_INST_FENCE = 36 // FENCE: [ordering, synchscope] + FUNC_CODE_INST_FENCE = 36, // FENCE: [ordering, synchscope] + FUNC_CODE_INST_LANDINGPAD = 37 // LANDINGPAD: [ty,val,val,num,id0,val0...] }; } // End bitc namespace } // End llvm namespace diff --git a/include/llvm/Instruction.def b/include/llvm/Instruction.def index 81e306779e..a68601fbcd 100644 --- a/include/llvm/Instruction.def +++ b/include/llvm/Instruction.def @@ -100,41 +100,42 @@ HANDLE_TERM_INST ( 3, Switch , SwitchInst) HANDLE_TERM_INST ( 4, IndirectBr , IndirectBrInst) HANDLE_TERM_INST ( 5, Invoke , InvokeInst) HANDLE_TERM_INST ( 6, Unwind , UnwindInst) -HANDLE_TERM_INST ( 7, Unreachable, UnreachableInst) - LAST_TERM_INST ( 7) +HANDLE_TERM_INST ( 7, Resume , ResumeInst) +HANDLE_TERM_INST ( 8, Unreachable, UnreachableInst) + LAST_TERM_INST ( 8) // Standard binary operators... - FIRST_BINARY_INST( 8) -HANDLE_BINARY_INST( 8, Add , BinaryOperator) -HANDLE_BINARY_INST( 9, FAdd , BinaryOperator) -HANDLE_BINARY_INST(10, Sub , BinaryOperator) -HANDLE_BINARY_INST(11, FSub , BinaryOperator) -HANDLE_BINARY_INST(12, Mul , BinaryOperator) -HANDLE_BINARY_INST(13, FMul , BinaryOperator) -HANDLE_BINARY_INST(14, UDiv , BinaryOperator) -HANDLE_BINARY_INST(15, SDiv , BinaryOperator) -HANDLE_BINARY_INST(16, FDiv , BinaryOperator) -HANDLE_BINARY_INST(17, URem , BinaryOperator) -HANDLE_BINARY_INST(18, SRem , BinaryOperator) -HANDLE_BINARY_INST(19, FRem , BinaryOperator) + FIRST_BINARY_INST( 9) +HANDLE_BINARY_INST( 9, Add , BinaryOperator) +HANDLE_BINARY_INST(10, FAdd , BinaryOperator) +HANDLE_BINARY_INST(11, Sub , BinaryOperator) +HANDLE_BINARY_INST(12, FSub , BinaryOperator) +HANDLE_BINARY_INST(13, Mul , BinaryOperator) +HANDLE_BINARY_INST(14, FMul , BinaryOperator) +HANDLE_BINARY_INST(15, UDiv , BinaryOperator) +HANDLE_BINARY_INST(16, SDiv , BinaryOperator) +HANDLE_BINARY_INST(17, FDiv , BinaryOperator) +HANDLE_BINARY_INST(18, URem , BinaryOperator) +HANDLE_BINARY_INST(19, SRem , BinaryOperator) +HANDLE_BINARY_INST(20, FRem , BinaryOperator) // Logical operators (integer operands) -HANDLE_BINARY_INST(20, Shl , BinaryOperator) // Shift left (logical) -HANDLE_BINARY_INST(21, LShr , BinaryOperator) // Shift right (logical) -HANDLE_BINARY_INST(22, AShr , BinaryOperator) // Shift right (arithmetic) -HANDLE_BINARY_INST(23, And , BinaryOperator) -HANDLE_BINARY_INST(24, Or , BinaryOperator) -HANDLE_BINARY_INST(25, Xor , BinaryOperator) - LAST_BINARY_INST(25) +HANDLE_BINARY_INST(21, Shl , BinaryOperator) // Shift left (logical) +HANDLE_BINARY_INST(22, LShr , BinaryOperator) // Shift right (logical) +HANDLE_BINARY_INST(23, AShr , BinaryOperator) // Shift right (arithmetic) +HANDLE_BINARY_INST(24, And , BinaryOperator) +HANDLE_BINARY_INST(25, Or , BinaryOperator) +HANDLE_BINARY_INST(26, Xor , BinaryOperator) + LAST_BINARY_INST(26) // Memory operators... - FIRST_MEMORY_INST(26) -HANDLE_MEMORY_INST(26, Alloca, AllocaInst) // Stack management -HANDLE_MEMORY_INST(27, Load , LoadInst ) // Memory manipulation instrs -HANDLE_MEMORY_INST(28, Store , StoreInst ) -HANDLE_MEMORY_INST(29, GetElementPtr, GetElementPtrInst) -HANDLE_MEMORY_INST(30, Fence , FenceInst ) - LAST_MEMORY_INST(30) + FIRST_MEMORY_INST(27) +HANDLE_MEMORY_INST(27, Alloca, AllocaInst) // Stack management +HANDLE_MEMORY_INST(28, Load , LoadInst ) // Memory manipulation instrs +HANDLE_MEMORY_INST(29, Store , StoreInst ) +HANDLE_MEMORY_INST(30, GetElementPtr, GetElementPtrInst) +HANDLE_MEMORY_INST(31, Fence , FenceInst ) + LAST_MEMORY_INST(31) // Cast operators ... // NOTE: The order matters here because CastInst::isEliminableCastPair @@ -169,8 +170,8 @@ HANDLE_OTHER_INST(54, InsertElement, InsertElementInst) // insert into vector HANDLE_OTHER_INST(55, ShuffleVector, ShuffleVectorInst) // shuffle two vectors. HANDLE_OTHER_INST(56, ExtractValue, ExtractValueInst)// extract from aggregate HANDLE_OTHER_INST(57, InsertValue, InsertValueInst) // insert into aggregate - - LAST_OTHER_INST(57) +HANDLE_OTHER_INST(58, LandingPad, LandingPadInst) // Landing pad instruction. + LAST_OTHER_INST(58) #undef FIRST_TERM_INST #undef HANDLE_TERM_INST diff --git a/include/llvm/Instructions.h b/include/llvm/Instructions.h index 89eb901c1d..d337002e0b 100644 --- a/include/llvm/Instructions.h +++ b/include/llvm/Instructions.h @@ -1775,6 +1775,116 @@ struct OperandTraits : public HungoffOperandTraits<2> { DEFINE_TRANSPARENT_OPERAND_ACCESSORS(PHINode, Value) +//===----------------------------------------------------------------------===// +// LandingPadInst Class +//===----------------------------------------------------------------------===// + +//===--------------------------------------------------------------------------- +/// LandingPadInst - The landingpad instruction holds all of the information +/// necessary to generate correct exception handling. The landingpad instruction +/// cannot be moved from the top of a landing pad block, which itself is +/// accessible only from the 'unwind' edge of an invoke. +/// +class LandingPadInst : public Instruction { + /// ReservedSpace - The number of operands actually allocated. NumOperands is + /// the number actually in use. + unsigned ReservedSpace; + + /// IsCleanup - True if the landingpad instruction is also a cleanup. + bool IsCleanup; + LandingPadInst(const LandingPadInst &LP); +public: + enum ClauseType { Catch, Filter }; +private: + /// ClauseIdxs - This indexes into the OperandList, indicating what the + /// values are at a given index. + SmallVector ClauseIdxs; + + void *operator new(size_t, unsigned); // DO NOT IMPLEMENT + // Allocate space for exactly zero operands. + void *operator new(size_t s) { + return User::operator new(s, 0); + } + void growOperands(); + void init(Value *PersFn, unsigned NumReservedValues, const Twine &NameStr); + + explicit LandingPadInst(Type *RetTy, Value *PersonalityFn, + unsigned NumReservedValues, const Twine &NameStr, + Instruction *InsertBefore) + : Instruction(RetTy, Instruction::LandingPad, 0, 0, InsertBefore), + IsCleanup(false) { + init(PersonalityFn, 1 + NumReservedValues, NameStr); + } + explicit LandingPadInst(Type *RetTy, Value *PersonalityFn, + unsigned NumReservedValues, const Twine &NameStr, + BasicBlock *InsertAtEnd) + : Instruction(RetTy, Instruction::LandingPad, 0, 0, InsertAtEnd), + IsCleanup(false) { + init(PersonalityFn, 1 + NumReservedValues, NameStr); + } +protected: + virtual LandingPadInst *clone_impl() const; +public: + static LandingPadInst *Create(Type *RetTy, Value *PersonalityFn, + unsigned NumReservedValues, + const Twine &NameStr = "", + Instruction *InsertBefore = 0) { + return new LandingPadInst(RetTy, PersonalityFn, NumReservedValues, NameStr, + InsertBefore); + } + static LandingPadInst *Create(Type *RetTy, Value *PersonalityFn, + unsigned NumReservedValues, + const Twine &NameStr, BasicBlock *InsertAtEnd) { + return new LandingPadInst(RetTy, PersonalityFn, NumReservedValues, NameStr, + InsertAtEnd); + } + ~LandingPadInst(); + + /// Provide fast operand accessors + DECLARE_TRANSPARENT_OPERAND_ACCESSORS(Value); + + /// getPersonalityFn - Get the personality function associated with this + /// landing pad. + const Value *getPersonalityFn() const { return getOperand(0); } + + // Simple accessors. + bool isCleanup() const { return IsCleanup; } + void setCleanup(bool Val) { IsCleanup = Val; } + + /// addClause - Add a clause to the landing pad. + void addClause(ClauseType CT, Value *ClauseVal); + + /// getClauseType - Return the type of the clause at this index. The two + /// supported clauses are Catch and Filter. + ClauseType getClauseType(unsigned I) const { + assert(I < ClauseIdxs.size() && "Index too large!"); + return ClauseIdxs[I]; + } + + /// getClauseValue - Return the value of the clause at this index. + Value *getClauseValue(unsigned I) const { + assert(I + 1 < getNumOperands() && "Index too large!"); + return OperandList[I + 1]; + } + + /// getNumClauses - Get the number of clauses for this landing pad. + unsigned getNumClauses() const { return getNumOperands() - 1; } + + // Methods for support type inquiry through isa, cast, and dyn_cast: + static inline bool classof(const LandingPadInst *) { return true; } + static inline bool classof(const Instruction *I) { + return I->getOpcode() == Instruction::LandingPad; + } + static inline bool classof(const Value *V) { + return isa(V) && classof(cast(V)); + } +}; + +template <> +struct OperandTraits : public HungoffOperandTraits<2> { +}; + +DEFINE_TRANSPARENT_OPERAND_ACCESSORS(LandingPadInst, Value) //===----------------------------------------------------------------------===// // ReturnInst Class @@ -2462,6 +2572,59 @@ private: virtual void setSuccessorV(unsigned idx, BasicBlock *B); }; +//===----------------------------------------------------------------------===// +// ResumeInst Class +//===----------------------------------------------------------------------===// + +//===--------------------------------------------------------------------------- +/// ResumeInst - Resume the propagation of an exception. +/// +class ResumeInst : public TerminatorInst { + ResumeInst(const ResumeInst &RI); + + explicit ResumeInst(LLVMContext &C, Value *Exn, Instruction *InsertBefore=0); + ResumeInst(LLVMContext &C, Value *Exn, BasicBlock *InsertAtEnd); +protected: + virtual ResumeInst *clone_impl() const; +public: + static ResumeInst *Create(LLVMContext &C, Value *Exn, + Instruction *InsertBefore = 0) { + return new(1) ResumeInst(C, Exn, InsertBefore); + } + static ResumeInst *Create(LLVMContext &C, Value *Exn, + BasicBlock *InsertAtEnd) { + return new(1) ResumeInst(C, Exn, InsertAtEnd); + } + + /// Provide fast operand accessors + DECLARE_TRANSPARENT_OPERAND_ACCESSORS(Value); + + /// Convenience accessor. + Value *getResumeValue() const { return Op<0>(); } + + unsigned getNumSuccessors() const { return 0; } + + // Methods for support type inquiry through isa, cast, and dyn_cast: + static inline bool classof(const ResumeInst *) { return true; } + static inline bool classof(const Instruction *I) { + return I->getOpcode() == Instruction::Resume; + } + static inline bool classof(const Value *V) { + return isa(V) && classof(cast(V)); + } +private: + virtual BasicBlock *getSuccessorV(unsigned idx) const; + virtual unsigned getNumSuccessorsV() const; + virtual void setSuccessorV(unsigned idx, BasicBlock *B); +}; + +template <> +struct OperandTraits : + public FixedNumOperandTraits { +}; + +DEFINE_TRANSPARENT_OPERAND_ACCESSORS(ResumeInst, Value) + //===----------------------------------------------------------------------===// // UnreachableInst Class //===----------------------------------------------------------------------===// diff --git a/include/llvm/Support/IRBuilder.h b/include/llvm/Support/IRBuilder.h index 0a2800eacd..7f89b247c4 100644 --- a/include/llvm/Support/IRBuilder.h +++ b/include/llvm/Support/IRBuilder.h @@ -479,6 +479,10 @@ public: return Insert(new UnwindInst(Context)); } + ResumeInst *CreateResume(Value *Exn) { + return Insert(ResumeInst::Create(Context, Exn)); + } + UnreachableInst *CreateUnreachable() { return Insert(new UnreachableInst(Context)); } @@ -1194,6 +1198,11 @@ public: return Insert(InsertValueInst::Create(Agg, Val, Idxs), Name); } + Value *CreateLandingPad(Type *Ty, Value *PersFn, unsigned NumClauses, + const Twine &Name = "") { + return Insert(LandingPadInst::Create(Ty, PersFn, NumClauses, Name)); + } + //===--------------------------------------------------------------------===// // Utility creation methods //===--------------------------------------------------------------------===// diff --git a/include/llvm/Support/InstVisitor.h b/include/llvm/Support/InstVisitor.h index 83b26f5c22..85e6f62903 100644 --- a/include/llvm/Support/InstVisitor.h +++ b/include/llvm/Support/InstVisitor.h @@ -163,6 +163,7 @@ public: RetTy visitIndirectBrInst(IndirectBrInst &I) { DELEGATE(TerminatorInst);} RetTy visitInvokeInst(InvokeInst &I) { DELEGATE(TerminatorInst);} RetTy visitUnwindInst(UnwindInst &I) { DELEGATE(TerminatorInst);} + RetTy visitResumeInst(ResumeInst &I) { DELEGATE(TerminatorInst);} RetTy visitUnreachableInst(UnreachableInst &I) { DELEGATE(TerminatorInst);} RetTy visitICmpInst(ICmpInst &I) { DELEGATE(CmpInst);} RetTy visitFCmpInst(FCmpInst &I) { DELEGATE(CmpInst);} @@ -192,6 +193,7 @@ public: RetTy visitShuffleVectorInst(ShuffleVectorInst &I) { DELEGATE(Instruction); } RetTy visitExtractValueInst(ExtractValueInst &I) { DELEGATE(Instruction);} RetTy visitInsertValueInst(InsertValueInst &I) { DELEGATE(Instruction); } + RetTy visitLandingPadInst(LandingPadInst &I) { DELEGATE(Instruction); } // Next level propagators: If the user does not overload a specific // instruction type, they can overload one of these to get the whole class diff --git a/lib/AsmParser/LLLexer.cpp b/lib/AsmParser/LLLexer.cpp index cdee98bd0c..970d7aa7ed 100644 --- a/lib/AsmParser/LLLexer.cpp +++ b/lib/AsmParser/LLLexer.cpp @@ -581,6 +581,11 @@ lltok::Kind LLLexer::LexIdentifier() { KEYWORD(x); KEYWORD(blockaddress); + + KEYWORD(personality); + KEYWORD(cleanup); + KEYWORD(catch); + KEYWORD(filter); #undef KEYWORD // Keywords for types. @@ -633,6 +638,7 @@ lltok::Kind LLLexer::LexIdentifier() { INSTKEYWORD(switch, Switch); INSTKEYWORD(indirectbr, IndirectBr); INSTKEYWORD(invoke, Invoke); + INSTKEYWORD(resume, Resume); INSTKEYWORD(unwind, Unwind); INSTKEYWORD(unreachable, Unreachable); @@ -647,6 +653,7 @@ lltok::Kind LLLexer::LexIdentifier() { INSTKEYWORD(shufflevector, ShuffleVector); INSTKEYWORD(extractvalue, ExtractValue); INSTKEYWORD(insertvalue, InsertValue); + INSTKEYWORD(landingpad, LandingPad); #undef INSTKEYWORD // Check for [us]0x[0-9A-Fa-f]+ which are Hexadecimal constant generated by @@ -674,7 +681,6 @@ lltok::Kind LLLexer::LexIdentifier() { return lltok::Error; } - /// Lex0x: Handle productions that start with 0x, knowing that it matches and /// that this is not a label: /// HexFPConstant 0x[0-9A-Fa-f]+ diff --git a/lib/AsmParser/LLParser.cpp b/lib/AsmParser/LLParser.cpp index 76771c29ba..547abfe24e 100644 --- a/lib/AsmParser/LLParser.cpp +++ b/lib/AsmParser/LLParser.cpp @@ -2885,6 +2885,7 @@ int LLParser::ParseInstruction(Instruction *&Inst, BasicBlock *BB, case lltok::kw_switch: return ParseSwitch(Inst, PFS); case lltok::kw_indirectbr: return ParseIndirectBr(Inst, PFS); case lltok::kw_invoke: return ParseInvoke(Inst, PFS); + case lltok::kw_resume: return ParseResume(Inst, PFS); // Binary Operators. case lltok::kw_add: case lltok::kw_sub: @@ -2944,6 +2945,7 @@ int LLParser::ParseInstruction(Instruction *&Inst, BasicBlock *BB, case lltok::kw_insertelement: return ParseInsertElement(Inst, PFS); case lltok::kw_shufflevector: return ParseShuffleVector(Inst, PFS); case lltok::kw_phi: return ParsePHI(Inst, PFS); + case lltok::kw_landingpad: return ParseLandingPad(Inst, PFS); case lltok::kw_call: return ParseCall(Inst, PFS, false); case lltok::kw_tail: return ParseCall(Inst, PFS, true); // Memory. @@ -3247,7 +3249,18 @@ bool LLParser::ParseInvoke(Instruction *&Inst, PerFunctionState &PFS) { return false; } +/// ParseResume +/// ::= 'resume' TypeAndValue +bool LLParser::ParseResume(Instruction *&Inst, PerFunctionState &PFS) { + Value *Exn; LocTy ExnLoc; + LocTy Loc = Lex.getLoc(); + if (ParseTypeAndValue(Exn, ExnLoc, PFS)) + return true; + ResumeInst *RI = ResumeInst::Create(Context, Exn); + Inst = RI; + return false; +} //===----------------------------------------------------------------------===// // Binary Operators. @@ -3495,6 +3508,56 @@ int LLParser::ParsePHI(Instruction *&Inst, PerFunctionState &PFS) { return AteExtraComma ? InstExtraComma : InstNormal; } +/// ParseLandingPad +/// ::= 'landingpad' Type 'personality' TypeAndValue 'cleanup'? +/// (ClauseID ClauseList)+ +/// ClauseID +/// ::= 'catch' +/// ::= 'filter' +/// ClauseList +/// ::= TypeAndValue (',' TypeAndValue)* +bool LLParser::ParseLandingPad(Instruction *&Inst, PerFunctionState &PFS) { + Type *Ty = 0; LocTy TyLoc; + Value *PersFn; LocTy PersFnLoc; + LocTy LPLoc = Lex.getLoc(); + + if (ParseType(Ty, TyLoc) || + ParseToken(lltok::kw_personality, "expected 'personality'") || + ParseTypeAndValue(PersFn, PersFnLoc, PFS)) + return true; + + bool IsCleanup = EatIfPresent(lltok::kw_cleanup); + + SmallVector, 16> Clauses; + while (Lex.getKind() == lltok::kw_catch || Lex.getKind() == lltok::kw_filter){ + LandingPadInst::ClauseType CT; + if (Lex.getKind() == lltok::kw_catch) { + CT = LandingPadInst::Catch; + ParseToken(lltok::kw_catch, "expected 'catch'"); + } else { + CT = LandingPadInst::Filter; + ParseToken(lltok::kw_filter, "expected 'filter'"); + } + + do { + Value *V; LocTy VLoc; + if (ParseTypeAndValue(V, VLoc, PFS)) + return true; + Clauses.push_back(std::make_pair(CT, V)); + } while (EatIfPresent(lltok::comma)); + } + + LandingPadInst *LP = LandingPadInst::Create(Ty, PersFn, Clauses.size()); + LP->setCleanup(IsCleanup); + + for (SmallVectorImpl >::iterator + I = Clauses.begin(), E = Clauses.end(); I != E; ++I) + LP->addClause(I->first, I->second); + + Inst = LP; + return false; +} + /// ParseCall /// ::= 'tail'? 'call' OptionalCallingConv OptionalAttrs Type Value /// ParameterList OptionalAttrs diff --git a/lib/AsmParser/LLParser.h b/lib/AsmParser/LLParser.h index 1eaf3252a8..6d2a929cc4 100644 --- a/lib/AsmParser/LLParser.h +++ b/lib/AsmParser/LLParser.h @@ -347,6 +347,7 @@ namespace llvm { bool ParseSwitch(Instruction *&Inst, PerFunctionState &PFS); bool ParseIndirectBr(Instruction *&Inst, PerFunctionState &PFS); bool ParseInvoke(Instruction *&Inst, PerFunctionState &PFS); + bool ParseResume(Instruction *&Inst, PerFunctionState &PFS); bool ParseArithmetic(Instruction *&I, PerFunctionState &PFS, unsigned Opc, unsigned OperandType); @@ -359,6 +360,7 @@ namespace llvm { bool ParseInsertElement(Instruction *&I, PerFunctionState &PFS); bool ParseShuffleVector(Instruction *&I, PerFunctionState &PFS); int ParsePHI(Instruction *&I, PerFunctionState &PFS); + bool ParseLandingPad(Instruction *&I, PerFunctionState &PFS); bool ParseCall(Instruction *&I, PerFunctionState &PFS, bool isTail); int ParseAlloc(Instruction *&I, PerFunctionState &PFS); int ParseLoad(Instruction *&I, PerFunctionState &PFS, bool isVolatile); diff --git a/lib/AsmParser/LLToken.h b/lib/AsmParser/LLToken.h index bf41c68ffe..f4c834ac23 100644 --- a/lib/AsmParser/LLToken.h +++ b/lib/AsmParser/LLToken.h @@ -121,7 +121,9 @@ namespace lltok { kw_fptoui, kw_fptosi, kw_inttoptr, kw_ptrtoint, kw_bitcast, kw_select, kw_va_arg, - kw_ret, kw_br, kw_switch, kw_indirectbr, kw_invoke, kw_unwind, + kw_landingpad, kw_personality, kw_cleanup, kw_catch, kw_filter, + + kw_ret, kw_br, kw_switch, kw_indirectbr, kw_invoke, kw_unwind, kw_resume, kw_unreachable, kw_alloca, kw_load, kw_store, kw_fence, kw_getelementptr, @@ -143,8 +145,8 @@ namespace lltok { // Type valued tokens (TyVal). Type, - APFloat, // APFloatVal - APSInt // APSInt + APFloat, // APFloatVal + APSInt // APSInt }; } // end namespace lltok } // end namespace llvm diff --git a/lib/Bitcode/Reader/BitcodeReader.cpp b/lib/Bitcode/Reader/BitcodeReader.cpp index 2029f438b4..37cc7949af 100644 --- a/lib/Bitcode/Reader/BitcodeReader.cpp +++ b/lib/Bitcode/Reader/BitcodeReader.cpp @@ -2491,6 +2491,14 @@ bool BitcodeReader::ParseFunctionBody(Function *F) { cast(I)->setAttributes(PAL); break; } + case bitc::FUNC_CODE_INST_RESUME: { // RESUME: [opval] + unsigned Idx = 0; + Value *Val = 0; + if (getValueTypePair(Record, Idx, NextValueNo, Val)) + return Error("Invalid RESUME record"); + I = ResumeInst::Create(Context, Val); + break; + } case bitc::FUNC_CODE_INST_UNWIND: // UNWIND I = new UnwindInst(Context); InstructionList.push_back(I); @@ -2518,6 +2526,37 @@ bool BitcodeReader::ParseFunctionBody(Function *F) { break; } + case bitc::FUNC_CODE_INST_LANDINGPAD: { + // LANDINGPAD: [ty, val, val, num, (id0,val0 ...)?] + unsigned Idx = 0; + if (Record.size() < 4) + return Error("Invalid LANDINGPAD record"); + Type *Ty = getTypeByID(Record[Idx++]); + if (!Ty) return Error("Invalid LANDINGPAD record"); + Value *PersFn = 0; + if (getValueTypePair(Record, Idx, NextValueNo, PersFn)) + return Error("Invalid LANDINGPAD record"); + + bool IsCleanup = !!Record[Idx++]; + unsigned NumClauses = Record[Idx++]; + LandingPadInst *LP = LandingPadInst::Create(Ty, PersFn, NumClauses); + LP->setCleanup(IsCleanup); + for (unsigned J = 0; J != NumClauses; ++J) { + LandingPadInst::ClauseType CT = + LandingPadInst::ClauseType(Record[Idx++]); + Value *Val = 0; + if (getValueTypePair(Record, Idx, NextValueNo, Val)) { + delete LP; + return Error("Invalid LANDINGPAD record"); + } + + LP->addClause(CT, Val); + } + + I = LP; + break; + } + case bitc::FUNC_CODE_INST_ALLOCA: { // ALLOCA: [instty, opty, op, align] if (Record.size() != 4) return Error("Invalid ALLOCA record"); diff --git a/lib/Bitcode/Writer/BitcodeWriter.cpp b/lib/Bitcode/Writer/BitcodeWriter.cpp index 9df3c17bf4..87154fc9c6 100644 --- a/lib/Bitcode/Writer/BitcodeWriter.cpp +++ b/lib/Bitcode/Writer/BitcodeWriter.cpp @@ -1126,6 +1126,10 @@ static void WriteInstruction(const Instruction &I, unsigned InstID, } break; } + case Instruction::Resume: + Code = bitc::FUNC_CODE_INST_RESUME; + PushValueAndType(I.getOperand(0), InstID, Vals, VE); + break; case Instruction::Unwind: Code = bitc::FUNC_CODE_INST_UNWIND; break; @@ -1145,6 +1149,20 @@ static void WriteInstruction(const Instruction &I, unsigned InstID, break; } + case Instruction::LandingPad: { + const LandingPadInst &LP = cast(I); + Code = bitc::FUNC_CODE_INST_LANDINGPAD; + Vals.push_back(VE.getTypeID(LP.getType())); + PushValueAndType(LP.getPersonalityFn(), InstID, Vals, VE); + Vals.push_back(LP.isCleanup()); + Vals.push_back(LP.getNumClauses()); + for (unsigned I = 0, E = LP.getNumClauses(); I != E; ++I) { + Vals.push_back(LP.getClauseType(I)); + PushValueAndType(LP.getClauseValue(I), InstID, Vals, VE); + } + break; + } + case Instruction::Alloca: Code = bitc::FUNC_CODE_INST_ALLOCA; Vals.push_back(VE.getTypeID(I.getType())); diff --git a/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp b/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp index a101df0d15..bdddca3514 100644 --- a/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp +++ b/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp @@ -914,6 +914,10 @@ void SelectionDAGBuilder::visitPHI(const PHINode &) { llvm_unreachable("SelectionDAGBuilder shouldn't visit PHI nodes!"); } +void SelectionDAGBuilder::visitLandingPad(const LandingPadInst &) { + // FIXME: Handle this +} + void SelectionDAGBuilder::visit(unsigned Opcode, const User &I) { // Note: this doesn't use InstVisitor, because it has to work with // ConstantExpr's in addition to instructions. @@ -1808,6 +1812,10 @@ void SelectionDAGBuilder::visitInvoke(const InvokeInst &I) { void SelectionDAGBuilder::visitUnwind(const UnwindInst &I) { } +void SelectionDAGBuilder::visitResume(const ResumeInst &RI) { + // FIXME: Handle this +} + /// handleSmallSwitchCaseRange - Emit a series of specific tests (suitable for /// small case ranges). bool SelectionDAGBuilder::handleSmallSwitchRange(CaseRec& CR, diff --git a/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.h b/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.h index d5d106b427..11c4a48384 100644 --- a/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.h +++ b/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.h @@ -453,6 +453,7 @@ public: private: // These all get lowered before this pass. void visitInvoke(const InvokeInst &I); + void visitResume(const ResumeInst &I); void visitUnwind(const UnwindInst &I); void visitBinary(const User &I, unsigned OpCode); @@ -497,6 +498,7 @@ private: void visitExtractValue(const ExtractValueInst &I); void visitInsertValue(const InsertValueInst &I); + void visitLandingPad(const LandingPadInst &I); void visitGetElementPtr(const User &I); void visitSelect(const User &I); diff --git a/lib/CodeGen/ShadowStackGC.cpp b/lib/CodeGen/ShadowStackGC.cpp index 9807c8cb27..daab89b8f2 100644 --- a/lib/CodeGen/ShadowStackGC.cpp +++ b/lib/CodeGen/ShadowStackGC.cpp @@ -113,9 +113,11 @@ namespace { while (StateBB != StateE) { BasicBlock *CurBB = StateBB++; - // Branches and invokes do not escape, only unwind and return do. + // Branches and invokes do not escape, only unwind, resume, and return + // do. TerminatorInst *TI = CurBB->getTerminator(); - if (!isa(TI) && !isa(TI)) + if (!isa(TI) && !isa(TI) && + !isa(TI)) continue; Builder.SetInsertPoint(TI->getParent(), TI); diff --git a/lib/Target/CBackend/CBackend.cpp b/lib/Target/CBackend/CBackend.cpp index 18a27d2dc3..eb25537548 100644 --- a/lib/Target/CBackend/CBackend.cpp +++ b/lib/Target/CBackend/CBackend.cpp @@ -288,10 +288,12 @@ namespace { void visitInvokeInst(InvokeInst &I) { llvm_unreachable("Lowerinvoke pass didn't work!"); } - void visitUnwindInst(UnwindInst &I) { llvm_unreachable("Lowerinvoke pass didn't work!"); } + void visitResumeInst(ResumeInst &I) { + llvm_unreachable("Lowerinvoke pass didn't work!"); + } void visitUnreachableInst(UnreachableInst &I); void visitPHINode(PHINode &I); diff --git a/lib/Target/CppBackend/CPPBackend.cpp b/lib/Target/CppBackend/CPPBackend.cpp index 7f5f5e189e..09f7ed51a3 100644 --- a/lib/Target/CppBackend/CPPBackend.cpp +++ b/lib/Target/CppBackend/CPPBackend.cpp @@ -1064,6 +1064,11 @@ void CppWriter::printInstruction(const Instruction *I, } break; } + case Instruction::Resume: { + Out << "ResumeInst::Create(mod->getContext(), " << opNames[0] + << ", " << bbname << ");"; + break; + } case Instruction::Invoke: { const InvokeInst* inv = cast(I); Out << "std::vector " << iName << "_params;"; @@ -1423,6 +1428,9 @@ void CppWriter::printInstruction(const Instruction *I, Out << "\", " << bbname << ");"; break; } + case Instruction::LandingPad: { + break; + } } DefinedValues.insert(I); nl(Out); diff --git a/lib/Transforms/IPO/GlobalOpt.cpp b/lib/Transforms/IPO/GlobalOpt.cpp index 0283568f2c..771a50b49d 100644 --- a/lib/Transforms/IPO/GlobalOpt.cpp +++ b/lib/Transforms/IPO/GlobalOpt.cpp @@ -2506,7 +2506,7 @@ static bool EvaluateFunction(Function *F, Constant *&RetVal, CallStack.pop_back(); // return from fn. return true; // We succeeded at evaluating this ctor! } else { - // invoke, unwind, unreachable. + // invoke, unwind, resume, unreachable. return false; // Cannot handle this terminator. } diff --git a/lib/Transforms/InstCombine/InstCombineCalls.cpp b/lib/Transforms/InstCombine/InstCombineCalls.cpp index c33dec1740..09edc41997 100644 --- a/lib/Transforms/InstCombine/InstCombineCalls.cpp +++ b/lib/Transforms/InstCombine/InstCombineCalls.cpp @@ -732,9 +732,11 @@ Instruction *InstCombiner::visitCallInst(CallInst &CI) { } } - // If the stack restore is in a return/unwind block and if there are no - // allocas or calls between the restore and the return, nuke the restore. - if (!CannotRemove && (isa(TI) || isa(TI))) + // If the stack restore is in a return, resume, or unwind block and if there + // are no allocas or calls between the restore and the return, nuke the + // restore. + if (!CannotRemove && (isa(TI) || isa(TI) || + isa(TI))) return EraseInstFromFunction(CI); break; } diff --git a/lib/Transforms/Scalar/SCCP.cpp b/lib/Transforms/Scalar/SCCP.cpp index 749ba40a64..ba6e51fbf5 100644 --- a/lib/Transforms/Scalar/SCCP.cpp +++ b/lib/Transforms/Scalar/SCCP.cpp @@ -515,6 +515,7 @@ private: void visitShuffleVectorInst(ShuffleVectorInst &I); void visitExtractValueInst(ExtractValueInst &EVI); void visitInsertValueInst(InsertValueInst &IVI); + void visitLandingPadInst(LandingPadInst &I) { markAnythingOverdefined(&I); } // Instructions that cannot be folded away. void visitStoreInst (StoreInst &I); @@ -528,6 +529,7 @@ private: visitTerminatorInst(II); } void visitCallSite (CallSite CS); + void visitResumeInst (TerminatorInst &I) { /*returns void*/ } void visitUnwindInst (TerminatorInst &I) { /*returns void*/ } void visitUnreachableInst(TerminatorInst &I) { /*returns void*/ } void visitFenceInst (FenceInst &I) { /*returns void*/ } diff --git a/lib/VMCore/AsmWriter.cpp b/lib/VMCore/AsmWriter.cpp index 1f8e89173c..e6cd418c32 100644 --- a/lib/VMCore/AsmWriter.cpp +++ b/lib/VMCore/AsmWriter.cpp @@ -1710,6 +1710,9 @@ void AssemblyWriter::printInstruction(const Instruction &I) { writeOperand(I.getOperand(i), true); } Out << ']'; + } else if (isa(I)) { + Out << ' '; + writeOperand(Operand, true); } else if (const PHINode *PN = dyn_cast(&I)) { Out << ' '; TypePrinter.print(I.getType(), Out); @@ -1732,6 +1735,33 @@ void AssemblyWriter::printInstruction(const Instruction &I) { writeOperand(I.getOperand(1), true); for (const unsigned *i = IVI->idx_begin(), *e = IVI->idx_end(); i != e; ++i) Out << ", " << *i; + } else if (const LandingPadInst *LPI = dyn_cast(&I)) { + Out << ' '; + TypePrinter.print(I.getType(), Out); + Out << " personality "; + writeOperand(LPI->getPersonalityFn(), true); Out << '\n'; + + if (LPI->isCleanup()) + Out << " cleanup"; + + for (unsigned i = 0, e = LPI->getNumClauses(); i != e; ) { + if (i != 0 || LPI->isCleanup()) Out << "\n"; + + SmallVector Vals; + LandingPadInst::ClauseType CT = LPI->getClauseType(i); + for (; i != e && LPI->getClauseType(i) == CT; ++i) + Vals.push_back(LPI->getClauseValue(i)); + + if (CT == LandingPadInst::Catch) + Out << " catch "; + else + Out << " filter "; + + for (unsigned II = 0, IE = Vals.size(); II != IE; ++II) { + if (II != 0) Out << ", "; + writeOperand(Vals[II], true); + } + } } else if (isa(I) && !Operand) { Out << " void"; } else if (const CallInst *CI = dyn_cast(&I)) { diff --git a/lib/VMCore/Core.cpp b/lib/VMCore/Core.cpp index 3c93736ce1..6664afc188 100644 --- a/lib/VMCore/Core.cpp +++ b/lib/VMCore/Core.cpp @@ -1683,10 +1683,21 @@ LLVMValueRef LLVMBuildInvoke(LLVMBuilderRef B, LLVMValueRef Fn, Name)); } +LLVMValueRef LLVMBuildLandingPad(LLVMBuilderRef B, LLVMTypeRef Ty, + LLVMValueRef PersFn, unsigned NumClauses, + const char *Name) { + return wrap(unwrap(B)->CreateLandingPad(unwrap(Ty), unwrap(PersFn), + NumClauses, Name)); +} + LLVMValueRef LLVMBuildUnwind(LLVMBuilderRef B) { return wrap(unwrap(B)->CreateUnwind()); } +LLVMValueRef LLVMBuildResume(LLVMBuilderRef B, LLVMValueRef Exn) { + return wrap(unwrap(B)->CreateResume(unwrap(Exn))); +} + LLVMValueRef LLVMBuildUnreachable(LLVMBuilderRef B) { return wrap(unwrap(B)->CreateUnreachable()); } @@ -1700,6 +1711,17 @@ void LLVMAddDestination(LLVMValueRef IndirectBr, LLVMBasicBlockRef Dest) { unwrap(IndirectBr)->addDestination(unwrap(Dest)); } +void LLVMAddClause(LLVMValueRef LandingPad, LLVMLandingPadClauseTy ClauseTy, + LLVMValueRef ClauseVal) { + unwrap(LandingPad)-> + addClause(static_cast(ClauseTy), + unwrap(ClauseVal)); +} + +void LLVMSetCleanup(LLVMValueRef LandingPad, LLVMBool Val) { + unwrap(LandingPad)->setCleanup(Val); +} + /*--.. Arithmetic ..........................................................--*/ LLVMValueRef LLVMBuildAdd(LLVMBuilderRef B, LLVMValueRef LHS, LLVMValueRef RHS, diff --git a/lib/VMCore/Instruction.cpp b/lib/VMCore/Instruction.cpp index cd8f737e28..09d16e7d44 100644 --- a/lib/VMCore/Instruction.cpp +++ b/lib/VMCore/Instruction.cpp @@ -101,6 +101,7 @@ const char *Instruction::getOpcodeName(unsigned OpCode) { case Switch: return "switch"; case IndirectBr: return "indirectbr"; case Invoke: return "invoke"; + case Resume: return "resume"; case Unwind: return "unwind"; case Unreachable: return "unreachable"; @@ -159,6 +160,7 @@ const char *Instruction::getOpcodeName(unsigned OpCode) { case ShuffleVector: return "shufflevector"; case ExtractValue: return "extractvalue"; case InsertValue: return "insertvalue"; + case LandingPad: return "landingpad"; default: return " "; } diff --git a/lib/VMCore/Instructions.cpp b/lib/VMCore/Instructions.cpp index ba4dae5c29..e7dd40d059 100644 --- a/lib/VMCore/Instructions.cpp +++ b/lib/VMCore/Instructions.cpp @@ -166,6 +166,63 @@ Value *PHINode::hasConstantValue() const { return ConstantValue; } +//===----------------------------------------------------------------------===// +// LandingPadInst Implementation +//===----------------------------------------------------------------------===// + +void LandingPadInst::init(Value *PersFn, unsigned NumReservedValues, + const Twine &NameStr) { + ReservedSpace = NumReservedValues; + NumOperands = 1; + OperandList = allocHungoffUses(ReservedSpace); + OperandList[0] = PersFn; + setName(NameStr); +} + +LandingPadInst::LandingPadInst(const LandingPadInst &LP) + : Instruction(LP.getType(), Instruction::LandingPad, + allocHungoffUses(LP.getNumOperands()), LP.getNumOperands()), + ReservedSpace(LP.getNumOperands()) { + Use *OL = OperandList, *InOL = LP.OperandList; + for (unsigned I = 0, E = ReservedSpace; I != E; ++I) + OL[I] = InOL[I]; + + for (SmallVectorImpl::const_iterator + I = LP.ClauseIdxs.begin(), E = LP.ClauseIdxs.end(); I != E; ++I) + ClauseIdxs.push_back(*I); + + IsCleanup = LP.IsCleanup; + SubclassOptionalData = LP.SubclassOptionalData; +} + +LandingPadInst::~LandingPadInst() { + dropHungoffUses(); +} + +/// growOperands - grow operands - This grows the operand list in response to a +/// push_back style of operation. This grows the number of ops by 2 times. +void LandingPadInst::growOperands() { + unsigned e = getNumOperands(); + ReservedSpace = e * 2; + + Use *NewOps = allocHungoffUses(ReservedSpace); + Use *OldOps = OperandList; + for (unsigned i = 0; i != e; ++i) + NewOps[i] = OldOps[i]; + + OperandList = NewOps; + Use::zap(OldOps, OldOps + e, true); +} + +void LandingPadInst::addClause(ClauseType CT, Value *ClauseVal) { + unsigned OpNo = getNumOperands(); + if (OpNo + 1 > ReservedSpace) + growOperands(); + assert(OpNo < ReservedSpace && "Growing didn't work!"); + ClauseIdxs.push_back(CT); + ++NumOperands; + OperandList[OpNo] = ClauseVal; +} //===----------------------------------------------------------------------===// // CallInst Implementation @@ -573,6 +630,42 @@ BasicBlock *UnwindInst::getSuccessorV(unsigned idx) const { return 0; } +//===----------------------------------------------------------------------===// +// ResumeInst Implementation +//===----------------------------------------------------------------------===// + +ResumeInst::ResumeInst(const ResumeInst &RI) + : TerminatorInst(Type::getVoidTy(RI.getContext()), Instruction::Resume, + OperandTraits::op_begin(this), 1) { + Op<0>() = RI.Op<0>(); + SubclassOptionalData = RI.SubclassOptionalData; +} + +ResumeInst::ResumeInst(LLVMContext &C, Value *Exn, Instruction *InsertBefore) + : TerminatorInst(Type::getVoidTy(C), Instruction::Resume, + OperandTraits::op_begin(this), 1, InsertBefore) { + Op<0>() = Exn; +} + +ResumeInst::ResumeInst(LLVMContext &C, Value *Exn, BasicBlock *InsertAtEnd) + : TerminatorInst(Type::getVoidTy(C), Instruction::Resume, + OperandTraits::op_begin(this), 1, InsertAtEnd) { + Op<0>() = Exn; +} + +unsigned ResumeInst::getNumSuccessorsV() const { + return getNumSuccessors(); +} + +void ResumeInst::setSuccessorV(unsigned idx, BasicBlock *NewSucc) { + llvm_unreachable("ResumeInst has no successors!"); +} + +BasicBlock *ResumeInst::getSuccessorV(unsigned idx) const { + llvm_unreachable("ResumeInst has no successors!"); + return 0; +} + //===----------------------------------------------------------------------===// // UnreachableInst Implementation //===----------------------------------------------------------------------===// @@ -592,11 +685,11 @@ unsigned UnreachableInst::getNumSuccessorsV() const { } void UnreachableInst::setSuccessorV(unsigned idx, BasicBlock *NewSucc) { - llvm_unreachable("UnwindInst has no successors!"); + llvm_unreachable("UnreachableInst has no successors!"); } BasicBlock *UnreachableInst::getSuccessorV(unsigned idx) const { - llvm_unreachable("UnwindInst has no successors!"); + llvm_unreachable("UnreachableInst has no successors!"); return 0; } @@ -3122,6 +3215,10 @@ PHINode *PHINode::clone_impl() const { return new PHINode(*this); } +LandingPadInst *LandingPadInst::clone_impl() const { + return new LandingPadInst(*this); +} + ReturnInst *ReturnInst::clone_impl() const { return new(getNumOperands()) ReturnInst(*this); } @@ -3143,6 +3240,10 @@ InvokeInst *InvokeInst::clone_impl() const { return new(getNumOperands()) InvokeInst(*this); } +ResumeInst *ResumeInst::clone_impl() const { + return new(1) ResumeInst(*this); +} + UnwindInst *UnwindInst::clone_impl() const { LLVMContext &Context = getContext(); return new UnwindInst(Context); diff --git a/lib/VMCore/Verifier.cpp b/lib/VMCore/Verifier.cpp index 2b2b815946..9ec2edf3fc 100644 --- a/lib/VMCore/Verifier.cpp +++ b/lib/VMCore/Verifier.cpp @@ -35,6 +35,12 @@ // * It is illegal to have a ret instruction that returns a value that does not // agree with the function return value type. // * Function call argument types match the function prototype +// * A landing pad is defined by a landingpad instruction, and can be jumped to +// only by the unwind edge of an invoke instruction. +// * A landingpad instruction must be the first non-PHI instruction in the +// block. +// * All landingpad instructions must use the same personality function with +// the same function. // * All other things that are tested by asserts spread about the code... // //===----------------------------------------------------------------------===// @@ -131,18 +137,22 @@ namespace { /// already. SmallPtrSet MDNodes; + /// PersonalityFn - The personality function referenced by the + /// LandingPadInsts. All LandingPadInsts within the same function must use + /// the same personality function. + const Value *PersonalityFn; + Verifier() - : FunctionPass(ID), - Broken(false), RealPass(true), action(AbortProcessAction), - Mod(0), Context(0), DT(0), MessagesStr(Messages) { - initializeVerifierPass(*PassRegistry::getPassRegistry()); - } + : FunctionPass(ID), Broken(false), RealPass(true), + action(AbortProcessAction), Mod(0), Context(0), DT(0), + MessagesStr(Messages), PersonalityFn(0) { + initializeVerifierPass(*PassRegistry::getPassRegistry()); + } explicit Verifier(VerifierFailureAction ctn) - : FunctionPass(ID), - Broken(false), RealPass(true), action(ctn), Mod(0), Context(0), DT(0), - MessagesStr(Messages) { - initializeVerifierPass(*PassRegistry::getPassRegistry()); - } + : FunctionPass(ID), Broken(false), RealPass(true), action(ctn), Mod(0), + Context(0), DT(0), MessagesStr(Messages), PersonalityFn(0) { + initializeVerifierPass(*PassRegistry::getPassRegistry()); + } bool doInitialization(Module &M) { Mod = &M; @@ -282,6 +292,7 @@ namespace { void visitAllocaInst(AllocaInst &AI); void visitExtractValueInst(ExtractValueInst &EVI); void visitInsertValueInst(InsertValueInst &IVI); + void visitLandingPadInst(LandingPadInst &LPI); void VerifyCallSite(CallSite CS); bool PerformTypeCheck(Intrinsic::ID ID, Function *F, Type *Ty, @@ -1321,7 +1332,7 @@ void Verifier::visitFenceInst(FenceInst &FI) { Assert1(Ordering == Acquire || Ordering == Release || Ordering == AcquireRelease || Ordering == SequentiallyConsistent, "fence instructions may only have " - " acquire, release, acq_rel, or seq_cst ordering.", &FI); + "acquire, release, acq_rel, or seq_cst ordering.", &FI); visitInstruction(FI); } @@ -1343,6 +1354,42 @@ void Verifier::visitInsertValueInst(InsertValueInst &IVI) { visitInstruction(IVI); } +void Verifier::visitLandingPadInst(LandingPadInst &LPI) { + BasicBlock *BB = LPI.getParent(); + + // The landingpad instruction is ill-formed if it doesn't have any clauses and + // isn't a cleanup. + Assert1(LPI.getNumClauses() > 0 || LPI.isCleanup(), + "LandingPadInst needs at least one clause or to be a cleanup.", &LPI); + + // The landingpad instruction defines its parent as a landing pad block. The + // landing pad block may be branched to only by the unwind edge of an invoke. + for (pred_iterator I = pred_begin(BB), E = pred_end(BB); I != E; ++I) { + const InvokeInst *II = dyn_cast((*I)->getTerminator()); + Assert1(II && II->getUnwindDest() == BB, + "Block containing LandingPadInst must be jumped to " + "only by the unwind edge of an invoke.", &LPI); + } + + // The landingpad instruction must be the first non-PHI instruction in the + // block. + BasicBlock::iterator I = BB->begin(), E = BB->end(); + while (I != E && isa(I)) + ++I; + Assert1(I != E && isa(I) && I == LPI, + "LandingPadInst not the first non-PHI instruction in the block.", + &LPI); + + // The personality functions for all landingpad instructions within the same + // function should match. + if (PersonalityFn) + Assert1(LPI.getPersonalityFn() == PersonalityFn, + "Personality function doesn't match others in function", &LPI); + PersonalityFn = LPI.getPersonalityFn(); + + visitInstruction(LPI); +} + /// verifyInstruction - Verify that an instruction is well formed. /// void Verifier::visitInstruction(Instruction &I) { diff --git a/test/Feature/exceptionhandling.ll b/test/Feature/exceptionhandling.ll new file mode 100644 index 0000000000..aa30f30743 --- /dev/null +++ b/test/Feature/exceptionhandling.ll @@ -0,0 +1,54 @@ +; RUN: llvm-as < %s | llvm-dis > %t1.ll +; RUN: llvm-as %t1.ll -o - | llvm-dis > %t2.ll +; RUN: diff %t1.ll %t2.ll + +@_ZTIc = external constant i8* +@_ZTId = external constant i8* +@_ZTIPKc = external constant i8* +@.str = private unnamed_addr constant [16 x i8] c"caught char %c\0A\00", align 1 + +define void @_Z3barv() uwtable optsize alwaysinline ssp { +entry: + invoke void @_Z3quxv() optsize + to label %try.cont unwind label %lpad + +invoke.cont4: ; preds = %lpad + %eh.obj = extractvalue {i8*, i32} %exn, 0 + %tmp0 = tail call i8* @__cxa_begin_catch(i8* %eh.obj) nounwind + %exn.scalar = load i8* %tmp0, align 1 + %conv = sext i8 %exn.scalar to i32 + %call = tail call i32 (i8*, ...)* @printf(i8* getelementptr inbounds ([16 x i8]* @.str, i64 0, i64 0), i32 %conv) optsize + tail call void @__cxa_end_catch() nounwind + br label %try.cont + +try.cont: ; preds = %entry, %invoke.cont4 + ret void + +lpad: ; preds = %entry + %exn = landingpad {i8*, i32} personality i32 (...)* @__gxx_personality_v0 + cleanup + catch i8** @_ZTIc + filter i8** @_ZTIPKc + catch i8** @_ZTId + %tmp1 = extractvalue {i8*, i32} %exn, 1 + %tmp2 = tail call i32 @llvm.eh.typeid.for(i8* bitcast (i8** @_ZTIc to i8*)) nounwind + %tmp3 = icmp eq i32 %tmp1, %tmp2 + br i1 %tmp3, label %invoke.cont4, label %eh.resume + +eh.resume: + resume { i8*, i32 } %exn +} + +declare void @_Z3quxv() optsize + +declare i32 @__gxx_personality_v0(...) + +declare i32 @llvm.eh.typeid.for(i8*) nounwind + +declare void @llvm.eh.resume(i8*, i32) + +declare i8* @__cxa_begin_catch(i8*) + +declare i32 @printf(i8* nocapture, ...) nounwind optsize + +declare void @__cxa_end_catch() -- cgit v1.2.3