Index: lib/CodeGen/WinEHPrepare.cpp =================================================================== --- lib/CodeGen/WinEHPrepare.cpp +++ lib/CodeGen/WinEHPrepare.cpp @@ -20,6 +20,7 @@ #include "llvm/ADT/DenseMap.h" #include "llvm/ADT/MapVector.h" #include "llvm/ADT/STLExtras.h" +#include "llvm/ADT/StringSwitch.h" #include "llvm/Analysis/CFG.h" #include "llvm/Analysis/EHPersonalities.h" #include "llvm/CodeGen/MachineBasicBlock.h" @@ -67,6 +68,7 @@ } private: + void promoteEHPersonality(Function &F); void insertPHIStores(PHINode *OriginalPHI, AllocaInst *SpillSlot); void insertPHIStore(BasicBlock *PredBlock, Value *PredVal, AllocaInst *SpillSlot, @@ -464,6 +466,39 @@ return FuncInfo.ClrEHUnwindMap.size() - 1; } +static Value *getStackGuardEHPersonality(Value *Pers) { + Function *F = + Pers ? dyn_cast(Pers->stripPointerCasts()) : nullptr; + if (!F) + return nullptr; + + // TODO(etienneb): Upgrade exception handlers when they are working. + StringRef NewName = llvm::StringSwitch(F->getName()) + .Case("_except_handler3", "_except_handler4") + .Default(""); + if (NewName.empty()) + return nullptr; + + Module *M = F->getParent(); + return M->getOrInsertFunction("_except_handler4", F->getFunctionType(), + F->getAttributes()); +} + +void WinEHPrepare::promoteEHPersonality(Function &F) { + // Promote the exception handler when stack protection is activated. + if (!F.hasFnAttribute(Attribute::StackProtect) && + !F.hasFnAttribute(Attribute::StackProtectReq) && + !F.hasFnAttribute(Attribute::StackProtectStrong)) + return; + + if (Value *PersonalityFn = F.getPersonalityFn()) { + if (Value *Personality = getStackGuardEHPersonality(PersonalityFn)) { + Function* PromotedFn = cast(Personality); + F.setPersonalityFn(PromotedFn); + } + } +} + void llvm::calculateClrEHStateNumbers(const Function *Fn, WinEHFuncInfo &FuncInfo) { // Return if it's already been done. @@ -1028,6 +1063,10 @@ } bool WinEHPrepare::prepareExplicitEH(Function &F) { + // When stack-protector is present, some exception handlers need to be + // promoted to a compatible handlers. + promoteEHPersonality(F); + // Remove unreachable blocks. It is not valuable to assign them a color and // their existence can trick us into thinking values are alive when they are // not. Index: test/CodeGen/WinEH/wineh-promote-eh.ll =================================================================== --- /dev/null +++ test/CodeGen/WinEH/wineh-promote-eh.ll @@ -0,0 +1,16 @@ +; RUN: opt -mtriple=i686-windows-msvc -S -winehprepare %s | FileCheck %s + +declare i32 @_except_handler3(...) + +define void @test1a() personality i32 (...)* @_except_handler3 { +; CHECK: define void @test1a() personality i32 (...)* @_except_handler3 +entry: + ret void +} + +define void @test1b() ssp personality i32 (...)* @_except_handler3 { +; CHECK: define void @test1b() [[attr:.*]] personality i32 (...)* @_except_handler4 +entry: + ret void +} +