diff --git a/clang/lib/CodeGen/CodeGenFunction.cpp b/clang/lib/CodeGen/CodeGenFunction.cpp --- a/clang/lib/CodeGen/CodeGenFunction.cpp +++ b/clang/lib/CodeGen/CodeGenFunction.cpp @@ -1050,6 +1050,10 @@ Fn->addFnAttr("packed-stack"); } + if (CGM.getCodeGenOpts().WarnStackSize != UINT_MAX) + Fn->addFnAttr("warn-stack-size", + std::to_string(CGM.getCodeGenOpts().WarnStackSize)); + if (RetTy->isVoidType()) { // Void type; nothing to return. ReturnValue = Address::invalid(); diff --git a/clang/lib/CodeGen/CodeGenModule.cpp b/clang/lib/CodeGen/CodeGenModule.cpp --- a/clang/lib/CodeGen/CodeGenModule.cpp +++ b/clang/lib/CodeGen/CodeGenModule.cpp @@ -787,8 +787,6 @@ getCodeGenOpts().StackProtectorGuardOffset); if (getCodeGenOpts().StackAlignment) getModule().setOverrideStackAlignment(getCodeGenOpts().StackAlignment); - if (getCodeGenOpts().WarnStackSize != UINT_MAX) - getModule().setWarnStackSize(getCodeGenOpts().WarnStackSize); getTargetCodeGenInfo().emitTargetMetadata(*this, MangledDeclNames); diff --git a/clang/test/Frontend/fwarn-stack-size.c b/clang/test/Frontend/fwarn-stack-size.c new file mode 100644 --- /dev/null +++ b/clang/test/Frontend/fwarn-stack-size.c @@ -0,0 +1,4 @@ +// RUN: %clang_cc1 -fwarn-stack-size=42 -emit-llvm -o - %s | FileCheck %s +void foo(void) {} +// CHECK: define {{.*}} @foo() [[ATTR:#[0-9]+]] { +// CHECK: attributes [[ATTR]] = {{.*}} "warn-stack-size"="42" diff --git a/llvm/docs/LangRef.rst b/llvm/docs/LangRef.rst --- a/llvm/docs/LangRef.rst +++ b/llvm/docs/LangRef.rst @@ -2048,6 +2048,11 @@ function does not satisfy this contract, the behavior is undefined. This attribute does not apply transitively to callees, but does apply to call sites within the function. Note that `willreturn` implies `mustprogress`. +``"warn-stack-size"=""`` + This attribute sets a threshold to emit diagnostics for once the frame size + is known should the frame size exceed the specified value. It takes one + required integer value, which should be greater than or equal to 0, and + less than `UINT_MAX`. ``vscale_range([, ])`` This attribute indicates the minimum and maximum vscale value for the given function. A value of 0 means unbounded. If the optional max value is omitted diff --git a/llvm/include/llvm/IR/Module.h b/llvm/include/llvm/IR/Module.h --- a/llvm/include/llvm/IR/Module.h +++ b/llvm/include/llvm/IR/Module.h @@ -913,10 +913,6 @@ unsigned getOverrideStackAlignment() const; void setOverrideStackAlignment(unsigned Align); - /// Get/set the stack frame size threshold to warn on. - unsigned getWarnStackSize() const; - void setWarnStackSize(unsigned Threshold); - /// @name Utility functions for querying and setting the build SDK version /// @{ diff --git a/llvm/lib/CodeGen/PrologEpilogInserter.cpp b/llvm/lib/CodeGen/PrologEpilogInserter.cpp --- a/llvm/lib/CodeGen/PrologEpilogInserter.cpp +++ b/llvm/lib/CodeGen/PrologEpilogInserter.cpp @@ -274,7 +274,12 @@ MachineFrameInfo &MFI = MF.getFrameInfo(); uint64_t StackSize = MFI.getStackSize(); - unsigned Threshold = MF.getFunction().getParent()->getWarnStackSize(); + unsigned Threshold = UINT_MAX; + if (MF.getFunction().hasFnAttribute("warn-stack-size")) + MF.getFunction() + .getFnAttribute("warn-stack-size") + .getValueAsString() + .getAsInteger(0, Threshold); if (StackSize > Threshold) { DiagnosticInfoStackSize DiagStackSize(F, StackSize); F.getContext().diagnose(DiagStackSize); diff --git a/llvm/lib/IR/Module.cpp b/llvm/lib/IR/Module.cpp --- a/llvm/lib/IR/Module.cpp +++ b/llvm/lib/IR/Module.cpp @@ -732,17 +732,6 @@ addModuleFlag(ModFlagBehavior::Error, "override-stack-alignment", Align); } -unsigned Module::getWarnStackSize() const { - Metadata *MD = getModuleFlag("warn-stack-size"); - if (auto *CI = mdconst::dyn_extract_or_null(MD)) - return CI->getZExtValue(); - return UINT_MAX; -} - -void Module::setWarnStackSize(unsigned Threshold) { - addModuleFlag(ModFlagBehavior::Error, "warn-stack-size", Threshold); -} - void Module::setSDKVersion(const VersionTuple &V) { SmallVector Entries; Entries.push_back(V.getMajor()); diff --git a/llvm/test/CodeGen/ARM/warn-stack.ll b/llvm/test/CodeGen/ARM/warn-stack.ll --- a/llvm/test/CodeGen/ARM/warn-stack.ll +++ b/llvm/test/CodeGen/ARM/warn-stack.ll @@ -4,7 +4,7 @@ ; ; CHECK-NOT: nowarn -define void @nowarn() nounwind ssp "frame-pointer"="all" { +define void @nowarn() nounwind ssp "frame-pointer"="all" "warn-stack-size"="80" { entry: %buffer = alloca [12 x i8], align 1 %arraydecay = getelementptr inbounds [12 x i8], [12 x i8]* %buffer, i64 0, i64 0 @@ -13,7 +13,7 @@ } ; CHECK: warning: stack size limit exceeded (92) in warn -define void @warn() nounwind ssp "frame-pointer"="all" { +define void @warn() nounwind ssp "frame-pointer"="all" "warn-stack-size"="80" { entry: %buffer = alloca [80 x i8], align 1 %arraydecay = getelementptr inbounds [80 x i8], [80 x i8]* %buffer, i64 0, i64 0 @@ -22,6 +22,3 @@ } declare void @doit(i8*) - -!llvm.module.flags = !{!0} -!0 = !{i32 1, !"warn-stack-size", i32 80} diff --git a/llvm/test/CodeGen/X86/warn-stack.ll b/llvm/test/CodeGen/X86/warn-stack.ll --- a/llvm/test/CodeGen/X86/warn-stack.ll +++ b/llvm/test/CodeGen/X86/warn-stack.ll @@ -4,7 +4,7 @@ ; ; CHECK-NOT: nowarn -define void @nowarn() nounwind ssp { +define void @nowarn() nounwind ssp "warn-stack-size"="80" { entry: %buffer = alloca [12 x i8], align 1 %arraydecay = getelementptr inbounds [12 x i8], [12 x i8]* %buffer, i64 0, i64 0 @@ -13,7 +13,7 @@ } ; CHECK: warning: stack size limit exceeded (88) in warn -define void @warn() nounwind ssp { +define void @warn() nounwind ssp "warn-stack-size"="80" { entry: %buffer = alloca [80 x i8], align 1 %arraydecay = getelementptr inbounds [80 x i8], [80 x i8]* %buffer, i64 0, i64 0 @@ -22,6 +22,3 @@ } declare void @doit(i8*) - -!llvm.module.flags = !{!0} -!0 = !{i32 1, !"warn-stack-size", i32 80} diff --git a/llvm/test/Linker/warn-stack-frame.ll b/llvm/test/Linker/warn-stack-frame.ll deleted file mode 100644 --- a/llvm/test/Linker/warn-stack-frame.ll +++ /dev/null @@ -1,16 +0,0 @@ -; RUN: split-file %s %t -; RUN: llvm-link %t/main.ll %t/match.ll -; RUN: not llvm-link %t/main.ll %t/mismatch.ll 2>&1 | \ -; RUN: FileCheck --check-prefix=CHECK-MISMATCH %s - -; CHECK-MISMATCH: error: linking module flags 'warn-stack-size': IDs have conflicting values - -;--- main.ll -!llvm.module.flags = !{!0} -!0 = !{i32 1, !"warn-stack-size", i32 80} -;--- match.ll -!llvm.module.flags = !{!0} -!0 = !{i32 1, !"warn-stack-size", i32 80} -;--- mismatch.ll -!llvm.module.flags = !{!0} -!0 = !{i32 1, !"warn-stack-size", i32 81}