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
+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 = 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 , 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: