1
0
mirror of https://github.com/RPCS3/llvm-mirror.git synced 2024-10-21 03:53:04 +02:00

[SEH] Emit the parent frame offset label even if there are no funclets

This avoids errors about references to undefined local labels from
unreferenced filter functions.

Fixes (sort of) PR30431

llvm-svn: 282967
This commit is contained in:
Reid Kleckner 2016-09-30 22:10:12 +00:00
parent 86ffc4ee4a
commit 5f6739ae19
2 changed files with 115 additions and 19 deletions

View File

@ -72,17 +72,21 @@ void WinException::beginFunction(const MachineFunction *MF) {
const TargetLoweringObjectFile &TLOF = Asm->getObjFileLowering(); const TargetLoweringObjectFile &TLOF = Asm->getObjFileLowering();
unsigned PerEncoding = TLOF.getPersonalityEncoding(); unsigned PerEncoding = TLOF.getPersonalityEncoding();
const Function *Per = nullptr;
if (F->hasPersonalityFn())
Per = dyn_cast<Function>(F->getPersonalityFn()->stripPointerCasts());
bool forceEmitPersonality = EHPersonality Per = EHPersonality::Unknown;
F->hasPersonalityFn() && !isNoOpWithoutInvoke(classifyEHPersonality(Per)) && const Function *PerFn = nullptr;
F->needsUnwindTableEntry(); if (F->hasPersonalityFn()) {
PerFn = dyn_cast<Function>(F->getPersonalityFn()->stripPointerCasts());
Per = classifyEHPersonality(PerFn);
}
bool forceEmitPersonality = F->hasPersonalityFn() &&
!isNoOpWithoutInvoke(Per) &&
F->needsUnwindTableEntry();
shouldEmitPersonality = shouldEmitPersonality =
forceEmitPersonality || ((hasLandingPads || hasEHFunclets) && forceEmitPersonality || ((hasLandingPads || hasEHFunclets) &&
PerEncoding != dwarf::DW_EH_PE_omit && Per); PerEncoding != dwarf::DW_EH_PE_omit && PerFn);
unsigned LSDAEncoding = TLOF.getLSDAEncoding(); unsigned LSDAEncoding = TLOF.getLSDAEncoding();
shouldEmitLSDA = shouldEmitPersonality && shouldEmitLSDA = shouldEmitPersonality &&
@ -90,7 +94,16 @@ void WinException::beginFunction(const MachineFunction *MF) {
// If we're not using CFI, we don't want the CFI or the personality, but we // If we're not using CFI, we don't want the CFI or the personality, but we
// might want EH tables if we had EH pads. // might want EH tables if we had EH pads.
if (!Asm->MAI->usesWindowsCFI() || (!MF->hasWinCFI() && !Per)) { if (!Asm->MAI->usesWindowsCFI() || (!MF->hasWinCFI() && !PerFn)) {
if (Per == EHPersonality::MSVC_X86SEH && !hasEHFunclets) {
// If this is 32-bit SEH and we don't have any funclets (really invokes),
// make sure we emit the parent offset label. Some unreferenced filter
// functions may still refer to it.
const WinEHFuncInfo &FuncInfo = *MF->getWinEHFuncInfo();
StringRef FLinkageName =
GlobalValue::getRealLinkageName(MF->getFunction()->getName());
emitEHRegistrationOffsetLabel(FuncInfo, FLinkageName);
}
shouldEmitLSDA = hasEHFunclets; shouldEmitLSDA = hasEHFunclets;
shouldEmitPersonality = false; shouldEmitPersonality = false;
return; return;
@ -108,7 +121,7 @@ void WinException::endFunction(const MachineFunction *MF) {
const Function *F = MF->getFunction(); const Function *F = MF->getFunction();
EHPersonality Per = EHPersonality::Unknown; EHPersonality Per = EHPersonality::Unknown;
if (F->hasPersonalityFn()) if (F->hasPersonalityFn())
Per = classifyEHPersonality(F->getPersonalityFn()); Per = classifyEHPersonality(F->getPersonalityFn()->stripPointerCasts());
// Get rid of any dead landing pads if we're not using funclets. In funclet // Get rid of any dead landing pads if we're not using funclets. In funclet
// schemes, the landing pad is not actually reachable. It only exists so // schemes, the landing pad is not actually reachable. It only exists so
@ -207,9 +220,7 @@ void WinException::beginFunclet(const MachineBasicBlock &MBB,
TLOF.getCFIPersonalitySymbol(PerFn, Asm->TM, MMI); TLOF.getCFIPersonalitySymbol(PerFn, Asm->TM, MMI);
// Classify the personality routine so that we may reason about it. // Classify the personality routine so that we may reason about it.
EHPersonality Per = EHPersonality::Unknown; EHPersonality Per = classifyEHPersonality(PerFn);
if (F->hasPersonalityFn())
Per = classifyEHPersonality(F->getPersonalityFn());
// Do not emit a .seh_handler directive if it is a C++ cleanup funclet. // Do not emit a .seh_handler directive if it is a C++ cleanup funclet.
if (Per != EHPersonality::MSVC_CXX || if (Per != EHPersonality::MSVC_CXX ||
@ -227,7 +238,7 @@ void WinException::endFunclet() {
const Function *F = Asm->MF->getFunction(); const Function *F = Asm->MF->getFunction();
EHPersonality Per = EHPersonality::Unknown; EHPersonality Per = EHPersonality::Unknown;
if (F->hasPersonalityFn()) if (F->hasPersonalityFn())
Per = classifyEHPersonality(F->getPersonalityFn()); Per = classifyEHPersonality(F->getPersonalityFn()->stripPointerCasts());
// The .seh_handlerdata directive implicitly switches section, push the // The .seh_handlerdata directive implicitly switches section, push the
// current section so that we may return to it. // current section so that we may return to it.
@ -905,15 +916,24 @@ void WinException::emitEHRegistrationOffsetLabel(const WinEHFuncInfo &FuncInfo,
// registration in order to recover the parent frame pointer. Now that we know // registration in order to recover the parent frame pointer. Now that we know
// we've code generated the parent, we can emit the label assignment that // we've code generated the parent, we can emit the label assignment that
// those helpers use to get the offset of the registration node. // those helpers use to get the offset of the registration node.
// Compute the parent frame offset. The EHRegNodeFrameIndex will be invalid if
// after optimization all the invokes were eliminated. We still need to emit
// the parent frame offset label, but it should be garbage and should never be
// used.
int64_t Offset = 0;
int FI = FuncInfo.EHRegNodeFrameIndex;
if (FI != INT_MAX) {
const TargetFrameLowering *TFI = Asm->MF->getSubtarget().getFrameLowering();
unsigned UnusedReg;
Offset = TFI->getFrameIndexReference(*Asm->MF, FI, UnusedReg);
}
MCContext &Ctx = Asm->OutContext; MCContext &Ctx = Asm->OutContext;
MCSymbol *ParentFrameOffset = MCSymbol *ParentFrameOffset =
Ctx.getOrCreateParentFrameOffsetSymbol(FLinkageName); Ctx.getOrCreateParentFrameOffsetSymbol(FLinkageName);
unsigned UnusedReg; Asm->OutStreamer->EmitAssignment(ParentFrameOffset,
const TargetFrameLowering *TFI = Asm->MF->getSubtarget().getFrameLowering(); MCConstantExpr::create(Offset, Ctx));
int64_t Offset = TFI->getFrameIndexReference(
*Asm->MF, FuncInfo.EHRegNodeFrameIndex, UnusedReg);
const MCExpr *MCOffset = MCConstantExpr::create(Offset, Ctx);
Asm->OutStreamer->EmitAssignment(ParentFrameOffset, MCOffset);
} }
/// Emit the language-specific data that _except_handler3 and 4 expect. This is /// Emit the language-specific data that _except_handler3 and 4 expect. This is

View File

@ -0,0 +1,76 @@
; RUN: llc < %s | FileCheck %s
; Generated with this C source:
; static __forceinline void __cpuid() { __asm__(""); }
; void f() {
; __try {
; __cpuid();
; } __except (1) {
; }
; }
; When running clang at -O1, we can end up deleting unreachable SEH catchpads
; without running GlobalDCE to remove the associated filter. This used to
; result in references to undefined labels. Now we check that we emit the
; label. This was PR30431.
; CHECK-LABEL: _f: # @f
; CHECK: Lf$parent_frame_offset = 0
; CHECK: retl
; CHECK-LABEL: "?filt$0@0@f@@": # @"\01?filt$0@0@f@@"
; CHECK: movl $Lf$parent_frame_offset,
; ModuleID = 't.c'
source_filename = "t.c"
target datalayout = "e-m:x-p:32:32-i64:64-f80:32-n8:16:32-a:0:32-S32"
target triple = "i386-pc-windows-msvc19.0.24210"
define void @f() #0 personality i8* bitcast (i32 (...)* @_except_handler3 to i8*) {
__try.cont:
%__exception_code = alloca i32, align 4
call void (...) @llvm.localescape(i32* nonnull %__exception_code)
call void asm sideeffect "", "~{dirflag},~{fpsr},~{flags}"() #3, !srcloc !1
ret void
}
; Function Attrs: nounwind
define internal i32 @"\01?filt$0@0@f@@"() #1 {
entry:
%0 = tail call i8* @llvm.frameaddress(i32 1)
%1 = tail call i8* @llvm.x86.seh.recoverfp(i8* bitcast (void ()* @f to i8*), i8* %0)
%2 = tail call i8* @llvm.localrecover(i8* bitcast (void ()* @f to i8*), i8* %1, i32 0)
%__exception_code = bitcast i8* %2 to i32*
%3 = getelementptr inbounds i8, i8* %0, i32 -20
%4 = bitcast i8* %3 to { i32*, i8* }**
%5 = load { i32*, i8* }*, { i32*, i8* }** %4, align 4
%6 = getelementptr inbounds { i32*, i8* }, { i32*, i8* }* %5, i32 0, i32 0
%7 = load i32*, i32** %6, align 4
%8 = load i32, i32* %7, align 4
store i32 %8, i32* %__exception_code, align 4
ret i32 1
}
; Function Attrs: nounwind readnone
declare i8* @llvm.frameaddress(i32) #2
; Function Attrs: nounwind readnone
declare i8* @llvm.x86.seh.recoverfp(i8*, i8*) #2
; Function Attrs: nounwind readnone
declare i8* @llvm.localrecover(i8*, i8*, i32) #2
declare i32 @_except_handler3(...)
; Function Attrs: nounwind
declare void @llvm.localescape(...) #3
attributes #0 = { "correctly-rounded-divide-sqrt-fp-math"="false" "disable-tail-calls"="false" "less-precise-fpmad"="false" "no-frame-pointer-elim"="false" "no-infs-fp-math"="false" "no-jump-tables"="false" "no-nans-fp-math"="false" "no-signed-zeros-fp-math"="false" "no-trapping-math"="false" "stack-protector-buffer-size"="8" "target-cpu"="pentium4" "target-features"="+fxsr,+mmx,+sse,+sse2,+x87" "unsafe-fp-math"="false" "use-soft-float"="false" }
attributes #1 = { nounwind "correctly-rounded-divide-sqrt-fp-math"="false" "disable-tail-calls"="false" "less-precise-fpmad"="false" "no-frame-pointer-elim"="false" "no-infs-fp-math"="false" "no-nans-fp-math"="false" "no-signed-zeros-fp-math"="false" "no-trapping-math"="false" "stack-protector-buffer-size"="8" "target-cpu"="pentium4" "target-features"="+fxsr,+mmx,+sse,+sse2,+x87" "unsafe-fp-math"="false" "use-soft-float"="false" }
attributes #2 = { nounwind readnone }
attributes #3 = { nounwind }
!llvm.ident = !{!0}
!0 = !{!"clang version 4.0.0 (trunk 282900) (llvm/trunk 282903)"}
!1 = !{i32 48}