mirror of
https://github.com/c64scene-ar/llvm-6502.git
synced 2025-02-22 13:29:44 +00:00
[WinEH] Make llvm.eh.actions use frameescape indices for catch params
This makes it possible to use the same representation of llvm.eh.actions in outlined handlers as we use in the parent function because i32's are just constants that can be copied freely between functions. I had to add a sentinel alloca to the list of child allocas so that we don't try to sink the catch object into the handler. Normally, one would use nullptr for this kind of thing, but TinyPtrVector doesn't support null elements. More than that, it's elements have to have a suitable alignment. Therefore, I settled on this for my sentinel: AllocaInst *getCatchObjectSentinel() { return static_cast<AllocaInst *>(nullptr) + 1; } git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@233947 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
parent
5b93ab6cde
commit
df4fd4fc4e
@ -519,25 +519,29 @@ action.
|
|||||||
|
|
||||||
A code of ``i32 1`` indicates a catch action, which expects three additional
|
A code of ``i32 1`` indicates a catch action, which expects three additional
|
||||||
arguments. Different EH schemes give different meanings to the three arguments,
|
arguments. Different EH schemes give different meanings to the three arguments,
|
||||||
but the first argument indicates whether the catch should fire, the second is a
|
but the first argument indicates whether the catch should fire, the second is
|
||||||
pointer to stack object where the exception object should be stored, and the
|
the frameescape index of the exception object, and the third is the code to run
|
||||||
third is the code to run to catch the exception.
|
to catch the exception.
|
||||||
|
|
||||||
For Windows C++ exception handling, the first argument for a catch handler is a
|
For Windows C++ exception handling, the first argument for a catch handler is a
|
||||||
pointer to the RTTI type descriptor for the object to catch. The third argument
|
pointer to the RTTI type descriptor for the object to catch. The second
|
||||||
is a pointer to a function implementing the catch. This function returns the
|
argument is an index into the argument list of the ``llvm.frameescape`` call in
|
||||||
address of the basic block where execution should resume after handling the
|
the main function. The exception object will be copied into the provided stack
|
||||||
exception.
|
object. If the exception object is not required, this argument should be -1.
|
||||||
|
The third argument is a pointer to a function implementing the catch. This
|
||||||
|
function returns the address of the basic block where execution should resume
|
||||||
|
after handling the exception.
|
||||||
|
|
||||||
For Windows SEH, the first argument is a pointer to the filter function, which
|
For Windows SEH, the first argument is a pointer to the filter function, which
|
||||||
indicates if the exception should be caught or not. The second argument is
|
indicates if the exception should be caught or not. The second argument is
|
||||||
typically null. The third argument is the address of a basic block where the
|
typically negative one. The third argument is the address of a basic block
|
||||||
exception will be handled. In other words, catch handlers are not outlined in
|
where the exception will be handled. In other words, catch handlers are not
|
||||||
SEH. After running cleanups, execution immediately resumes at this PC.
|
outlined in SEH. After running cleanups, execution immediately resumes at this
|
||||||
|
PC.
|
||||||
|
|
||||||
In order to preserve the structure of the CFG, a call to '``llvm.eh.actions``'
|
In order to preserve the structure of the CFG, a call to '``llvm.eh.actions``'
|
||||||
must be followed by an ':ref:`indirectbr <i_indirectbr>`' instruction that jumps
|
must be followed by an ':ref:`indirectbr <i_indirectbr>`' instruction that
|
||||||
to the result of the intrinsic call.
|
jumps to the result of the intrinsic call.
|
||||||
|
|
||||||
``llvm.eh.unwindhelp``
|
``llvm.eh.unwindhelp``
|
||||||
----------------------
|
----------------------
|
||||||
|
@ -52,6 +52,12 @@ namespace {
|
|||||||
// frame allocation structure.
|
// frame allocation structure.
|
||||||
typedef MapVector<Value *, TinyPtrVector<AllocaInst *>> FrameVarInfoMap;
|
typedef MapVector<Value *, TinyPtrVector<AllocaInst *>> FrameVarInfoMap;
|
||||||
|
|
||||||
|
// TinyPtrVector cannot hold nullptr, so we need our own sentinel that isn't
|
||||||
|
// quite null.
|
||||||
|
AllocaInst *getCatchObjectSentinel() {
|
||||||
|
return static_cast<AllocaInst *>(nullptr) + 1;
|
||||||
|
}
|
||||||
|
|
||||||
typedef SmallSet<BasicBlock *, 4> VisitedBlockSet;
|
typedef SmallSet<BasicBlock *, 4> VisitedBlockSet;
|
||||||
|
|
||||||
class LandingPadActions;
|
class LandingPadActions;
|
||||||
@ -107,6 +113,8 @@ public:
|
|||||||
|
|
||||||
virtual Value *materializeValueFor(Value *V) override;
|
virtual Value *materializeValueFor(Value *V) override;
|
||||||
|
|
||||||
|
void escapeCatchObject(Value *V);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
FrameVarInfoMap &FrameVarInfo;
|
FrameVarInfoMap &FrameVarInfo;
|
||||||
IRBuilder<> Builder;
|
IRBuilder<> Builder;
|
||||||
@ -193,13 +201,13 @@ public:
|
|||||||
CloningAction handleResume(ValueToValueMapTy &VMap, const ResumeInst *Resume,
|
CloningAction handleResume(ValueToValueMapTy &VMap, const ResumeInst *Resume,
|
||||||
BasicBlock *NewBB) override;
|
BasicBlock *NewBB) override;
|
||||||
|
|
||||||
const Value *getExceptionVar() { return ExceptionObjectVar; }
|
Value *getExceptionVar() { return ExceptionObjectVar; }
|
||||||
TinyPtrVector<BasicBlock *> &getReturnTargets() { return ReturnTargets; }
|
TinyPtrVector<BasicBlock *> &getReturnTargets() { return ReturnTargets; }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
Value *CurrentSelector;
|
Value *CurrentSelector;
|
||||||
|
|
||||||
const Value *ExceptionObjectVar;
|
Value *ExceptionObjectVar;
|
||||||
TinyPtrVector<BasicBlock *> ReturnTargets;
|
TinyPtrVector<BasicBlock *> ReturnTargets;
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -405,11 +413,17 @@ bool WinEHPrepare::prepareExceptionHandlers(
|
|||||||
if (auto *CatchAction = dyn_cast<CatchHandler>(Action)) {
|
if (auto *CatchAction = dyn_cast<CatchHandler>(Action)) {
|
||||||
ActionArgs.push_back(ConstantInt::get(Int32Type, 1));
|
ActionArgs.push_back(ConstantInt::get(Int32Type, 1));
|
||||||
ActionArgs.push_back(CatchAction->getSelector());
|
ActionArgs.push_back(CatchAction->getSelector());
|
||||||
|
// Find the frame escape index of the exception object alloca in the
|
||||||
|
// parent.
|
||||||
|
int FrameEscapeIdx = -1;
|
||||||
Value *EHObj = const_cast<Value *>(CatchAction->getExceptionVar());
|
Value *EHObj = const_cast<Value *>(CatchAction->getExceptionVar());
|
||||||
if (EHObj)
|
if (EHObj && !isa<ConstantPointerNull>(EHObj)) {
|
||||||
ActionArgs.push_back(EHObj);
|
auto I = FrameVarInfo.find(EHObj);
|
||||||
else
|
assert(I != FrameVarInfo.end() &&
|
||||||
ActionArgs.push_back(ConstantPointerNull::get(Int8PtrType));
|
"failed to map llvm.eh.begincatch var");
|
||||||
|
FrameEscapeIdx = std::distance(FrameVarInfo.begin(), I);
|
||||||
|
}
|
||||||
|
ActionArgs.push_back(ConstantInt::get(Int32Type, FrameEscapeIdx));
|
||||||
} else {
|
} else {
|
||||||
ActionArgs.push_back(ConstantInt::get(Int32Type, 0));
|
ActionArgs.push_back(ConstantInt::get(Int32Type, 0));
|
||||||
}
|
}
|
||||||
@ -495,10 +509,15 @@ bool WinEHPrepare::prepareExceptionHandlers(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// If the parent alloca is no longer used and only one of the handlers used
|
// If the parent alloca is used by exactly one handler and is not a catch
|
||||||
// it, erase the parent and leave the copy in the outlined handler.
|
// parameter, erase the parent and leave the copy in the outlined handler.
|
||||||
if (ParentAlloca->getNumUses() == 0 && Allocas.size() == 1) {
|
// Catch parameters are indicated by a single null pointer in Allocas.
|
||||||
|
if (ParentAlloca->getNumUses() == 0 && Allocas.size() == 1 &&
|
||||||
|
Allocas[0] != getCatchObjectSentinel()) {
|
||||||
ParentAlloca->eraseFromParent();
|
ParentAlloca->eraseFromParent();
|
||||||
|
// FIXME: Put a null entry in the llvm.frameescape call because we've
|
||||||
|
// already created llvm.eh.actions calls with indices into it.
|
||||||
|
AllocasToEscape.push_back(Constant::getNullValue(Int8PtrType));
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -507,6 +526,8 @@ bool WinEHPrepare::prepareExceptionHandlers(
|
|||||||
|
|
||||||
// Next replace all outlined allocas that are mapped to it.
|
// Next replace all outlined allocas that are mapped to it.
|
||||||
for (AllocaInst *TempAlloca : Allocas) {
|
for (AllocaInst *TempAlloca : Allocas) {
|
||||||
|
if (TempAlloca == getCatchObjectSentinel())
|
||||||
|
continue; // Skip catch parameter sentinels.
|
||||||
Function *HandlerFn = TempAlloca->getParent()->getParent();
|
Function *HandlerFn = TempAlloca->getParent()->getParent();
|
||||||
// FIXME: Sink this GEP into the blocks where it is used.
|
// FIXME: Sink this GEP into the blocks where it is used.
|
||||||
Builder.SetInsertPoint(TempAlloca);
|
Builder.SetInsertPoint(TempAlloca);
|
||||||
@ -859,6 +880,11 @@ CloningDirector::CloningAction WinEHCatchDirector::handleBeginCatch(
|
|||||||
"llvm.eh.begincatch found while "
|
"llvm.eh.begincatch found while "
|
||||||
"outlining catch handler.");
|
"outlining catch handler.");
|
||||||
ExceptionObjectVar = Inst->getOperand(1)->stripPointerCasts();
|
ExceptionObjectVar = Inst->getOperand(1)->stripPointerCasts();
|
||||||
|
if (isa<ConstantPointerNull>(ExceptionObjectVar))
|
||||||
|
return CloningDirector::SkipInstruction;
|
||||||
|
AllocaInst *AI = dyn_cast<AllocaInst>(ExceptionObjectVar);
|
||||||
|
assert(AI && AI->isStaticAlloca() && "catch parameter is not static alloca");
|
||||||
|
Materializer.escapeCatchObject(ExceptionObjectVar);
|
||||||
return CloningDirector::SkipInstruction;
|
return CloningDirector::SkipInstruction;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1045,6 +1071,15 @@ Value *WinEHFrameVariableMaterializer::materializeValueFor(Value *V) {
|
|||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void WinEHFrameVariableMaterializer::escapeCatchObject(Value *V) {
|
||||||
|
// Catch parameter objects have to live in the parent frame. When we see a use
|
||||||
|
// of a catch parameter, add a sentinel to the multimap to indicate that it's
|
||||||
|
// used from another handler. This will prevent us from trying to sink the
|
||||||
|
// alloca into the handler and ensure that the catch parameter is present in
|
||||||
|
// the call to llvm.frameescape.
|
||||||
|
FrameVarInfo[V].push_back(getCatchObjectSentinel());
|
||||||
|
}
|
||||||
|
|
||||||
// This function maps the catch and cleanup handlers that are reachable from the
|
// This function maps the catch and cleanup handlers that are reachable from the
|
||||||
// specified landing pad. The landing pad sequence will have this basic shape:
|
// specified landing pad. The landing pad sequence will have this basic shape:
|
||||||
//
|
//
|
||||||
|
@ -3204,6 +3204,8 @@ void Verifier::visitIntrinsicFunctionCall(Intrinsic::ID ID, CallInst &CI) {
|
|||||||
Assert(!SawFrameEscape,
|
Assert(!SawFrameEscape,
|
||||||
"multiple calls to llvm.frameescape in one function", &CI);
|
"multiple calls to llvm.frameescape in one function", &CI);
|
||||||
for (Value *Arg : CI.arg_operands()) {
|
for (Value *Arg : CI.arg_operands()) {
|
||||||
|
if (isa<ConstantPointerNull>(Arg))
|
||||||
|
continue; // Null values are allowed as placeholders.
|
||||||
auto *AI = dyn_cast<AllocaInst>(Arg->stripPointerCasts());
|
auto *AI = dyn_cast<AllocaInst>(Arg->stripPointerCasts());
|
||||||
Assert(AI && AI->isStaticAlloca(),
|
Assert(AI && AI->isStaticAlloca(),
|
||||||
"llvm.frameescape only accepts static allocas", &CI);
|
"llvm.frameescape only accepts static allocas", &CI);
|
||||||
|
@ -38,7 +38,7 @@ invoke.cont: ; preds = %entry
|
|||||||
; CHECK: [[LPAD_LABEL]]:{{[ ]+}}; preds = %entry
|
; CHECK: [[LPAD_LABEL]]:{{[ ]+}}; preds = %entry
|
||||||
; CHECK: landingpad { i8*, i32 } personality i8* bitcast (i32 (...)* @__CxxFrameHandler3 to i8*)
|
; CHECK: landingpad { i8*, i32 } personality i8* bitcast (i32 (...)* @__CxxFrameHandler3 to i8*)
|
||||||
; CHECK-NEXT: catch i8* null
|
; CHECK-NEXT: catch i8* null
|
||||||
; CHECK-NEXT: [[RECOVER:\%.+]] = call i8* (...)* @llvm.eh.actions(i32 1, i8* null, i8* null, i8* (i8*, i8*)* @_Z4testv.catch)
|
; CHECK-NEXT: [[RECOVER:\%.+]] = call i8* (...)* @llvm.eh.actions(i32 1, i8* null, i32 -1, i8* (i8*, i8*)* @_Z4testv.catch)
|
||||||
; CHECK-NEXT: indirectbr i8* [[RECOVER]], [label %try.cont]
|
; CHECK-NEXT: indirectbr i8* [[RECOVER]], [label %try.cont]
|
||||||
|
|
||||||
lpad: ; preds = %entry
|
lpad: ; preds = %entry
|
||||||
|
@ -43,7 +43,7 @@ invoke.cont: ; preds = %entry
|
|||||||
; CHECK: [[LPAD_LABEL]]:{{[ ]+}}; preds = %entry
|
; CHECK: [[LPAD_LABEL]]:{{[ ]+}}; preds = %entry
|
||||||
; CHECK: landingpad { i8*, i32 } personality i8* bitcast (i32 (...)* @__CxxFrameHandler3 to i8*)
|
; CHECK: landingpad { i8*, i32 } personality i8* bitcast (i32 (...)* @__CxxFrameHandler3 to i8*)
|
||||||
; CHECK-NEXT: catch i8* bitcast (i8** @_ZTIi to i8*)
|
; CHECK-NEXT: catch i8* bitcast (i8** @_ZTIi to i8*)
|
||||||
; CHECK-NEXT: [[RECOVER:\%.+]] = call i8* (...)* @llvm.eh.actions(i32 1, i8* bitcast (i8** @_ZTIi to i8*), i32* %i, i8* (i8*, i8*)* @_Z4testv.catch)
|
; CHECK-NEXT: [[RECOVER:\%.+]] = call i8* (...)* @llvm.eh.actions(i32 1, i8* bitcast (i8** @_ZTIi to i8*), i32 0, i8* (i8*, i8*)* @_Z4testv.catch)
|
||||||
; CHECK-NEXT: indirectbr i8* [[RECOVER]], [label %try.cont]
|
; CHECK-NEXT: indirectbr i8* [[RECOVER]], [label %try.cont]
|
||||||
|
|
||||||
lpad: ; preds = %entry
|
lpad: ; preds = %entry
|
||||||
|
@ -71,7 +71,7 @@ invoke.cont2: ; preds = %invoke.cont
|
|||||||
; CHECK: [[LPAD_LABEL]]:{{[ ]+}}; preds = %entry
|
; CHECK: [[LPAD_LABEL]]:{{[ ]+}}; preds = %entry
|
||||||
; CHECK: [[LPAD_VAL:\%.+]] = landingpad { i8*, i32 } personality i8* bitcast (i32 (...)* @__CxxFrameHandler3 to i8*)
|
; CHECK: [[LPAD_VAL:\%.+]] = landingpad { i8*, i32 } personality i8* bitcast (i32 (...)* @__CxxFrameHandler3 to i8*)
|
||||||
; CHECK-NEXT: catch i8* bitcast (%rtti.TypeDescriptor2* @"\01??_R0H@8" to i8*)
|
; CHECK-NEXT: catch i8* bitcast (%rtti.TypeDescriptor2* @"\01??_R0H@8" to i8*)
|
||||||
; CHECK-NEXT: [[RECOVER:\%.+]] = call i8* (...)* @llvm.eh.actions(i32 1, i8* bitcast (%rtti.TypeDescriptor2* @"\01??_R0H@8" to i8*), i32* [[TMP1]], i8* (i8*, i8*)* @"\01?test@@YAXXZ.catch")
|
; CHECK-NEXT: [[RECOVER:\%.+]] = call i8* (...)* @llvm.eh.actions(i32 1, i8* bitcast (%rtti.TypeDescriptor2* @"\01??_R0H@8" to i8*), i32 0, i8* (i8*, i8*)* @"\01?test@@YAXXZ.catch")
|
||||||
; CHECK-NEXT: indirectbr i8* [[RECOVER]], [label %try.cont15]
|
; CHECK-NEXT: indirectbr i8* [[RECOVER]], [label %try.cont15]
|
||||||
|
|
||||||
lpad: ; preds = %entry
|
lpad: ; preds = %entry
|
||||||
@ -85,7 +85,7 @@ lpad: ; preds = %entry
|
|||||||
; CHECK: [[LPAD1_VAL:\%.+]] = landingpad { i8*, i32 } personality i8* bitcast (i32 (...)* @__CxxFrameHandler3 to i8*)
|
; CHECK: [[LPAD1_VAL:\%.+]] = landingpad { i8*, i32 } personality i8* bitcast (i32 (...)* @__CxxFrameHandler3 to i8*)
|
||||||
; CHECK-NEXT: cleanup
|
; CHECK-NEXT: cleanup
|
||||||
; CHECK-NEXT: catch i8* bitcast (%rtti.TypeDescriptor2* @"\01??_R0H@8" to i8*)
|
; CHECK-NEXT: catch i8* bitcast (%rtti.TypeDescriptor2* @"\01??_R0H@8" to i8*)
|
||||||
; CHECK-NEXT: [[RECOVER1:\%.+]] = call i8* (...)* @llvm.eh.actions(i32 0, void (i8*, i8*)* @"\01?test@@YAXXZ.cleanup", i32 1, i8* bitcast (%rtti.TypeDescriptor2* @"\01??_R0H@8" to i8*), i32* [[TMP1]], i8* (i8*, i8*)* @"\01?test@@YAXXZ.catch")
|
; CHECK-NEXT: [[RECOVER1:\%.+]] = call i8* (...)* @llvm.eh.actions(i32 0, void (i8*, i8*)* @"\01?test@@YAXXZ.cleanup", i32 1, i8* bitcast (%rtti.TypeDescriptor2* @"\01??_R0H@8" to i8*), i32 0, i8* (i8*, i8*)* @"\01?test@@YAXXZ.catch")
|
||||||
; CHECK-NEXT: indirectbr i8* [[RECOVER1]], [label %try.cont15]
|
; CHECK-NEXT: indirectbr i8* [[RECOVER1]], [label %try.cont15]
|
||||||
|
|
||||||
lpad1: ; preds = %invoke.cont
|
lpad1: ; preds = %invoke.cont
|
||||||
@ -100,7 +100,7 @@ lpad1: ; preds = %invoke.cont
|
|||||||
; CHECK: [[LPAD3_VAL:\%.+]] = landingpad { i8*, i32 } personality i8* bitcast (i32 (...)* @__CxxFrameHandler3 to i8*)
|
; CHECK: [[LPAD3_VAL:\%.+]] = landingpad { i8*, i32 } personality i8* bitcast (i32 (...)* @__CxxFrameHandler3 to i8*)
|
||||||
; CHECK-NEXT: cleanup
|
; CHECK-NEXT: cleanup
|
||||||
; CHECK-NEXT: catch i8* bitcast (%rtti.TypeDescriptor2* @"\01??_R0H@8" to i8*)
|
; CHECK-NEXT: catch i8* bitcast (%rtti.TypeDescriptor2* @"\01??_R0H@8" to i8*)
|
||||||
; CHECK-NEXT: [[RECOVER3:\%.+]] = call i8* (...)* @llvm.eh.actions(i32 1, i8* bitcast (%rtti.TypeDescriptor2* @"\01??_R0H@8" to i8*), i32* [[TMP0]], i8* (i8*, i8*)* @"\01?test@@YAXXZ.catch1", i32 0, void (i8*, i8*)* @"\01?test@@YAXXZ.cleanup")
|
; CHECK-NEXT: [[RECOVER3:\%.+]] = call i8* (...)* @llvm.eh.actions(i32 1, i8* bitcast (%rtti.TypeDescriptor2* @"\01??_R0H@8" to i8*), i32 2, i8* (i8*, i8*)* @"\01?test@@YAXXZ.catch1", i32 0, void (i8*, i8*)* @"\01?test@@YAXXZ.cleanup")
|
||||||
; CHECK-NEXT: indirectbr i8* [[RECOVER3]], [label %try.cont]
|
; CHECK-NEXT: indirectbr i8* [[RECOVER3]], [label %try.cont]
|
||||||
|
|
||||||
lpad3: ; preds = %invoke.cont2
|
lpad3: ; preds = %invoke.cont2
|
||||||
|
@ -101,7 +101,7 @@ invoke.cont: ; preds = %for.body
|
|||||||
; CHECK: [[LPAD_LABEL]]:{{[ ]+}}; preds = %for.body
|
; CHECK: [[LPAD_LABEL]]:{{[ ]+}}; preds = %for.body
|
||||||
; CHECK: landingpad { i8*, i32 } personality i8* bitcast (i32 (...)* @__CxxFrameHandler3 to i8*)
|
; CHECK: landingpad { i8*, i32 } personality i8* bitcast (i32 (...)* @__CxxFrameHandler3 to i8*)
|
||||||
; CHECK-NEXT: catch i8* bitcast (%rtti.TypeDescriptor2* @"\01??_R0H@8" to i8*)
|
; CHECK-NEXT: catch i8* bitcast (%rtti.TypeDescriptor2* @"\01??_R0H@8" to i8*)
|
||||||
; CHECK-NEXT: [[RECOVER:\%.+]] = call i8* (...)* @llvm.eh.actions(i32 1, i8* bitcast (%rtti.TypeDescriptor2* @"\01??_R0H@8" to i8*), i32* %e, i8* (i8*, i8*)* @"\01?test@@YAXXZ.catch")
|
; CHECK-NEXT: [[RECOVER:\%.+]] = call i8* (...)* @llvm.eh.actions(i32 1, i8* bitcast (%rtti.TypeDescriptor2* @"\01??_R0H@8" to i8*), i32 0, i8* (i8*, i8*)* @"\01?test@@YAXXZ.catch")
|
||||||
; CHECK-NEXT: indirectbr i8* [[RECOVER]], [label %try.cont]
|
; CHECK-NEXT: indirectbr i8* [[RECOVER]], [label %try.cont]
|
||||||
|
|
||||||
lpad: ; preds = %for.body
|
lpad: ; preds = %for.body
|
||||||
|
@ -65,7 +65,7 @@ invoke.cont: ; preds = %entry
|
|||||||
; CHECK: landingpad { i8*, i32 } personality i8* bitcast (i32 (...)* @__CxxFrameHandler3 to i8*)
|
; CHECK: landingpad { i8*, i32 } personality i8* bitcast (i32 (...)* @__CxxFrameHandler3 to i8*)
|
||||||
; CHECK-NEXT: cleanup
|
; CHECK-NEXT: cleanup
|
||||||
; CHECK-NEXT: catch i8* bitcast (%rtti.TypeDescriptor2* @"\01??_R0H@8" to i8*)
|
; CHECK-NEXT: catch i8* bitcast (%rtti.TypeDescriptor2* @"\01??_R0H@8" to i8*)
|
||||||
; CHECK-NEXT: [[RECOVER:\%recover.*]] = call i8* (...)* @llvm.eh.actions(i32 1, i8* bitcast (%rtti.TypeDescriptor2* @"\01??_R0H@8" to i8*), i32* %e, i8* (i8*, i8*)* @"\01?test@@YAHUA@@@Z.catch", i32 0, void (i8*, i8*)* @"\01?test@@YAHUA@@@Z.cleanup")
|
; CHECK-NEXT: [[RECOVER:\%recover.*]] = call i8* (...)* @llvm.eh.actions(i32 1, i8* bitcast (%rtti.TypeDescriptor2* @"\01??_R0H@8" to i8*), i32 0, i8* (i8*, i8*)* @"\01?test@@YAHUA@@@Z.catch", i32 0, void (i8*, i8*)* @"\01?test@@YAHUA@@@Z.cleanup")
|
||||||
; CHECK-NEXT: indirectbr i8* [[RECOVER]], [label %cleanup]
|
; CHECK-NEXT: indirectbr i8* [[RECOVER]], [label %cleanup]
|
||||||
|
|
||||||
lpad: ; preds = %entry
|
lpad: ; preds = %entry
|
||||||
|
@ -78,7 +78,11 @@ invoke.cont: ; preds = %entry
|
|||||||
; CHECK-NEXT: catch %eh.HandlerMapEntry* @llvm.eh.handlermapentry._J
|
; CHECK-NEXT: catch %eh.HandlerMapEntry* @llvm.eh.handlermapentry._J
|
||||||
; CHECK-NEXT: catch %eh.HandlerMapEntry* @"llvm.eh.handlermapentry.reference.?AVSomeClass@@"
|
; CHECK-NEXT: catch %eh.HandlerMapEntry* @"llvm.eh.handlermapentry.reference.?AVSomeClass@@"
|
||||||
; CHECK-NEXT: catch i8* null
|
; CHECK-NEXT: catch i8* null
|
||||||
; CHECK-NEXT: [[RECOVER:\%.+]] = call i8* (...)* @llvm.eh.actions(i32 1, i8* bitcast (%eh.HandlerMapEntry* @llvm.eh.handlermapentry.H to i8*), i32* %i, i8* (i8*, i8*)* @"\01?test@@YAXXZ.catch", i32 1, i8* bitcast (%eh.HandlerMapEntry* @llvm.eh.handlermapentry._J to i8*), i64* %ll, i8* (i8*, i8*)* @"\01?test@@YAXXZ.catch1", i32 1, i8* bitcast (%eh.HandlerMapEntry* @"llvm.eh.handlermapentry.reference.?AVSomeClass@@" to i8*), %class.SomeClass** %obj, i8* (i8*, i8*)* @"\01?test@@YAXXZ.catch2", i32 1, i8* null, i8* null, i8* (i8*, i8*)* @"\01?test@@YAXXZ.catch3")
|
; CHECK-NEXT: [[RECOVER:\%.+]] = call i8* (...)* @llvm.eh.actions(
|
||||||
|
; CHECK-SAME: i32 1, i8* bitcast (%eh.HandlerMapEntry* @llvm.eh.handlermapentry.H to i8*), i32 0, i8* (i8*, i8*)* @"\01?test@@YAXXZ.catch",
|
||||||
|
; CHECK-SAME: i32 1, i8* bitcast (%eh.HandlerMapEntry* @llvm.eh.handlermapentry._J to i8*), i32 1, i8* (i8*, i8*)* @"\01?test@@YAXXZ.catch1",
|
||||||
|
; CHECK-SAME: i32 1, i8* bitcast (%eh.HandlerMapEntry* @"llvm.eh.handlermapentry.reference.?AVSomeClass@@" to i8*), i32 2, i8* (i8*, i8*)* @"\01?test@@YAXXZ.catch2",
|
||||||
|
; CHECK-SAME: i32 1, i8* null, i32 -1, i8* (i8*, i8*)* @"\01?test@@YAXXZ.catch3")
|
||||||
; CHECK-NEXT: indirectbr i8* [[RECOVER]], [label %catch14.split, label %catch10.split, label %catch6.split, label %catch.split]
|
; CHECK-NEXT: indirectbr i8* [[RECOVER]], [label %catch14.split, label %catch10.split, label %catch6.split, label %catch.split]
|
||||||
|
|
||||||
lpad: ; preds = %entry
|
lpad: ; preds = %entry
|
||||||
|
@ -93,7 +93,7 @@ invoke.cont5: ; preds = %invoke.cont4
|
|||||||
; CHECK: [[LPAD_LABEL]]:
|
; CHECK: [[LPAD_LABEL]]:
|
||||||
; CHECK: landingpad { i8*, i32 } personality i8* bitcast (i32 (...)* @__CxxFrameHandler3 to i8*)
|
; CHECK: landingpad { i8*, i32 } personality i8* bitcast (i32 (...)* @__CxxFrameHandler3 to i8*)
|
||||||
; CHECK-NEXT: catch i8* bitcast (i8** @_ZTIf to i8*)
|
; CHECK-NEXT: catch i8* bitcast (i8** @_ZTIf to i8*)
|
||||||
; CHECK-NEXT: [[RECOVER:\%.+]] = call i8* (...)* @llvm.eh.actions(i32 1, i8* bitcast (i8** @_ZTIf to i8*), float* %f, i8* (i8*, i8*)* @_Z4testv.catch)
|
; CHECK-NEXT: [[RECOVER:\%.+]] = call i8* (...)* @llvm.eh.actions(i32 1, i8* bitcast (i8** @_ZTIf to i8*), i32 0, i8* (i8*, i8*)* @_Z4testv.catch)
|
||||||
; CHECK-NEXT: indirectbr i8* [[RECOVER]], [label %try.cont19]
|
; CHECK-NEXT: indirectbr i8* [[RECOVER]], [label %try.cont19]
|
||||||
|
|
||||||
lpad: ; preds = %try.cont, %entry
|
lpad: ; preds = %try.cont, %entry
|
||||||
@ -111,9 +111,9 @@ lpad: ; preds = %try.cont, %entry
|
|||||||
; CHECK-NEXT: catch i8* bitcast (i8** @_ZTIi to i8*)
|
; CHECK-NEXT: catch i8* bitcast (i8** @_ZTIi to i8*)
|
||||||
; CHECK-NEXT: catch i8* bitcast (i8** @_ZTIf to i8*)
|
; CHECK-NEXT: catch i8* bitcast (i8** @_ZTIf to i8*)
|
||||||
; CHECK-NEXT: [[RECOVER1:\%.+]] = call i8* (...)* @llvm.eh.actions(
|
; CHECK-NEXT: [[RECOVER1:\%.+]] = call i8* (...)* @llvm.eh.actions(
|
||||||
; CHECK-SAME: i32 1, i8* bitcast (i8** @_ZTIi to i8*), i32* %i, i8* (i8*, i8*)* @_Z4testv.catch1,
|
; CHECK-SAME: i32 1, i8* bitcast (i8** @_ZTIi to i8*), i32 1, i8* (i8*, i8*)* @_Z4testv.catch1,
|
||||||
; CHECK-SAME: i32 0, void (i8*, i8*)* @_Z4testv.cleanup,
|
; CHECK-SAME: i32 0, void (i8*, i8*)* @_Z4testv.cleanup,
|
||||||
; CHECK-SAME: i32 1, i8* bitcast (i8** @_ZTIf to i8*), float* %f, i8* (i8*, i8*)* @_Z4testv.catch)
|
; CHECK-SAME: i32 1, i8* bitcast (i8** @_ZTIf to i8*), i32 0, i8* (i8*, i8*)* @_Z4testv.catch)
|
||||||
; CHECK-NEXT: indirectbr i8* [[RECOVER1]], [label %try.cont, label %try.cont19]
|
; CHECK-NEXT: indirectbr i8* [[RECOVER1]], [label %try.cont, label %try.cont19]
|
||||||
|
|
||||||
lpad1: ; preds = %invoke.cont4, %invoke.cont
|
lpad1: ; preds = %invoke.cont4, %invoke.cont
|
||||||
@ -134,9 +134,9 @@ lpad1: ; preds = %invoke.cont4, %invo
|
|||||||
; CHECK-NEXT: catch i8* bitcast (i8** @_ZTIf to i8*)
|
; CHECK-NEXT: catch i8* bitcast (i8** @_ZTIf to i8*)
|
||||||
; CHECK-NEXT: [[RECOVER3:\%.+]] = call i8* (...)* @llvm.eh.actions(
|
; CHECK-NEXT: [[RECOVER3:\%.+]] = call i8* (...)* @llvm.eh.actions(
|
||||||
; CHECK-SAME: i32 0, void (i8*, i8*)* @_Z4testv.cleanup2,
|
; CHECK-SAME: i32 0, void (i8*, i8*)* @_Z4testv.cleanup2,
|
||||||
; CHECK-SAME: i32 1, i8* bitcast (i8** @_ZTIi to i8*), i32* %i, i8* (i8*, i8*)* @_Z4testv.catch1,
|
; CHECK-SAME: i32 1, i8* bitcast (i8** @_ZTIi to i8*), i32 1, i8* (i8*, i8*)* @_Z4testv.catch1,
|
||||||
; CHECK-SAME: i32 0, void (i8*, i8*)* @_Z4testv.cleanup,
|
; CHECK-SAME: i32 0, void (i8*, i8*)* @_Z4testv.cleanup,
|
||||||
; CHECK-SAME: i32 1, i8* bitcast (i8** @_ZTIf to i8*), float* %f, i8* (i8*, i8*)* @_Z4testv.catch)
|
; CHECK-SAME: i32 1, i8* bitcast (i8** @_ZTIf to i8*), i32 0, i8* (i8*, i8*)* @_Z4testv.catch)
|
||||||
; CHECK-NEXT: indirectbr i8* [[RECOVER3]], [label %try.cont, label %try.cont19]
|
; CHECK-NEXT: indirectbr i8* [[RECOVER3]], [label %try.cont, label %try.cont19]
|
||||||
|
|
||||||
lpad3: ; preds = %invoke.cont2
|
lpad3: ; preds = %invoke.cont2
|
||||||
|
@ -114,7 +114,7 @@ invoke.cont: ; preds = %for.body
|
|||||||
; CHECK: [[LPAD_LABEL:lpad[0-9]*]]:{{[ ]+}}; preds = %for.body
|
; CHECK: [[LPAD_LABEL:lpad[0-9]*]]:{{[ ]+}}; preds = %for.body
|
||||||
; CHECK: landingpad { i8*, i32 } personality i8* bitcast (i32 (...)* @__CxxFrameHandler3 to i8*)
|
; CHECK: landingpad { i8*, i32 } personality i8* bitcast (i32 (...)* @__CxxFrameHandler3 to i8*)
|
||||||
; CHECK-NEXT: catch i8* bitcast (%rtti.TypeDescriptor2* @"\01??_R0H@8" to i8*)
|
; CHECK-NEXT: catch i8* bitcast (%rtti.TypeDescriptor2* @"\01??_R0H@8" to i8*)
|
||||||
; CHECK-NEXT: [[RECOVER:\%.+]] = call i8* (...)* @llvm.eh.actions(i32 1, i8* bitcast (%rtti.TypeDescriptor2* @"\01??_R0H@8" to i8*), i32* %e, i8* (i8*, i8*)* @"\01?test@@YAXXZ.catch")
|
; CHECK-NEXT: [[RECOVER:\%.+]] = call i8* (...)* @llvm.eh.actions(i32 1, i8* bitcast (%rtti.TypeDescriptor2* @"\01??_R0H@8" to i8*), i32 0, i8* (i8*, i8*)* @"\01?test@@YAXXZ.catch")
|
||||||
; CHECK-NEXT: indirectbr i8* [[RECOVER]], [label %try.cont]
|
; CHECK-NEXT: indirectbr i8* [[RECOVER]], [label %try.cont]
|
||||||
|
|
||||||
lpad: ; preds = %for.body
|
lpad: ; preds = %for.body
|
||||||
|
@ -39,7 +39,7 @@ eh.resume:
|
|||||||
; CHECK-LABEL: define i32 @simple_except_store()
|
; CHECK-LABEL: define i32 @simple_except_store()
|
||||||
; CHECK: landingpad { i8*, i32 }
|
; CHECK: landingpad { i8*, i32 }
|
||||||
; CHECK-NEXT: catch i32 ()* @filt
|
; CHECK-NEXT: catch i32 ()* @filt
|
||||||
; CHECK-NEXT: call i8* (...)* @llvm.eh.actions(i32 1, i8* bitcast (i32 ()* @filt to i8*), i8* null, i8* blockaddress(@simple_except_store, %__except))
|
; CHECK-NEXT: call i8* (...)* @llvm.eh.actions(i32 1, i8* bitcast (i32 ()* @filt to i8*), i32 -1, i8* blockaddress(@simple_except_store, %__except))
|
||||||
; CHECK-NEXT: indirectbr {{.*}} [label %__except]
|
; CHECK-NEXT: indirectbr {{.*}} [label %__except]
|
||||||
|
|
||||||
define i32 @catch_all() {
|
define i32 @catch_all() {
|
||||||
@ -63,7 +63,7 @@ return:
|
|||||||
; CHECK-LABEL: define i32 @catch_all()
|
; CHECK-LABEL: define i32 @catch_all()
|
||||||
; CHECK: landingpad { i8*, i32 }
|
; CHECK: landingpad { i8*, i32 }
|
||||||
; CHECK-NEXT: catch i8* null
|
; CHECK-NEXT: catch i8* null
|
||||||
; CHECK-NEXT: call i8* (...)* @llvm.eh.actions(i32 1, i8* null, i8* null, i8* blockaddress(@catch_all, %catch.all))
|
; CHECK-NEXT: call i8* (...)* @llvm.eh.actions(i32 1, i8* null, i32 -1, i8* blockaddress(@catch_all, %catch.all))
|
||||||
; CHECK-NEXT: indirectbr {{.*}} [label %catch.all]
|
; CHECK-NEXT: indirectbr {{.*}} [label %catch.all]
|
||||||
;
|
;
|
||||||
; CHECK: catch.all:
|
; CHECK: catch.all:
|
||||||
@ -94,7 +94,7 @@ eh.resume:
|
|||||||
; CHECK-LABEL: define i32 @except_phi()
|
; CHECK-LABEL: define i32 @except_phi()
|
||||||
; CHECK: landingpad { i8*, i32 }
|
; CHECK: landingpad { i8*, i32 }
|
||||||
; CHECK-NEXT: catch i32 ()* @filt
|
; CHECK-NEXT: catch i32 ()* @filt
|
||||||
; CHECK-NEXT: call i8* (...)* @llvm.eh.actions(i32 1, i8* bitcast (i32 ()* @filt to i8*), i8* null, i8* blockaddress(@except_phi, %return))
|
; CHECK-NEXT: call i8* (...)* @llvm.eh.actions(i32 1, i8* bitcast (i32 ()* @filt to i8*), i32 -1, i8* blockaddress(@except_phi, %return))
|
||||||
; CHECK-NEXT: indirectbr {{.*}} [label %return]
|
; CHECK-NEXT: indirectbr {{.*}} [label %return]
|
||||||
;
|
;
|
||||||
; CHECK: return:
|
; CHECK: return:
|
||||||
@ -130,7 +130,7 @@ eh.resume:
|
|||||||
; CHECK-NEXT: catch i32 ()* @filt
|
; CHECK-NEXT: catch i32 ()* @filt
|
||||||
; CHECK-NEXT: call i8* (...)* @llvm.eh.actions(
|
; CHECK-NEXT: call i8* (...)* @llvm.eh.actions(
|
||||||
; CHECK: i32 0, void (i8*, i8*)* @cleanup_and_except.cleanup,
|
; CHECK: i32 0, void (i8*, i8*)* @cleanup_and_except.cleanup,
|
||||||
; CHECK: i32 1, i8* bitcast (i32 ()* @filt to i8*), i8* null, i8* blockaddress(@cleanup_and_except, %return))
|
; CHECK: i32 1, i8* bitcast (i32 ()* @filt to i8*), i32 -1, i8* blockaddress(@cleanup_and_except, %return))
|
||||||
; CHECK-NEXT: indirectbr {{.*}} [label %return]
|
; CHECK-NEXT: indirectbr {{.*}} [label %return]
|
||||||
;
|
;
|
||||||
; CHECK: return:
|
; CHECK: return:
|
||||||
|
Loading…
x
Reference in New Issue
Block a user