aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBill Wendling <isanbard@gmail.com>2011-08-12 20:24:12 +0000
committerBill Wendling <isanbard@gmail.com>2011-08-12 20:24:12 +0000
commite6e8826870bee3facb04f950f0bd725f8a88623d (patch)
tree5fe10abfdbebc25ea75271004fe7afae60a3943e
parent79628e92e1f903d50340d4cd3d1ea8c5fff63a87 (diff)
Initial commit of the 'landingpad' instruction.
This implements the 'landingpad' instruction. It's used to indicate that a basic block is a landing pad. There are several restrictions on its use (see LangRef.html for more detail). These restrictions allow the exception handling code to gather the information it needs in a much more sane way. This patch has the definition, implementation, C interface, parsing, and bitcode support in it. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@137501 91177308-0d34-0410-b5e6-96231b3b80d8
-rw-r--r--docs/LangRef.html14
-rw-r--r--include/llvm-c/Core.h15
-rw-r--r--include/llvm/BasicBlock.h9
-rw-r--r--include/llvm/Bitcode/LLVMBitCodes.h5
-rw-r--r--include/llvm/Instruction.def3
-rw-r--r--include/llvm/Instructions.h109
-rw-r--r--include/llvm/Support/IRBuilder.h5
-rw-r--r--include/llvm/Support/InstVisitor.h1
-rw-r--r--lib/AsmParser/LLLexer.cpp6
-rw-r--r--lib/AsmParser/LLParser.cpp42
-rw-r--r--lib/AsmParser/LLParser.h1
-rw-r--r--lib/AsmParser/LLToken.h2
-rw-r--r--lib/Bitcode/Reader/BitcodeReader.cpp38
-rw-r--r--lib/Bitcode/Writer/BitcodeWriter.cpp17
-rw-r--r--lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp3
-rw-r--r--lib/CodeGen/SelectionDAG/SelectionDAGBuilder.h1
-rw-r--r--lib/Transforms/Scalar/SCCP.cpp1
-rw-r--r--lib/VMCore/AsmWriter.cpp18
-rw-r--r--lib/VMCore/BasicBlock.cpp12
-rw-r--r--lib/VMCore/Core.cpp17
-rw-r--r--lib/VMCore/Instruction.cpp1
-rw-r--r--lib/VMCore/Instructions.cpp89
-rw-r--r--lib/VMCore/Verifier.cpp65
23 files changed, 454 insertions, 20 deletions
diff --git a/docs/LangRef.html b/docs/LangRef.html
index 20250201b0..725691c14f 100644
--- a/docs/LangRef.html
+++ b/docs/LangRef.html
@@ -6022,7 +6022,7 @@ freestanding environments and non-C-based languages.</p>
&lt;resultval&gt; = landingpad &lt;somety&gt; personality &lt;type&gt; &lt;pers_fn&gt; cleanup &lt;clause&gt;*
&lt;clause&gt; := catch &lt;type&gt; &lt;value&gt;
- &lt;clause&gt; := filter &lt;type&gt; &lt;value&gt; {, &lt;type&gt; &lt;value&gt;}*
+ &lt;clause&gt; := filter &lt;array constant type&gt; &lt;array constant&gt;
</pre>
<h5>Overview:</h5>
@@ -6041,9 +6041,11 @@ freestanding environments and non-C-based languages.</p>
<tt>cleanup</tt> flag indicates that the landing pad block is a cleanup.</p>
<p>A <tt>clause</tt> begins with the clause type &mdash; <tt>catch</tt>
- or <tt>filter</tt> &mdash; and contains a list of global variables
- representing the "types" that may be caught or filtered respectively. The
- '<tt>landingpad</tt>' instruction must contain <em>at least</em>
+ or <tt>filter</tt> &mdash; and contains the global variable representing the
+ "type" that may be caught or filtered respectively. Unlike the
+ <tt>catch</tt> clause, the <tt>filter</tt> clause takes an array constant as
+ its argument. Use "<tt>[0 x i8**] undef</tt>" for a filter which cannot
+ throw. The '<tt>landingpad</tt>' instruction must contain <em>at least</em>
one <tt>clause</tt> or the <tt>cleanup</tt> flag.</p>
<h5>Semantics:</h5>
@@ -6079,11 +6081,11 @@ freestanding environments and non-C-based languages.</p>
catch i8** @_ZTIi
;; A landing pad that is a cleanup.
%res = landingpad { i8*, i32 } personality i32 (...)* @__gxx_personality_v0
- cleanup
+ cleanup
;; A landing pad which can catch an integer and can only throw a double.
%res = landingpad { i8*, i32 } personality i32 (...)* @__gxx_personality_v0
catch i8** @_ZTIi
- filter i8** @_ZTId
+ filter [1 x i8**] [@_ZTId]
</pre>
</div>
diff --git a/include/llvm-c/Core.h b/include/llvm-c/Core.h
index 0acf5a23af..2562757a2e 100644
--- a/include/llvm-c/Core.h
+++ b/include/llvm-c/Core.h
@@ -191,7 +191,8 @@ typedef enum {
LLVMAtomicRMW = 57,
/* Exception Handling Operators */
- LLVMResume = 58
+ LLVMResume = 58,
+ LLVMLandingPad = 59
} LLVMOpcode;
@@ -283,6 +284,11 @@ typedef enum {
LLVMRealPredicateTrue /**< Always true (always folded) */
} LLVMRealPredicate;
+typedef enum {
+ LLVMLandingPadCatch, /**< A catch clause */
+ LLVMLandingPadFilter /**< A filter clause */
+} LLVMLandingPadClauseTy;
+
void LLVMInitializeCore(LLVMPassRegistryRef R);
@@ -469,6 +475,7 @@ LLVMTypeRef LLVMX86MMXType(void);
macro(GetElementPtrInst) \
macro(InsertElementInst) \
macro(InsertValueInst) \
+ macro(LandingPadInst) \
macro(PHINode) \
macro(SelectInst) \
macro(ShuffleVectorInst) \
@@ -837,6 +844,12 @@ void LLVMAddCase(LLVMValueRef Switch, LLVMValueRef OnVal,
/* Add a destination to the indirectbr instruction */
void LLVMAddDestination(LLVMValueRef IndirectBr, LLVMBasicBlockRef Dest);
+/* Add a catch or filter clause to the landingpad instruction */
+void LLVMAddClause(LLVMValueRef LandingPad, 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/BasicBlock.h b/include/llvm/BasicBlock.h
index 3b953c06a8..d5966290a1 100644
--- a/include/llvm/BasicBlock.h
+++ b/include/llvm/BasicBlock.h
@@ -22,6 +22,7 @@
namespace llvm {
+class LandingPadInst;
class TerminatorInst;
class LLVMContext;
class BlockAddress;
@@ -258,6 +259,14 @@ public:
/// to refer to basic block New instead of to us.
void replaceSuccessorsPhiUsesWith(BasicBlock *New);
+ /// isLandingPad - Return true if this basic block is a landing pad. I.e.,
+ /// it's the destination of the 'unwind' edge of an invoke instruction.
+ bool isLandingPad() const;
+
+ /// getLandingPadInst() - Return the landingpad instruction associated with
+ /// the landing pad.
+ LandingPadInst *getLandingPadInst();
+
private:
/// AdjustBlockAddressRefCount - BasicBlock stores the number of BlockAddress
/// objects using it. This is almost always 0, sometimes one, possibly but
diff --git a/include/llvm/Bitcode/LLVMBitCodes.h b/include/llvm/Bitcode/LLVMBitCodes.h
index e2e5f0b087..4b0dcc3623 100644
--- a/include/llvm/Bitcode/LLVMBitCodes.h
+++ b/include/llvm/Bitcode/LLVMBitCodes.h
@@ -308,9 +308,10 @@ namespace bitc {
// align, vol,
// ordering, synchscope]
FUNC_CODE_INST_RESUME = 39, // RESUME: [opval]
- FUNC_CODE_INST_LOADATOMIC = 40, // LOAD: [opty, op, align, vol,
+ FUNC_CODE_INST_LANDINGPAD = 40, // LANDINGPAD: [ty,val,val,num,id0,val0...]
+ FUNC_CODE_INST_LOADATOMIC = 41, // LOAD: [opty, op, align, vol,
// ordering, synchscope]
- FUNC_CODE_INST_STOREATOMIC = 41 // STORE: [ptrty,ptr,val, align, vol
+ FUNC_CODE_INST_STOREATOMIC = 42 // STORE: [ptrty,ptr,val, align, vol
// ordering, synchscope]
};
} // End bitc namespace
diff --git a/include/llvm/Instruction.def b/include/llvm/Instruction.def
index 2e02b670cf..d36e4be1d9 100644
--- a/include/llvm/Instruction.def
+++ b/include/llvm/Instruction.def
@@ -172,7 +172,8 @@ 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)
+HANDLE_OTHER_INST(59, LandingPad, LandingPadInst) // Landing pad instruction.
+ LAST_OTHER_INST(59)
#undef FIRST_TERM_INST
#undef HANDLE_TERM_INST
diff --git a/include/llvm/Instructions.h b/include/llvm/Instructions.h
index 4103362dd8..2b681abbbd 100644
--- a/include/llvm/Instructions.h
+++ b/include/llvm/Instructions.h
@@ -2106,6 +2106,111 @@ 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. This uses the
+/// SubclassData field in Value to store whether or not the landingpad is a
+/// cleanup.
+///
+class LandingPadInst : public Instruction {
+ /// ReservedSpace - The number of operands actually allocated. NumOperands is
+ /// the number actually in use.
+ unsigned ReservedSpace;
+ LandingPadInst(const LandingPadInst &LP);
+public:
+ enum ClauseType { Catch, Filter };
+private:
+ 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(unsigned Size);
+ void init(Value *PersFn, unsigned NumReservedValues, const Twine &NameStr);
+
+ explicit LandingPadInst(Type *RetTy, Value *PersonalityFn,
+ unsigned NumReservedValues, const Twine &NameStr,
+ Instruction *InsertBefore);
+ explicit LandingPadInst(Type *RetTy, Value *PersonalityFn,
+ unsigned NumReservedValues, const Twine &NameStr,
+ BasicBlock *InsertAtEnd);
+protected:
+ virtual LandingPadInst *clone_impl() const;
+public:
+ /// Constructors - NumReservedClauses is a hint for the number of incoming
+ /// clauses that this landingpad will have (use 0 if you really have no idea).
+ static LandingPadInst *Create(Type *RetTy, Value *PersonalityFn,
+ unsigned NumReservedClauses,
+ const Twine &NameStr = "",
+ Instruction *InsertBefore = 0);
+ static LandingPadInst *Create(Type *RetTy, Value *PersonalityFn,
+ unsigned NumReservedClauses,
+ const Twine &NameStr, BasicBlock *InsertAtEnd);
+ ~LandingPadInst();
+
+ /// Provide fast operand accessors
+ DECLARE_TRANSPARENT_OPERAND_ACCESSORS(Value);
+
+ /// getPersonalityFn - Get the personality function associated with this
+ /// landing pad.
+ Value *getPersonalityFn() const { return getOperand(0); }
+
+ /// isCleanup - Return 'true' if this landingpad instruction is a
+ /// cleanup. I.e., it should be run when unwinding even if its landing pad
+ /// doesn't catch the exception.
+ bool isCleanup() const { return getSubclassDataFromInstruction() & 1; }
+
+ /// setCleanup - Indicate that this landingpad instruction is a cleanup.
+ void setCleanup(bool V) {
+ setInstructionSubclassData((getSubclassDataFromInstruction() & ~1) |
+ (V ? 1 : 0));
+ }
+
+ /// addClause - Add a catch or filter clause to the landing pad.
+ void addClause(Value *ClauseVal);
+
+ /// getClause - Get the value of the clause at index Idx. Use isCatch/isFilter
+ /// to determine what type of clause this is.
+ Value *getClause(unsigned Idx) const { return OperandList[Idx + 1]; }
+
+ /// isCatch - Return 'true' if the clause and index Idx is a catch clause.
+ bool isCatch(unsigned Idx) const {
+ return !isa<ArrayType>(OperandList[Idx + 1]->getType());
+ }
+
+ /// isFilter - Return 'true' if the clause and index Idx is a filter clause.
+ bool isFilter(unsigned Idx) const {
+ return isa<ArrayType>(OperandList[Idx + 1]->getType());
+ }
+
+ /// getNumClauses - Get the number of clauses for this landing pad.
+ unsigned getNumClauses() const { return getNumOperands() - 1; }
+
+ /// reserveClauses - Grow the size of the operand list to accomodate the new
+ /// number of clauses.
+ void reserveClauses(unsigned Size) { growOperands(Size); }
+
+ // 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
@@ -2695,6 +2800,10 @@ public:
Op<-1>() = reinterpret_cast<Value*>(B);
}
+ /// getLandingPadInst - Get the landingpad instruction from the landing pad
+ /// block (the unwind destination).
+ LandingPadInst *getLandingPadInst() const;
+
BasicBlock *getSuccessor(unsigned i) const {
assert(i < 2 && "Successor # out of range for invoke!");
return i == 0 ? getNormalDest() : getUnwindDest();
diff --git a/include/llvm/Support/IRBuilder.h b/include/llvm/Support/IRBuilder.h
index 133b1c3fd5..782800173f 100644
--- a/include/llvm/Support/IRBuilder.h
+++ b/include/llvm/Support/IRBuilder.h
@@ -1204,6 +1204,11 @@ public:
return Insert(InsertValueInst::Create(Agg, Val, Idxs), Name);
}
+ LandingPadInst *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 591de6f40d..a661c4fac6 100644
--- a/include/llvm/Support/InstVisitor.h
+++ b/include/llvm/Support/InstVisitor.h
@@ -195,6 +195,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 c3a5a4d0db..fdadd1ba93 100644
--- a/lib/AsmParser/LLLexer.cpp
+++ b/lib/AsmParser/LLLexer.cpp
@@ -584,6 +584,11 @@ lltok::Kind LLLexer::LexIdentifier() {
KEYWORD(x);
KEYWORD(blockaddress);
+
+ KEYWORD(personality);
+ KEYWORD(cleanup);
+ KEYWORD(catch);
+ KEYWORD(filter);
#undef KEYWORD
// Keywords for types.
@@ -653,6 +658,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
diff --git a/lib/AsmParser/LLParser.cpp b/lib/AsmParser/LLParser.cpp
index 8b30eef3d5..6a4c2a8fb9 100644
--- a/lib/AsmParser/LLParser.cpp
+++ b/lib/AsmParser/LLParser.cpp
@@ -2945,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.
@@ -3519,6 +3520,47 @@ int LLParser::ParsePHI(Instruction *&Inst, PerFunctionState &PFS) {
return AteExtraComma ? InstExtraComma : InstNormal;
}
+/// ParseLandingPad
+/// ::= 'landingpad' Type 'personality' TypeAndValue 'cleanup'? Clause+
+/// Clause
+/// ::= 'catch' TypeAndValue
+/// ::= 'filter'
+/// ::= 'filter' 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;
+
+ LandingPadInst *LP = LandingPadInst::Create(Ty, PersFn, 0);
+ LP->setCleanup(EatIfPresent(lltok::kw_cleanup));
+
+ while (Lex.getKind() == lltok::kw_catch || Lex.getKind() == lltok::kw_filter){
+ LandingPadInst::ClauseType CT;
+ if (EatIfPresent(lltok::kw_catch))
+ CT = LandingPadInst::Catch;
+ else if (EatIfPresent(lltok::kw_filter))
+ CT = LandingPadInst::Filter;
+ else
+ return TokError("expected 'catch' or 'filter' clause type");
+
+ Value *V; LocTy VLoc;
+ if (ParseTypeAndValue(V, VLoc, PFS)) {
+ delete LP;
+ return true;
+ }
+
+ LP->addClause(V);
+ }
+
+ 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 815f062026..ef4d3dba9e 100644
--- a/lib/AsmParser/LLParser.h
+++ b/lib/AsmParser/LLParser.h
@@ -360,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,
diff --git a/lib/AsmParser/LLToken.h b/lib/AsmParser/LLToken.h
index 3da85ad5d7..d22ecf31bd 100644
--- a/lib/AsmParser/LLToken.h
+++ b/lib/AsmParser/LLToken.h
@@ -124,6 +124,8 @@ namespace lltok {
kw_fptoui, kw_fptosi, kw_inttoptr, kw_ptrtoint, kw_bitcast,
kw_select, kw_va_arg,
+ 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,
diff --git a/lib/Bitcode/Reader/BitcodeReader.cpp b/lib/Bitcode/Reader/BitcodeReader.cpp
index 8f4e8c3e46..a33705d2dd 100644
--- a/lib/Bitcode/Reader/BitcodeReader.cpp
+++ b/lib/Bitcode/Reader/BitcodeReader.cpp
@@ -2543,6 +2543,44 @@ 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++]); (void)CT;
+ Value *Val;
+
+ if (getValueTypePair(Record, Idx, NextValueNo, Val)) {
+ delete LP;
+ return Error("Invalid LANDINGPAD record");
+ }
+
+ assert((CT != LandingPadInst::Catch ||
+ !isa<ArrayType>(Val->getType())) &&
+ "Catch clause has a invalid type!");
+ assert((CT != LandingPadInst::Filter ||
+ isa<ArrayType>(Val->getType())) &&
+ "Filter clause has invalid type!");
+ LP->addClause(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 12f0715f1a..5b3d96953a 100644
--- a/lib/Bitcode/Writer/BitcodeWriter.cpp
+++ b/lib/Bitcode/Writer/BitcodeWriter.cpp
@@ -1165,6 +1165,23 @@ 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) {
+ if (LP.isCatch(I))
+ Vals.push_back(LandingPadInst::Catch);
+ else
+ Vals.push_back(LandingPadInst::Filter);
+ PushValueAndType(LP.getClause(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 438667e005..c1d533582f 100644
--- a/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp
+++ b/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp
@@ -2985,6 +2985,9 @@ void SelectionDAGBuilder::visitExtractValue(const ExtractValueInst &I) {
&Values[0], NumValValues));
}
+void SelectionDAGBuilder::visitLandingPad(const LandingPadInst &I) {
+}
+
void SelectionDAGBuilder::visitGetElementPtr(const User &I) {
SDValue N = getValue(I.getOperand(0));
Type *Ty = I.getOperand(0)->getType();
diff --git a/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.h b/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.h
index 050b86fb60..776b07072b 100644
--- a/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.h
+++ b/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.h
@@ -512,6 +512,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/Transforms/Scalar/SCCP.cpp b/lib/Transforms/Scalar/SCCP.cpp
index c84d67b49a..59d96bee1c 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);
diff --git a/lib/VMCore/AsmWriter.cpp b/lib/VMCore/AsmWriter.cpp
index 62214a1a2e..d166604113 100644
--- a/lib/VMCore/AsmWriter.cpp
+++ b/lib/VMCore/AsmWriter.cpp
@@ -1748,6 +1748,24 @@ 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(I.getOperand(0), true); Out << '\n';
+
+ if (LPI->isCleanup())
+ Out << " cleanup";
+
+ for (unsigned i = 0, e = LPI->getNumClauses(); i != e; ++i) {
+ if (i != 0 || LPI->isCleanup()) Out << "\n";
+ if (LPI->isCatch(i))
+ Out << " catch ";
+ else
+ Out << " filter ";
+
+ writeOperand(LPI->getClause(i), true);
+ }
} else if (isa<ReturnInst>(I) && !Operand) {
Out << " void";
} else if (const CallInst *CI = dyn_cast<CallInst>(&I)) {
diff --git a/lib/VMCore/BasicBlock.cpp b/lib/VMCore/BasicBlock.cpp
index 5fab1d39ae..3e29f05d51 100644
--- a/lib/VMCore/BasicBlock.cpp
+++ b/lib/VMCore/BasicBlock.cpp
@@ -348,3 +348,15 @@ void BasicBlock::replaceSuccessorsPhiUsesWith(BasicBlock *New) {
}
}
}
+
+/// isLandingPad - Return true if this basic block is a landing pad. I.e., it's
+/// the destination of the 'unwind' edge of an invoke instruction.
+bool BasicBlock::isLandingPad() const {
+ return isa<LandingPadInst>(getFirstNonPHI());
+}
+
+/// getLandingPadInst() - Return the landingpad instruction associated with
+/// the landing pad.
+LandingPadInst *BasicBlock::getLandingPadInst() {
+ return dyn_cast<LandingPadInst>(getFirstNonPHI());
+}
diff --git a/lib/VMCore/Core.cpp b/lib/VMCore/Core.cpp
index 883ad91343..7e87103a0d 100644
--- a/lib/VMCore/Core.cpp
+++ b/lib/VMCore/Core.cpp
@@ -1683,6 +1683,14 @@ 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),
+ cast<Function>(unwrap(PersFn)),
+ NumClauses, Name));
+}
+
LLVMValueRef LLVMBuildResume(LLVMBuilderRef B, LLVMValueRef Exn) {
return wrap(unwrap(B)->CreateResume(unwrap(Exn)));
}
@@ -1700,6 +1708,15 @@ void LLVMAddDestination(LLVMValueRef IndirectBr, LLVMBasicBlockRef Dest) {
unwrap<IndirectBrInst>(IndirectBr)->addDestination(unwrap(Dest));
}
+void LLVMAddClause(LLVMValueRef LandingPad, LLVMValueRef ClauseVal) {
+ unwrap<LandingPadInst>(LandingPad)->
+ addClause(cast<Constant>(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 216bb35d4d..eadcd098b1 100644
--- a/lib/VMCore/Instruction.cpp
+++ b/lib/VMCore/Instruction.cpp
@@ -162,6 +162,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 8966bbe1dd..2f6c069a2d 100644
--- a/lib/VMCore/Instructions.cpp
+++ b/lib/VMCore/Instructions.cpp
@@ -166,6 +166,88 @@ Value *PHINode::hasConstantValue() const {
return ConstantValue;
}
+//===----------------------------------------------------------------------===//
+// LandingPadInst Implementation
+//===----------------------------------------------------------------------===//
+
+LandingPadInst::LandingPadInst(Type *RetTy, Value *PersonalityFn,
+ unsigned NumReservedValues, const Twine &NameStr,
+ Instruction *InsertBefore)
+ : Instruction(RetTy, Instruction::LandingPad, 0, 0, InsertBefore) {
+ init(PersonalityFn, 1 + NumReservedValues, NameStr);
+}
+
+LandingPadInst::LandingPadInst(Type *RetTy, Value *PersonalityFn,
+ unsigned NumReservedValues, const Twine &NameStr,
+ BasicBlock *InsertAtEnd)
+ : Instruction(RetTy, Instruction::LandingPad, 0, 0, InsertAtEnd) {
+ init(PersonalityFn, 1 + NumReservedValues, 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];
+
+ setCleanup(LP.isCleanup());
+}
+
+LandingPadInst::~LandingPadInst() {
+ dropHungoffUses();
+}
+
+LandingPadInst *LandingPadInst::Create(Type *RetTy, Value *PersonalityFn,
+ unsigned NumReservedClauses,
+ const Twine &NameStr,
+ Instruction *InsertBefore) {
+ return new LandingPadInst(RetTy, PersonalityFn, NumReservedClauses, NameStr,
+ InsertBefore);
+}
+
+LandingPadInst *LandingPadInst::Create(Type *RetTy, Value *PersonalityFn,
+ unsigned NumReservedClauses,
+ const Twine &NameStr,
+ BasicBlock *InsertAtEnd) {
+ return new LandingPadInst(RetTy, PersonalityFn, NumReservedClauses, NameStr,
+ InsertAtEnd);
+}
+
+void LandingPadInst::init(Value *PersFn, unsigned NumReservedValues,
+ const Twine &NameStr) {
+ ReservedSpace = NumReservedValues;
+ NumOperands = 1;
+ OperandList = allocHungoffUses(ReservedSpace);
+ OperandList[0] = PersFn;
+ setName(NameStr);
+ setCleanup(false);
+}
+
+/// 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 Size) {
+ unsigned e = getNumOperands();
+ if (ReservedSpace >= e + Size) return;
+ ReservedSpace = (e + Size / 2) * 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(Value *Val) {
+ unsigned OpNo = getNumOperands();
+ growOperands(1);
+ assert(OpNo < ReservedSpace && "Growing didn't work!");
+ ++NumOperands;
+ OperandList[OpNo] = Val;
+}
//===----------------------------------------------------------------------===//
// CallInst Implementation
@@ -494,6 +576,9 @@ void InvokeInst::removeAttribute(unsigned i, Attributes attr) {
setAttributes(PAL);
}
+LandingPadInst *InvokeInst::getLandingPadInst() const {
+ return cast<LandingPadInst>(getUnwindDest()->getFirstNonPHI());
+}
//===----------------------------------------------------------------------===//
// ReturnInst Implementation
@@ -3344,6 +3429,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);
}
diff --git a/lib/VMCore/Verifier.cpp b/lib/VMCore/Verifier.cpp
index 415c85e142..7635998a59 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;
@@ -165,6 +175,7 @@ namespace {
visit(F);
InstsInThisBlock.clear();
+ PersonalityFn = 0;
// If this is a real pass, in a pass manager, we must abort before
// returning back to the pass manager, or else the pass manager may try to
@@ -284,6 +295,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,
@@ -1401,6 +1413,39 @@ 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.
+ Assert1(LPI.getParent()->getLandingPadInst() == &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) {