New EH representation for MSVC compatibility

This introduces new instructions neccessary to implement MSVC-compatible
exception handling support.  Most of the middle-end and none of the
back-end haven't been audited or updated to take them into account.

Differential Revision: http://reviews.llvm.org/D11097

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@243766 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
David Majnemer
2015-07-31 17:58:14 +00:00
parent aa50fa7c2f
commit 4a45f0871a
39 changed files with 2313 additions and 121 deletions

View File

@@ -4532,6 +4532,12 @@ int LLParser::ParseInstruction(Instruction *&Inst, BasicBlock *BB,
case lltok::kw_indirectbr: return ParseIndirectBr(Inst, PFS);
case lltok::kw_invoke: return ParseInvoke(Inst, PFS);
case lltok::kw_resume: return ParseResume(Inst, PFS);
case lltok::kw_cleanupret: return ParseCleanupRet(Inst, PFS);
case lltok::kw_catchret: return ParseCatchRet(Inst, PFS);
case lltok::kw_catchpad: return ParseCatchPad(Inst, PFS);
case lltok::kw_terminatepad: return ParseTerminatePad(Inst, PFS);
case lltok::kw_cleanuppad: return ParseCleanupPad(Inst, PFS);
case lltok::kw_catchendpad: return ParseCatchEndPad(Inst, PFS);
// Binary Operators.
case lltok::kw_add:
case lltok::kw_sub:
@@ -4936,6 +4942,161 @@ bool LLParser::ParseResume(Instruction *&Inst, PerFunctionState &PFS) {
return false;
}
bool LLParser::ParseExceptionArgs(SmallVectorImpl<Value *> &Args,
PerFunctionState &PFS) {
if (ParseToken(lltok::lsquare, "expected '[' in cleanuppad"))
return true;
while (Lex.getKind() != lltok::rsquare) {
// If this isn't the first argument, we need a comma.
if (!Args.empty() &&
ParseToken(lltok::comma, "expected ',' in argument list"))
return true;
// Parse the argument.
LocTy ArgLoc;
Type *ArgTy = nullptr;
if (ParseType(ArgTy, ArgLoc))
return true;
Value *V;
if (ArgTy->isMetadataTy()) {
if (ParseMetadataAsValue(V, PFS))
return true;
} else {
if (ParseValue(ArgTy, V, PFS))
return true;
}
Args.push_back(V);
}
Lex.Lex(); // Lex the ']'.
return false;
}
/// ParseCleanupRet
/// ::= 'cleanupret' ('void' | TypeAndValue) unwind ('to' 'caller' | TypeAndValue)
bool LLParser::ParseCleanupRet(Instruction *&Inst, PerFunctionState &PFS) {
Type *RetTy = nullptr;
Value *RetVal = nullptr;
if (ParseType(RetTy, /*AllowVoid=*/true))
return true;
if (!RetTy->isVoidTy())
if (ParseValue(RetTy, RetVal, PFS))
return true;
if (ParseToken(lltok::kw_unwind, "expected 'unwind' in cleanupret"))
return true;
BasicBlock *UnwindBB = nullptr;
if (Lex.getKind() == lltok::kw_to) {
Lex.Lex();
if (ParseToken(lltok::kw_caller, "expected 'caller' in cleanupret"))
return true;
} else {
if (ParseTypeAndBasicBlock(UnwindBB, PFS)) {
return true;
}
}
Inst = CleanupReturnInst::Create(Context, RetVal, UnwindBB);
return false;
}
/// ParseCatchRet
/// ::= 'catchret' TypeAndValue
bool LLParser::ParseCatchRet(Instruction *&Inst, PerFunctionState &PFS) {
BasicBlock *BB;
if (ParseTypeAndBasicBlock(BB, PFS))
return true;
Inst = CatchReturnInst::Create(BB);
return false;
}
/// ParseCatchPad
/// ::= 'catchpad' Type ParamList 'to' TypeAndValue 'unwind' TypeAndValue
bool LLParser::ParseCatchPad(Instruction *&Inst, PerFunctionState &PFS) {
Type *RetType = nullptr;
SmallVector<Value *, 8> Args;
if (ParseType(RetType, /*AllowVoid=*/true) || ParseExceptionArgs(Args, PFS))
return true;
BasicBlock *NormalBB, *UnwindBB;
if (ParseToken(lltok::kw_to, "expected 'to' in catchpad") ||
ParseTypeAndBasicBlock(NormalBB, PFS) ||
ParseToken(lltok::kw_unwind, "expected 'unwind' in catchpad") ||
ParseTypeAndBasicBlock(UnwindBB, PFS))
return true;
Inst = CatchPadInst::Create(RetType, NormalBB, UnwindBB, Args);
return false;
}
/// ParseTerminatePad
/// ::= 'terminatepad' ParamList 'to' TypeAndValue
bool LLParser::ParseTerminatePad(Instruction *&Inst, PerFunctionState &PFS) {
SmallVector<Value *, 8> Args;
if (ParseExceptionArgs(Args, PFS))
return true;
if (ParseToken(lltok::kw_unwind, "expected 'unwind' in terminatepad"))
return true;
BasicBlock *UnwindBB = nullptr;
if (Lex.getKind() == lltok::kw_to) {
Lex.Lex();
if (ParseToken(lltok::kw_caller, "expected 'caller' in terminatepad"))
return true;
} else {
if (ParseTypeAndBasicBlock(UnwindBB, PFS)) {
return true;
}
}
Inst = TerminatePadInst::Create(Context, UnwindBB, Args);
return false;
}
/// ParseCleanupPad
/// ::= 'cleanuppad' ParamList
bool LLParser::ParseCleanupPad(Instruction *&Inst, PerFunctionState &PFS) {
Type *RetType = nullptr;
SmallVector<Value *, 8> Args;
if (ParseType(RetType, /*AllowVoid=*/true) || ParseExceptionArgs(Args, PFS))
return true;
Inst = CleanupPadInst::Create(RetType, Args);
return false;
}
/// ParseCatchEndPad
/// ::= 'catchendpad' unwind ('to' 'caller' | TypeAndValue)
bool LLParser::ParseCatchEndPad(Instruction *&Inst, PerFunctionState &PFS) {
if (ParseToken(lltok::kw_unwind, "expected 'unwind' in catchendpad"))
return true;
BasicBlock *UnwindBB = nullptr;
if (Lex.getKind() == lltok::kw_to) {
Lex.Lex();
if (Lex.getKind() == lltok::kw_caller) {
Lex.Lex();
} else {
return true;
}
} else {
if (ParseTypeAndBasicBlock(UnwindBB, PFS)) {
return true;
}
}
Inst = CatchEndPadInst::Create(Context, UnwindBB);
return false;
}
//===----------------------------------------------------------------------===//
// Binary Operators.
//===----------------------------------------------------------------------===//