diff --git a/llvm/docs/LangRef.rst b/llvm/docs/LangRef.rst --- a/llvm/docs/LangRef.rst +++ b/llvm/docs/LangRef.rst @@ -8608,7 +8608,7 @@ :: - resume + resume [unwindabort] Overview: """"""""" @@ -8630,6 +8630,11 @@ (in-flight) exception whose unwinding was interrupted with a :ref:`landingpad ` instruction. +If the ``unwindabort`` flag is set, the personality function will be +instructed to abort instead of proceeding to unwind to the +caller. See also the description of ``unwindabort`` for the +:ref:`call ` instruction. + Example: """""""" diff --git a/llvm/include/llvm/Bitcode/LLVMBitCodes.h b/llvm/include/llvm/Bitcode/LLVMBitCodes.h --- a/llvm/include/llvm/Bitcode/LLVMBitCodes.h +++ b/llvm/include/llvm/Bitcode/LLVMBitCodes.h @@ -529,6 +529,10 @@ CALL_UNWINDABORT = 18 }; +enum ResumeFlags { + RESUME_UNWINDABORT = 0, +}; + // The function body block (FUNCTION_BLOCK_ID) describes function bodies. It // can contain a constant block (CONSTANTS_BLOCK_ID). enum FunctionCodes { diff --git a/llvm/include/llvm/IR/Instructions.h b/llvm/include/llvm/IR/Instructions.h --- a/llvm/include/llvm/IR/Instructions.h +++ b/llvm/include/llvm/IR/Instructions.h @@ -4263,6 +4263,8 @@ explicit ResumeInst(Value *Exn, Instruction *InsertBefore=nullptr); ResumeInst(Value *Exn, BasicBlock *InsertAtEnd); + using UnwindAbortField = BoolBitfieldElementT<0>; + protected: // Note: Instruction needs to be a friend here to call cloneImpl. friend class Instruction; @@ -4286,6 +4288,11 @@ unsigned getNumSuccessors() const { return 0; } + bool isUnwindAbort() const { return getSubclassData(); } + void setUnwindAbort(bool IsUA = true) { + setSubclassData(IsUA); + } + // Methods for support type inquiry through isa, cast, and dyn_cast: static bool classof(const Instruction *I) { return I->getOpcode() == Instruction::Resume; diff --git a/llvm/lib/AsmParser/LLParser.cpp b/llvm/lib/AsmParser/LLParser.cpp --- a/llvm/lib/AsmParser/LLParser.cpp +++ b/llvm/lib/AsmParser/LLParser.cpp @@ -6772,13 +6772,23 @@ } /// parseResume -/// ::= 'resume' TypeAndValue +/// ::= 'resume' 'unwindabort'? TypeAndValue bool LLParser::parseResume(Instruction *&Inst, PerFunctionState &PFS) { Value *Exn; LocTy ExnLoc; + bool UnwindAbort = false; + + if (Lex.getKind() == lltok::kw_unwindabort) { + Lex.Lex(); + UnwindAbort = true; + } + if (parseTypeAndValue(Exn, ExnLoc, PFS)) return true; ResumeInst *RI = ResumeInst::Create(Exn); + if (UnwindAbort) + RI->setUnwindAbort(); + Inst = RI; return false; } @@ -7384,14 +7394,16 @@ } /// parseCall -/// ::= 'call' OptionalFastMathFlags OptionalCallingConv -/// OptionalAttrs Type Value ParameterList OptionalAttrs -/// ::= 'tail' 'call' OptionalFastMathFlags OptionalCallingConv -/// OptionalAttrs Type Value ParameterList OptionalAttrs -/// ::= 'musttail' 'call' OptionalFastMathFlags OptionalCallingConv +/// ::= 'call' 'unwindabort'? OptionalFastMathFlags OptionalCallingConv /// OptionalAttrs Type Value ParameterList OptionalAttrs -/// ::= 'notail' 'call' OptionalFastMathFlags OptionalCallingConv +/// ::= 'tail' 'call' 'unwindabort'? OptionalFastMathFlags OptionalCallingConv /// OptionalAttrs Type Value ParameterList OptionalAttrs +/// ::= 'musttail' 'call' 'unwindabort'? OptionalFastMathFlags +/// OptionalCallingConv OptionalAttrs Type Value ParameterList +/// OptionalAttrs +/// ::= 'notail' 'call' 'unwindabort'? OptionalFastMathFlags +/// OptionalCallingConv OptionalAttrs Type Value ParameterList +/// OptionalAttrs bool LLParser::parseCall(Instruction *&Inst, PerFunctionState &PFS, CallInst::TailCallKind TCK) { AttrBuilder RetAttrs(M->getContext()), FnAttrs(M->getContext()); diff --git a/llvm/lib/Bitcode/Reader/BitcodeReader.cpp b/llvm/lib/Bitcode/Reader/BitcodeReader.cpp --- a/llvm/lib/Bitcode/Reader/BitcodeReader.cpp +++ b/llvm/lib/Bitcode/Reader/BitcodeReader.cpp @@ -5568,12 +5568,18 @@ break; } case bitc::FUNC_CODE_INST_RESUME: { // RESUME: [opval] - unsigned Idx = 0; + unsigned OpNum = 0; Value *Val = nullptr; unsigned ValTypeID; - if (getValueTypePair(Record, Idx, NextValueNo, Val, ValTypeID, CurBB)) + if (getValueTypePair(Record, OpNum, NextValueNo, Val, ValTypeID, CurBB)) return error("Invalid record"); I = ResumeInst::Create(Val); + unsigned Flags = 0; + if (OpNum < Record.size()) + Flags = Record[OpNum++]; + if (Flags & (1 << bitc::RESUME_UNWINDABORT)) + cast(I)->setUnwindAbort(); + InstructionList.push_back(I); break; } diff --git a/llvm/lib/Bitcode/Writer/BitcodeWriter.cpp b/llvm/lib/Bitcode/Writer/BitcodeWriter.cpp --- a/llvm/lib/Bitcode/Writer/BitcodeWriter.cpp +++ b/llvm/lib/Bitcode/Writer/BitcodeWriter.cpp @@ -2999,10 +2999,15 @@ } break; } - case Instruction::Resume: + case Instruction::Resume: { Code = bitc::FUNC_CODE_INST_RESUME; + unsigned Flags = 0; + if (cast(I).isUnwindAbort()) + Flags |= 1 << bitc::RESUME_UNWINDABORT; pushValueAndType(I.getOperand(0), InstID, Vals); + Vals.push_back(Flags); break; + } case Instruction::CleanupRet: { Code = bitc::FUNC_CODE_INST_CLEANUPRET; const auto &CRI = cast(I); diff --git a/llvm/lib/IR/AsmWriter.cpp b/llvm/lib/IR/AsmWriter.cpp --- a/llvm/lib/IR/AsmWriter.cpp +++ b/llvm/lib/IR/AsmWriter.cpp @@ -4077,6 +4077,11 @@ (isa(I) && cast(I).isVolatile())) Out << " volatile"; + if (const ResumeInst *RI = dyn_cast(&I)) { + if (RI->isUnwindAbort()) + Out << " unwindabort"; + } + // Print out optimization information. WriteOptimizationInfo(Out, &I); diff --git a/llvm/lib/IR/Instructions.cpp b/llvm/lib/IR/Instructions.cpp --- a/llvm/lib/IR/Instructions.cpp +++ b/llvm/lib/IR/Instructions.cpp @@ -1144,6 +1144,7 @@ : Instruction(Type::getVoidTy(RI.getContext()), Instruction::Resume, OperandTraits::op_begin(this), 1) { Op<0>() = RI.Op<0>(); + setUnwindAbort(RI.isUnwindAbort()); } ResumeInst::ResumeInst(Value *Exn, Instruction *InsertBefore) diff --git a/llvm/test/Bitcode/compatibility.ll b/llvm/test/Bitcode/compatibility.ll --- a/llvm/test/Bitcode/compatibility.ll +++ b/llvm/test/Bitcode/compatibility.ll @@ -1612,6 +1612,25 @@ ret void } +define void @instructions.resume() personality i32 -1 { + invoke void @llvm.donothing() to label %proceed unwind label %catch1 + invoke void @llvm.donothing() to label %proceed unwind label %catch2 + +catch1: +landingpad i32 cleanup +; CHECK: resume i32 0 +resume i32 0 + +catch2: +landingpad i32 cleanup +; CHECK: resume unwindabort i32 0 +resume unwindabort i32 0 + +proceed: + ret void +} + + ;; Intrinsic Functions ; Intrinsic Functions -- Variable Argument Handling