diff options
author | Reid Kleckner <reid@kleckner.net> | 2015-02-11 01:23:16 +0000 |
---|---|---|
committer | Reid Kleckner <reid@kleckner.net> | 2015-02-11 01:23:16 +0000 |
commit | 96d011315aa01de179897eaf4e7baeddc5de1cda (patch) | |
tree | ccced202122ff25d6362be653140bfe079ab5925 /llvm/lib | |
parent | 58e985c2db3045f1416520212108f93c8c257b18 (diff) | |
download | bcm5719-llvm-96d011315aa01de179897eaf4e7baeddc5de1cda.tar.gz bcm5719-llvm-96d011315aa01de179897eaf4e7baeddc5de1cda.zip |
Don't promote asynch EH invokes of nounwind functions to calls
If the landingpad of the invoke is using a personality function that
catches asynch exceptions, then it can catch a trap.
Also add some landingpads to invalid LLVM IR test cases that lack them.
Over-the-shoulder reviewed by David Majnemer.
llvm-svn: 228782
Diffstat (limited to 'llvm/lib')
-rw-r--r-- | llvm/lib/Analysis/LibCallSemantics.cpp | 25 | ||||
-rw-r--r-- | llvm/lib/CodeGen/WinEHPrepare.cpp | 2 | ||||
-rw-r--r-- | llvm/lib/Transforms/IPO/PruneEH.cpp | 4 | ||||
-rw-r--r-- | llvm/lib/Transforms/InstCombine/InstructionCombining.cpp | 3 | ||||
-rw-r--r-- | llvm/lib/Transforms/Utils/Local.cpp | 3 |
5 files changed, 32 insertions, 5 deletions
diff --git a/llvm/lib/Analysis/LibCallSemantics.cpp b/llvm/lib/Analysis/LibCallSemantics.cpp index 3a345c45d07..6c2ebdb4594 100644 --- a/llvm/lib/Analysis/LibCallSemantics.cpp +++ b/llvm/lib/Analysis/LibCallSemantics.cpp @@ -64,7 +64,7 @@ LibCallInfo::getFunctionInfo(const Function *F) const { /// 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) { +EHPersonality llvm::classifyEHPersonality(Value *Pers) { Function *F = dyn_cast<Function>(Pers->stripPointerCasts()); if (!F) return EHPersonality::Unknown; @@ -73,7 +73,30 @@ EHPersonality llvm::ClassifyEHPersonality(Value *Pers) { .Case("__gxx_personality_v0", EHPersonality::GNU_CXX) .Case("__gcc_personality_v0", EHPersonality::GNU_C) .Case("__objc_personality_v0", EHPersonality::GNU_ObjC) + .Case("__except_handler3", EHPersonality::MSVC_X86SEH) + .Case("__except_handler4", EHPersonality::MSVC_X86SEH) .Case("__C_specific_handler", EHPersonality::MSVC_Win64SEH) .Case("__CxxFrameHandler3", EHPersonality::MSVC_CXX) .Default(EHPersonality::Unknown); } + +bool llvm::isAsynchronousEHPersonality(EHPersonality Pers) { + // The two SEH personality functions can catch asynch exceptions. We assume + // unknown personalities don't catch asynch exceptions. + switch (Pers) { + case EHPersonality::MSVC_X86SEH: + case EHPersonality::MSVC_Win64SEH: + return true; + default: return false; + } + llvm_unreachable("invalid enum"); +} + +bool llvm::canSimplifyInvokeNoUnwind(const InvokeInst *II) { + const LandingPadInst *LP = II->getLandingPadInst(); + EHPersonality Personality = classifyEHPersonality(LP->getPersonalityFn()); + // We can't simplify any invokes to nounwind functions if the personality + // function wants to catch asynch exceptions. The nounwind attribute only + // implies that the function does not throw synchronous exceptions. + return !isAsynchronousEHPersonality(Personality); +} diff --git a/llvm/lib/CodeGen/WinEHPrepare.cpp b/llvm/lib/CodeGen/WinEHPrepare.cpp index c608bb0a31e..b4019b48617 100644 --- a/llvm/lib/CodeGen/WinEHPrepare.cpp +++ b/llvm/lib/CodeGen/WinEHPrepare.cpp @@ -75,7 +75,7 @@ bool WinEHPrepare::runOnFunction(Function &Fn) { return false; // Classify the personality to see what kind of preparation we need. - EHPersonality Pers = ClassifyEHPersonality(LPads.back()->getPersonalityFn()); + EHPersonality Pers = classifyEHPersonality(LPads.back()->getPersonalityFn()); // Delegate through to the DWARF pass if this is unrecognized. if (!isMSVCPersonality(Pers)) diff --git a/llvm/lib/Transforms/IPO/PruneEH.cpp b/llvm/lib/Transforms/IPO/PruneEH.cpp index 7bd4ce12860..1943b930cbf 100644 --- a/llvm/lib/Transforms/IPO/PruneEH.cpp +++ b/llvm/lib/Transforms/IPO/PruneEH.cpp @@ -18,8 +18,10 @@ #include "llvm/ADT/SmallPtrSet.h" #include "llvm/ADT/SmallVector.h" #include "llvm/ADT/Statistic.h" +#include "llvm/Support/raw_ostream.h" #include "llvm/Analysis/CallGraph.h" #include "llvm/Analysis/CallGraphSCCPass.h" +#include "llvm/Analysis/LibCallSemantics.h" #include "llvm/IR/CFG.h" #include "llvm/IR/Constants.h" #include "llvm/IR/Function.h" @@ -175,7 +177,7 @@ bool PruneEH::SimplifyFunction(Function *F) { bool MadeChange = false; for (Function::iterator BB = F->begin(), E = F->end(); BB != E; ++BB) { if (InvokeInst *II = dyn_cast<InvokeInst>(BB->getTerminator())) - if (II->doesNotThrow()) { + if (II->doesNotThrow() && canSimplifyInvokeNoUnwind(II)) { SmallVector<Value*, 8> Args(II->op_begin(), II->op_end() - 3); // Insert a call instruction before the invoke. CallInst *Call = CallInst::Create(II->getCalledValue(), Args, "", II); diff --git a/llvm/lib/Transforms/InstCombine/InstructionCombining.cpp b/llvm/lib/Transforms/InstCombine/InstructionCombining.cpp index 3cfcc90a8ed..ffc8ff5b16c 100644 --- a/llvm/lib/Transforms/InstCombine/InstructionCombining.cpp +++ b/llvm/lib/Transforms/InstCombine/InstructionCombining.cpp @@ -2275,6 +2275,7 @@ static bool isCatchAll(EHPersonality Personality, Constant *TypeInfo) { return false; case EHPersonality::GNU_CXX: case EHPersonality::GNU_ObjC: + case EHPersonality::MSVC_X86SEH: case EHPersonality::MSVC_Win64SEH: case EHPersonality::MSVC_CXX: return TypeInfo->isNullValue(); @@ -2293,7 +2294,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. - EHPersonality Personality = ClassifyEHPersonality(LI.getPersonalityFn()); + EHPersonality Personality = classifyEHPersonality(LI.getPersonalityFn()); // Simplify the list of clauses, eg by removing repeated catch clauses // (these are often created by inlining). diff --git a/llvm/lib/Transforms/Utils/Local.cpp b/llvm/lib/Transforms/Utils/Local.cpp index b8c0a7e47b5..48305684721 100644 --- a/llvm/lib/Transforms/Utils/Local.cpp +++ b/llvm/lib/Transforms/Utils/Local.cpp @@ -17,6 +17,7 @@ #include "llvm/ADT/STLExtras.h" #include "llvm/ADT/SmallPtrSet.h" #include "llvm/ADT/Statistic.h" +#include "llvm/Analysis/LibCallSemantics.h" #include "llvm/Analysis/InstructionSimplify.h" #include "llvm/Analysis/MemoryBuiltins.h" #include "llvm/Analysis/ValueTracking.h" @@ -1260,7 +1261,7 @@ static bool markAliveBlocks(BasicBlock *BB, if (isa<ConstantPointerNull>(Callee) || isa<UndefValue>(Callee)) { changeToUnreachable(II, true); Changed = true; - } else if (II->doesNotThrow()) { + } else if (II->doesNotThrow() && canSimplifyInvokeNoUnwind(II)) { if (II->use_empty() && II->onlyReadsMemory()) { // jump to the normal destination branch. BranchInst::Create(II->getNormalDest(), II); |