rsanthir.quic created this revision.
Herald added subscribers: dexonsmith, dang, hiraditya.
rsanthir.quic requested review of this revision.
Herald added projects: clang, LLVM.
Herald added subscribers: llvm-commits, cfe-commits.
This patch adds support for the -Wstack-usage flag. It also changes
how -Wframe-larger-than reports it's frame size. It now excludes the
space allocated to hold parameters for called functions.


Repository:
  rG LLVM Github Monorepo

https://reviews.llvm.org/D101964

Files:
  clang/include/clang/Basic/DiagnosticFrontendKinds.td
  clang/include/clang/Basic/DiagnosticGroups.td
  clang/include/clang/Driver/Options.td
  clang/lib/CodeGen/CodeGenAction.cpp
  clang/lib/Driver/ToolChains/Clang.cpp
  clang/test/Frontend/backend-diagnostic.c
  clang/test/Frontend/backend-stack-usage-diagnostic.c
  clang/test/Misc/backend-stack-frame-diagnostics-fallback.cpp
  llvm/include/llvm/CodeGen/MachineFrameInfo.h
  llvm/include/llvm/IR/DiagnosticInfo.h
  llvm/lib/CodeGen/PrologEpilogInserter.cpp

Index: llvm/lib/CodeGen/PrologEpilogInserter.cpp
===================================================================
--- llvm/lib/CodeGen/PrologEpilogInserter.cpp
+++ llvm/lib/CodeGen/PrologEpilogInserter.cpp
@@ -139,9 +139,14 @@
 char &llvm::PrologEpilogCodeInserterID = PEI::ID;
 
 static cl::opt<unsigned>
-WarnStackSize("warn-stack-size", cl::Hidden, cl::init((unsigned)-1),
-              cl::desc("Warn for stack size bigger than the given"
-                       " number"));
+    WarnFrameSize("warn-frame-size", cl::Hidden, cl::init((unsigned)-1),
+                  cl::desc("Warn for frame size bigger than the given"
+                           " number"));
+
+static cl::opt<unsigned>
+    WarnStackUsage("warn-stack-usage", cl::Hidden, cl::init((unsigned)-1),
+                   cl::desc("Warn for stack size bigger than the given"
+                            " number"));
 
 INITIALIZE_PASS_BEGIN(PEI, DEBUG_TYPE, "Prologue/Epilogue Insertion", false,
                       false)
@@ -275,11 +280,19 @@
   if (TRI->requiresRegisterScavenging(MF) && FrameIndexVirtualScavenging)
     scavengeFrameVirtualRegs(MF, *RS);
 
-  // Warn on stack size when we exceeds the given limit.
+  // Warn on stack usage size when we exceed the given limit
   MachineFrameInfo &MFI = MF.getFrameInfo();
   uint64_t StackSize = MFI.getStackSize();
-  if (WarnStackSize.getNumOccurrences() > 0 && WarnStackSize < StackSize) {
-    DiagnosticInfoStackSize DiagStackSize(F, StackSize);
+  if (WarnStackUsage.getNumOccurrences() > 0 && WarnStackUsage <= StackSize) {
+    DiagnosticInfoStackSize DiagStackUsage(
+        F, StackSize, MFI.hasVarSizedObjects(), true /*Stack Usage*/);
+    F.getContext().diagnose(DiagStackUsage);
+  }
+
+  uint64_t FrameSize = MFI.getFrameSize();
+  // Warn on Frame size when we exceed the given limit.
+  if (WarnFrameSize.getNumOccurrences() > 0 && WarnFrameSize < FrameSize) {
+    DiagnosticInfoStackSize DiagStackSize(F, FrameSize);
     F.getContext().diagnose(DiagStackSize);
   }
   ORE->emit([&]() {
@@ -1048,6 +1061,10 @@
       AdjustStackOffset(MFI, SFI, StackGrowsDown, Offset, MaxAlign, Skew);
   }
 
+  int64_t OffsetBeforeMaxCallFrameSize = Offset;
+  int64_t FrameSize = OffsetBeforeMaxCallFrameSize - LocalAreaOffset;
+  MFI.setFrameSize(FrameSize);
+
   if (!TFI.targetHandlesStackFrameRounding()) {
     // If we have reserved argument space for call sites in the function
     // immediately on entry to the current function, count it as part of the
@@ -1073,6 +1090,11 @@
     int64_t OffsetBeforeAlignment = Offset;
     Offset = alignTo(Offset, StackAlign, Skew);
 
+    OffsetBeforeMaxCallFrameSize =
+        alignTo(OffsetBeforeMaxCallFrameSize, StackAlign, Skew);
+    int64_t FrameSize = OffsetBeforeMaxCallFrameSize - LocalAreaOffset;
+    MFI.setFrameSize(FrameSize);
+
     // If we have increased the offset to fulfill the alignment constrants,
     // then the scavenging spill slots may become harder to reach from the
     // stack pointer, float them so they stay close.
Index: llvm/include/llvm/IR/DiagnosticInfo.h
===================================================================
--- llvm/include/llvm/IR/DiagnosticInfo.h
+++ llvm/include/llvm/IR/DiagnosticInfo.h
@@ -216,15 +216,24 @@
 
 class DiagnosticInfoStackSize : public DiagnosticInfoResourceLimit {
   void anchor() override;
+  bool HasVarSizedObjects;
+  bool PrintStackUsageInfo;
+
 public:
   DiagnosticInfoStackSize(const Function &Fn, uint64_t StackSize,
+                          bool HasVarSizedObjects = false,
+                          bool PrintStackUsageInfo = false,
                           DiagnosticSeverity Severity = DS_Warning,
                           uint64_t StackLimit = 0)
       : DiagnosticInfoResourceLimit(Fn, "stack size", StackSize, Severity,
-                                    DK_StackSize, StackLimit) {}
+                                    DK_StackSize, StackLimit),
+        HasVarSizedObjects(HasVarSizedObjects),
+        PrintStackUsageInfo(PrintStackUsageInfo) {}
 
   uint64_t getStackSize() const { return getResourceSize(); }
   uint64_t getStackLimit() const { return getResourceLimit(); }
+  bool hasVarSizedObjects() const { return HasVarSizedObjects; }
+  bool printStackUsageInfo() const { return PrintStackUsageInfo; }
 
   static bool classof(const DiagnosticInfo *DI) {
     return DI->getKind() == DK_StackSize;
Index: llvm/include/llvm/CodeGen/MachineFrameInfo.h
===================================================================
--- llvm/include/llvm/CodeGen/MachineFrameInfo.h
+++ llvm/include/llvm/CodeGen/MachineFrameInfo.h
@@ -243,6 +243,10 @@
   /// to be allocated on entry to the function.
   uint64_t StackSize = 0;
 
+  /// The FrameSize is the StackSize above, minus any reserved argument space
+  /// for call sites in the function.
+  uint64_t FrameSize = 0;
+
   /// The amount that a frame offset needs to be adjusted to
   /// have the actual offset from the stack/frame pointer.  The exact usage of
   /// this is target-dependent, but it is typically used to adjust between
@@ -568,6 +572,14 @@
   /// Estimate and return the size of the stack frame.
   uint64_t estimateStackSize(const MachineFunction &MF) const;
 
+  /// Returns the StackSize without the stack space allocated to hold
+  /// parameters for other functions called from inside the current
+  /// function
+  uint64_t getFrameSize() const { return FrameSize; }
+
+  /// Set the size of the frame.
+  void setFrameSize(uint64_t Size) { FrameSize = Size; }
+
   /// Return the correction for frame offsets.
   int getOffsetAdjustment() const { return OffsetAdjustment; }
 
Index: clang/test/Misc/backend-stack-frame-diagnostics-fallback.cpp
===================================================================
--- clang/test/Misc/backend-stack-frame-diagnostics-fallback.cpp
+++ clang/test/Misc/backend-stack-frame-diagnostics-fallback.cpp
@@ -1,5 +1,5 @@
 // REQUIRES: x86-registered-target
-// RUN: %clang_cc1 %s -mllvm -warn-stack-size=0 -emit-codegen-only -triple=i386-apple-darwin 2>&1 | FileCheck %s
+// RUN: %clang_cc1 %s -mllvm -warn-frame-size=0 -emit-codegen-only -triple=i386-apple-darwin 2>&1 | FileCheck %s
 
 // TODO: Emit rich diagnostics for thunks and move this into the appropriate test file.
 // Until then, test that we fall back and display the LLVM backend diagnostic.
Index: clang/test/Frontend/backend-stack-usage-diagnostic.c
===================================================================
--- /dev/null
+++ clang/test/Frontend/backend-stack-usage-diagnostic.c
@@ -0,0 +1,24 @@
+
+// RUN: %clang -Wstack-usage=0 -o /dev/null -c %s 2> %t.err
+// RUN: FileCheck < %t.err %s --check-prefix=WARN
+// RUN: %clang -Wstack-usage=0 -Wno-stack-usage= -o /dev/null -c %s 2> %t.err
+// RUN: FileCheck < %t.err %s --check-prefix=IGNORE --allow-empty
+// RUN: %clang -Wstack-usage=0 -w -o /dev/null -c %s 2> %t.err
+// RUN: FileCheck < %t.err %s --check-prefix=IGNORE --allow-empty
+// RUN: %clang -Wstack-usage=3 -o /dev/null -c %s 2> %t.err
+// RUN: FileCheck < %t.err %s --check-prefix=WARN
+// RUN: %clang -Wstack-usage=100 -o /dev/null -c %s 2> %t.err
+// RUN: FileCheck < %t.err %s --check-prefix=IGNORE --allow-empty
+
+// WARN: warning: stack usage is {{[0-9]+}} bytes in function 'test_square'
+// IGNORE-NOT:  stack usage is {{[0-9]+}} bytes in function 'test_square'
+int test_square(int num) {
+  return num * num;
+}
+
+// WARN: warning: stack usage might be {{[0-9]+}} bytes in function 'test_unbounded'
+// IGNORE-NOT:  stack usage might be {{[0-9]+}} bytes in function 'test_unbounded'
+int test_unbounded(int len) {
+  char a[len];
+  return 1;
+}
Index: clang/test/Frontend/backend-diagnostic.c
===================================================================
--- clang/test/Frontend/backend-diagnostic.c
+++ clang/test/Frontend/backend-diagnostic.c
@@ -4,11 +4,11 @@
 // _PROMOTE_: Promote warning to error.
 // _IGNORE_: Drop backend warning.
 //
-// RUN: not %clang_cc1 %s -mllvm -warn-stack-size=0 -no-integrated-as -S -o - -triple=i386-apple-darwin 2> %t.err
+// RUN: not %clang_cc1 %s -mllvm -warn-frame-size=0 -no-integrated-as -S -o - -triple=i386-apple-darwin 2> %t.err
 // RUN: FileCheck < %t.err %s --check-prefix=REGULAR --check-prefix=ASM
-// RUN: not %clang_cc1 %s -mllvm -warn-stack-size=0 -no-integrated-as -S -o - -triple=i386-apple-darwin -Werror=frame-larger-than= 2> %t.err
+// RUN: not %clang_cc1 %s -mllvm -warn-frame-size=0 -no-integrated-as -S -o - -triple=i386-apple-darwin -Werror=frame-larger-than= 2> %t.err
 // RUN: FileCheck < %t.err %s --check-prefix=PROMOTE --check-prefix=ASM
-// RUN: not %clang_cc1 %s -mllvm -warn-stack-size=0 -no-integrated-as -S -o - -triple=i386-apple-darwin -Wno-frame-larger-than= 2> %t.err
+// RUN: not %clang_cc1 %s -mllvm -warn-frame-size=0 -no-integrated-as -S -o - -triple=i386-apple-darwin -Wno-frame-larger-than= 2> %t.err
 // RUN: FileCheck < %t.err %s --check-prefix=IGNORE --check-prefix=ASM
 //
 // RUN: %clang_cc1 %s -S -o - -triple=i386-apple-darwin -verify -no-integrated-as
Index: clang/lib/Driver/ToolChains/Clang.cpp
===================================================================
--- clang/lib/Driver/ToolChains/Clang.cpp
+++ clang/lib/Driver/ToolChains/Clang.cpp
@@ -4777,10 +4777,16 @@
   if (Arg *A = Args.getLastArg(options::OPT_Wframe_larger_than_EQ)) {
     StringRef v = A->getValue();
     CmdArgs.push_back("-mllvm");
-    CmdArgs.push_back(Args.MakeArgString("-warn-stack-size=" + v));
+    CmdArgs.push_back(Args.MakeArgString("-warn-frame-size=" + v));
     A->claim();
   }
 
+  if (Arg *A = Args.getLastArg(options::OPT_Wstack_usage_EQ)) {
+    StringRef bytes = A->getValue();
+    CmdArgs.push_back("-mllvm");
+    CmdArgs.push_back(Args.MakeArgString("-warn-stack-usage=" + bytes));
+  }
+
   if (!Args.hasFlag(options::OPT_fjump_tables, options::OPT_fno_jump_tables,
                     true))
     CmdArgs.push_back("-fno-jump-tables");
Index: clang/lib/CodeGen/CodeGenAction.cpp
===================================================================
--- clang/lib/CodeGen/CodeGenAction.cpp
+++ clang/lib/CodeGen/CodeGenAction.cpp
@@ -567,15 +567,19 @@
     // We do not know how to format other severities.
     return false;
 
-  if (const Decl *ND = Gen->GetDeclForMangledName(D.getFunction().getName())) {
-    // FIXME: Shouldn't need to truncate to uint32_t
-    Diags.Report(ND->getASTContext().getFullLoc(ND->getLocation()),
-                 diag::warn_fe_frame_larger_than)
+  const Decl *ND = Gen->GetDeclForMangledName(D.getFunction().getName());
+  if (!ND)
+    return false;
+
+  unsigned DiagID = diag::warn_fe_frame_larger_than;
+  if (D.printStackUsageInfo())
+    DiagID = D.hasVarSizedObjects() ? diag::warn_fe_stack_usage_dynam
+                                    : diag::warn_fe_stack_usage;
+  // FIXME: Shouldn't need to truncate to uint32_t
+  Diags.Report(ND->getASTContext().getFullLoc(ND->getLocation()), DiagID)
       << static_cast<uint32_t>(D.getStackSize()) << Decl::castToDeclContext(ND);
-    return true;
-  }
 
-  return false;
+  return true;
 }
 
 const FullSourceLoc BackendConsumer::getBestLocationFromDebugLoc(
@@ -774,7 +778,10 @@
   case llvm::DK_StackSize:
     if (StackSizeDiagHandler(cast<DiagnosticInfoStackSize>(DI)))
       return;
-    ComputeDiagID(Severity, backend_frame_larger_than, DiagID);
+    if (cast<DiagnosticInfoStackSize>(DI).printStackUsageInfo())
+      ComputeDiagID(Severity, backend_stack_usage, DiagID);
+    else
+      ComputeDiagID(Severity, backend_frame_larger_than, DiagID);
     break;
   case DK_Linker:
     assert(CurLinkModule);
Index: clang/include/clang/Driver/Options.td
===================================================================
--- clang/include/clang/Driver/Options.td
+++ clang/include/clang/Driver/Options.td
@@ -2537,6 +2537,8 @@
 def Wlarger_than_ : Joined<["-"], "Wlarger-than-">, Alias<Wlarger_than_EQ>;
 def Wframe_larger_than_EQ : Joined<["-"], "Wframe-larger-than=">, Group<f_Group>, Flags<[NoXarchOption]>;
 
+def Wstack_usage_EQ : Joined<["-"], "Wstack-usage=">, Group<f_Group>, Flags<[NoXarchOption]>;
+
 def : Flag<["-"], "fterminated-vtables">, Alias<fapple_kext>;
 defm threadsafe_statics : BoolFOption<"threadsafe-statics",
   LangOpts<"ThreadsafeStatics">, DefaultTrue,
Index: clang/include/clang/Basic/DiagnosticGroups.td
===================================================================
--- clang/include/clang/Basic/DiagnosticGroups.td
+++ clang/include/clang/Basic/DiagnosticGroups.td
@@ -1189,6 +1189,7 @@
 def BackendInlineAsm : DiagGroup<"inline-asm">;
 def BackendSourceMgr : DiagGroup<"source-mgr">;
 def BackendFrameLargerThanEQ : DiagGroup<"frame-larger-than=">;
+def BackendStackUsageEQ : DiagGroup<"stack-usage=">;
 def BackendPlugin : DiagGroup<"backend-plugin">;
 def RemarkBackendPlugin : DiagGroup<"remark-backend-plugin">;
 def BackendOptimizationRemark : DiagGroup<"pass">;
Index: clang/include/clang/Basic/DiagnosticFrontendKinds.td
===================================================================
--- clang/include/clang/Basic/DiagnosticFrontendKinds.td
+++ clang/include/clang/Basic/DiagnosticFrontendKinds.td
@@ -25,6 +25,15 @@
 def err_fe_cannot_link_module : Error<"cannot link module '%0': %1">,
   DefaultFatal;
 
+def warn_fe_stack_usage : Warning<"stack usage is %0 bytes in %1">,
+    BackendInfo, InGroup<BackendStackUsageEQ>;
+def warn_fe_stack_usage_dynam : Warning<"stack usage might be %0 bytes in %1">,
+    BackendInfo, InGroup<BackendStackUsageEQ>;
+def warn_fe_backend_stack_usage: Warning<"%0">,
+    BackendInfo, InGroup<BackendStackUsageEQ>;
+def err_fe_backend_stack_usage: Error<"%0">, BackendInfo;
+def note_fe_backend_stack_usage: Note<"%0">, BackendInfo;
+
 def warn_fe_frame_larger_than : Warning<"stack frame size of %0 bytes in %q1">,
     BackendInfo, InGroup<BackendFrameLargerThanEQ>;
 def warn_fe_backend_frame_larger_than: Warning<"%0">,
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
  • [PATCH] D101964: Added ... Ryan Santhirarajan via Phabricator via cfe-commits

Reply via email to