118334Speter//===- Mips16FrameLowering.cpp - Mips16 Frame Information -----------------===//
218334Speter//
318334Speter// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
490075Sobrien// See https://llvm.org/LICENSE.txt for license information.
590075Sobrien// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
618334Speter//
718334Speter//===----------------------------------------------------------------------===//
890075Sobrien//
918334Speter// This file contains the Mips16 implementation of TargetFrameLowering class.
1090075Sobrien//
1190075Sobrien//===----------------------------------------------------------------------===//
1290075Sobrien
1390075Sobrien#include "Mips16FrameLowering.h"
1418334Speter#include "MCTargetDesc/MipsBaseInfo.h"
1590075Sobrien#include "Mips16InstrInfo.h"
1690075Sobrien#include "MipsInstrInfo.h"
1790075Sobrien#include "MipsRegisterInfo.h"
1890075Sobrien#include "MipsSubtarget.h"
1918334Speter#include "llvm/ADT/BitVector.h"
2018334Speter#include "llvm/CodeGen/MachineBasicBlock.h"
2190075Sobrien#include "llvm/CodeGen/MachineFrameInfo.h"
2290075Sobrien#include "llvm/CodeGen/MachineFunction.h"
2390075Sobrien#include "llvm/CodeGen/MachineInstr.h"
2418334Speter#include "llvm/CodeGen/MachineInstrBuilder.h"
2518334Speter#include "llvm/CodeGen/MachineModuleInfo.h"
2650397Sobrien#include "llvm/IR/DebugLoc.h"
2752284Sobrien#include "llvm/MC/MCContext.h"
2818334Speter#include "llvm/MC/MCDwarf.h"
2918334Speter#include "llvm/MC/MCRegisterInfo.h"
3018334Speter#include "llvm/MC/MachineLocation.h"
3118334Speter#include "llvm/Support/MathExtras.h"
3218334Speter#include "llvm/CodeGen/TargetFrameLowering.h"
3318334Speter#include <cassert>
3418334Speter#include <cstdint>
3518334Speter#include <vector>
3618334Speter
3718334Speterusing namespace llvm;
3818334Speter
3918334SpeterMips16FrameLowering::Mips16FrameLowering(const MipsSubtarget &STI)
4052284Sobrien    : MipsFrameLowering(STI, STI.getStackAlignment()) {}
4118334Speter
4290075Sobrienvoid Mips16FrameLowering::emitPrologue(MachineFunction &MF,
4390075Sobrien                                       MachineBasicBlock &MBB) const {
4490075Sobrien  MachineFrameInfo &MFI = MF.getFrameInfo();
4590075Sobrien  const Mips16InstrInfo &TII =
4690075Sobrien      *static_cast<const Mips16InstrInfo *>(STI.getInstrInfo());
4790075Sobrien  MachineBasicBlock::iterator MBBI = MBB.begin();
4818334Speter
4918334Speter  // Debug location must be unknown since the first debug location is used
5018334Speter  // to determine the end of the prologue.
5118334Speter  DebugLoc dl;
5218334Speter
5318334Speter  uint64_t StackSize = MFI.getStackSize();
5418334Speter
5518334Speter  // No need to allocate space on the stack.
5618334Speter  if (StackSize == 0 && !MFI.adjustsStack()) return;
5718334Speter
5818334Speter  MachineModuleInfo &MMI = MF.getMMI();
5918334Speter  const MCRegisterInfo *MRI = MMI.getContext().getRegisterInfo();
6018334Speter
6118334Speter  // Adjust stack.
6218334Speter  TII.makeFrame(Mips::SP, StackSize, MBB, MBBI);
6350397Sobrien
6452284Sobrien  // emit ".cfi_def_cfa_offset StackSize"
6552284Sobrien  unsigned CFIIndex =
6618334Speter      MF.addFrameInst(MCCFIInstruction::cfiDefCfaOffset(nullptr, StackSize));
6790075Sobrien  BuildMI(MBB, MBBI, dl, TII.get(TargetOpcode::CFI_INSTRUCTION))
6818334Speter      .addCFIIndex(CFIIndex);
6918334Speter
7018334Speter  const std::vector<CalleeSavedInfo> &CSI = MFI.getCalleeSavedInfo();
7118334Speter
7218334Speter  if (!CSI.empty()) {
7318334Speter    const std::vector<CalleeSavedInfo> &CSI = MFI.getCalleeSavedInfo();
7418334Speter
7518334Speter    for (const CalleeSavedInfo &I : CSI) {
7618334Speter      int64_t Offset = MFI.getObjectOffset(I.getFrameIdx());
7718334Speter      Register Reg = I.getReg();
7818334Speter      unsigned DReg = MRI->getDwarfRegNum(Reg, true);
7918334Speter      unsigned CFIIndex = MF.addFrameInst(
8018334Speter          MCCFIInstruction::createOffset(nullptr, DReg, Offset));
8118334Speter      BuildMI(MBB, MBBI, dl, TII.get(TargetOpcode::CFI_INSTRUCTION))
8218334Speter          .addCFIIndex(CFIIndex);
8318334Speter    }
8418334Speter  }
8518334Speter  if (hasFP(MF))
8618334Speter    BuildMI(MBB, MBBI, dl, TII.get(Mips::MoveR3216), Mips::S0)
8718334Speter      .addReg(Mips::SP).setMIFlag(MachineInstr::FrameSetup);
8818334Speter}
8918334Speter
9018334Spetervoid Mips16FrameLowering::emitEpilogue(MachineFunction &MF,
9118334Speter                                 MachineBasicBlock &MBB) const {
9218334Speter  MachineBasicBlock::iterator MBBI = MBB.getFirstTerminator();
9390075Sobrien  MachineFrameInfo &MFI = MF.getFrameInfo();
9418334Speter  const Mips16InstrInfo &TII =
9518334Speter      *static_cast<const Mips16InstrInfo *>(STI.getInstrInfo());
9618334Speter  DebugLoc dl = MBBI != MBB.end() ? MBBI->getDebugLoc() : DebugLoc();
9790075Sobrien  uint64_t StackSize = MFI.getStackSize();
9818334Speter
9990075Sobrien  if (!StackSize)
10090075Sobrien    return;
10118334Speter
10218334Speter  if (hasFP(MF))
10318334Speter    BuildMI(MBB, MBBI, dl, TII.get(Mips::Move32R16), Mips::SP)
10418334Speter      .addReg(Mips::S0);
10518334Speter
10618334Speter  // Adjust stack.
10718334Speter  // assumes stacksize multiple of 8
10850397Sobrien  TII.restoreFrame(Mips::SP, StackSize, MBB, MBBI);
10918334Speter}
11052284Sobrien
11118334Speterbool Mips16FrameLowering::spillCalleeSavedRegisters(
11218334Speter    MachineBasicBlock &MBB, MachineBasicBlock::iterator MI,
11318334Speter    ArrayRef<CalleeSavedInfo> CSI, const TargetRegisterInfo *TRI) const {
11418334Speter  MachineFunction *MF = MBB.getParent();
11552284Sobrien
11618334Speter  //
11718334Speter  // Registers RA, S0,S1 are the callee saved registers and they
11818334Speter  // will be saved with the "save" instruction
11918334Speter  // during emitPrologue
12018334Speter  //
12118334Speter  for (const CalleeSavedInfo &I : CSI) {
12218334Speter    // Add the callee-saved register as live-in. Do not add if the register is
12318334Speter    // RA and return address is taken, because it has already been added in
12452284Sobrien    // method MipsTargetLowering::lowerRETURNADDR.
12518334Speter    // It's killed at the spill, unless the register is RA and return address
12618334Speter    // is taken.
12790075Sobrien    Register Reg = I.getReg();
12818334Speter    bool IsRAAndRetAddrIsTaken = (Reg == Mips::RA)
12918334Speter      && MF->getFrameInfo().isReturnAddressTaken();
13050397Sobrien    if (!IsRAAndRetAddrIsTaken)
13150397Sobrien      MBB.addLiveIn(Reg);
13290075Sobrien  }
13390075Sobrien
13418334Speter  return true;
13518334Speter}
13618334Speter
13718334Speterbool Mips16FrameLowering::restoreCalleeSavedRegisters(
13818334Speter    MachineBasicBlock &MBB, MachineBasicBlock::iterator MI,
13918334Speter    MutableArrayRef<CalleeSavedInfo> CSI, const TargetRegisterInfo *TRI) const {
14018334Speter  //
14118334Speter  // Registers RA,S0,S1 are the callee saved registers and they will be restored
14218334Speter  // with the restore instruction during emitEpilogue.
14318334Speter  // We need to override this virtual function, otherwise llvm will try and
14418334Speter  // restore the registers on it's on from the stack.
14518334Speter  //
14618334Speter
14718334Speter  return true;
14818334Speter}
14918334Speter
15018334Speterbool
15118334SpeterMips16FrameLowering::hasReservedCallFrame(const MachineFunction &MF) const {
15218334Speter  const MachineFrameInfo &MFI = MF.getFrameInfo();
15318334Speter  // Reserve call frame if the size of the maximum call frame fits into 15-bit
15418334Speter  // immediate field and there are no variable sized objects on the stack.
15518334Speter  return isInt<15>(MFI.getMaxCallFrameSize()) && !MFI.hasVarSizedObjects();
15618334Speter}
15718334Speter
15818334Spetervoid Mips16FrameLowering::determineCalleeSaves(MachineFunction &MF,
15918334Speter                                               BitVector &SavedRegs,
16018334Speter                                               RegScavenger *RS) const {
16118334Speter  TargetFrameLowering::determineCalleeSaves(MF, SavedRegs, RS);
16218334Speter  const Mips16InstrInfo &TII =
16318334Speter      *static_cast<const Mips16InstrInfo *>(STI.getInstrInfo());
16418334Speter  const MipsRegisterInfo &RI = TII.getRegisterInfo();
16518334Speter  const BitVector Reserved = RI.getReservedRegs(MF);
16618334Speter  bool SaveS2 = Reserved[Mips::S2];
16718334Speter  if (SaveS2)
16818334Speter    SavedRegs.set(Mips::S2);
16918334Speter  if (hasFP(MF))
17018334Speter    SavedRegs.set(Mips::S0);
17118334Speter}
17218334Speter
17318334Speterconst MipsFrameLowering *
17418334Speterllvm::createMips16FrameLowering(const MipsSubtarget &ST) {
17518334Speter  return new Mips16FrameLowering(ST);
17618334Speter}
17718334Speter