]> granicus.if.org Git - llvm/commitdiff
[MC] Function stack size section.
authorSean Eveson <eveson.sean@gmail.com>
Thu, 30 Nov 2017 13:05:14 +0000 (13:05 +0000)
committerSean Eveson <eveson.sean@gmail.com>
Thu, 30 Nov 2017 13:05:14 +0000 (13:05 +0000)
Re applying after fixing issues in the diff, sorry for any painful conflicts/merges!

Original RFC: http://lists.llvm.org/pipermail/llvm-dev/2017-August/117028.html

This change adds a '.stack-size' section containing metadata on function stack sizes to output ELF files behind the new -stack-size-section flag. The section contains pairs of function symbol references (8 byte) and stack sizes (unsigned LEB128).

The contents of this section can be used to measure changes to stack sizes between different versions of the compiler or a source base. The advantage of having a section is that we can extract this information when examining binaries that we didn't build, and it allows users and tools easy access to that information just by referencing the binary.

There is a follow up change to add an option to clang.

Thanks.

Reviewers: hfinkel, MatzeB

Reviewed By: MatzeB

Subscribers: thegameg, asb, llvm-commits

Differential Revision: https://reviews.llvm.org/D39788

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@319430 91177308-0d34-0410-b5e6-96231b3b80d8

docs/CodeGenerator.rst
docs/CommandGuide/llc.rst
include/llvm/CodeGen/AsmPrinter.h
include/llvm/CodeGen/CommandFlags.def
include/llvm/MC/MCObjectFileInfo.h
include/llvm/Target/TargetOptions.h
lib/CodeGen/AsmPrinter/AsmPrinter.cpp
lib/MC/MCObjectFileInfo.cpp
test/CodeGen/X86/stack-size-section.ll [new file with mode: 0644]

index bcdc7228356653479d18e2b7bcb11e39b1a558df..5c0fb064959ef9d7bf2ab1d0ba5eafc7547244e7 100644 (file)
@@ -1578,6 +1578,17 @@ which lowers MCInst's into machine code bytes and relocations.  This is
 important if you want to support direct .o file emission, or would like to
 implement an assembler for your target.
 
+Emitting function stack size information
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+A section containing metadata on function stack sizes will be emitted when
+``TargetLoweringObjectFile::StackSizesSection`` is not null, and
+``TargetOptions::EmitStackSizeSection`` is set (-stack-size-section). The
+section will contain an array of pairs of function symbol references (8 byte)
+and stack sizes (unsigned LEB128). The stack size values only include the space
+allocated in the function prologue. Functions with dynamic stack allocations are
+not included.
+
 VLIW Packetizer
 ---------------
 
index 5094259f9f952775536709da9287306f691a1d54..95945e68d13f341c6d17fdac9148761cc6a15e78 100644 (file)
@@ -132,6 +132,14 @@ End-user Options
  Specify which EABI version should conform to.  Valid EABI versions are *gnu*,
  *4* and *5*.  Default value (*default*) depends on the triple.
 
+.. option:: -stack-size-section
+
+ Emit the .stack_sizes section which contains stack size metadata. The section
+ contains an array of pairs of function symbol references (8 byte) and stack
+ sizes (unsigned LEB128). The stack size values only include the space allocated
+ in the function prologue. Functions with dynamic stack allocations are not
+ included.
+
 
 Tuning/Configuration Options
 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~
index 1d65f703b84d2633490351b035cbc8e4f96a805c..b8944a668000dbe2f6fa1d33f50ec7e55682a1ea 100644 (file)
@@ -295,6 +295,8 @@ public:
 
   void emitFrameAlloc(const MachineInstr &MI);
 
+  void emitStackSizeSection(const MachineFunction &MF);
+
   enum CFIMoveType { CFI_M_None, CFI_M_EH, CFI_M_Debug };
   CFIMoveType needsCFIMoves() const;
 
index 83cbeb0341fa7b1440a20432129429be7e1d4309..fe96033a9c617b50fd9b2eea6a77829362358365 100644 (file)
@@ -255,6 +255,10 @@ static cl::opt<DebuggerKind> DebuggerTuningOpt(
                clEnumValN(DebuggerKind::LLDB, "lldb", "lldb"),
                clEnumValN(DebuggerKind::SCE, "sce", "SCE targets (e.g. PS4)")));
 
+static cl::opt<bool> EnableStackSizeSection(
+    "stack-size-section",
+    cl::desc("Emit a section containing stack size metadata"), cl::init(false));
+
 // Common utility function tightly tied to the options listed here. Initializes
 // a TargetOptions object with CodeGen flags and returns it.
 static TargetOptions InitTargetOptionsFromCodeGenFlags() {
@@ -281,6 +285,7 @@ static TargetOptions InitTargetOptionsFromCodeGenFlags() {
   Options.UniqueSectionNames = UniqueSectionNames;
   Options.EmulatedTLS = EmulatedTLS;
   Options.ExceptionModel = ExceptionModel;
+  Options.EmitStackSizeSection = EnableStackSizeSection;
 
   Options.MCOptions = InitMCTargetOptionsFromFlags();
 
index d95f84d1d816e5573d079eed92237b24f7eb1e9c..c0b1443591c6ee73a011b2a54da0071187bc47b9 100644 (file)
@@ -154,6 +154,9 @@ protected:
   /// It is initialized on demand so it can be overwritten (with uniquing).
   MCSection *EHFrameSection;
 
+  /// Section containing metadata on function stack sizes.
+  MCSection *StackSizesSection;
+
   // ELF specific sections.
   MCSection *DataRelROSection;
   MCSection *MergeableConst4Section;
@@ -287,6 +290,8 @@ public:
   MCSection *getStackMapSection() const { return StackMapSection; }
   MCSection *getFaultMapSection() const { return FaultMapSection; }
 
+  MCSection *getStackSizesSection() const { return StackSizesSection; }
+
   // ELF specific sections.
   MCSection *getDataRelROSection() const { return DataRelROSection; }
   const MCSection *getMergeableConst4Section() const {
index 5c2063880f8be89a2cbe5bd797b8ebf092a8acd8..70fac7833f32421d4b1293defc8a6584b9cfde72 100644 (file)
@@ -108,7 +108,7 @@ namespace llvm {
           DisableIntegratedAS(false), RelaxELFRelocations(false),
           FunctionSections(false), DataSections(false),
           UniqueSectionNames(true), TrapUnreachable(false), EmulatedTLS(false),
-          EnableIPRA(false) {}
+          EnableIPRA(false), EmitStackSizeSection(false) {}
 
     /// PrintMachineCode - This flag is enabled when the -print-machineinstrs
     /// option is specified on the command line, and should enable debugging
@@ -216,6 +216,9 @@ namespace llvm {
     /// This flag enables InterProcedural Register Allocation (IPRA).
     unsigned EnableIPRA : 1;
 
+    /// Emit section containing metadata on function stack sizes.
+    unsigned EmitStackSizeSection : 1;
+
     /// FloatABIType - This setting is set by -float-abi=xxx option is specfied
     /// on the command line. This setting may either be Default, Soft, or Hard.
     /// Default selects the target's default behavior. Soft selects the ABI for
index c9b0f9aa556fe455cb6edc7651b2eacda0db88a0..2d82f81ed70f84b9e494032f820c242e05a67f3d 100644 (file)
@@ -964,6 +964,31 @@ void AsmPrinter::emitFrameAlloc(const MachineInstr &MI) {
                              MCConstantExpr::create(FrameOffset, OutContext));
 }
 
+void AsmPrinter::emitStackSizeSection(const MachineFunction &MF) {
+  if (!MF.getTarget().Options.EmitStackSizeSection)
+    return;
+
+  MCSection *StackSizeSection = getObjFileLowering().getStackSizesSection();
+  if (!StackSizeSection)
+    return;
+
+  const MachineFrameInfo &FrameInfo = MF.getFrameInfo();
+  // Don't emit functions with dynamic stack allocations.
+  if (FrameInfo.hasVarSizedObjects())
+    return;
+
+  OutStreamer->PushSection();
+  OutStreamer->SwitchSection(StackSizeSection);
+
+  const MCSymbol *FunctionSymbol = getSymbol(MF.getFunction());
+  uint64_t StackSize = FrameInfo.getStackSize();
+  OutStreamer->EmitValue(MCSymbolRefExpr::create(FunctionSymbol, OutContext),
+                         /* size = */ 8);
+  OutStreamer->EmitULEB128IntValue(StackSize);
+
+  OutStreamer->PopSection();
+}
+
 static bool needFuncLabelsForEHOrDebugInfo(const MachineFunction &MF,
                                            MachineModuleInfo *MMI) {
   if (!MF.getLandingPads().empty() || MF.hasEHFunclets() || MMI->hasDebugInfo())
@@ -1135,6 +1160,9 @@ void AsmPrinter::EmitFunctionBody() {
     HI.Handler->endFunction(MF);
   }
 
+  // Emit section containing stack size metadata.
+  emitStackSizeSection(*MF);
+
   if (isVerbose())
     OutStreamer->GetCommentOS() << "-- End function\n";
 
index d8077df14698672474d76c383267d6b74266fdb9..ba0146fd9fcac9671fe5f7a8903f5300b59b4784 100644 (file)
@@ -594,6 +594,8 @@ void MCObjectFileInfo::initELFMCObjectFileInfo(const Triple &T, bool Large) {
 
   EHFrameSection =
       Ctx->getELFSection(".eh_frame", EHSectionType, EHSectionFlags);
+
+  StackSizesSection = Ctx->getELFSection(".stack_sizes", ELF::SHT_PROGBITS, 0);
 }
 
 void MCObjectFileInfo::initCOFFMCObjectFileInfo(const Triple &T) {
diff --git a/test/CodeGen/X86/stack-size-section.ll b/test/CodeGen/X86/stack-size-section.ll
new file mode 100644 (file)
index 0000000..28b26ae
--- /dev/null
@@ -0,0 +1,30 @@
+; RUN: llc < %s -mtriple=x86_64-linux -stack-size-section | FileCheck %s
+
+; CHECK-LABEL: func1:
+; CHECK: .section .stack_sizes,"",@progbits
+; CHECK-NEXT: .quad func1
+; CHECK-NEXT: .byte 8
+define void @func1(i32, i32) #0 {
+  alloca i32, align 4
+  alloca i32, align 4
+  ret void
+}
+
+; CHECK-LABEL: func2:
+; CHECK: .section .stack_sizes,"",@progbits
+; CHECK-NEXT: .quad func2
+; CHECK-NEXT: .byte 24
+define void @func2() #0 {
+  alloca i32, align 4
+  call void @func1(i32 1, i32 2)
+  ret void
+}
+
+; CHECK-LABEL: dynalloc:
+; CHECK-NOT: .section .stack_sizes
+define void @dynalloc(i32 %N) #0 {
+  alloca i32, i32 %N
+  ret void
+}
+
+attributes #0 = { "no-frame-pointer-elim"="true" }