1*e4e14ae5SMatthias Braun //===-- MachineFrameInfo.cpp ---------------------------------------------===//
2*e4e14ae5SMatthias Braun //
3*e4e14ae5SMatthias Braun //                     The LLVM Compiler Infrastructure
4*e4e14ae5SMatthias Braun //
5*e4e14ae5SMatthias Braun // This file is distributed under the University of Illinois Open Source
6*e4e14ae5SMatthias Braun // License. See LICENSE.TXT for details.
7*e4e14ae5SMatthias Braun //
8*e4e14ae5SMatthias Braun //===----------------------------------------------------------------------===//
9*e4e14ae5SMatthias Braun //
10*e4e14ae5SMatthias Braun /// \file Implements MachineFrameInfo that manages the stack frame.
11*e4e14ae5SMatthias Braun //
12*e4e14ae5SMatthias Braun //===----------------------------------------------------------------------===//
13*e4e14ae5SMatthias Braun 
14*e4e14ae5SMatthias Braun #include "llvm/CodeGen/MachineFrameInfo.h"
15*e4e14ae5SMatthias Braun 
16*e4e14ae5SMatthias Braun #include "llvm/ADT/BitVector.h"
17*e4e14ae5SMatthias Braun #include "llvm/CodeGen/MachineFunction.h"
18*e4e14ae5SMatthias Braun #include "llvm/CodeGen/MachineRegisterInfo.h"
19*e4e14ae5SMatthias Braun #include "llvm/Support/Debug.h"
20*e4e14ae5SMatthias Braun #include "llvm/Support/raw_ostream.h"
21*e4e14ae5SMatthias Braun #include "llvm/Target/TargetFrameLowering.h"
22*e4e14ae5SMatthias Braun #include "llvm/Target/TargetRegisterInfo.h"
23*e4e14ae5SMatthias Braun #include "llvm/Target/TargetSubtargetInfo.h"
24*e4e14ae5SMatthias Braun #include <cassert>
25*e4e14ae5SMatthias Braun 
26*e4e14ae5SMatthias Braun #define DEBUG_TYPE "codegen"
27*e4e14ae5SMatthias Braun 
28*e4e14ae5SMatthias Braun using namespace llvm;
29*e4e14ae5SMatthias Braun 
30*e4e14ae5SMatthias Braun void MachineFrameInfo::ensureMaxAlignment(unsigned Align) {
31*e4e14ae5SMatthias Braun   if (!StackRealignable)
32*e4e14ae5SMatthias Braun     assert(Align <= StackAlignment &&
33*e4e14ae5SMatthias Braun            "For targets without stack realignment, Align is out of limit!");
34*e4e14ae5SMatthias Braun   if (MaxAlignment < Align) MaxAlignment = Align;
35*e4e14ae5SMatthias Braun }
36*e4e14ae5SMatthias Braun 
37*e4e14ae5SMatthias Braun /// Clamp the alignment if requested and emit a warning.
38*e4e14ae5SMatthias Braun static inline unsigned clampStackAlignment(bool ShouldClamp, unsigned Align,
39*e4e14ae5SMatthias Braun                                            unsigned StackAlign) {
40*e4e14ae5SMatthias Braun   if (!ShouldClamp || Align <= StackAlign)
41*e4e14ae5SMatthias Braun     return Align;
42*e4e14ae5SMatthias Braun   DEBUG(dbgs() << "Warning: requested alignment " << Align
43*e4e14ae5SMatthias Braun                << " exceeds the stack alignment " << StackAlign
44*e4e14ae5SMatthias Braun                << " when stack realignment is off" << '\n');
45*e4e14ae5SMatthias Braun   return StackAlign;
46*e4e14ae5SMatthias Braun }
47*e4e14ae5SMatthias Braun 
48*e4e14ae5SMatthias Braun int MachineFrameInfo::CreateStackObject(uint64_t Size, unsigned Alignment,
49*e4e14ae5SMatthias Braun                       bool isSS, const AllocaInst *Alloca) {
50*e4e14ae5SMatthias Braun   assert(Size != 0 && "Cannot allocate zero size stack objects!");
51*e4e14ae5SMatthias Braun   Alignment = clampStackAlignment(!StackRealignable, Alignment, StackAlignment);
52*e4e14ae5SMatthias Braun   Objects.push_back(StackObject(Size, Alignment, 0, false, isSS, Alloca,
53*e4e14ae5SMatthias Braun                                 !isSS));
54*e4e14ae5SMatthias Braun   int Index = (int)Objects.size() - NumFixedObjects - 1;
55*e4e14ae5SMatthias Braun   assert(Index >= 0 && "Bad frame index!");
56*e4e14ae5SMatthias Braun   ensureMaxAlignment(Alignment);
57*e4e14ae5SMatthias Braun   return Index;
58*e4e14ae5SMatthias Braun }
59*e4e14ae5SMatthias Braun 
60*e4e14ae5SMatthias Braun int MachineFrameInfo::CreateSpillStackObject(uint64_t Size,
61*e4e14ae5SMatthias Braun                                              unsigned Alignment) {
62*e4e14ae5SMatthias Braun   Alignment = clampStackAlignment(!StackRealignable, Alignment, StackAlignment);
63*e4e14ae5SMatthias Braun   CreateStackObject(Size, Alignment, true);
64*e4e14ae5SMatthias Braun   int Index = (int)Objects.size() - NumFixedObjects - 1;
65*e4e14ae5SMatthias Braun   ensureMaxAlignment(Alignment);
66*e4e14ae5SMatthias Braun   return Index;
67*e4e14ae5SMatthias Braun }
68*e4e14ae5SMatthias Braun 
69*e4e14ae5SMatthias Braun int MachineFrameInfo::CreateVariableSizedObject(unsigned Alignment,
70*e4e14ae5SMatthias Braun                                                 const AllocaInst *Alloca) {
71*e4e14ae5SMatthias Braun   HasVarSizedObjects = true;
72*e4e14ae5SMatthias Braun   Alignment = clampStackAlignment(!StackRealignable, Alignment, StackAlignment);
73*e4e14ae5SMatthias Braun   Objects.push_back(StackObject(0, Alignment, 0, false, false, Alloca, true));
74*e4e14ae5SMatthias Braun   ensureMaxAlignment(Alignment);
75*e4e14ae5SMatthias Braun   return (int)Objects.size()-NumFixedObjects-1;
76*e4e14ae5SMatthias Braun }
77*e4e14ae5SMatthias Braun 
78*e4e14ae5SMatthias Braun int MachineFrameInfo::CreateFixedObject(uint64_t Size, int64_t SPOffset,
79*e4e14ae5SMatthias Braun                                         bool Immutable, bool isAliased) {
80*e4e14ae5SMatthias Braun   assert(Size != 0 && "Cannot allocate zero size fixed stack objects!");
81*e4e14ae5SMatthias Braun   // The alignment of the frame index can be determined from its offset from
82*e4e14ae5SMatthias Braun   // the incoming frame position.  If the frame object is at offset 32 and
83*e4e14ae5SMatthias Braun   // the stack is guaranteed to be 16-byte aligned, then we know that the
84*e4e14ae5SMatthias Braun   // object is 16-byte aligned. Note that unlike the non-fixed case, if the
85*e4e14ae5SMatthias Braun   // stack needs realignment, we can't assume that the stack will in fact be
86*e4e14ae5SMatthias Braun   // aligned.
87*e4e14ae5SMatthias Braun   unsigned Align = MinAlign(SPOffset, ForcedRealign ? 1 : StackAlignment);
88*e4e14ae5SMatthias Braun   Align = clampStackAlignment(!StackRealignable, Align, StackAlignment);
89*e4e14ae5SMatthias Braun   Objects.insert(Objects.begin(), StackObject(Size, Align, SPOffset, Immutable,
90*e4e14ae5SMatthias Braun                                               /*isSS*/   false,
91*e4e14ae5SMatthias Braun                                               /*Alloca*/ nullptr, isAliased));
92*e4e14ae5SMatthias Braun   return -++NumFixedObjects;
93*e4e14ae5SMatthias Braun }
94*e4e14ae5SMatthias Braun 
95*e4e14ae5SMatthias Braun int MachineFrameInfo::CreateFixedSpillStackObject(uint64_t Size,
96*e4e14ae5SMatthias Braun                                                   int64_t SPOffset,
97*e4e14ae5SMatthias Braun                                                   bool Immutable) {
98*e4e14ae5SMatthias Braun   unsigned Align = MinAlign(SPOffset, ForcedRealign ? 1 : StackAlignment);
99*e4e14ae5SMatthias Braun   Align = clampStackAlignment(!StackRealignable, Align, StackAlignment);
100*e4e14ae5SMatthias Braun   Objects.insert(Objects.begin(), StackObject(Size, Align, SPOffset, Immutable,
101*e4e14ae5SMatthias Braun                                               /*isSS*/ true,
102*e4e14ae5SMatthias Braun                                               /*Alloca*/ nullptr,
103*e4e14ae5SMatthias Braun                                               /*isAliased*/ false));
104*e4e14ae5SMatthias Braun   return -++NumFixedObjects;
105*e4e14ae5SMatthias Braun }
106*e4e14ae5SMatthias Braun 
107*e4e14ae5SMatthias Braun BitVector MachineFrameInfo::getPristineRegs(const MachineFunction &MF) const {
108*e4e14ae5SMatthias Braun   const TargetRegisterInfo *TRI = MF.getSubtarget().getRegisterInfo();
109*e4e14ae5SMatthias Braun   BitVector BV(TRI->getNumRegs());
110*e4e14ae5SMatthias Braun 
111*e4e14ae5SMatthias Braun   // Before CSI is calculated, no registers are considered pristine. They can be
112*e4e14ae5SMatthias Braun   // freely used and PEI will make sure they are saved.
113*e4e14ae5SMatthias Braun   if (!isCalleeSavedInfoValid())
114*e4e14ae5SMatthias Braun     return BV;
115*e4e14ae5SMatthias Braun 
116*e4e14ae5SMatthias Braun   const MachineRegisterInfo &MRI = MF.getRegInfo();
117*e4e14ae5SMatthias Braun   for (const MCPhysReg *CSR = MRI.getCalleeSavedRegs(); CSR && *CSR;
118*e4e14ae5SMatthias Braun        ++CSR)
119*e4e14ae5SMatthias Braun     BV.set(*CSR);
120*e4e14ae5SMatthias Braun 
121*e4e14ae5SMatthias Braun   // Saved CSRs are not pristine.
122*e4e14ae5SMatthias Braun   for (auto &I : getCalleeSavedInfo())
123*e4e14ae5SMatthias Braun     for (MCSubRegIterator S(I.getReg(), TRI, true); S.isValid(); ++S)
124*e4e14ae5SMatthias Braun       BV.reset(*S);
125*e4e14ae5SMatthias Braun 
126*e4e14ae5SMatthias Braun   return BV;
127*e4e14ae5SMatthias Braun }
128*e4e14ae5SMatthias Braun 
129*e4e14ae5SMatthias Braun unsigned MachineFrameInfo::estimateStackSize(const MachineFunction &MF) const {
130*e4e14ae5SMatthias Braun   const TargetFrameLowering *TFI = MF.getSubtarget().getFrameLowering();
131*e4e14ae5SMatthias Braun   const TargetRegisterInfo *RegInfo = MF.getSubtarget().getRegisterInfo();
132*e4e14ae5SMatthias Braun   unsigned MaxAlign = getMaxAlignment();
133*e4e14ae5SMatthias Braun   int Offset = 0;
134*e4e14ae5SMatthias Braun 
135*e4e14ae5SMatthias Braun   // This code is very, very similar to PEI::calculateFrameObjectOffsets().
136*e4e14ae5SMatthias Braun   // It really should be refactored to share code. Until then, changes
137*e4e14ae5SMatthias Braun   // should keep in mind that there's tight coupling between the two.
138*e4e14ae5SMatthias Braun 
139*e4e14ae5SMatthias Braun   for (int i = getObjectIndexBegin(); i != 0; ++i) {
140*e4e14ae5SMatthias Braun     int FixedOff = -getObjectOffset(i);
141*e4e14ae5SMatthias Braun     if (FixedOff > Offset) Offset = FixedOff;
142*e4e14ae5SMatthias Braun   }
143*e4e14ae5SMatthias Braun   for (unsigned i = 0, e = getObjectIndexEnd(); i != e; ++i) {
144*e4e14ae5SMatthias Braun     if (isDeadObjectIndex(i))
145*e4e14ae5SMatthias Braun       continue;
146*e4e14ae5SMatthias Braun     Offset += getObjectSize(i);
147*e4e14ae5SMatthias Braun     unsigned Align = getObjectAlignment(i);
148*e4e14ae5SMatthias Braun     // Adjust to alignment boundary
149*e4e14ae5SMatthias Braun     Offset = (Offset+Align-1)/Align*Align;
150*e4e14ae5SMatthias Braun 
151*e4e14ae5SMatthias Braun     MaxAlign = std::max(Align, MaxAlign);
152*e4e14ae5SMatthias Braun   }
153*e4e14ae5SMatthias Braun 
154*e4e14ae5SMatthias Braun   if (adjustsStack() && TFI->hasReservedCallFrame(MF))
155*e4e14ae5SMatthias Braun     Offset += getMaxCallFrameSize();
156*e4e14ae5SMatthias Braun 
157*e4e14ae5SMatthias Braun   // Round up the size to a multiple of the alignment.  If the function has
158*e4e14ae5SMatthias Braun   // any calls or alloca's, align to the target's StackAlignment value to
159*e4e14ae5SMatthias Braun   // ensure that the callee's frame or the alloca data is suitably aligned;
160*e4e14ae5SMatthias Braun   // otherwise, for leaf functions, align to the TransientStackAlignment
161*e4e14ae5SMatthias Braun   // value.
162*e4e14ae5SMatthias Braun   unsigned StackAlign;
163*e4e14ae5SMatthias Braun   if (adjustsStack() || hasVarSizedObjects() ||
164*e4e14ae5SMatthias Braun       (RegInfo->needsStackRealignment(MF) && getObjectIndexEnd() != 0))
165*e4e14ae5SMatthias Braun     StackAlign = TFI->getStackAlignment();
166*e4e14ae5SMatthias Braun   else
167*e4e14ae5SMatthias Braun     StackAlign = TFI->getTransientStackAlignment();
168*e4e14ae5SMatthias Braun 
169*e4e14ae5SMatthias Braun   // If the frame pointer is eliminated, all frame offsets will be relative to
170*e4e14ae5SMatthias Braun   // SP not FP. Align to MaxAlign so this works.
171*e4e14ae5SMatthias Braun   StackAlign = std::max(StackAlign, MaxAlign);
172*e4e14ae5SMatthias Braun   unsigned AlignMask = StackAlign - 1;
173*e4e14ae5SMatthias Braun   Offset = (Offset + AlignMask) & ~uint64_t(AlignMask);
174*e4e14ae5SMatthias Braun 
175*e4e14ae5SMatthias Braun   return (unsigned)Offset;
176*e4e14ae5SMatthias Braun }
177*e4e14ae5SMatthias Braun 
178*e4e14ae5SMatthias Braun void MachineFrameInfo::print(const MachineFunction &MF, raw_ostream &OS) const{
179*e4e14ae5SMatthias Braun   if (Objects.empty()) return;
180*e4e14ae5SMatthias Braun 
181*e4e14ae5SMatthias Braun   const TargetFrameLowering *FI = MF.getSubtarget().getFrameLowering();
182*e4e14ae5SMatthias Braun   int ValOffset = (FI ? FI->getOffsetOfLocalArea() : 0);
183*e4e14ae5SMatthias Braun 
184*e4e14ae5SMatthias Braun   OS << "Frame Objects:\n";
185*e4e14ae5SMatthias Braun 
186*e4e14ae5SMatthias Braun   for (unsigned i = 0, e = Objects.size(); i != e; ++i) {
187*e4e14ae5SMatthias Braun     const StackObject &SO = Objects[i];
188*e4e14ae5SMatthias Braun     OS << "  fi#" << (int)(i-NumFixedObjects) << ": ";
189*e4e14ae5SMatthias Braun     if (SO.Size == ~0ULL) {
190*e4e14ae5SMatthias Braun       OS << "dead\n";
191*e4e14ae5SMatthias Braun       continue;
192*e4e14ae5SMatthias Braun     }
193*e4e14ae5SMatthias Braun     if (SO.Size == 0)
194*e4e14ae5SMatthias Braun       OS << "variable sized";
195*e4e14ae5SMatthias Braun     else
196*e4e14ae5SMatthias Braun       OS << "size=" << SO.Size;
197*e4e14ae5SMatthias Braun     OS << ", align=" << SO.Alignment;
198*e4e14ae5SMatthias Braun 
199*e4e14ae5SMatthias Braun     if (i < NumFixedObjects)
200*e4e14ae5SMatthias Braun       OS << ", fixed";
201*e4e14ae5SMatthias Braun     if (i < NumFixedObjects || SO.SPOffset != -1) {
202*e4e14ae5SMatthias Braun       int64_t Off = SO.SPOffset - ValOffset;
203*e4e14ae5SMatthias Braun       OS << ", at location [SP";
204*e4e14ae5SMatthias Braun       if (Off > 0)
205*e4e14ae5SMatthias Braun         OS << "+" << Off;
206*e4e14ae5SMatthias Braun       else if (Off < 0)
207*e4e14ae5SMatthias Braun         OS << Off;
208*e4e14ae5SMatthias Braun       OS << "]";
209*e4e14ae5SMatthias Braun     }
210*e4e14ae5SMatthias Braun     OS << "\n";
211*e4e14ae5SMatthias Braun   }
212*e4e14ae5SMatthias Braun }
213*e4e14ae5SMatthias Braun 
214*e4e14ae5SMatthias Braun #if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
215*e4e14ae5SMatthias Braun LLVM_DUMP_METHOD void MachineFrameInfo::dump(const MachineFunction &MF) const {
216*e4e14ae5SMatthias Braun   print(MF, dbgs());
217*e4e14ae5SMatthias Braun }
218*e4e14ae5SMatthias Braun #endif
219