if (CodeGenOpts.UnwindTables)
getModule().setUwtable();
+ switch (CodeGenOpts.getFramePointer()) {
+ case CodeGenOptions::FramePointerKind::None:
+ // 0 ("none") is the default.
+ break;
+ case CodeGenOptions::FramePointerKind::NonLeaf:
+ getModule().setFramePointer(llvm::FramePointerKind::NonLeaf);
+ break;
+ case CodeGenOptions::FramePointerKind::All:
+ getModule().setFramePointer(llvm::FramePointerKind::All);
+ break;
+ }
+
SimplifyPersonality();
if (getCodeGenOpts().EmitDeclMetadata)
--- /dev/null
+/// -mframe-pointer=none sets the module flag "frame-pointer" (merge behavior: max).
+/// asan synthesized ctor/dtor get the "frame-pointer" function attribute if not zero (default).
+// RUN: %clang_cc1 -emit-llvm -fsanitize=address -mframe-pointer=none %s -o - | FileCheck %s --check-prefix=NONE
+// RUN: %clang_cc1 -emit-llvm -fsanitize=address -mframe-pointer=non-leaf %s -o - | FileCheck %s --check-prefix=NONLEAF
+// RUN: %clang_cc1 -emit-llvm -fsanitize=address -mframe-pointer=all %s -o - | FileCheck %s --check-prefix=ALL
+
+int global;
+
+// NONE: define internal void @asan.module_ctor() #[[#ATTR:]] {
+// NONE: define internal void @asan.module_dtor() #[[#ATTR]] {
+// NONE: attributes #[[#ATTR]] = { nounwind }
+
+// NONLEAF: define internal void @asan.module_ctor() #[[#ATTR:]] {
+// NONLEAF: define internal void @asan.module_dtor() #[[#ATTR]] {
+// NONLEAF: attributes #[[#ATTR]] = { nounwind "frame-pointer"="non-leaf" }
+
+// ALL: define internal void @asan.module_ctor() #[[#ATTR:]] {
+// ALL: define internal void @asan.module_dtor() #[[#ATTR]] {
+// ALL: attributes #[[#ATTR]] = { nounwind "frame-pointer"="all" }
can prove that the function does not execute any convergent operations.
Similarly, the optimizer may remove ``convergent`` on calls/invokes when it
can prove that the call/invoke cannot call a convergent function.
+``"frame-pointer"``
+ This attribute tells the code generator whether the function
+ should keep the frame pointer. The code generator may emit the frame pointer
+ even if this attribute says the frame pointer can be eliminated.
+ The allowed string values are:
+
+ * ``"none"`` (default) - the frame pointer can be eliminated.
+ * ``"non-leaf"`` - the frame pointer should be kept if the function calls
+ other functions.
+ * ``"all"`` - the frame pointer should be kept.
``hot``
This attribute indicates that this function is a hot spot of the program
execution. The function will be optimized more aggressively and will be
contain a flag with the ID ``!"foo"`` that has the value '1' after linking is
performed.
+Synthesized Functions Module Flags Metadata
+-------------------------------------------
+
+These metadata specify the default attributes synthesized functions should have.
+These metadata are currently respected by a few instrumentation passes, such as
+sanitizers.
+
+These metadata correspond to a few function attributes with significant code
+generation behaviors. Function attributes with just optimization purposes
+should not be listed because the performance impact of these synthesized
+functions is small.
+
+- "frame-pointer": **Max**. The value can be 0, 1, or 2. A synthesized function
+ will get the "frame-pointer" function attribute, with value being "none",
+ "non-leaf", or "all", respectively.
+- "uwtable": **Max**. The value can be 0 or 1. If the value is 1, a synthesized
+ function will get the ``uwtable`` function attribute.
+
Objective-C Garbage Collection Module Flags Metadata
----------------------------------------------------
CodeGenFileType getFileType();
-llvm::FramePointer::FP getFramePointerUsage();
+FramePointerKind getFramePointerUsage();
bool getEnableUnsafeFPMath();
bool getUwtable() const;
void setUwtable();
+ /// Get/set whether synthesized functions should get the "frame-pointer"
+ /// attribute.
+ FramePointerKind getFramePointer() const;
+ void setFramePointer(FramePointerKind Kind);
+
/// @name Utility functions for querying and setting the build SDK version
/// @{
CGFT_Null // Do not emit any output.
};
- // Specify effect of frame pointer elimination optimization.
- namespace FramePointer {
- enum FP {All, NonLeaf, None};
- }
+ // Specify what functions should keep the frame pointer.
+ enum class FramePointerKind { None, NonLeaf, All };
} // end llvm namespace
CGOPT_EXP(CodeModel::Model, CodeModel)
CGOPT(ExceptionHandling, ExceptionModel)
CGOPT_EXP(CodeGenFileType, FileType)
-CGOPT(FramePointer::FP, FramePointerUsage)
+CGOPT(FramePointerKind, FramePointerUsage)
CGOPT(bool, EnableUnsafeFPMath)
CGOPT(bool, EnableNoInfsFPMath)
CGOPT(bool, EnableNoNaNsFPMath)
"Emit nothing, for performance testing")));
CGBINDOPT(FileType);
- static cl::opt<FramePointer::FP> FramePointerUsage(
+ static cl::opt<FramePointerKind> FramePointerUsage(
"frame-pointer",
cl::desc("Specify frame pointer elimination optimization"),
- cl::init(FramePointer::None),
+ cl::init(FramePointerKind::None),
cl::values(
- clEnumValN(FramePointer::All, "all",
+ clEnumValN(FramePointerKind::All, "all",
"Disable frame pointer elimination"),
- clEnumValN(FramePointer::NonLeaf, "non-leaf",
+ clEnumValN(FramePointerKind::NonLeaf, "non-leaf",
"Disable frame pointer elimination for non-leaf frame"),
- clEnumValN(FramePointer::None, "none",
+ clEnumValN(FramePointerKind::None, "none",
"Enable frame pointer elimination")));
CGBINDOPT(FramePointerUsage);
}
if (FramePointerUsageView->getNumOccurrences() > 0 &&
!F.hasFnAttribute("frame-pointer")) {
- if (getFramePointerUsage() == FramePointer::All)
+ if (getFramePointerUsage() == FramePointerKind::All)
NewAttrs.addAttribute("frame-pointer", "all");
- else if (getFramePointerUsage() == FramePointer::NonLeaf)
+ else if (getFramePointerUsage() == FramePointerKind::NonLeaf)
NewAttrs.addAttribute("frame-pointer", "non-leaf");
- else if (getFramePointerUsage() == FramePointer::None)
+ else if (getFramePointerUsage() == FramePointerKind::None)
NewAttrs.addAttribute("frame-pointer", "none");
}
if (DisableTailCallsView->getNumOccurrences() > 0)
unsigned AddrSpace, const Twine &N,
Module *M) {
auto *F = new Function(Ty, Linkage, AddrSpace, N, M);
+ AttrBuilder B;
if (M->getUwtable())
- F->addAttribute(AttributeList::FunctionIndex, Attribute::UWTable);
+ B.addAttribute(Attribute::UWTable);
+ switch (M->getFramePointer()) {
+ case FramePointerKind::None:
+ // 0 ("none") is the default.
+ break;
+ case FramePointerKind::NonLeaf:
+ B.addAttribute("frame-pointer", "non-leaf");
+ break;
+ case FramePointerKind::All:
+ B.addAttribute("frame-pointer", "all");
+ break;
+ }
+ F->addAttributes(AttributeList::FunctionIndex, B);
return F;
}
void Module::setUwtable() { addModuleFlag(ModFlagBehavior::Max, "uwtable", 1); }
+FramePointerKind Module::getFramePointer() const {
+ auto *Val = cast_or_null<ConstantAsMetadata>(getModuleFlag("frame-pointer"));
+ return static_cast<FramePointerKind>(
+ Val ? cast<ConstantInt>(Val->getValue())->getZExtValue() : 0);
+}
+
+void Module::setFramePointer(FramePointerKind Kind) {
+ addModuleFlag(ModFlagBehavior::Max, "frame-pointer", static_cast<int>(Kind));
+}
+
void Module::setSDKVersion(const VersionTuple &V) {
SmallVector<unsigned, 3> Entries;
Entries.push_back(V.getMajor());
ret i32 %tmp
}
-!llvm.module.flags = !{!0}
+!llvm.module.flags = !{!0, !1}
;; Due to -fasynchronous-unwind-tables.
!0 = !{i32 7, !"uwtable", i32 1}
+;; Due to -fno-omit-frame-pointer.
+!1 = !{i32 7, !"frame-pointer", i32 2}
+
;; Set the uwtable attribute on ctor/dtor.
; CHECK: define internal void @asan.module_ctor() #[[#ATTR:]]
; CHECK: define internal void @asan.module_dtor() #[[#ATTR]]
-; CHECK: attributes #[[#ATTR]] = { nounwind uwtable }
+; CHECK: attributes #[[#ATTR]] = { nounwind uwtable "frame-pointer"="all" }