New EH representation for MSVC compatibility

Summary:
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.

Reviewers: rnk, JosephTremoulet, reames, nlewycky, rjmccall

Subscribers: llvm-commits

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

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@241888 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
David Majnemer
2015-07-10 07:00:44 +00:00
parent 86ef198476
commit 751c4be705
35 changed files with 2042 additions and 91 deletions

View File

@ -3793,6 +3793,134 @@ std::error_code BitcodeReader::parseFunctionBody(Function *F) {
}
break;
}
// CLEANUPRET: [] or [ty,val] or [bb#] or [ty,val,bb#]
case bitc::FUNC_CODE_INST_CLEANUPRET: {
if (Record.size() < 2)
return error("Invalid record");
unsigned Idx = 0;
bool HasReturnValue = !!Record[Idx++];
bool HasUnwindDest = !!Record[Idx++];
Value *RetVal = nullptr;
BasicBlock *UnwindDest = nullptr;
if (HasReturnValue && getValueTypePair(Record, Idx, NextValueNo, RetVal))
return error("Invalid record");
if (HasUnwindDest) {
if (Idx == Record.size())
return error("Invalid record");
UnwindDest = getBasicBlock(Record[Idx++]);
if (!UnwindDest)
return error("Invalid record");
}
if (Record.size() != Idx)
return error("Invalid record");
I = CleanupReturnInst::Create(Context, RetVal, UnwindDest);
InstructionList.push_back(I);
break;
}
case bitc::FUNC_CODE_INST_CATCHRET: { // CATCHRET: [bb#]
if (Record.size() != 1)
return error("Invalid record");
BasicBlock *BB = getBasicBlock(Record[0]);
if (!BB)
return error("Invalid record");
I = CatchReturnInst::Create(BB);
InstructionList.push_back(I);
break;
}
case bitc::FUNC_CODE_INST_CATCHBLOCK: { // CATCHBLOCK: [ty,bb#,bb#,num,(ty,val)*]
if (Record.size() < 4)
return error("Invalid record");
unsigned Idx = 0;
Type *Ty = getTypeByID(Record[Idx++]);
if (!Ty)
return error("Invalid record");
BasicBlock *NormalBB = getBasicBlock(Record[Idx++]);
if (!NormalBB)
return error("Invalid record");
BasicBlock *UnwindBB = getBasicBlock(Record[Idx++]);
if (!UnwindBB)
return error("Invalid record");
unsigned NumArgOperands = Record[Idx++];
SmallVector<Value *, 2> Args;
for (unsigned Op = 0; Op != NumArgOperands; ++Op) {
Value *Val;
if (getValueTypePair(Record, Idx, NextValueNo, Val))
return error("Invalid record");
Args.push_back(Val);
}
if (Record.size() != Idx)
return error("Invalid record");
I = CatchBlockInst::Create(Ty, NormalBB, UnwindBB, Args);
InstructionList.push_back(I);
break;
}
case bitc::FUNC_CODE_INST_TERMINATEBLOCK: { // TERMINATEBLOCK: [bb#,num,(ty,val)*]
if (Record.size() < 1)
return error("Invalid record");
unsigned Idx = 0;
bool HasUnwindDest = !!Record[Idx++];
BasicBlock *UnwindDest = nullptr;
if (HasUnwindDest) {
if (Idx == Record.size())
return error("Invalid record");
UnwindDest = getBasicBlock(Record[Idx++]);
if (!UnwindDest)
return error("Invalid record");
}
unsigned NumArgOperands = Record[Idx++];
SmallVector<Value *, 2> Args;
for (unsigned Op = 0; Op != NumArgOperands; ++Op) {
Value *Val;
if (getValueTypePair(Record, Idx, NextValueNo, Val))
return error("Invalid record");
Args.push_back(Val);
}
if (Record.size() != Idx)
return error("Invalid record");
I = TerminateBlockInst::Create(Context, UnwindDest, Args);
InstructionList.push_back(I);
break;
}
case bitc::FUNC_CODE_INST_CLEANUPBLOCK: { // CLEANUPBLOCK: [ty, num,(ty,val)*]
if (Record.size() < 2)
return error("Invalid record");
unsigned Idx = 0;
Type *Ty = getTypeByID(Record[Idx++]);
if (!Ty)
return error("Invalid record");
unsigned NumArgOperands = Record[Idx++];
SmallVector<Value *, 2> Args;
for (unsigned Op = 0; Op != NumArgOperands; ++Op) {
Value *Val;
if (getValueTypePair(Record, Idx, NextValueNo, Val))
return error("Invalid record");
Args.push_back(Val);
}
if (Record.size() != Idx)
return error("Invalid record");
I = CleanupBlockInst::Create(Ty, Args);
InstructionList.push_back(I);
break;
}
case bitc::FUNC_CODE_INST_CATCHENDBLOCK: { // CATCHENDBLOCKINST: [bb#] or []
if (Record.size() > 1)
return error("Invalid record");
BasicBlock *BB = nullptr;
if (Record.size() == 1) {
BB = getBasicBlock(Record[0]);
if (!BB)
return error("Invalid record");
}
I = CatchEndBlockInst::Create(Context, BB);
InstructionList.push_back(I);
break;
}
case bitc::FUNC_CODE_INST_SWITCH: { // SWITCH: [opty, op0, op1, ...]
// Check magic
if ((Record[0] >> 16) == SWITCH_INST_MAGIC) {