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.

The -Wstack-usage flag has been added, which provides a
warning message when size of stack exceeds user provided value.


Repository:
  rG LLVM Github Monorepo

https://reviews.llvm.org/D101965

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-stack-usage-diagnostic.c
  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
@@ -143,6 +143,11 @@
               cl::desc("Warn for stack 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)
 INITIALIZE_PASS_DEPENDENCY(MachineLoopInfo)
@@ -275,9 +280,16 @@
   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 (WarnStackUsage.getNumOccurrences() > 0 && WarnStackUsage <= StackSize) {
+    DiagnosticInfoStackSize DiagStackUsage(
+        F, StackSize, MFI.hasVarSizedObjects(), true /*Stack Usage*/);
+    F.getContext().diagnose(DiagStackUsage);
+  }
+
+  // Warn on stack size when we exceeds the given limit.
   if (WarnStackSize.getNumOccurrences() > 0 && WarnStackSize < StackSize) {
     DiagnosticInfoStackSize DiagStackSize(F, StackSize);
     F.getContext().diagnose(DiagStackSize);
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: 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/lib/Driver/ToolChains/Clang.cpp
===================================================================
--- clang/lib/Driver/ToolChains/Clang.cpp
+++ clang/lib/Driver/ToolChains/Clang.cpp
@@ -4781,6 +4781,12 @@
     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] D101965: Added ... Ryan Santhirarajan via Phabricator via cfe-commits

Reply via email to