summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBill Wendling <isanbard@gmail.com>2011-07-27 20:18:04 +0000
committerBill Wendling <isanbard@gmail.com>2011-07-27 20:18:04 +0000
commit772fe17a6d07304ae2e6b3052bbb24ebb751f0f3 (patch)
tree650bbc3bc584177420dee94b9fdb338ca8109bb9
parent7e1547ebf726a40e7ed3dbe89a77e1b946a8e2d0 (diff)
downloadllvm-772fe17a6d07304ae2e6b3052bbb24ebb751f0f3.tar.gz
llvm-772fe17a6d07304ae2e6b3052bbb24ebb751f0f3.tar.bz2
llvm-772fe17a6d07304ae2e6b3052bbb24ebb751f0f3.tar.xz
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
-rw-r--r--docs/LangRef.html35
-rw-r--r--include/llvm-c/Core.h111
-rw-r--r--include/llvm/Bitcode/LLVMBitCodes.h5
-rw-r--r--include/llvm/Instruction.def63
-rw-r--r--include/llvm/Instructions.h163
-rw-r--r--include/llvm/Support/IRBuilder.h9
-rw-r--r--include/llvm/Support/InstVisitor.h2
-rw-r--r--lib/AsmParser/LLLexer.cpp8
-rw-r--r--lib/AsmParser/LLParser.cpp63
-rw-r--r--lib/AsmParser/LLParser.h2
-rw-r--r--lib/AsmParser/LLToken.h8
-rw-r--r--lib/Bitcode/Reader/BitcodeReader.cpp39
-rw-r--r--lib/Bitcode/Writer/BitcodeWriter.cpp18
-rw-r--r--lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp8
-rw-r--r--lib/CodeGen/SelectionDAG/SelectionDAGBuilder.h2
-rw-r--r--lib/CodeGen/ShadowStackGC.cpp6
-rw-r--r--lib/Target/CBackend/CBackend.cpp4
-rw-r--r--lib/Target/CppBackend/CPPBackend.cpp8
-rw-r--r--lib/Transforms/IPO/GlobalOpt.cpp2
-rw-r--r--lib/Transforms/InstCombine/InstCombineCalls.cpp8
-rw-r--r--lib/Transforms/Scalar/SCCP.cpp2
-rw-r--r--lib/VMCore/AsmWriter.cpp30
-rw-r--r--lib/VMCore/Core.cpp22
-rw-r--r--lib/VMCore/Instruction.cpp2
-rw-r--r--lib/VMCore/Instructions.cpp105
-rw-r--r--lib/VMCore/Verifier.cpp69
-rw-r--r--test/Feature/exceptionhandling.ll54
27 files changed, 742 insertions, 106 deletions
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 @@
<li><a href="#i_indirectbr">'<tt>indirectbr</tt>' Instruction</a></li>
<li><a href="#i_invoke">'<tt>invoke</tt>' Instruction</a></li>
<li><a href="#i_unwind">'<tt>unwind</tt>' Instruction</a></li>
+ <li><a href="#i_resume">'<tt>resume</tt>' Instruction</a></li>
<li><a href="#i_unreachable">'<tt>unreachable</tt>' Instruction</a></li>
</ol>
</li>
@@ -2942,13 +2943,14 @@ should not be exposed to source languages.</p>
control flow, not values (the one exception being the
'<a href="#i_invoke"><tt>invoke</tt></a>' instruction).</p>
-<p>There are seven different terminator instructions: the
+<p>There are eight different terminator instructions: the
'<a href="#i_ret"><tt>ret</tt></a>' instruction, the
'<a href="#i_br"><tt>br</tt></a>' instruction, the
'<a href="#i_switch"><tt>switch</tt></a>' instruction, the
'<a href="#i_indirectbr">'<tt>indirectbr</tt></a>' Instruction, the
'<a href="#i_invoke"><tt>invoke</tt></a>' instruction, the
- '<a href="#i_unwind"><tt>unwind</tt></a>' instruction, and the
+ '<a href="#i_unwind"><tt>unwind</tt></a>' instruction, the
+ '<a href="#i_resume"><tt>resume</tt></a>' instruction, and the
'<a href="#i_unreachable"><tt>unreachable</tt></a>' instruction.</p>
<!-- _______________________________________________________________________ -->
@@ -3272,6 +3274,35 @@ that the invoke/unwind semantics are likely to change in future versions.</p>
<!-- _______________________________________________________________________ -->
<h4>
+ <a name="i_resume">'<tt>resume</tt>' Instruction</a>
+</h4>
+
+<div>
+
+<h5>Syntax:</h5>
+<pre>
+ resume &lt;type&gt; &lt;value&gt;
+</pre>
+
+<h5>Overview:</h5>
+<p>The '<tt>resume</tt>' instruction is a terminator instruction that has no
+ successors. Its operand must have the same type as the result of any
+ '<tt>landingpad</tt>' instruction in the same function.</p>
+
+<h5>Semantics:</h5>
+<p>The '<tt>resume</tt>' instruction resumes propagation of an existing
+ (in-flight) exception.</p>
+
+<h5>Example:</h5>
+<pre>
+ resume { i8*, i32 } %exn
+</pre>
+
+</div>
+
+<!-- _______________________________________________________________________ -->
+
+<h4>
<a name="i_unreachable">'<tt>unreachable</tt>' Instruction</a>
</h4>
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<PHINode> : 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<ClauseType, 8> 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<Instruction>(V) && classof(cast<Instruction>(V));
+ }
+};
+
+template <>
+struct OperandTraits<LandingPadInst> : public HungoffOperandTraits<2> {
+};
+
+DEFINE_TRANSPARENT_OPERAND_ACCESSORS(LandingPadInst, Value)
//===----------------------------------------------------------------------===//
// ReturnInst Class
@@ -2463,6 +2573,59 @@ private:
};
//===----------------------------------------------------------------------===//
+// 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<Instruction>(V) && classof(cast<Instruction>(V));
+ }
+private:
+ virtual BasicBlock *getSuccessorV(unsigned idx) const;
+ virtual unsigned getNumSuccessorsV() const;
+ virtual void setSuccessorV(unsigned idx, BasicBlock *B);
+};
+
+template <>
+struct OperandTraits<ResumeInst> :
+ public FixedNumOperandTraits<ResumeInst, 1> {
+};
+
+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<std::pair<LandingPadInst::ClauseType, Value*>, 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<std::pair<LandingPadInst::ClauseType, Value*> >::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<InvokeInst>(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<LandingPadInst>(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<UnwindInst>(TI) && !isa<ReturnInst>(TI))
+ if (!isa<UnwindInst>(TI) && !isa<ReturnInst>(TI) &&
+ !isa<ResumeInst>(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<InvokeInst>(I);
Out << "std::vector<Value*> " << 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<ReturnInst>(TI) || isa<UnwindInst>(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<ReturnInst>(TI) || isa<ResumeInst>(TI) ||
+ isa<UnwindInst>(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<ResumeInst>(I)) {
+ Out << ' ';
+ writeOperand(Operand, true);
} else if (const PHINode *PN = dyn_cast<PHINode>(&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<LandingPadInst>(&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<const Value*, 8> 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<ReturnInst>(I) && !Operand) {
Out << " void";
} else if (const CallInst *CI = dyn_cast<CallInst>(&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<IndirectBrInst>(IndirectBr)->addDestination(unwrap(Dest));
}
+void LLVMAddClause(LLVMValueRef LandingPad, LLVMLandingPadClauseTy ClauseTy,
+ LLVMValueRef ClauseVal) {
+ unwrap<LandingPadInst>(LandingPad)->
+ addClause(static_cast<LandingPadInst::ClauseType>(ClauseTy),
+ unwrap(ClauseVal));
+}
+
+void LLVMSetCleanup(LLVMValueRef LandingPad, LLVMBool Val) {
+ unwrap<LandingPadInst>(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 "<Invalid operator> ";
}
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<ClauseType>::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
@@ -574,6 +631,42 @@ BasicBlock *UnwindInst::getSuccessorV(unsigned idx) const {
}
//===----------------------------------------------------------------------===//
+// ResumeInst Implementation
+//===----------------------------------------------------------------------===//
+
+ResumeInst::ResumeInst(const ResumeInst &RI)
+ : TerminatorInst(Type::getVoidTy(RI.getContext()), Instruction::Resume,
+ OperandTraits<ResumeInst>::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<ResumeInst>::op_begin(this), 1, InsertBefore) {
+ Op<0>() = Exn;
+}
+
+ResumeInst::ResumeInst(LLVMContext &C, Value *Exn, BasicBlock *InsertAtEnd)
+ : TerminatorInst(Type::getVoidTy(C), Instruction::Resume,
+ OperandTraits<ResumeInst>::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<MDNode *, 32> 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<InvokeInst>((*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<PHINode>(I))
+ ++I;
+ Assert1(I != E && isa<LandingPadInst>(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()