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:
Reid Kleckner 2015-01-28 01:17:38 +00:00
parent d1f2536829
commit 4af6415237
4 changed files with 97 additions and 28 deletions

View File

@ -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

View File

@ -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);
}

View File

@ -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).

View File

@ -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
}