summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--docs/LangRef.html39
-rw-r--r--include/llvm-c/Core.h7
-rw-r--r--include/llvm/Bitcode/LLVMBitCodes.h3
-rw-r--r--include/llvm/Instruction.def122
-rw-r--r--include/llvm/Instructions.h51
-rw-r--r--include/llvm/Support/IRBuilder.h4
-rw-r--r--include/llvm/Support/InstVisitor.h1
-rw-r--r--lib/AsmParser/LLLexer.cpp1
-rw-r--r--lib/AsmParser/LLParser.cpp12
-rw-r--r--lib/AsmParser/LLParser.h1
-rw-r--r--lib/AsmParser/LLToken.h2
-rw-r--r--lib/Bitcode/Reader/BitcodeReader.cpp8
-rw-r--r--lib/Bitcode/Writer/BitcodeWriter.cpp4
-rw-r--r--lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp4
-rw-r--r--lib/CodeGen/SelectionDAG/SelectionDAGBuilder.h1
-rw-r--r--lib/CodeGen/ShadowStackGC.cpp6
-rw-r--r--lib/Target/CBackend/CBackend.cpp4
-rw-r--r--lib/Target/CppBackend/CPPBackend.cpp5
-rw-r--r--lib/Transforms/IPO/GlobalOpt.cpp2
-rw-r--r--lib/Transforms/InstCombine/InstCombineCalls.cpp8
-rw-r--r--lib/Transforms/Scalar/SCCP.cpp1
-rw-r--r--lib/VMCore/Core.cpp4
-rw-r--r--lib/VMCore/Instruction.cpp1
-rw-r--r--lib/VMCore/Instructions.cpp39
24 files changed, 257 insertions, 73 deletions
diff --git a/docs/LangRef.html b/docs/LangRef.html
index 6c36ea1870..ac527c4df5 100644
--- a/docs/LangRef.html
+++ b/docs/LangRef.html
@@ -124,6 +124,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>
@@ -3023,13 +3024,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>
<!-- _______________________________________________________________________ -->
@@ -3350,6 +3352,39 @@ that the invoke/unwind semantics are likely to change in future versions.</p>
</div>
+ <!-- _______________________________________________________________________ -->
+
+<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.</p>
+
+<h5>Arguments:</h5>
+<p>The '<tt>resume</tt>' instruction's argument 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 whose unwinding was interrupted with
+ a landingpad instruction.</p>
+
+<h5>Example:</h5>
+<pre>
+ resume { i8*, i32 } %exn
+</pre>
+
+</div>
+
<!-- _______________________________________________________________________ -->
<h4>
diff --git a/include/llvm-c/Core.h b/include/llvm-c/Core.h
index 51da66231d..782b7eae9a 100644
--- a/include/llvm-c/Core.h
+++ b/include/llvm-c/Core.h
@@ -188,7 +188,10 @@ typedef enum {
/* Atomic operators */
LLVMFence = 55,
LLVMAtomicCmpXchg = 56,
- LLVMAtomicRMW = 57
+ LLVMAtomicRMW = 57,
+
+ /* Exception Handling Operators */
+ LLVMResume = 58
} LLVMOpcode;
@@ -477,6 +480,7 @@ LLVMTypeRef LLVMX86MMXType(void);
macro(SwitchInst) \
macro(UnreachableInst) \
macro(UnwindInst) \
+ macro(ResumeInst) \
macro(UnaryInstruction) \
macro(AllocaInst) \
macro(CastInst) \
@@ -825,6 +829,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 */
diff --git a/include/llvm/Bitcode/LLVMBitCodes.h b/include/llvm/Bitcode/LLVMBitCodes.h
index 404e3dea49..92d2c2dda5 100644
--- a/include/llvm/Bitcode/LLVMBitCodes.h
+++ b/include/llvm/Bitcode/LLVMBitCodes.h
@@ -304,9 +304,10 @@ namespace bitc {
FUNC_CODE_INST_FENCE = 36, // FENCE: [ordering, synchscope]
FUNC_CODE_INST_CMPXCHG = 37, // CMPXCHG: [ptrty,ptr,cmp,new, align, vol,
// ordering, synchscope]
- FUNC_CODE_INST_ATOMICRMW = 38 // ATOMICRMW: [ptrty,ptr,val, operation,
+ FUNC_CODE_INST_ATOMICRMW = 38, // ATOMICRMW: [ptrty,ptr,val, operation,
// align, vol,
// ordering, synchscope]
+ FUNC_CODE_INST_RESUME = 39 // RESUME: [opval]
};
} // End bitc namespace
} // End llvm namespace
diff --git a/include/llvm/Instruction.def b/include/llvm/Instruction.def
index b2c7d63eba..2e02b670cf 100644
--- a/include/llvm/Instruction.def
+++ b/include/llvm/Instruction.def
@@ -100,79 +100,79 @@ 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 )
-HANDLE_MEMORY_INST(31, AtomicCmpXchg , AtomicCmpXchgInst )
-HANDLE_MEMORY_INST(32, AtomicRMW , AtomicRMWInst )
- LAST_MEMORY_INST(32)
+ 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 )
+HANDLE_MEMORY_INST(32, AtomicCmpXchg , AtomicCmpXchgInst )
+HANDLE_MEMORY_INST(33, AtomicRMW , AtomicRMWInst )
+ LAST_MEMORY_INST(33)
// Cast operators ...
// NOTE: The order matters here because CastInst::isEliminableCastPair
// NOTE: (see Instructions.cpp) encodes a table based on this ordering.
- FIRST_CAST_INST(33)
-HANDLE_CAST_INST(33, Trunc , TruncInst ) // Truncate integers
-HANDLE_CAST_INST(34, ZExt , ZExtInst ) // Zero extend integers
-HANDLE_CAST_INST(35, SExt , SExtInst ) // Sign extend integers
-HANDLE_CAST_INST(36, FPToUI , FPToUIInst ) // floating point -> UInt
-HANDLE_CAST_INST(37, FPToSI , FPToSIInst ) // floating point -> SInt
-HANDLE_CAST_INST(38, UIToFP , UIToFPInst ) // UInt -> floating point
-HANDLE_CAST_INST(39, SIToFP , SIToFPInst ) // SInt -> floating point
-HANDLE_CAST_INST(40, FPTrunc , FPTruncInst ) // Truncate floating point
-HANDLE_CAST_INST(41, FPExt , FPExtInst ) // Extend floating point
-HANDLE_CAST_INST(42, PtrToInt, PtrToIntInst) // Pointer -> Integer
-HANDLE_CAST_INST(43, IntToPtr, IntToPtrInst) // Integer -> Pointer
-HANDLE_CAST_INST(44, BitCast , BitCastInst ) // Type cast
- LAST_CAST_INST(44)
+ FIRST_CAST_INST(34)
+HANDLE_CAST_INST(34, Trunc , TruncInst ) // Truncate integers
+HANDLE_CAST_INST(35, ZExt , ZExtInst ) // Zero extend integers
+HANDLE_CAST_INST(36, SExt , SExtInst ) // Sign extend integers
+HANDLE_CAST_INST(37, FPToUI , FPToUIInst ) // floating point -> UInt
+HANDLE_CAST_INST(38, FPToSI , FPToSIInst ) // floating point -> SInt
+HANDLE_CAST_INST(39, UIToFP , UIToFPInst ) // UInt -> floating point
+HANDLE_CAST_INST(40, SIToFP , SIToFPInst ) // SInt -> floating point
+HANDLE_CAST_INST(41, FPTrunc , FPTruncInst ) // Truncate floating point
+HANDLE_CAST_INST(42, FPExt , FPExtInst ) // Extend floating point
+HANDLE_CAST_INST(43, PtrToInt, PtrToIntInst) // Pointer -> Integer
+HANDLE_CAST_INST(44, IntToPtr, IntToPtrInst) // Integer -> Pointer
+HANDLE_CAST_INST(45, BitCast , BitCastInst ) // Type cast
+ LAST_CAST_INST(45)
// Other operators...
- FIRST_OTHER_INST(45)
-HANDLE_OTHER_INST(45, ICmp , ICmpInst ) // Integer comparison instruction
-HANDLE_OTHER_INST(46, FCmp , FCmpInst ) // Floating point comparison instr.
-HANDLE_OTHER_INST(47, PHI , PHINode ) // PHI node instruction
-HANDLE_OTHER_INST(48, Call , CallInst ) // Call a function
-HANDLE_OTHER_INST(49, Select , SelectInst ) // select instruction
-HANDLE_OTHER_INST(50, UserOp1, Instruction) // May be used internally in a pass
-HANDLE_OTHER_INST(51, UserOp2, Instruction) // Internal to passes only
-HANDLE_OTHER_INST(52, VAArg , VAArgInst ) // vaarg instruction
-HANDLE_OTHER_INST(53, ExtractElement, ExtractElementInst)// extract from vector
-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)
+ FIRST_OTHER_INST(46)
+HANDLE_OTHER_INST(46, ICmp , ICmpInst ) // Integer comparison instruction
+HANDLE_OTHER_INST(47, FCmp , FCmpInst ) // Floating point comparison instr.
+HANDLE_OTHER_INST(48, PHI , PHINode ) // PHI node instruction
+HANDLE_OTHER_INST(49, Call , CallInst ) // Call a function
+HANDLE_OTHER_INST(50, Select , SelectInst ) // select instruction
+HANDLE_OTHER_INST(51, UserOp1, Instruction) // May be used internally in a pass
+HANDLE_OTHER_INST(52, UserOp2, Instruction) // Internal to passes only
+HANDLE_OTHER_INST(53, VAArg , VAArgInst ) // vaarg instruction
+HANDLE_OTHER_INST(54, ExtractElement, ExtractElementInst)// extract from vector
+HANDLE_OTHER_INST(55, InsertElement, InsertElementInst) // insert into vector
+HANDLE_OTHER_INST(56, ShuffleVector, ShuffleVectorInst) // shuffle two vectors.
+HANDLE_OTHER_INST(57, ExtractValue, ExtractValueInst)// extract from aggregate
+HANDLE_OTHER_INST(58, InsertValue, InsertValueInst) // insert into aggregate
+ 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 69538e954f..dbbf5f9242 100644
--- a/include/llvm/Instructions.h
+++ b/include/llvm/Instructions.h
@@ -2716,6 +2716,57 @@ private:
};
//===----------------------------------------------------------------------===//
+// ResumeInst Class
+//===----------------------------------------------------------------------===//
+
+//===---------------------------------------------------------------------------
+/// ResumeInst - Resume the propagation of an exception.
+///
+class ResumeInst : public TerminatorInst {
+ ResumeInst(const ResumeInst &RI);
+
+ explicit ResumeInst(Value *Exn, Instruction *InsertBefore=0);
+ ResumeInst(Value *Exn, BasicBlock *InsertAtEnd);
+protected:
+ virtual ResumeInst *clone_impl() const;
+public:
+ static ResumeInst *Create(Value *Exn, Instruction *InsertBefore = 0) {
+ return new(1) ResumeInst(Exn, InsertBefore);
+ }
+ static ResumeInst *Create(Value *Exn, BasicBlock *InsertAtEnd) {
+ return new(1) ResumeInst(Exn, InsertAtEnd);
+ }
+
+ /// Provide fast operand accessors
+ DECLARE_TRANSPARENT_OPERAND_ACCESSORS(Value);
+
+ /// Convenience accessor.
+ Value *getValue() 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 87a017d400..01244b8bc4 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(Exn));
+ }
+
UnreachableInst *CreateUnreachable() {
return Insert(new UnreachableInst(Context));
}
diff --git a/include/llvm/Support/InstVisitor.h b/include/llvm/Support/InstVisitor.h
index dc29d6a23a..591de6f40d 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);}
diff --git a/lib/AsmParser/LLLexer.cpp b/lib/AsmParser/LLLexer.cpp
index 95b40c9838..c3a5a4d0db 100644
--- a/lib/AsmParser/LLLexer.cpp
+++ b/lib/AsmParser/LLLexer.cpp
@@ -636,6 +636,7 @@ lltok::Kind LLLexer::LexIdentifier() {
INSTKEYWORD(switch, Switch);
INSTKEYWORD(indirectbr, IndirectBr);
INSTKEYWORD(invoke, Invoke);
+ INSTKEYWORD(resume, Resume);
INSTKEYWORD(unwind, Unwind);
INSTKEYWORD(unreachable, Unreachable);
diff --git a/lib/AsmParser/LLParser.cpp b/lib/AsmParser/LLParser.cpp
index 4727fac8ef..82fab917fe 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:
@@ -3253,7 +3254,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(Exn);
+ Inst = RI;
+ return false;
+}
//===----------------------------------------------------------------------===//
// Binary Operators.
diff --git a/lib/AsmParser/LLParser.h b/lib/AsmParser/LLParser.h
index 2a7210a311..df058edd76 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);
diff --git a/lib/AsmParser/LLToken.h b/lib/AsmParser/LLToken.h
index 75b332b6be..3da85ad5d7 100644
--- a/lib/AsmParser/LLToken.h
+++ b/lib/AsmParser/LLToken.h
@@ -124,7 +124,7 @@ 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_ret, kw_br, kw_switch, kw_indirectbr, kw_invoke, kw_unwind, kw_resume,
kw_unreachable,
kw_alloca, kw_load, kw_store, kw_fence, kw_cmpxchg, kw_atomicrmw,
diff --git a/lib/Bitcode/Reader/BitcodeReader.cpp b/lib/Bitcode/Reader/BitcodeReader.cpp
index b4f47ad670..b4e105055e 100644
--- a/lib/Bitcode/Reader/BitcodeReader.cpp
+++ b/lib/Bitcode/Reader/BitcodeReader.cpp
@@ -2508,6 +2508,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(Val);
+ break;
+ }
case bitc::FUNC_CODE_INST_UNWIND: // UNWIND
I = new UnwindInst(Context);
InstructionList.push_back(I);
diff --git a/lib/Bitcode/Writer/BitcodeWriter.cpp b/lib/Bitcode/Writer/BitcodeWriter.cpp
index dd071d89a6..9954400e5e 100644
--- a/lib/Bitcode/Writer/BitcodeWriter.cpp
+++ b/lib/Bitcode/Writer/BitcodeWriter.cpp
@@ -1143,6 +1143,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;
diff --git a/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp b/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp
index 86d32c218b..449f87ebda 100644
--- a/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp
+++ b/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp
@@ -1810,6 +1810,10 @@ void SelectionDAGBuilder::visitInvoke(const InvokeInst &I) {
void SelectionDAGBuilder::visitUnwind(const UnwindInst &I) {
}
+void SelectionDAGBuilder::visitResume(const ResumeInst &RI) {
+ llvm_unreachable("SelectionDAGBuilder shouldn't visit resume instructions!");
+}
+
/// 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 aae56ba06a..050b86fb60 100644
--- a/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.h
+++ b/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.h
@@ -467,6 +467,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);
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..5b9a0a297f 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("DwarfEHPrepare 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..108023da95 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;";
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..4e1c27446c 100644
--- a/lib/Transforms/Scalar/SCCP.cpp
+++ b/lib/Transforms/Scalar/SCCP.cpp
@@ -528,6 +528,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/Core.cpp b/lib/VMCore/Core.cpp
index 3c93736ce1..ce010c1b7d 100644
--- a/lib/VMCore/Core.cpp
+++ b/lib/VMCore/Core.cpp
@@ -1687,6 +1687,10 @@ 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());
}
diff --git a/lib/VMCore/Instruction.cpp b/lib/VMCore/Instruction.cpp
index c4365fcca6..216bb35d4d 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";
diff --git a/lib/VMCore/Instructions.cpp b/lib/VMCore/Instructions.cpp
index 75458babfb..c36102d706 100644
--- a/lib/VMCore/Instructions.cpp
+++ b/lib/VMCore/Instructions.cpp
@@ -574,6 +574,41 @@ 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>();
+}
+
+ResumeInst::ResumeInst(Value *Exn, Instruction *InsertBefore)
+ : TerminatorInst(Type::getVoidTy(Exn->getContext()), Instruction::Resume,
+ OperandTraits<ResumeInst>::op_begin(this), 1, InsertBefore) {
+ Op<0>() = Exn;
+}
+
+ResumeInst::ResumeInst(Value *Exn, BasicBlock *InsertAtEnd)
+ : TerminatorInst(Type::getVoidTy(Exn->getContext()), 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
//===----------------------------------------------------------------------===//
@@ -3254,6 +3289,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);