From 772fe17a6d07304ae2e6b3052bbb24ebb751f0f3 Mon Sep 17 00:00:00 2001 From: Bill Wendling Date: Wed, 27 Jul 2011 20:18:04 +0000 Subject: Merge the contents from exception-handling-rewrite to the mainline. This adds the new instructions 'landingpad' and 'resume'. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@136253 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/AsmParser/LLLexer.cpp | 8 +- lib/AsmParser/LLParser.cpp | 63 ++++++++++++++ lib/AsmParser/LLParser.h | 2 + lib/AsmParser/LLToken.h | 8 +- lib/Bitcode/Reader/BitcodeReader.cpp | 39 +++++++++ lib/Bitcode/Writer/BitcodeWriter.cpp | 18 ++++ lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp | 8 ++ lib/CodeGen/SelectionDAG/SelectionDAGBuilder.h | 2 + lib/CodeGen/ShadowStackGC.cpp | 6 +- lib/Target/CBackend/CBackend.cpp | 4 +- lib/Target/CppBackend/CPPBackend.cpp | 8 ++ lib/Transforms/IPO/GlobalOpt.cpp | 2 +- lib/Transforms/InstCombine/InstCombineCalls.cpp | 8 +- lib/Transforms/Scalar/SCCP.cpp | 2 + lib/VMCore/AsmWriter.cpp | 30 +++++++ lib/VMCore/Core.cpp | 22 +++++ lib/VMCore/Instruction.cpp | 2 + lib/VMCore/Instructions.cpp | 105 ++++++++++++++++++++++- lib/VMCore/Verifier.cpp | 69 ++++++++++++--- 19 files changed, 382 insertions(+), 24 deletions(-) (limited to 'lib') diff --git a/lib/AsmParser/LLLexer.cpp b/lib/AsmParser/LLLexer.cpp index cdee98bd0c..970d7aa7ed 100644 --- a/lib/AsmParser/LLLexer.cpp +++ b/lib/AsmParser/LLLexer.cpp @@ -581,6 +581,11 @@ lltok::Kind LLLexer::LexIdentifier() { KEYWORD(x); KEYWORD(blockaddress); + + KEYWORD(personality); + KEYWORD(cleanup); + KEYWORD(catch); + KEYWORD(filter); #undef KEYWORD // Keywords for types. @@ -633,6 +638,7 @@ lltok::Kind LLLexer::LexIdentifier() { INSTKEYWORD(switch, Switch); INSTKEYWORD(indirectbr, IndirectBr); INSTKEYWORD(invoke, Invoke); + INSTKEYWORD(resume, Resume); INSTKEYWORD(unwind, Unwind); INSTKEYWORD(unreachable, Unreachable); @@ -647,6 +653,7 @@ lltok::Kind LLLexer::LexIdentifier() { INSTKEYWORD(shufflevector, ShuffleVector); INSTKEYWORD(extractvalue, ExtractValue); INSTKEYWORD(insertvalue, InsertValue); + INSTKEYWORD(landingpad, LandingPad); #undef INSTKEYWORD // Check for [us]0x[0-9A-Fa-f]+ which are Hexadecimal constant generated by @@ -674,7 +681,6 @@ lltok::Kind LLLexer::LexIdentifier() { return lltok::Error; } - /// Lex0x: Handle productions that start with 0x, knowing that it matches and /// that this is not a label: /// HexFPConstant 0x[0-9A-Fa-f]+ diff --git a/lib/AsmParser/LLParser.cpp b/lib/AsmParser/LLParser.cpp index 76771c29ba..547abfe24e 100644 --- a/lib/AsmParser/LLParser.cpp +++ b/lib/AsmParser/LLParser.cpp @@ -2885,6 +2885,7 @@ int LLParser::ParseInstruction(Instruction *&Inst, BasicBlock *BB, case lltok::kw_switch: return ParseSwitch(Inst, PFS); case lltok::kw_indirectbr: return ParseIndirectBr(Inst, PFS); case lltok::kw_invoke: return ParseInvoke(Inst, PFS); + case lltok::kw_resume: return ParseResume(Inst, PFS); // Binary Operators. case lltok::kw_add: case lltok::kw_sub: @@ -2944,6 +2945,7 @@ int LLParser::ParseInstruction(Instruction *&Inst, BasicBlock *BB, case lltok::kw_insertelement: return ParseInsertElement(Inst, PFS); case lltok::kw_shufflevector: return ParseShuffleVector(Inst, PFS); case lltok::kw_phi: return ParsePHI(Inst, PFS); + case lltok::kw_landingpad: return ParseLandingPad(Inst, PFS); case lltok::kw_call: return ParseCall(Inst, PFS, false); case lltok::kw_tail: return ParseCall(Inst, PFS, true); // Memory. @@ -3247,7 +3249,18 @@ bool LLParser::ParseInvoke(Instruction *&Inst, PerFunctionState &PFS) { return false; } +/// ParseResume +/// ::= 'resume' TypeAndValue +bool LLParser::ParseResume(Instruction *&Inst, PerFunctionState &PFS) { + Value *Exn; LocTy ExnLoc; + LocTy Loc = Lex.getLoc(); + if (ParseTypeAndValue(Exn, ExnLoc, PFS)) + return true; + ResumeInst *RI = ResumeInst::Create(Context, Exn); + Inst = RI; + return false; +} //===----------------------------------------------------------------------===// // Binary Operators. @@ -3495,6 +3508,56 @@ int LLParser::ParsePHI(Instruction *&Inst, PerFunctionState &PFS) { return AteExtraComma ? InstExtraComma : InstNormal; } +/// ParseLandingPad +/// ::= 'landingpad' Type 'personality' TypeAndValue 'cleanup'? +/// (ClauseID ClauseList)+ +/// ClauseID +/// ::= 'catch' +/// ::= 'filter' +/// ClauseList +/// ::= TypeAndValue (',' TypeAndValue)* +bool LLParser::ParseLandingPad(Instruction *&Inst, PerFunctionState &PFS) { + Type *Ty = 0; LocTy TyLoc; + Value *PersFn; LocTy PersFnLoc; + LocTy LPLoc = Lex.getLoc(); + + if (ParseType(Ty, TyLoc) || + ParseToken(lltok::kw_personality, "expected 'personality'") || + ParseTypeAndValue(PersFn, PersFnLoc, PFS)) + return true; + + bool IsCleanup = EatIfPresent(lltok::kw_cleanup); + + SmallVector, 16> Clauses; + while (Lex.getKind() == lltok::kw_catch || Lex.getKind() == lltok::kw_filter){ + LandingPadInst::ClauseType CT; + if (Lex.getKind() == lltok::kw_catch) { + CT = LandingPadInst::Catch; + ParseToken(lltok::kw_catch, "expected 'catch'"); + } else { + CT = LandingPadInst::Filter; + ParseToken(lltok::kw_filter, "expected 'filter'"); + } + + do { + Value *V; LocTy VLoc; + if (ParseTypeAndValue(V, VLoc, PFS)) + return true; + Clauses.push_back(std::make_pair(CT, V)); + } while (EatIfPresent(lltok::comma)); + } + + LandingPadInst *LP = LandingPadInst::Create(Ty, PersFn, Clauses.size()); + LP->setCleanup(IsCleanup); + + for (SmallVectorImpl >::iterator + I = Clauses.begin(), E = Clauses.end(); I != E; ++I) + LP->addClause(I->first, I->second); + + Inst = LP; + return false; +} + /// ParseCall /// ::= 'tail'? 'call' OptionalCallingConv OptionalAttrs Type Value /// ParameterList OptionalAttrs diff --git a/lib/AsmParser/LLParser.h b/lib/AsmParser/LLParser.h index 1eaf3252a8..6d2a929cc4 100644 --- a/lib/AsmParser/LLParser.h +++ b/lib/AsmParser/LLParser.h @@ -347,6 +347,7 @@ namespace llvm { bool ParseSwitch(Instruction *&Inst, PerFunctionState &PFS); bool ParseIndirectBr(Instruction *&Inst, PerFunctionState &PFS); bool ParseInvoke(Instruction *&Inst, PerFunctionState &PFS); + bool ParseResume(Instruction *&Inst, PerFunctionState &PFS); bool ParseArithmetic(Instruction *&I, PerFunctionState &PFS, unsigned Opc, unsigned OperandType); @@ -359,6 +360,7 @@ namespace llvm { bool ParseInsertElement(Instruction *&I, PerFunctionState &PFS); bool ParseShuffleVector(Instruction *&I, PerFunctionState &PFS); int ParsePHI(Instruction *&I, PerFunctionState &PFS); + bool ParseLandingPad(Instruction *&I, PerFunctionState &PFS); bool ParseCall(Instruction *&I, PerFunctionState &PFS, bool isTail); int ParseAlloc(Instruction *&I, PerFunctionState &PFS); int ParseLoad(Instruction *&I, PerFunctionState &PFS, bool isVolatile); diff --git a/lib/AsmParser/LLToken.h b/lib/AsmParser/LLToken.h index bf41c68ffe..f4c834ac23 100644 --- a/lib/AsmParser/LLToken.h +++ b/lib/AsmParser/LLToken.h @@ -121,7 +121,9 @@ namespace lltok { kw_fptoui, kw_fptosi, kw_inttoptr, kw_ptrtoint, kw_bitcast, kw_select, kw_va_arg, - kw_ret, kw_br, kw_switch, kw_indirectbr, kw_invoke, kw_unwind, + kw_landingpad, kw_personality, kw_cleanup, kw_catch, kw_filter, + + kw_ret, kw_br, kw_switch, kw_indirectbr, kw_invoke, kw_unwind, kw_resume, kw_unreachable, kw_alloca, kw_load, kw_store, kw_fence, kw_getelementptr, @@ -143,8 +145,8 @@ namespace lltok { // Type valued tokens (TyVal). Type, - APFloat, // APFloatVal - APSInt // APSInt + APFloat, // APFloatVal + APSInt // APSInt }; } // end namespace lltok } // end namespace llvm diff --git a/lib/Bitcode/Reader/BitcodeReader.cpp b/lib/Bitcode/Reader/BitcodeReader.cpp index 2029f438b4..37cc7949af 100644 --- a/lib/Bitcode/Reader/BitcodeReader.cpp +++ b/lib/Bitcode/Reader/BitcodeReader.cpp @@ -2491,6 +2491,14 @@ bool BitcodeReader::ParseFunctionBody(Function *F) { cast(I)->setAttributes(PAL); break; } + case bitc::FUNC_CODE_INST_RESUME: { // RESUME: [opval] + unsigned Idx = 0; + Value *Val = 0; + if (getValueTypePair(Record, Idx, NextValueNo, Val)) + return Error("Invalid RESUME record"); + I = ResumeInst::Create(Context, Val); + break; + } case bitc::FUNC_CODE_INST_UNWIND: // UNWIND I = new UnwindInst(Context); InstructionList.push_back(I); @@ -2518,6 +2526,37 @@ bool BitcodeReader::ParseFunctionBody(Function *F) { break; } + case bitc::FUNC_CODE_INST_LANDINGPAD: { + // LANDINGPAD: [ty, val, val, num, (id0,val0 ...)?] + unsigned Idx = 0; + if (Record.size() < 4) + return Error("Invalid LANDINGPAD record"); + Type *Ty = getTypeByID(Record[Idx++]); + if (!Ty) return Error("Invalid LANDINGPAD record"); + Value *PersFn = 0; + if (getValueTypePair(Record, Idx, NextValueNo, PersFn)) + return Error("Invalid LANDINGPAD record"); + + bool IsCleanup = !!Record[Idx++]; + unsigned NumClauses = Record[Idx++]; + LandingPadInst *LP = LandingPadInst::Create(Ty, PersFn, NumClauses); + LP->setCleanup(IsCleanup); + for (unsigned J = 0; J != NumClauses; ++J) { + LandingPadInst::ClauseType CT = + LandingPadInst::ClauseType(Record[Idx++]); + Value *Val = 0; + if (getValueTypePair(Record, Idx, NextValueNo, Val)) { + delete LP; + return Error("Invalid LANDINGPAD record"); + } + + LP->addClause(CT, Val); + } + + I = LP; + break; + } + case bitc::FUNC_CODE_INST_ALLOCA: { // ALLOCA: [instty, opty, op, align] if (Record.size() != 4) return Error("Invalid ALLOCA record"); diff --git a/lib/Bitcode/Writer/BitcodeWriter.cpp b/lib/Bitcode/Writer/BitcodeWriter.cpp index 9df3c17bf4..87154fc9c6 100644 --- a/lib/Bitcode/Writer/BitcodeWriter.cpp +++ b/lib/Bitcode/Writer/BitcodeWriter.cpp @@ -1126,6 +1126,10 @@ static void WriteInstruction(const Instruction &I, unsigned InstID, } break; } + case Instruction::Resume: + Code = bitc::FUNC_CODE_INST_RESUME; + PushValueAndType(I.getOperand(0), InstID, Vals, VE); + break; case Instruction::Unwind: Code = bitc::FUNC_CODE_INST_UNWIND; break; @@ -1145,6 +1149,20 @@ static void WriteInstruction(const Instruction &I, unsigned InstID, break; } + case Instruction::LandingPad: { + const LandingPadInst &LP = cast(I); + Code = bitc::FUNC_CODE_INST_LANDINGPAD; + Vals.push_back(VE.getTypeID(LP.getType())); + PushValueAndType(LP.getPersonalityFn(), InstID, Vals, VE); + Vals.push_back(LP.isCleanup()); + Vals.push_back(LP.getNumClauses()); + for (unsigned I = 0, E = LP.getNumClauses(); I != E; ++I) { + Vals.push_back(LP.getClauseType(I)); + PushValueAndType(LP.getClauseValue(I), InstID, Vals, VE); + } + break; + } + case Instruction::Alloca: Code = bitc::FUNC_CODE_INST_ALLOCA; Vals.push_back(VE.getTypeID(I.getType())); diff --git a/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp b/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp index a101df0d15..bdddca3514 100644 --- a/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp +++ b/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp @@ -914,6 +914,10 @@ void SelectionDAGBuilder::visitPHI(const PHINode &) { llvm_unreachable("SelectionDAGBuilder shouldn't visit PHI nodes!"); } +void SelectionDAGBuilder::visitLandingPad(const LandingPadInst &) { + // FIXME: Handle this +} + void SelectionDAGBuilder::visit(unsigned Opcode, const User &I) { // Note: this doesn't use InstVisitor, because it has to work with // ConstantExpr's in addition to instructions. @@ -1808,6 +1812,10 @@ void SelectionDAGBuilder::visitInvoke(const InvokeInst &I) { void SelectionDAGBuilder::visitUnwind(const UnwindInst &I) { } +void SelectionDAGBuilder::visitResume(const ResumeInst &RI) { + // FIXME: Handle this +} + /// handleSmallSwitchCaseRange - Emit a series of specific tests (suitable for /// small case ranges). bool SelectionDAGBuilder::handleSmallSwitchRange(CaseRec& CR, diff --git a/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.h b/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.h index d5d106b427..11c4a48384 100644 --- a/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.h +++ b/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.h @@ -453,6 +453,7 @@ public: private: // These all get lowered before this pass. void visitInvoke(const InvokeInst &I); + void visitResume(const ResumeInst &I); void visitUnwind(const UnwindInst &I); void visitBinary(const User &I, unsigned OpCode); @@ -497,6 +498,7 @@ private: void visitExtractValue(const ExtractValueInst &I); void visitInsertValue(const InsertValueInst &I); + void visitLandingPad(const LandingPadInst &I); void visitGetElementPtr(const User &I); void visitSelect(const User &I); diff --git a/lib/CodeGen/ShadowStackGC.cpp b/lib/CodeGen/ShadowStackGC.cpp index 9807c8cb27..daab89b8f2 100644 --- a/lib/CodeGen/ShadowStackGC.cpp +++ b/lib/CodeGen/ShadowStackGC.cpp @@ -113,9 +113,11 @@ namespace { while (StateBB != StateE) { BasicBlock *CurBB = StateBB++; - // Branches and invokes do not escape, only unwind and return do. + // Branches and invokes do not escape, only unwind, resume, and return + // do. TerminatorInst *TI = CurBB->getTerminator(); - if (!isa(TI) && !isa(TI)) + if (!isa(TI) && !isa(TI) && + !isa(TI)) continue; Builder.SetInsertPoint(TI->getParent(), TI); diff --git a/lib/Target/CBackend/CBackend.cpp b/lib/Target/CBackend/CBackend.cpp index 18a27d2dc3..eb25537548 100644 --- a/lib/Target/CBackend/CBackend.cpp +++ b/lib/Target/CBackend/CBackend.cpp @@ -288,10 +288,12 @@ namespace { void visitInvokeInst(InvokeInst &I) { llvm_unreachable("Lowerinvoke pass didn't work!"); } - void visitUnwindInst(UnwindInst &I) { llvm_unreachable("Lowerinvoke pass didn't work!"); } + void visitResumeInst(ResumeInst &I) { + llvm_unreachable("Lowerinvoke pass didn't work!"); + } void visitUnreachableInst(UnreachableInst &I); void visitPHINode(PHINode &I); diff --git a/lib/Target/CppBackend/CPPBackend.cpp b/lib/Target/CppBackend/CPPBackend.cpp index 7f5f5e189e..09f7ed51a3 100644 --- a/lib/Target/CppBackend/CPPBackend.cpp +++ b/lib/Target/CppBackend/CPPBackend.cpp @@ -1064,6 +1064,11 @@ void CppWriter::printInstruction(const Instruction *I, } break; } + case Instruction::Resume: { + Out << "ResumeInst::Create(mod->getContext(), " << opNames[0] + << ", " << bbname << ");"; + break; + } case Instruction::Invoke: { const InvokeInst* inv = cast(I); Out << "std::vector " << iName << "_params;"; @@ -1423,6 +1428,9 @@ void CppWriter::printInstruction(const Instruction *I, Out << "\", " << bbname << ");"; break; } + case Instruction::LandingPad: { + break; + } } DefinedValues.insert(I); nl(Out); diff --git a/lib/Transforms/IPO/GlobalOpt.cpp b/lib/Transforms/IPO/GlobalOpt.cpp index 0283568f2c..771a50b49d 100644 --- a/lib/Transforms/IPO/GlobalOpt.cpp +++ b/lib/Transforms/IPO/GlobalOpt.cpp @@ -2506,7 +2506,7 @@ static bool EvaluateFunction(Function *F, Constant *&RetVal, CallStack.pop_back(); // return from fn. return true; // We succeeded at evaluating this ctor! } else { - // invoke, unwind, unreachable. + // invoke, unwind, resume, unreachable. return false; // Cannot handle this terminator. } diff --git a/lib/Transforms/InstCombine/InstCombineCalls.cpp b/lib/Transforms/InstCombine/InstCombineCalls.cpp index c33dec1740..09edc41997 100644 --- a/lib/Transforms/InstCombine/InstCombineCalls.cpp +++ b/lib/Transforms/InstCombine/InstCombineCalls.cpp @@ -732,9 +732,11 @@ Instruction *InstCombiner::visitCallInst(CallInst &CI) { } } - // If the stack restore is in a return/unwind block and if there are no - // allocas or calls between the restore and the return, nuke the restore. - if (!CannotRemove && (isa(TI) || isa(TI))) + // If the stack restore is in a return, resume, or unwind block and if there + // are no allocas or calls between the restore and the return, nuke the + // restore. + if (!CannotRemove && (isa(TI) || isa(TI) || + isa(TI))) return EraseInstFromFunction(CI); break; } diff --git a/lib/Transforms/Scalar/SCCP.cpp b/lib/Transforms/Scalar/SCCP.cpp index 749ba40a64..ba6e51fbf5 100644 --- a/lib/Transforms/Scalar/SCCP.cpp +++ b/lib/Transforms/Scalar/SCCP.cpp @@ -515,6 +515,7 @@ private: void visitShuffleVectorInst(ShuffleVectorInst &I); void visitExtractValueInst(ExtractValueInst &EVI); void visitInsertValueInst(InsertValueInst &IVI); + void visitLandingPadInst(LandingPadInst &I) { markAnythingOverdefined(&I); } // Instructions that cannot be folded away. void visitStoreInst (StoreInst &I); @@ -528,6 +529,7 @@ private: visitTerminatorInst(II); } void visitCallSite (CallSite CS); + void visitResumeInst (TerminatorInst &I) { /*returns void*/ } void visitUnwindInst (TerminatorInst &I) { /*returns void*/ } void visitUnreachableInst(TerminatorInst &I) { /*returns void*/ } void visitFenceInst (FenceInst &I) { /*returns void*/ } diff --git a/lib/VMCore/AsmWriter.cpp b/lib/VMCore/AsmWriter.cpp index 1f8e89173c..e6cd418c32 100644 --- a/lib/VMCore/AsmWriter.cpp +++ b/lib/VMCore/AsmWriter.cpp @@ -1710,6 +1710,9 @@ void AssemblyWriter::printInstruction(const Instruction &I) { writeOperand(I.getOperand(i), true); } Out << ']'; + } else if (isa(I)) { + Out << ' '; + writeOperand(Operand, true); } else if (const PHINode *PN = dyn_cast(&I)) { Out << ' '; TypePrinter.print(I.getType(), Out); @@ -1732,6 +1735,33 @@ void AssemblyWriter::printInstruction(const Instruction &I) { writeOperand(I.getOperand(1), true); for (const unsigned *i = IVI->idx_begin(), *e = IVI->idx_end(); i != e; ++i) Out << ", " << *i; + } else if (const LandingPadInst *LPI = dyn_cast(&I)) { + Out << ' '; + TypePrinter.print(I.getType(), Out); + Out << " personality "; + writeOperand(LPI->getPersonalityFn(), true); Out << '\n'; + + if (LPI->isCleanup()) + Out << " cleanup"; + + for (unsigned i = 0, e = LPI->getNumClauses(); i != e; ) { + if (i != 0 || LPI->isCleanup()) Out << "\n"; + + SmallVector Vals; + LandingPadInst::ClauseType CT = LPI->getClauseType(i); + for (; i != e && LPI->getClauseType(i) == CT; ++i) + Vals.push_back(LPI->getClauseValue(i)); + + if (CT == LandingPadInst::Catch) + Out << " catch "; + else + Out << " filter "; + + for (unsigned II = 0, IE = Vals.size(); II != IE; ++II) { + if (II != 0) Out << ", "; + writeOperand(Vals[II], true); + } + } } else if (isa(I) && !Operand) { Out << " void"; } else if (const CallInst *CI = dyn_cast(&I)) { diff --git a/lib/VMCore/Core.cpp b/lib/VMCore/Core.cpp index 3c93736ce1..6664afc188 100644 --- a/lib/VMCore/Core.cpp +++ b/lib/VMCore/Core.cpp @@ -1683,10 +1683,21 @@ LLVMValueRef LLVMBuildInvoke(LLVMBuilderRef B, LLVMValueRef Fn, Name)); } +LLVMValueRef LLVMBuildLandingPad(LLVMBuilderRef B, LLVMTypeRef Ty, + LLVMValueRef PersFn, unsigned NumClauses, + const char *Name) { + return wrap(unwrap(B)->CreateLandingPad(unwrap(Ty), unwrap(PersFn), + NumClauses, Name)); +} + LLVMValueRef LLVMBuildUnwind(LLVMBuilderRef B) { return wrap(unwrap(B)->CreateUnwind()); } +LLVMValueRef LLVMBuildResume(LLVMBuilderRef B, LLVMValueRef Exn) { + return wrap(unwrap(B)->CreateResume(unwrap(Exn))); +} + LLVMValueRef LLVMBuildUnreachable(LLVMBuilderRef B) { return wrap(unwrap(B)->CreateUnreachable()); } @@ -1700,6 +1711,17 @@ void LLVMAddDestination(LLVMValueRef IndirectBr, LLVMBasicBlockRef Dest) { unwrap(IndirectBr)->addDestination(unwrap(Dest)); } +void LLVMAddClause(LLVMValueRef LandingPad, LLVMLandingPadClauseTy ClauseTy, + LLVMValueRef ClauseVal) { + unwrap(LandingPad)-> + addClause(static_cast(ClauseTy), + unwrap(ClauseVal)); +} + +void LLVMSetCleanup(LLVMValueRef LandingPad, LLVMBool Val) { + unwrap(LandingPad)->setCleanup(Val); +} + /*--.. Arithmetic ..........................................................--*/ LLVMValueRef LLVMBuildAdd(LLVMBuilderRef B, LLVMValueRef LHS, LLVMValueRef RHS, diff --git a/lib/VMCore/Instruction.cpp b/lib/VMCore/Instruction.cpp index cd8f737e28..09d16e7d44 100644 --- a/lib/VMCore/Instruction.cpp +++ b/lib/VMCore/Instruction.cpp @@ -101,6 +101,7 @@ const char *Instruction::getOpcodeName(unsigned OpCode) { case Switch: return "switch"; case IndirectBr: return "indirectbr"; case Invoke: return "invoke"; + case Resume: return "resume"; case Unwind: return "unwind"; case Unreachable: return "unreachable"; @@ -159,6 +160,7 @@ const char *Instruction::getOpcodeName(unsigned OpCode) { case ShuffleVector: return "shufflevector"; case ExtractValue: return "extractvalue"; case InsertValue: return "insertvalue"; + case LandingPad: return "landingpad"; default: return " "; } diff --git a/lib/VMCore/Instructions.cpp b/lib/VMCore/Instructions.cpp index ba4dae5c29..e7dd40d059 100644 --- a/lib/VMCore/Instructions.cpp +++ b/lib/VMCore/Instructions.cpp @@ -166,6 +166,63 @@ Value *PHINode::hasConstantValue() const { return ConstantValue; } +//===----------------------------------------------------------------------===// +// LandingPadInst Implementation +//===----------------------------------------------------------------------===// + +void LandingPadInst::init(Value *PersFn, unsigned NumReservedValues, + const Twine &NameStr) { + ReservedSpace = NumReservedValues; + NumOperands = 1; + OperandList = allocHungoffUses(ReservedSpace); + OperandList[0] = PersFn; + setName(NameStr); +} + +LandingPadInst::LandingPadInst(const LandingPadInst &LP) + : Instruction(LP.getType(), Instruction::LandingPad, + allocHungoffUses(LP.getNumOperands()), LP.getNumOperands()), + ReservedSpace(LP.getNumOperands()) { + Use *OL = OperandList, *InOL = LP.OperandList; + for (unsigned I = 0, E = ReservedSpace; I != E; ++I) + OL[I] = InOL[I]; + + for (SmallVectorImpl::const_iterator + I = LP.ClauseIdxs.begin(), E = LP.ClauseIdxs.end(); I != E; ++I) + ClauseIdxs.push_back(*I); + + IsCleanup = LP.IsCleanup; + SubclassOptionalData = LP.SubclassOptionalData; +} + +LandingPadInst::~LandingPadInst() { + dropHungoffUses(); +} + +/// growOperands - grow operands - This grows the operand list in response to a +/// push_back style of operation. This grows the number of ops by 2 times. +void LandingPadInst::growOperands() { + unsigned e = getNumOperands(); + ReservedSpace = e * 2; + + Use *NewOps = allocHungoffUses(ReservedSpace); + Use *OldOps = OperandList; + for (unsigned i = 0; i != e; ++i) + NewOps[i] = OldOps[i]; + + OperandList = NewOps; + Use::zap(OldOps, OldOps + e, true); +} + +void LandingPadInst::addClause(ClauseType CT, Value *ClauseVal) { + unsigned OpNo = getNumOperands(); + if (OpNo + 1 > ReservedSpace) + growOperands(); + assert(OpNo < ReservedSpace && "Growing didn't work!"); + ClauseIdxs.push_back(CT); + ++NumOperands; + OperandList[OpNo] = ClauseVal; +} //===----------------------------------------------------------------------===// // CallInst Implementation @@ -573,6 +630,42 @@ BasicBlock *UnwindInst::getSuccessorV(unsigned idx) const { return 0; } +//===----------------------------------------------------------------------===// +// ResumeInst Implementation +//===----------------------------------------------------------------------===// + +ResumeInst::ResumeInst(const ResumeInst &RI) + : TerminatorInst(Type::getVoidTy(RI.getContext()), Instruction::Resume, + OperandTraits::op_begin(this), 1) { + Op<0>() = RI.Op<0>(); + SubclassOptionalData = RI.SubclassOptionalData; +} + +ResumeInst::ResumeInst(LLVMContext &C, Value *Exn, Instruction *InsertBefore) + : TerminatorInst(Type::getVoidTy(C), Instruction::Resume, + OperandTraits::op_begin(this), 1, InsertBefore) { + Op<0>() = Exn; +} + +ResumeInst::ResumeInst(LLVMContext &C, Value *Exn, BasicBlock *InsertAtEnd) + : TerminatorInst(Type::getVoidTy(C), Instruction::Resume, + OperandTraits::op_begin(this), 1, InsertAtEnd) { + Op<0>() = Exn; +} + +unsigned ResumeInst::getNumSuccessorsV() const { + return getNumSuccessors(); +} + +void ResumeInst::setSuccessorV(unsigned idx, BasicBlock *NewSucc) { + llvm_unreachable("ResumeInst has no successors!"); +} + +BasicBlock *ResumeInst::getSuccessorV(unsigned idx) const { + llvm_unreachable("ResumeInst has no successors!"); + return 0; +} + //===----------------------------------------------------------------------===// // UnreachableInst Implementation //===----------------------------------------------------------------------===// @@ -592,11 +685,11 @@ unsigned UnreachableInst::getNumSuccessorsV() const { } void UnreachableInst::setSuccessorV(unsigned idx, BasicBlock *NewSucc) { - llvm_unreachable("UnwindInst has no successors!"); + llvm_unreachable("UnreachableInst has no successors!"); } BasicBlock *UnreachableInst::getSuccessorV(unsigned idx) const { - llvm_unreachable("UnwindInst has no successors!"); + llvm_unreachable("UnreachableInst has no successors!"); return 0; } @@ -3122,6 +3215,10 @@ PHINode *PHINode::clone_impl() const { return new PHINode(*this); } +LandingPadInst *LandingPadInst::clone_impl() const { + return new LandingPadInst(*this); +} + ReturnInst *ReturnInst::clone_impl() const { return new(getNumOperands()) ReturnInst(*this); } @@ -3143,6 +3240,10 @@ InvokeInst *InvokeInst::clone_impl() const { return new(getNumOperands()) InvokeInst(*this); } +ResumeInst *ResumeInst::clone_impl() const { + return new(1) ResumeInst(*this); +} + UnwindInst *UnwindInst::clone_impl() const { LLVMContext &Context = getContext(); return new UnwindInst(Context); diff --git a/lib/VMCore/Verifier.cpp b/lib/VMCore/Verifier.cpp index 2b2b815946..9ec2edf3fc 100644 --- a/lib/VMCore/Verifier.cpp +++ b/lib/VMCore/Verifier.cpp @@ -35,6 +35,12 @@ // * It is illegal to have a ret instruction that returns a value that does not // agree with the function return value type. // * Function call argument types match the function prototype +// * A landing pad is defined by a landingpad instruction, and can be jumped to +// only by the unwind edge of an invoke instruction. +// * A landingpad instruction must be the first non-PHI instruction in the +// block. +// * All landingpad instructions must use the same personality function with +// the same function. // * All other things that are tested by asserts spread about the code... // //===----------------------------------------------------------------------===// @@ -131,18 +137,22 @@ namespace { /// already. SmallPtrSet MDNodes; + /// PersonalityFn - The personality function referenced by the + /// LandingPadInsts. All LandingPadInsts within the same function must use + /// the same personality function. + const Value *PersonalityFn; + Verifier() - : FunctionPass(ID), - Broken(false), RealPass(true), action(AbortProcessAction), - Mod(0), Context(0), DT(0), MessagesStr(Messages) { - initializeVerifierPass(*PassRegistry::getPassRegistry()); - } + : FunctionPass(ID), Broken(false), RealPass(true), + action(AbortProcessAction), Mod(0), Context(0), DT(0), + MessagesStr(Messages), PersonalityFn(0) { + initializeVerifierPass(*PassRegistry::getPassRegistry()); + } explicit Verifier(VerifierFailureAction ctn) - : FunctionPass(ID), - Broken(false), RealPass(true), action(ctn), Mod(0), Context(0), DT(0), - MessagesStr(Messages) { - initializeVerifierPass(*PassRegistry::getPassRegistry()); - } + : FunctionPass(ID), Broken(false), RealPass(true), action(ctn), Mod(0), + Context(0), DT(0), MessagesStr(Messages), PersonalityFn(0) { + initializeVerifierPass(*PassRegistry::getPassRegistry()); + } bool doInitialization(Module &M) { Mod = &M; @@ -282,6 +292,7 @@ namespace { void visitAllocaInst(AllocaInst &AI); void visitExtractValueInst(ExtractValueInst &EVI); void visitInsertValueInst(InsertValueInst &IVI); + void visitLandingPadInst(LandingPadInst &LPI); void VerifyCallSite(CallSite CS); bool PerformTypeCheck(Intrinsic::ID ID, Function *F, Type *Ty, @@ -1321,7 +1332,7 @@ void Verifier::visitFenceInst(FenceInst &FI) { Assert1(Ordering == Acquire || Ordering == Release || Ordering == AcquireRelease || Ordering == SequentiallyConsistent, "fence instructions may only have " - " acquire, release, acq_rel, or seq_cst ordering.", &FI); + "acquire, release, acq_rel, or seq_cst ordering.", &FI); visitInstruction(FI); } @@ -1343,6 +1354,42 @@ void Verifier::visitInsertValueInst(InsertValueInst &IVI) { visitInstruction(IVI); } +void Verifier::visitLandingPadInst(LandingPadInst &LPI) { + BasicBlock *BB = LPI.getParent(); + + // The landingpad instruction is ill-formed if it doesn't have any clauses and + // isn't a cleanup. + Assert1(LPI.getNumClauses() > 0 || LPI.isCleanup(), + "LandingPadInst needs at least one clause or to be a cleanup.", &LPI); + + // The landingpad instruction defines its parent as a landing pad block. The + // landing pad block may be branched to only by the unwind edge of an invoke. + for (pred_iterator I = pred_begin(BB), E = pred_end(BB); I != E; ++I) { + const InvokeInst *II = dyn_cast((*I)->getTerminator()); + Assert1(II && II->getUnwindDest() == BB, + "Block containing LandingPadInst must be jumped to " + "only by the unwind edge of an invoke.", &LPI); + } + + // The landingpad instruction must be the first non-PHI instruction in the + // block. + BasicBlock::iterator I = BB->begin(), E = BB->end(); + while (I != E && isa(I)) + ++I; + Assert1(I != E && isa(I) && I == LPI, + "LandingPadInst not the first non-PHI instruction in the block.", + &LPI); + + // The personality functions for all landingpad instructions within the same + // function should match. + if (PersonalityFn) + Assert1(LPI.getPersonalityFn() == PersonalityFn, + "Personality function doesn't match others in function", &LPI); + PersonalityFn = LPI.getPersonalityFn(); + + visitInstruction(LPI); +} + /// verifyInstruction - Verify that an instruction is well formed. /// void Verifier::visitInstruction(Instruction &I) { -- cgit v1.2.3