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

Reid Kleckner via llvm-commits llvm-commits at lists.llvm.org
Fri Sep 30 15:10:13 PDT 2016


Author: rnk
Date: Fri Sep 30 17:10:12 2016
New Revision: 282967

URL: http://llvm.org/viewvc/llvm-project?rev=282967&view=rev
Log:
[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

Added:
    llvm/trunk/test/CodeGen/X86/seh-no-invokes.ll
Modified:
    llvm/trunk/lib/CodeGen/AsmPrinter/WinException.cpp

Modified: llvm/trunk/lib/CodeGen/AsmPrinter/WinException.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/CodeGen/AsmPrinter/WinException.cpp?rev=282967&r1=282966&r2=282967&view=diff
==============================================================================
--- llvm/trunk/lib/CodeGen/AsmPrinter/WinException.cpp (original)
+++ llvm/trunk/lib/CodeGen/AsmPrinter/WinException.cpp Fri Sep 30 17:10:12 2016
@@ -72,17 +72,21 @@ void WinException::beginFunction(const M
 
   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 M
 
   // 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 Mac
   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 Ma
         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::emitEHRegistrationOff
   // 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

Added: llvm/trunk/test/CodeGen/X86/seh-no-invokes.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/X86/seh-no-invokes.ll?rev=282967&view=auto
==============================================================================
--- llvm/trunk/test/CodeGen/X86/seh-no-invokes.ll (added)
+++ llvm/trunk/test/CodeGen/X86/seh-no-invokes.ll Fri Sep 30 17:10:12 2016
@@ -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 at 0@f@@":                        # @"\01?filt$0 at 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 at 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}




More information about the llvm-commits mailing list