mirror of
https://github.com/RPCS3/llvm-mirror.git
synced 2024-11-23 19:23:23 +01: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:
parent
86ffc4ee4a
commit
5f6739ae19
@ -72,17 +72,21 @@ void WinException::beginFunction(const MachineFunction *MF) {
|
||||
|
||||
const TargetLoweringObjectFile &TLOF = Asm->getObjFileLowering();
|
||||
unsigned PerEncoding = TLOF.getPersonalityEncoding();
|
||||
const Function *Per = nullptr;
|
||||
if (F->hasPersonalityFn())
|
||||
Per = dyn_cast<Function>(F->getPersonalityFn()->stripPointerCasts());
|
||||
|
||||
bool forceEmitPersonality =
|
||||
F->hasPersonalityFn() && !isNoOpWithoutInvoke(classifyEHPersonality(Per)) &&
|
||||
F->needsUnwindTableEntry();
|
||||
EHPersonality Per = EHPersonality::Unknown;
|
||||
const Function *PerFn = nullptr;
|
||||
if (F->hasPersonalityFn()) {
|
||||
PerFn = dyn_cast<Function>(F->getPersonalityFn()->stripPointerCasts());
|
||||
Per = classifyEHPersonality(PerFn);
|
||||
}
|
||||
|
||||
bool forceEmitPersonality = F->hasPersonalityFn() &&
|
||||
!isNoOpWithoutInvoke(Per) &&
|
||||
F->needsUnwindTableEntry();
|
||||
|
||||
shouldEmitPersonality =
|
||||
forceEmitPersonality || ((hasLandingPads || hasEHFunclets) &&
|
||||
PerEncoding != dwarf::DW_EH_PE_omit && Per);
|
||||
PerEncoding != dwarf::DW_EH_PE_omit && PerFn);
|
||||
|
||||
unsigned LSDAEncoding = TLOF.getLSDAEncoding();
|
||||
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
|
||||
// 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;
|
||||
shouldEmitPersonality = false;
|
||||
return;
|
||||
@ -108,7 +121,7 @@ void WinException::endFunction(const MachineFunction *MF) {
|
||||
const Function *F = MF->getFunction();
|
||||
EHPersonality Per = EHPersonality::Unknown;
|
||||
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
|
||||
// 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);
|
||||
|
||||
// Classify the personality routine so that we may reason about it.
|
||||
EHPersonality Per = EHPersonality::Unknown;
|
||||
if (F->hasPersonalityFn())
|
||||
Per = classifyEHPersonality(F->getPersonalityFn());
|
||||
EHPersonality Per = classifyEHPersonality(PerFn);
|
||||
|
||||
// Do not emit a .seh_handler directive if it is a C++ cleanup funclet.
|
||||
if (Per != EHPersonality::MSVC_CXX ||
|
||||
@ -227,7 +238,7 @@ void WinException::endFunclet() {
|
||||
const Function *F = Asm->MF->getFunction();
|
||||
EHPersonality Per = EHPersonality::Unknown;
|
||||
if (F->hasPersonalityFn())
|
||||
Per = classifyEHPersonality(F->getPersonalityFn());
|
||||
Per = classifyEHPersonality(F->getPersonalityFn()->stripPointerCasts());
|
||||
|
||||
// The .seh_handlerdata directive implicitly switches section, push the
|
||||
// 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
|
||||
// we've code generated the parent, we can emit the label assignment that
|
||||
// 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;
|
||||
MCSymbol *ParentFrameOffset =
|
||||
Ctx.getOrCreateParentFrameOffsetSymbol(FLinkageName);
|
||||
unsigned UnusedReg;
|
||||
const TargetFrameLowering *TFI = Asm->MF->getSubtarget().getFrameLowering();
|
||||
int64_t Offset = TFI->getFrameIndexReference(
|
||||
*Asm->MF, FuncInfo.EHRegNodeFrameIndex, UnusedReg);
|
||||
const MCExpr *MCOffset = MCConstantExpr::create(Offset, Ctx);
|
||||
Asm->OutStreamer->EmitAssignment(ParentFrameOffset, MCOffset);
|
||||
Asm->OutStreamer->EmitAssignment(ParentFrameOffset,
|
||||
MCConstantExpr::create(Offset, Ctx));
|
||||
}
|
||||
|
||||
/// Emit the language-specific data that _except_handler3 and 4 expect. This is
|
||||
|
76
test/CodeGen/X86/seh-no-invokes.ll
Normal file
76
test/CodeGen/X86/seh-no-invokes.ll
Normal 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}
|
Loading…
Reference in New Issue
Block a user