1//===-- MachineFrameInfo.cpp ---------------------------------------------===//
2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//
7//===----------------------------------------------------------------------===//
8//
9/// \file Implements MachineFrameInfo that manages the stack frame.
10//
11//===----------------------------------------------------------------------===//
12
13#include "llvm/CodeGen/MachineFrameInfo.h"
14
15#include "llvm/ADT/BitVector.h"
16#include "llvm/CodeGen/MachineFunction.h"
17#include "llvm/CodeGen/MachineRegisterInfo.h"
18#include "llvm/CodeGen/TargetFrameLowering.h"
19#include "llvm/CodeGen/TargetInstrInfo.h"
20#include "llvm/CodeGen/TargetRegisterInfo.h"
21#include "llvm/CodeGen/TargetSubtargetInfo.h"
22#include "llvm/Config/llvm-config.h"
23#include "llvm/Support/Debug.h"
24#include "llvm/Support/raw_ostream.h"
25#include <cassert>
26
27#define DEBUG_TYPE "codegen"
28
29using namespace llvm;
30
31void MachineFrameInfo::ensureMaxAlignment(Align Alignment) {
32  if (!StackRealignable)
33    assert(Alignment <= StackAlignment &&
34           "For targets without stack realignment, Alignment is out of limit!");
35  if (MaxAlignment < Alignment)
36    MaxAlignment = Alignment;
37}
38
39/// Clamp the alignment if requested and emit a warning.
40static inline Align clampStackAlignment(bool ShouldClamp, Align Alignment,
41                                        Align StackAlignment) {
42  if (!ShouldClamp || Alignment <= StackAlignment)
43    return Alignment;
44  LLVM_DEBUG(dbgs() << "Warning: requested alignment " << DebugStr(Alignment)
45                    << " exceeds the stack alignment "
46                    << DebugStr(StackAlignment)
47                    << " when stack realignment is off" << '\n');
48  return StackAlignment;
49}
50
51int MachineFrameInfo::CreateStackObject(uint64_t Size, Align Alignment,
52                                        bool IsSpillSlot,
53                                        const AllocaInst *Alloca,
54                                        uint8_t StackID) {
55  assert(Size != 0 && "Cannot allocate zero size stack objects!");
56  Alignment = clampStackAlignment(!StackRealignable, Alignment, StackAlignment);
57  Objects.push_back(StackObject(Size, Alignment, 0, false, IsSpillSlot, Alloca,
58                                !IsSpillSlot, StackID));
59  int Index = (int)Objects.size() - NumFixedObjects - 1;
60  assert(Index >= 0 && "Bad frame index!");
61  if (contributesToMaxAlignment(StackID))
62    ensureMaxAlignment(Alignment);
63  return Index;
64}
65
66int MachineFrameInfo::CreateSpillStackObject(uint64_t Size, Align Alignment) {
67  Alignment = clampStackAlignment(!StackRealignable, Alignment, StackAlignment);
68  CreateStackObject(Size, Alignment, true);
69  int Index = (int)Objects.size() - NumFixedObjects - 1;
70  ensureMaxAlignment(Alignment);
71  return Index;
72}
73
74int MachineFrameInfo::CreateVariableSizedObject(Align Alignment,
75                                                const AllocaInst *Alloca) {
76  HasVarSizedObjects = true;
77  Alignment = clampStackAlignment(!StackRealignable, Alignment, StackAlignment);
78  Objects.push_back(StackObject(0, Alignment, 0, false, false, Alloca, true));
79  ensureMaxAlignment(Alignment);
80  return (int)Objects.size()-NumFixedObjects-1;
81}
82
83int MachineFrameInfo::CreateFixedObject(uint64_t Size, int64_t SPOffset,
84                                        bool IsImmutable, bool IsAliased) {
85  assert(Size != 0 && "Cannot allocate zero size fixed stack objects!");
86  // The alignment of the frame index can be determined from its offset from
87  // the incoming frame position.  If the frame object is at offset 32 and
88  // the stack is guaranteed to be 16-byte aligned, then we know that the
89  // object is 16-byte aligned. Note that unlike the non-fixed case, if the
90  // stack needs realignment, we can't assume that the stack will in fact be
91  // aligned.
92  Align Alignment =
93      commonAlignment(ForcedRealign ? Align(1) : StackAlignment, SPOffset);
94  Alignment = clampStackAlignment(!StackRealignable, Alignment, StackAlignment);
95  Objects.insert(Objects.begin(),
96                 StackObject(Size, Alignment, SPOffset, IsImmutable,
97                             /*IsSpillSlot=*/false, /*Alloca=*/nullptr,
98                             IsAliased));
99  return -++NumFixedObjects;
100}
101
102int MachineFrameInfo::CreateFixedSpillStackObject(uint64_t Size,
103                                                  int64_t SPOffset,
104                                                  bool IsImmutable) {
105  Align Alignment =
106      commonAlignment(ForcedRealign ? Align(1) : StackAlignment, SPOffset);
107  Alignment = clampStackAlignment(!StackRealignable, Alignment, StackAlignment);
108  Objects.insert(Objects.begin(),
109                 StackObject(Size, Alignment, SPOffset, IsImmutable,
110                             /*IsSpillSlot=*/true, /*Alloca=*/nullptr,
111                             /*IsAliased=*/false));
112  return -++NumFixedObjects;
113}
114
115BitVector MachineFrameInfo::getPristineRegs(const MachineFunction &MF) const {
116  const TargetRegisterInfo *TRI = MF.getSubtarget().getRegisterInfo();
117  BitVector BV(TRI->getNumRegs());
118
119  // Before CSI is calculated, no registers are considered pristine. They can be
120  // freely used and PEI will make sure they are saved.
121  if (!isCalleeSavedInfoValid())
122    return BV;
123
124  const MachineRegisterInfo &MRI = MF.getRegInfo();
125  for (const MCPhysReg *CSR = MRI.getCalleeSavedRegs(); CSR && *CSR;
126       ++CSR)
127    BV.set(*CSR);
128
129  // Saved CSRs are not pristine.
130  for (const auto &I : getCalleeSavedInfo())
131    for (MCSubRegIterator S(I.getReg(), TRI, true); S.isValid(); ++S)
132      BV.reset(*S);
133
134  return BV;
135}
136
137uint64_t MachineFrameInfo::estimateStackSize(const MachineFunction &MF) const {
138  const TargetFrameLowering *TFI = MF.getSubtarget().getFrameLowering();
139  const TargetRegisterInfo *RegInfo = MF.getSubtarget().getRegisterInfo();
140  Align MaxAlign = getMaxAlign();
141  int64_t Offset = 0;
142
143  // This code is very, very similar to PEI::calculateFrameObjectOffsets().
144  // It really should be refactored to share code. Until then, changes
145  // should keep in mind that there's tight coupling between the two.
146
147  for (int i = getObjectIndexBegin(); i != 0; ++i) {
148    // Only estimate stack size of default stack.
149    if (getStackID(i) != TargetStackID::Default)
150      continue;
151    int64_t FixedOff = -getObjectOffset(i);
152    if (FixedOff > Offset) Offset = FixedOff;
153  }
154  for (unsigned i = 0, e = getObjectIndexEnd(); i != e; ++i) {
155    // Only estimate stack size of live objects on default stack.
156    if (isDeadObjectIndex(i) || getStackID(i) != TargetStackID::Default)
157      continue;
158    Offset += getObjectSize(i);
159    Align Alignment = getObjectAlign(i);
160    // Adjust to alignment boundary
161    Offset = alignTo(Offset, Alignment);
162
163    MaxAlign = std::max(Alignment, MaxAlign);
164  }
165
166  if (adjustsStack() && TFI->hasReservedCallFrame(MF))
167    Offset += getMaxCallFrameSize();
168
169  // Round up the size to a multiple of the alignment.  If the function has
170  // any calls or alloca's, align to the target's StackAlignment value to
171  // ensure that the callee's frame or the alloca data is suitably aligned;
172  // otherwise, for leaf functions, align to the TransientStackAlignment
173  // value.
174  Align StackAlign;
175  if (adjustsStack() || hasVarSizedObjects() ||
176      (RegInfo->hasStackRealignment(MF) && getObjectIndexEnd() != 0))
177    StackAlign = TFI->getStackAlign();
178  else
179    StackAlign = TFI->getTransientStackAlign();
180
181  // If the frame pointer is eliminated, all frame offsets will be relative to
182  // SP not FP. Align to MaxAlign so this works.
183  StackAlign = std::max(StackAlign, MaxAlign);
184  return alignTo(Offset, StackAlign);
185}
186
187void MachineFrameInfo::computeMaxCallFrameSize(const MachineFunction &MF) {
188  const TargetInstrInfo &TII = *MF.getSubtarget().getInstrInfo();
189  unsigned FrameSetupOpcode = TII.getCallFrameSetupOpcode();
190  unsigned FrameDestroyOpcode = TII.getCallFrameDestroyOpcode();
191  assert(FrameSetupOpcode != ~0u && FrameDestroyOpcode != ~0u &&
192         "Can only compute MaxCallFrameSize if Setup/Destroy opcode are known");
193
194  MaxCallFrameSize = 0;
195  for (const MachineBasicBlock &MBB : MF) {
196    for (const MachineInstr &MI : MBB) {
197      unsigned Opcode = MI.getOpcode();
198      if (Opcode == FrameSetupOpcode || Opcode == FrameDestroyOpcode) {
199        unsigned Size = TII.getFrameSize(MI);
200        MaxCallFrameSize = std::max(MaxCallFrameSize, Size);
201        AdjustsStack = true;
202      } else if (MI.isInlineAsm()) {
203        // Some inline asm's need a stack frame, as indicated by operand 1.
204        unsigned ExtraInfo = MI.getOperand(InlineAsm::MIOp_ExtraInfo).getImm();
205        if (ExtraInfo & InlineAsm::Extra_IsAlignStack)
206          AdjustsStack = true;
207      }
208    }
209  }
210}
211
212void MachineFrameInfo::print(const MachineFunction &MF, raw_ostream &OS) const{
213  if (Objects.empty()) return;
214
215  const TargetFrameLowering *FI = MF.getSubtarget().getFrameLowering();
216  int ValOffset = (FI ? FI->getOffsetOfLocalArea() : 0);
217
218  OS << "Frame Objects:\n";
219
220  for (unsigned i = 0, e = Objects.size(); i != e; ++i) {
221    const StackObject &SO = Objects[i];
222    OS << "  fi#" << (int)(i-NumFixedObjects) << ": ";
223
224    if (SO.StackID != 0)
225      OS << "id=" << static_cast<unsigned>(SO.StackID) << ' ';
226
227    if (SO.Size == ~0ULL) {
228      OS << "dead\n";
229      continue;
230    }
231    if (SO.Size == 0)
232      OS << "variable sized";
233    else
234      OS << "size=" << SO.Size;
235    OS << ", align=" << SO.Alignment.value();
236
237    if (i < NumFixedObjects)
238      OS << ", fixed";
239    if (i < NumFixedObjects || SO.SPOffset != -1) {
240      int64_t Off = SO.SPOffset - ValOffset;
241      OS << ", at location [SP";
242      if (Off > 0)
243        OS << "+" << Off;
244      else if (Off < 0)
245        OS << Off;
246      OS << "]";
247    }
248    OS << "\n";
249  }
250}
251
252#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
253LLVM_DUMP_METHOD void MachineFrameInfo::dump(const MachineFunction &MF) const {
254  print(MF, dbgs());
255}
256#endif
257