LCOV - code coverage report
Current view: top level - lib/CodeGen - SafeStackLayout.cpp (source / functions) Hit Total Coverage
Test: llvm-toolchain.info Lines: 48 62 77.4 %
Date: 2017-09-14 15:23:50 Functions: 5 6 83.3 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : //===-- SafeStackLayout.cpp - SafeStack frame layout -----------*- C++ -*--===//
       2             : //
       3             : //                     The LLVM Compiler Infrastructure
       4             : //
       5             : // This file is distributed under the University of Illinois Open Source
       6             : // License. See LICENSE.TXT for details.
       7             : //
       8             : //===----------------------------------------------------------------------===//
       9             : 
      10             : #include "SafeStackLayout.h"
      11             : 
      12             : #include "llvm/IR/Instructions.h"
      13             : #include "llvm/Support/Debug.h"
      14             : 
      15             : using namespace llvm;
      16             : using namespace llvm::safestack;
      17             : 
      18             : #define DEBUG_TYPE "safestacklayout"
      19             : 
      20       72306 : static cl::opt<bool> ClLayout("safe-stack-layout",
      21      216918 :                               cl::desc("enable safe stack layout"), cl::Hidden,
      22      289224 :                               cl::init(true));
      23             : 
      24           0 : LLVM_DUMP_METHOD void StackLayout::print(raw_ostream &OS) {
      25           0 :   OS << "Stack regions:\n";
      26           0 :   for (unsigned i = 0; i < Regions.size(); ++i) {
      27           0 :     OS << "  " << i << ": [" << Regions[i].Start << ", " << Regions[i].End
      28           0 :        << "), range " << Regions[i].Range << "\n";
      29             :   }
      30           0 :   OS << "Stack objects:\n";
      31           0 :   for (auto &IT : ObjectOffsets) {
      32           0 :     OS << "  at " << IT.getSecond() << ": " << *IT.getFirst() << "\n";
      33             :   }
      34           0 : }
      35             : 
      36         243 : void StackLayout::addObject(const Value *V, unsigned Size, unsigned Alignment,
      37             :                             const StackColoring::LiveRange &Range) {
      38         729 :   StackObjects.push_back({V, Size, Alignment, Range});
      39         486 :   MaxAlignment = std::max(MaxAlignment, Alignment);
      40         243 : }
      41             : 
      42             : static unsigned AdjustStackOffset(unsigned Offset, unsigned Size,
      43             :                                   unsigned Alignment) {
      44         902 :   return alignTo(Offset + Size, Alignment) - Size;
      45             : }
      46             : 
      47         243 : void StackLayout::layoutObject(StackObject &Obj) {
      48         243 :   if (!ClLayout) {
      49             :     // If layout is disabled, just grab the next aligned address.
      50             :     // This effectively disables stack coloring as well.
      51           0 :     unsigned LastRegionEnd = Regions.empty() ? 0 : Regions.back().End;
      52           0 :     unsigned Start = AdjustStackOffset(LastRegionEnd, Obj.Size, Obj.Alignment);
      53           0 :     unsigned End = Start + Obj.Size;
      54           0 :     Regions.emplace_back(Start, End, Obj.Range);
      55           0 :     ObjectOffsets[Obj.Handle] = End;
      56             :     return;
      57             :   }
      58             : 
      59             :   DEBUG(dbgs() << "Layout: size " << Obj.Size << ", align " << Obj.Alignment
      60             :                << ", range " << Obj.Range << "\n");
      61             :   assert(Obj.Alignment <= MaxAlignment);
      62         486 :   unsigned Start = AdjustStackOffset(0, Obj.Size, Obj.Alignment);
      63         243 :   unsigned End = Start + Obj.Size;
      64             :   DEBUG(dbgs() << "  First candidate: " << Start << " .. " << End << "\n");
      65        1073 :   for (const StackRegion &R : Regions) {
      66             :     DEBUG(dbgs() << "  Examining region: " << R.Start << " .. " << R.End
      67             :                  << ", range " << R.Range << "\n");
      68             :     assert(End >= R.Start);
      69         385 :     if (Start >= R.End) {
      70             :       DEBUG(dbgs() << "  Does not intersect, skip.\n");
      71         134 :       continue;
      72             :     }
      73         710 :     if (Obj.Range.Overlaps(R.Range)) {
      74             :       // Find the next appropriate location.
      75         416 :       Start = AdjustStackOffset(R.End, Obj.Size, Obj.Alignment);
      76         208 :       End = Start + Obj.Size;
      77             :       DEBUG(dbgs() << "  Overlaps. Next candidate: " << Start << " .. " << End
      78             :                    << "\n");
      79         208 :       continue;
      80             :     }
      81          43 :     if (End <= R.End) {
      82             :       DEBUG(dbgs() << "  Reusing region(s).\n");
      83             :       break;
      84             :     }
      85             :   }
      86             : 
      87         343 :   unsigned LastRegionEnd = Regions.empty() ? 0 : Regions.back().End;
      88         243 :   if (End > LastRegionEnd) {
      89             :     // Insert a new region at the end. Maybe two.
      90         202 :     if (Start > LastRegionEnd) {
      91             :       DEBUG(dbgs() << "  Creating gap region: " << LastRegionEnd << " .. "
      92             :                    << Start << "\n");
      93         114 :       Regions.emplace_back(LastRegionEnd, Start, StackColoring::LiveRange());
      94          38 :       LastRegionEnd = Start;
      95             :     }
      96             :     DEBUG(dbgs() << "  Creating new region: " << LastRegionEnd << " .. " << End
      97             :                  << ", range " << Obj.Range << "\n");
      98         202 :     Regions.emplace_back(LastRegionEnd, End, Obj.Range);
      99         202 :     LastRegionEnd = End;
     100             :   }
     101             : 
     102             :   // Split starting and ending regions if necessary.
     103        2373 :   for (unsigned i = 0; i < Regions.size(); ++i) {
     104        1280 :     StackRegion &R = Regions[i];
     105         640 :     if (Start > R.Start && Start < R.End) {
     106          18 :       StackRegion R0 = R;
     107           9 :       R.Start = R0.End = Start;
     108           9 :       Regions.insert(&R, R0);
     109             :       continue;
     110             :     }
     111         631 :     if (End > R.Start && End < R.End) {
     112          22 :       StackRegion R0 = R;
     113          11 :       R0.End = R.Start = End;
     114          11 :       Regions.insert(&R, R0);
     115             :       break;
     116             :     }
     117             :   }
     118             : 
     119             :   // Update live ranges for all affected regions.
     120         877 :   for (StackRegion &R : Regions) {
     121         634 :     if (Start < R.End && End > R.Start)
     122         245 :       R.Range.Join(Obj.Range);
     123         634 :     if (End <= R.End)
     124             :       break;
     125             :   }
     126             : 
     127         486 :   ObjectOffsets[Obj.Handle] = End;
     128             : }
     129             : 
     130         143 : void StackLayout::computeLayout() {
     131             :   // Simple greedy algorithm.
     132             :   // If this is replaced with something smarter, it must preserve the property
     133             :   // that the first object is always at the offset 0 in the stack frame (for
     134             :   // StackProtectorSlot), or handle stack protector in some other way.
     135             : 
     136             :   // Sort objects by size (largest first) to reduce fragmentation.
     137         286 :   if (StackObjects.size() > 2)
     138          15 :     std::stable_sort(StackObjects.begin() + 1, StackObjects.end(),
     139             :                      [](const StackObject &a, const StackObject &b) {
     140             :                        return a.Size > b.Size;
     141             :                      });
     142             : 
     143         672 :   for (auto &Obj : StackObjects)
     144         243 :     layoutObject(Obj);
     145             : 
     146             :   DEBUG(print(dbgs()));
     147      217061 : }

Generated by: LCOV version 1.13