forked from OSchip/llvm-project
Move EH personality type classification to Analysis/LibCallSemantics.h
Summary: Also add enum types for __C_specific_handler and _CxxFrameHandler3 for which we know a few things. Reviewers: majnemer Subscribers: llvm-commits Differential Revision: http://reviews.llvm.org/D7214 llvm-svn: 227284
This commit is contained in:
parent
d1f2536829
commit
4af6415237
|
@ -162,6 +162,21 @@ namespace llvm {
|
|||
virtual const LibCallFunctionInfo *getFunctionInfoArray() const = 0;
|
||||
};
|
||||
|
||||
enum class EHPersonality {
|
||||
Unknown,
|
||||
GNU_Ada,
|
||||
GNU_C,
|
||||
GNU_CXX,
|
||||
GNU_ObjC,
|
||||
MSVC_Win64SEH,
|
||||
MSVC_CXX,
|
||||
};
|
||||
|
||||
/// ClassifyEHPersonality - See if the given exception handling personality
|
||||
/// function is one that we understand. If so, return a description of it;
|
||||
/// otherwise return Unknown_Personality.
|
||||
EHPersonality ClassifyEHPersonality(Value *Pers);
|
||||
|
||||
} // end namespace llvm
|
||||
|
||||
#endif
|
||||
|
|
|
@ -15,6 +15,7 @@
|
|||
|
||||
#include "llvm/Analysis/LibCallSemantics.h"
|
||||
#include "llvm/ADT/StringMap.h"
|
||||
#include "llvm/ADT/StringSwitch.h"
|
||||
#include "llvm/IR/Function.h"
|
||||
using namespace llvm;
|
||||
|
||||
|
@ -61,3 +62,18 @@ LibCallInfo::getFunctionInfo(const Function *F) const {
|
|||
return Map->lookup(F->getName());
|
||||
}
|
||||
|
||||
/// See if the given exception handling personality function is one that we
|
||||
/// understand. If so, return a description of it; otherwise return Unknown.
|
||||
EHPersonality llvm::ClassifyEHPersonality(Value *Pers) {
|
||||
Function *F = dyn_cast<Function>(Pers->stripPointerCasts());
|
||||
if (!F)
|
||||
return EHPersonality::Unknown;
|
||||
return StringSwitch<EHPersonality>(F->getName())
|
||||
.Case("__gnat_eh_personality", EHPersonality::GNU_Ada)
|
||||
.Case("__gxx_personality_v0", EHPersonality::GNU_CXX)
|
||||
.Case("__gcc_personality_v0", EHPersonality::GNU_C)
|
||||
.Case("__objc_personality_v0", EHPersonality::GNU_ObjC)
|
||||
.Case("__C_specific_handler", EHPersonality::MSVC_Win64SEH)
|
||||
.Case("__CxxFrameHandler3", EHPersonality::MSVC_CXX)
|
||||
.Default(EHPersonality::Unknown);
|
||||
}
|
||||
|
|
|
@ -43,6 +43,7 @@
|
|||
#include "llvm/Analysis/CFG.h"
|
||||
#include "llvm/Analysis/ConstantFolding.h"
|
||||
#include "llvm/Analysis/InstructionSimplify.h"
|
||||
#include "llvm/Analysis/LibCallSemantics.h"
|
||||
#include "llvm/Analysis/LoopInfo.h"
|
||||
#include "llvm/Analysis/MemoryBuiltins.h"
|
||||
#include "llvm/Analysis/TargetLibraryInfo.h"
|
||||
|
@ -2259,41 +2260,26 @@ Instruction *InstCombiner::visitExtractValueInst(ExtractValueInst &EV) {
|
|||
return nullptr;
|
||||
}
|
||||
|
||||
enum Personality_Type {
|
||||
Unknown_Personality,
|
||||
GNU_Ada_Personality,
|
||||
GNU_CXX_Personality,
|
||||
GNU_ObjC_Personality
|
||||
};
|
||||
|
||||
/// RecognizePersonality - See if the given exception handling personality
|
||||
/// function is one that we understand. If so, return a description of it;
|
||||
/// otherwise return Unknown_Personality.
|
||||
static Personality_Type RecognizePersonality(Value *Pers) {
|
||||
Function *F = dyn_cast<Function>(Pers->stripPointerCasts());
|
||||
if (!F)
|
||||
return Unknown_Personality;
|
||||
return StringSwitch<Personality_Type>(F->getName())
|
||||
.Case("__gnat_eh_personality", GNU_Ada_Personality)
|
||||
.Case("__gxx_personality_v0", GNU_CXX_Personality)
|
||||
.Case("__objc_personality_v0", GNU_ObjC_Personality)
|
||||
.Default(Unknown_Personality);
|
||||
}
|
||||
|
||||
/// isCatchAll - Return 'true' if the given typeinfo will match anything.
|
||||
static bool isCatchAll(Personality_Type Personality, Constant *TypeInfo) {
|
||||
static bool isCatchAll(EHPersonality Personality, Constant *TypeInfo) {
|
||||
switch (Personality) {
|
||||
case Unknown_Personality:
|
||||
case EHPersonality::GNU_C:
|
||||
// The GCC C EH personality only exists to support cleanups, so it's not
|
||||
// clear what the semantics of catch clauses are.
|
||||
return false;
|
||||
case GNU_Ada_Personality:
|
||||
case EHPersonality::Unknown:
|
||||
return false;
|
||||
case EHPersonality::GNU_Ada:
|
||||
// While __gnat_all_others_value will match any Ada exception, it doesn't
|
||||
// match foreign exceptions (or didn't, before gcc-4.7).
|
||||
return false;
|
||||
case GNU_CXX_Personality:
|
||||
case GNU_ObjC_Personality:
|
||||
case EHPersonality::GNU_CXX:
|
||||
case EHPersonality::GNU_ObjC:
|
||||
case EHPersonality::MSVC_Win64SEH:
|
||||
case EHPersonality::MSVC_CXX:
|
||||
return TypeInfo->isNullValue();
|
||||
}
|
||||
llvm_unreachable("Unknown personality!");
|
||||
llvm_unreachable("invalid enum");
|
||||
}
|
||||
|
||||
static bool shorter_filter(const Value *LHS, const Value *RHS) {
|
||||
|
@ -2307,7 +2293,7 @@ Instruction *InstCombiner::visitLandingPadInst(LandingPadInst &LI) {
|
|||
// The logic here should be correct for any real-world personality function.
|
||||
// However if that turns out not to be true, the offending logic can always
|
||||
// be conditioned on the personality function, like the catch-all logic is.
|
||||
Personality_Type Personality = RecognizePersonality(LI.getPersonalityFn());
|
||||
EHPersonality Personality = ClassifyEHPersonality(LI.getPersonalityFn());
|
||||
|
||||
// Simplify the list of clauses, eg by removing repeated catch clauses
|
||||
// (these are often created by inlining).
|
||||
|
|
|
@ -7,6 +7,7 @@
|
|||
declare i32 @generic_personality(i32, i64, i8*, i8*)
|
||||
declare i32 @__gxx_personality_v0(i32, i64, i8*, i8*)
|
||||
declare i32 @__objc_personality_v0(i32, i64, i8*, i8*)
|
||||
declare i32 @__C_specific_handler(...)
|
||||
|
||||
declare void @bar()
|
||||
|
||||
|
@ -231,3 +232,54 @@ lpad.d:
|
|||
; CHECK-NEXT: null
|
||||
; CHECK-NEXT: unreachable
|
||||
}
|
||||
|
||||
define void @foo_seh() {
|
||||
; CHECK-LABEL: @foo_seh(
|
||||
invoke void @bar()
|
||||
to label %cont.a unwind label %lpad.a
|
||||
cont.a:
|
||||
invoke void @bar()
|
||||
to label %cont.b unwind label %lpad.b
|
||||
cont.b:
|
||||
invoke void @bar()
|
||||
to label %cont.c unwind label %lpad.c
|
||||
cont.c:
|
||||
invoke void @bar()
|
||||
to label %cont.d unwind label %lpad.d
|
||||
cont.d:
|
||||
ret void
|
||||
|
||||
lpad.a:
|
||||
%a = landingpad { i8*, i32 } personality i32 (...)* @__C_specific_handler
|
||||
catch i32* null
|
||||
catch i32* @T1
|
||||
unreachable
|
||||
; CHECK: %a = landingpad
|
||||
; CHECK-NEXT: null
|
||||
; CHECK-NEXT: unreachable
|
||||
|
||||
lpad.b:
|
||||
%b = landingpad { i8*, i32 } personality i32 (...)* @__C_specific_handler
|
||||
filter [1 x i32*] zeroinitializer
|
||||
unreachable
|
||||
; CHECK: %b = landingpad
|
||||
; CHECK-NEXT: cleanup
|
||||
; CHECK-NEXT: unreachable
|
||||
|
||||
lpad.c:
|
||||
%c = landingpad { i8*, i32 } personality i32 (...)* @__C_specific_handler
|
||||
filter [2 x i32*] [i32* @T1, i32* null]
|
||||
unreachable
|
||||
; CHECK: %c = landingpad
|
||||
; CHECK-NEXT: cleanup
|
||||
; CHECK-NEXT: unreachable
|
||||
|
||||
lpad.d:
|
||||
%d = landingpad { i8*, i32 } personality i32 (...)* @__C_specific_handler
|
||||
cleanup
|
||||
catch i32* null
|
||||
unreachable
|
||||
; CHECK: %d = landingpad
|
||||
; CHECK-NEXT: null
|
||||
; CHECK-NEXT: unreachable
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue