2017-04-27 07:36:58 +08:00
|
|
|
//===-- MachineFrameInfo.cpp ---------------------------------------------===//
|
|
|
|
//
|
|
|
|
// The LLVM Compiler Infrastructure
|
|
|
|
//
|
|
|
|
// This file is distributed under the University of Illinois Open Source
|
|
|
|
// License. See LICENSE.TXT for details.
|
|
|
|
//
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
//
|
|
|
|
/// \file Implements MachineFrameInfo that manages the stack frame.
|
|
|
|
//
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
|
|
|
|
#include "llvm/CodeGen/MachineFrameInfo.h"
|
|
|
|
|
|
|
|
#include "llvm/ADT/BitVector.h"
|
|
|
|
#include "llvm/CodeGen/MachineFunction.h"
|
|
|
|
#include "llvm/CodeGen/MachineRegisterInfo.h"
|
2017-11-08 09:01:31 +08:00
|
|
|
#include "llvm/CodeGen/TargetFrameLowering.h"
|
|
|
|
#include "llvm/CodeGen/TargetInstrInfo.h"
|
2017-11-17 09:07:10 +08:00
|
|
|
#include "llvm/CodeGen/TargetRegisterInfo.h"
|
|
|
|
#include "llvm/CodeGen/TargetSubtargetInfo.h"
|
2018-04-30 22:59:11 +08:00
|
|
|
#include "llvm/Config/llvm-config.h"
|
2017-04-27 07:36:58 +08:00
|
|
|
#include "llvm/Support/Debug.h"
|
|
|
|
#include "llvm/Support/raw_ostream.h"
|
|
|
|
#include <cassert>
|
|
|
|
|
|
|
|
#define DEBUG_TYPE "codegen"
|
|
|
|
|
|
|
|
using namespace llvm;
|
|
|
|
|
|
|
|
void MachineFrameInfo::ensureMaxAlignment(unsigned Align) {
|
|
|
|
if (!StackRealignable)
|
|
|
|
assert(Align <= StackAlignment &&
|
|
|
|
"For targets without stack realignment, Align is out of limit!");
|
|
|
|
if (MaxAlignment < Align) MaxAlignment = Align;
|
|
|
|
}
|
|
|
|
|
|
|
|
/// Clamp the alignment if requested and emit a warning.
|
|
|
|
static inline unsigned clampStackAlignment(bool ShouldClamp, unsigned Align,
|
|
|
|
unsigned StackAlign) {
|
|
|
|
if (!ShouldClamp || Align <= StackAlign)
|
|
|
|
return Align;
|
2018-05-14 20:53:11 +08:00
|
|
|
LLVM_DEBUG(dbgs() << "Warning: requested alignment " << Align
|
|
|
|
<< " exceeds the stack alignment " << StackAlign
|
|
|
|
<< " when stack realignment is off" << '\n');
|
2017-04-27 07:36:58 +08:00
|
|
|
return StackAlign;
|
|
|
|
}
|
|
|
|
|
|
|
|
int MachineFrameInfo::CreateStackObject(uint64_t Size, unsigned Alignment,
|
2017-12-05 09:18:15 +08:00
|
|
|
bool IsSpillSlot,
|
|
|
|
const AllocaInst *Alloca,
|
|
|
|
uint8_t StackID) {
|
2017-04-27 07:36:58 +08:00
|
|
|
assert(Size != 0 && "Cannot allocate zero size stack objects!");
|
|
|
|
Alignment = clampStackAlignment(!StackRealignable, Alignment, StackAlignment);
|
2017-12-05 09:18:15 +08:00
|
|
|
Objects.push_back(StackObject(Size, Alignment, 0, false, IsSpillSlot, Alloca,
|
|
|
|
!IsSpillSlot, StackID));
|
2017-04-27 07:36:58 +08:00
|
|
|
int Index = (int)Objects.size() - NumFixedObjects - 1;
|
|
|
|
assert(Index >= 0 && "Bad frame index!");
|
|
|
|
ensureMaxAlignment(Alignment);
|
|
|
|
return Index;
|
|
|
|
}
|
|
|
|
|
|
|
|
int MachineFrameInfo::CreateSpillStackObject(uint64_t Size,
|
|
|
|
unsigned Alignment) {
|
|
|
|
Alignment = clampStackAlignment(!StackRealignable, Alignment, StackAlignment);
|
|
|
|
CreateStackObject(Size, Alignment, true);
|
|
|
|
int Index = (int)Objects.size() - NumFixedObjects - 1;
|
|
|
|
ensureMaxAlignment(Alignment);
|
|
|
|
return Index;
|
|
|
|
}
|
|
|
|
|
|
|
|
int MachineFrameInfo::CreateVariableSizedObject(unsigned Alignment,
|
|
|
|
const AllocaInst *Alloca) {
|
|
|
|
HasVarSizedObjects = true;
|
|
|
|
Alignment = clampStackAlignment(!StackRealignable, Alignment, StackAlignment);
|
|
|
|
Objects.push_back(StackObject(0, Alignment, 0, false, false, Alloca, true));
|
|
|
|
ensureMaxAlignment(Alignment);
|
|
|
|
return (int)Objects.size()-NumFixedObjects-1;
|
|
|
|
}
|
|
|
|
|
|
|
|
int MachineFrameInfo::CreateFixedObject(uint64_t Size, int64_t SPOffset,
|
2017-12-05 09:18:15 +08:00
|
|
|
bool IsImmutable, bool IsAliased) {
|
2017-04-27 07:36:58 +08:00
|
|
|
assert(Size != 0 && "Cannot allocate zero size fixed stack objects!");
|
|
|
|
// The alignment of the frame index can be determined from its offset from
|
|
|
|
// the incoming frame position. If the frame object is at offset 32 and
|
|
|
|
// the stack is guaranteed to be 16-byte aligned, then we know that the
|
|
|
|
// object is 16-byte aligned. Note that unlike the non-fixed case, if the
|
|
|
|
// stack needs realignment, we can't assume that the stack will in fact be
|
|
|
|
// aligned.
|
2017-12-05 09:18:15 +08:00
|
|
|
unsigned Alignment = MinAlign(SPOffset, ForcedRealign ? 1 : StackAlignment);
|
|
|
|
Alignment = clampStackAlignment(!StackRealignable, Alignment, StackAlignment);
|
|
|
|
Objects.insert(Objects.begin(),
|
|
|
|
StackObject(Size, Alignment, SPOffset, IsImmutable,
|
|
|
|
/*isSpillSlot=*/false, /*Alloca=*/nullptr,
|
|
|
|
IsAliased));
|
2017-04-27 07:36:58 +08:00
|
|
|
return -++NumFixedObjects;
|
|
|
|
}
|
|
|
|
|
|
|
|
int MachineFrameInfo::CreateFixedSpillStackObject(uint64_t Size,
|
|
|
|
int64_t SPOffset,
|
2017-12-05 09:18:15 +08:00
|
|
|
bool IsImmutable) {
|
|
|
|
unsigned Alignment = MinAlign(SPOffset, ForcedRealign ? 1 : StackAlignment);
|
|
|
|
Alignment = clampStackAlignment(!StackRealignable, Alignment, StackAlignment);
|
|
|
|
Objects.insert(Objects.begin(),
|
|
|
|
StackObject(Size, Alignment, SPOffset, IsImmutable,
|
|
|
|
/*IsSpillSlot=*/true, /*Alloca=*/nullptr,
|
|
|
|
/*IsAliased=*/false));
|
2017-04-27 07:36:58 +08:00
|
|
|
return -++NumFixedObjects;
|
|
|
|
}
|
|
|
|
|
|
|
|
BitVector MachineFrameInfo::getPristineRegs(const MachineFunction &MF) const {
|
|
|
|
const TargetRegisterInfo *TRI = MF.getSubtarget().getRegisterInfo();
|
|
|
|
BitVector BV(TRI->getNumRegs());
|
|
|
|
|
|
|
|
// Before CSI is calculated, no registers are considered pristine. They can be
|
|
|
|
// freely used and PEI will make sure they are saved.
|
|
|
|
if (!isCalleeSavedInfoValid())
|
|
|
|
return BV;
|
|
|
|
|
|
|
|
const MachineRegisterInfo &MRI = MF.getRegInfo();
|
|
|
|
for (const MCPhysReg *CSR = MRI.getCalleeSavedRegs(); CSR && *CSR;
|
|
|
|
++CSR)
|
|
|
|
BV.set(*CSR);
|
|
|
|
|
|
|
|
// Saved CSRs are not pristine.
|
|
|
|
for (auto &I : getCalleeSavedInfo())
|
|
|
|
for (MCSubRegIterator S(I.getReg(), TRI, true); S.isValid(); ++S)
|
|
|
|
BV.reset(*S);
|
|
|
|
|
|
|
|
return BV;
|
|
|
|
}
|
|
|
|
|
|
|
|
unsigned MachineFrameInfo::estimateStackSize(const MachineFunction &MF) const {
|
|
|
|
const TargetFrameLowering *TFI = MF.getSubtarget().getFrameLowering();
|
|
|
|
const TargetRegisterInfo *RegInfo = MF.getSubtarget().getRegisterInfo();
|
|
|
|
unsigned MaxAlign = getMaxAlignment();
|
|
|
|
int Offset = 0;
|
|
|
|
|
|
|
|
// This code is very, very similar to PEI::calculateFrameObjectOffsets().
|
|
|
|
// It really should be refactored to share code. Until then, changes
|
|
|
|
// should keep in mind that there's tight coupling between the two.
|
|
|
|
|
|
|
|
for (int i = getObjectIndexBegin(); i != 0; ++i) {
|
|
|
|
int FixedOff = -getObjectOffset(i);
|
|
|
|
if (FixedOff > Offset) Offset = FixedOff;
|
|
|
|
}
|
|
|
|
for (unsigned i = 0, e = getObjectIndexEnd(); i != e; ++i) {
|
|
|
|
if (isDeadObjectIndex(i))
|
|
|
|
continue;
|
|
|
|
Offset += getObjectSize(i);
|
|
|
|
unsigned Align = getObjectAlignment(i);
|
|
|
|
// Adjust to alignment boundary
|
|
|
|
Offset = (Offset+Align-1)/Align*Align;
|
|
|
|
|
|
|
|
MaxAlign = std::max(Align, MaxAlign);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (adjustsStack() && TFI->hasReservedCallFrame(MF))
|
|
|
|
Offset += getMaxCallFrameSize();
|
|
|
|
|
|
|
|
// Round up the size to a multiple of the alignment. If the function has
|
|
|
|
// any calls or alloca's, align to the target's StackAlignment value to
|
|
|
|
// ensure that the callee's frame or the alloca data is suitably aligned;
|
|
|
|
// otherwise, for leaf functions, align to the TransientStackAlignment
|
|
|
|
// value.
|
|
|
|
unsigned StackAlign;
|
|
|
|
if (adjustsStack() || hasVarSizedObjects() ||
|
|
|
|
(RegInfo->needsStackRealignment(MF) && getObjectIndexEnd() != 0))
|
|
|
|
StackAlign = TFI->getStackAlignment();
|
|
|
|
else
|
|
|
|
StackAlign = TFI->getTransientStackAlignment();
|
|
|
|
|
|
|
|
// If the frame pointer is eliminated, all frame offsets will be relative to
|
|
|
|
// SP not FP. Align to MaxAlign so this works.
|
|
|
|
StackAlign = std::max(StackAlign, MaxAlign);
|
|
|
|
unsigned AlignMask = StackAlign - 1;
|
|
|
|
Offset = (Offset + AlignMask) & ~uint64_t(AlignMask);
|
|
|
|
|
|
|
|
return (unsigned)Offset;
|
|
|
|
}
|
|
|
|
|
2017-05-06 06:04:05 +08:00
|
|
|
void MachineFrameInfo::computeMaxCallFrameSize(const MachineFunction &MF) {
|
|
|
|
const TargetInstrInfo &TII = *MF.getSubtarget().getInstrInfo();
|
|
|
|
unsigned FrameSetupOpcode = TII.getCallFrameSetupOpcode();
|
|
|
|
unsigned FrameDestroyOpcode = TII.getCallFrameDestroyOpcode();
|
|
|
|
assert(FrameSetupOpcode != ~0u && FrameDestroyOpcode != ~0u &&
|
|
|
|
"Can only compute MaxCallFrameSize if Setup/Destroy opcode are known");
|
|
|
|
|
|
|
|
MaxCallFrameSize = 0;
|
|
|
|
for (const MachineBasicBlock &MBB : MF) {
|
|
|
|
for (const MachineInstr &MI : MBB) {
|
|
|
|
unsigned Opcode = MI.getOpcode();
|
|
|
|
if (Opcode == FrameSetupOpcode || Opcode == FrameDestroyOpcode) {
|
|
|
|
unsigned Size = TII.getFrameSize(MI);
|
|
|
|
MaxCallFrameSize = std::max(MaxCallFrameSize, Size);
|
|
|
|
AdjustsStack = true;
|
|
|
|
} else if (MI.isInlineAsm()) {
|
|
|
|
// Some inline asm's need a stack frame, as indicated by operand 1.
|
|
|
|
unsigned ExtraInfo = MI.getOperand(InlineAsm::MIOp_ExtraInfo).getImm();
|
|
|
|
if (ExtraInfo & InlineAsm::Extra_IsAlignStack)
|
|
|
|
AdjustsStack = true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-04-27 07:36:58 +08:00
|
|
|
void MachineFrameInfo::print(const MachineFunction &MF, raw_ostream &OS) const{
|
|
|
|
if (Objects.empty()) return;
|
|
|
|
|
|
|
|
const TargetFrameLowering *FI = MF.getSubtarget().getFrameLowering();
|
|
|
|
int ValOffset = (FI ? FI->getOffsetOfLocalArea() : 0);
|
|
|
|
|
|
|
|
OS << "Frame Objects:\n";
|
|
|
|
|
|
|
|
for (unsigned i = 0, e = Objects.size(); i != e; ++i) {
|
|
|
|
const StackObject &SO = Objects[i];
|
|
|
|
OS << " fi#" << (int)(i-NumFixedObjects) << ": ";
|
2017-07-21 05:03:45 +08:00
|
|
|
|
|
|
|
if (SO.StackID != 0)
|
2018-04-10 05:04:30 +08:00
|
|
|
OS << "id=" << static_cast<unsigned>(SO.StackID) << ' ';
|
2017-07-21 05:03:45 +08:00
|
|
|
|
2017-04-27 07:36:58 +08:00
|
|
|
if (SO.Size == ~0ULL) {
|
|
|
|
OS << "dead\n";
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
if (SO.Size == 0)
|
|
|
|
OS << "variable sized";
|
|
|
|
else
|
|
|
|
OS << "size=" << SO.Size;
|
|
|
|
OS << ", align=" << SO.Alignment;
|
|
|
|
|
|
|
|
if (i < NumFixedObjects)
|
|
|
|
OS << ", fixed";
|
|
|
|
if (i < NumFixedObjects || SO.SPOffset != -1) {
|
|
|
|
int64_t Off = SO.SPOffset - ValOffset;
|
|
|
|
OS << ", at location [SP";
|
|
|
|
if (Off > 0)
|
|
|
|
OS << "+" << Off;
|
|
|
|
else if (Off < 0)
|
|
|
|
OS << Off;
|
|
|
|
OS << "]";
|
|
|
|
}
|
|
|
|
OS << "\n";
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-10-15 22:32:27 +08:00
|
|
|
#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
|
2017-04-27 07:36:58 +08:00
|
|
|
LLVM_DUMP_METHOD void MachineFrameInfo::dump(const MachineFunction &MF) const {
|
|
|
|
print(MF, dbgs());
|
|
|
|
}
|
|
|
|
#endif
|