1480093f4SDimitry Andric //===-- VEFrameLowering.cpp - VE Frame Information ------------------------===// 2480093f4SDimitry Andric // 3480093f4SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4480093f4SDimitry Andric // See https://llvm.org/LICENSE.txt for license information. 5480093f4SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6480093f4SDimitry Andric // 7480093f4SDimitry Andric //===----------------------------------------------------------------------===// 8480093f4SDimitry Andric // 9480093f4SDimitry Andric // This file contains the VE implementation of TargetFrameLowering class. 10480093f4SDimitry Andric // 11*e8d8bef9SDimitry Andric // On VE, stack frames are structured as follows: 12*e8d8bef9SDimitry Andric // 13*e8d8bef9SDimitry Andric // The stack grows downward. 14*e8d8bef9SDimitry Andric // 15*e8d8bef9SDimitry Andric // All of the individual frame areas on the frame below are optional, i.e. it's 16*e8d8bef9SDimitry Andric // possible to create a function so that the particular area isn't present 17*e8d8bef9SDimitry Andric // in the frame. 18*e8d8bef9SDimitry Andric // 19*e8d8bef9SDimitry Andric // At function entry, the "frame" looks as follows: 20*e8d8bef9SDimitry Andric // 21*e8d8bef9SDimitry Andric // | | Higher address 22*e8d8bef9SDimitry Andric // |----------------------------------------------| 23*e8d8bef9SDimitry Andric // | Parameter area for this function | 24*e8d8bef9SDimitry Andric // |----------------------------------------------| 25*e8d8bef9SDimitry Andric // | Register save area (RSA) for this function | 26*e8d8bef9SDimitry Andric // |----------------------------------------------| 27*e8d8bef9SDimitry Andric // | Return address for this function | 28*e8d8bef9SDimitry Andric // |----------------------------------------------| 29*e8d8bef9SDimitry Andric // | Frame pointer for this function | 30*e8d8bef9SDimitry Andric // |----------------------------------------------| <- sp 31*e8d8bef9SDimitry Andric // | | Lower address 32*e8d8bef9SDimitry Andric // 33*e8d8bef9SDimitry Andric // VE doesn't use on demand stack allocation, so user code generated by LLVM 34*e8d8bef9SDimitry Andric // needs to call VEOS to allocate stack frame. VE's ABI want to reduce the 35*e8d8bef9SDimitry Andric // number of VEOS calls, so ABI requires to allocate not only RSA (in general 36*e8d8bef9SDimitry Andric // CSR, callee saved register) area but also call frame at the prologue of 37*e8d8bef9SDimitry Andric // caller function. 38*e8d8bef9SDimitry Andric // 39*e8d8bef9SDimitry Andric // After the prologue has run, the frame has the following general structure. 40*e8d8bef9SDimitry Andric // Note that technically the last frame area (VLAs) doesn't get created until 41*e8d8bef9SDimitry Andric // in the main function body, after the prologue is run. However, it's depicted 42*e8d8bef9SDimitry Andric // here for completeness. 43*e8d8bef9SDimitry Andric // 44*e8d8bef9SDimitry Andric // | | Higher address 45*e8d8bef9SDimitry Andric // |----------------------------------------------| 46*e8d8bef9SDimitry Andric // | Parameter area for this function | 47*e8d8bef9SDimitry Andric // |----------------------------------------------| 48*e8d8bef9SDimitry Andric // | Register save area (RSA) for this function | 49*e8d8bef9SDimitry Andric // |----------------------------------------------| 50*e8d8bef9SDimitry Andric // | Return address for this function | 51*e8d8bef9SDimitry Andric // |----------------------------------------------| 52*e8d8bef9SDimitry Andric // | Frame pointer for this function | 53*e8d8bef9SDimitry Andric // |----------------------------------------------| <- fp(=old sp) 54*e8d8bef9SDimitry Andric // |.empty.space.to.make.part.below.aligned.in....| 55*e8d8bef9SDimitry Andric // |.case.it.needs.more.than.the.standard.16-byte.| (size of this area is 56*e8d8bef9SDimitry Andric // |.alignment....................................| unknown at compile time) 57*e8d8bef9SDimitry Andric // |----------------------------------------------| 58*e8d8bef9SDimitry Andric // | Local variables of fixed size including spill| 59*e8d8bef9SDimitry Andric // | slots | 60*e8d8bef9SDimitry Andric // |----------------------------------------------| <- bp(not defined by ABI, 61*e8d8bef9SDimitry Andric // |.variable-sized.local.variables.(VLAs)........| LLVM chooses SX17) 62*e8d8bef9SDimitry Andric // |..............................................| (size of this area is 63*e8d8bef9SDimitry Andric // |..............................................| unknown at compile time) 64*e8d8bef9SDimitry Andric // |----------------------------------------------| <- stack top (returned by 65*e8d8bef9SDimitry Andric // | Parameter area for callee | alloca) 66*e8d8bef9SDimitry Andric // |----------------------------------------------| 67*e8d8bef9SDimitry Andric // | Register save area (RSA) for callee | 68*e8d8bef9SDimitry Andric // |----------------------------------------------| 69*e8d8bef9SDimitry Andric // | Return address for callee | 70*e8d8bef9SDimitry Andric // |----------------------------------------------| 71*e8d8bef9SDimitry Andric // | Frame pointer for callee | 72*e8d8bef9SDimitry Andric // |----------------------------------------------| <- sp 73*e8d8bef9SDimitry Andric // | | Lower address 74*e8d8bef9SDimitry Andric // 75*e8d8bef9SDimitry Andric // To access the data in a frame, at-compile time, a constant offset must be 76*e8d8bef9SDimitry Andric // computable from one of the pointers (fp, bp, sp) to access it. The size 77*e8d8bef9SDimitry Andric // of the areas with a dotted background cannot be computed at compile-time 78*e8d8bef9SDimitry Andric // if they are present, making it required to have all three of fp, bp and 79*e8d8bef9SDimitry Andric // sp to be set up to be able to access all contents in the frame areas, 80*e8d8bef9SDimitry Andric // assuming all of the frame areas are non-empty. 81*e8d8bef9SDimitry Andric // 82*e8d8bef9SDimitry Andric // For most functions, some of the frame areas are empty. For those functions, 83*e8d8bef9SDimitry Andric // it may not be necessary to set up fp or bp: 84*e8d8bef9SDimitry Andric // * A base pointer is definitely needed when there are both VLAs and local 85*e8d8bef9SDimitry Andric // variables with more-than-default alignment requirements. 86*e8d8bef9SDimitry Andric // * A frame pointer is definitely needed when there are local variables with 87*e8d8bef9SDimitry Andric // more-than-default alignment requirements. 88*e8d8bef9SDimitry Andric // 89*e8d8bef9SDimitry Andric // In addition, VE ABI defines RSA frame, return address, and frame pointer 90*e8d8bef9SDimitry Andric // as follows: 91*e8d8bef9SDimitry Andric // 92*e8d8bef9SDimitry Andric // |----------------------------------------------| <- sp+176 93*e8d8bef9SDimitry Andric // | %s18...%s33 | 94*e8d8bef9SDimitry Andric // |----------------------------------------------| <- sp+48 95*e8d8bef9SDimitry Andric // | Linkage area register (%s17) | 96*e8d8bef9SDimitry Andric // |----------------------------------------------| <- sp+40 97*e8d8bef9SDimitry Andric // | Procedure linkage table register (%plt=%s16) | 98*e8d8bef9SDimitry Andric // |----------------------------------------------| <- sp+32 99*e8d8bef9SDimitry Andric // | Global offset table register (%got=%s15) | 100*e8d8bef9SDimitry Andric // |----------------------------------------------| <- sp+24 101*e8d8bef9SDimitry Andric // | Thread pointer register (%tp=%s14) | 102*e8d8bef9SDimitry Andric // |----------------------------------------------| <- sp+16 103*e8d8bef9SDimitry Andric // | Return address | 104*e8d8bef9SDimitry Andric // |----------------------------------------------| <- sp+8 105*e8d8bef9SDimitry Andric // | Frame pointer | 106*e8d8bef9SDimitry Andric // |----------------------------------------------| <- sp+0 107*e8d8bef9SDimitry Andric // 108*e8d8bef9SDimitry Andric // NOTE: This description is based on VE ABI and description in 109*e8d8bef9SDimitry Andric // AArch64FrameLowering.cpp. Thanks a lot. 110480093f4SDimitry Andric //===----------------------------------------------------------------------===// 111480093f4SDimitry Andric 112480093f4SDimitry Andric #include "VEFrameLowering.h" 113480093f4SDimitry Andric #include "VEInstrInfo.h" 1145ffd83dbSDimitry Andric #include "VEMachineFunctionInfo.h" 115480093f4SDimitry Andric #include "VESubtarget.h" 116480093f4SDimitry Andric #include "llvm/CodeGen/MachineFrameInfo.h" 117480093f4SDimitry Andric #include "llvm/CodeGen/MachineFunction.h" 118480093f4SDimitry Andric #include "llvm/CodeGen/MachineInstrBuilder.h" 119480093f4SDimitry Andric #include "llvm/CodeGen/MachineModuleInfo.h" 120480093f4SDimitry Andric #include "llvm/CodeGen/MachineRegisterInfo.h" 121480093f4SDimitry Andric #include "llvm/CodeGen/RegisterScavenging.h" 122480093f4SDimitry Andric #include "llvm/IR/DataLayout.h" 123480093f4SDimitry Andric #include "llvm/IR/Function.h" 124480093f4SDimitry Andric #include "llvm/Support/CommandLine.h" 125480093f4SDimitry Andric #include "llvm/Target/TargetOptions.h" 126480093f4SDimitry Andric #include "llvm/Support/MathExtras.h" 127480093f4SDimitry Andric 128480093f4SDimitry Andric using namespace llvm; 129480093f4SDimitry Andric 130480093f4SDimitry Andric VEFrameLowering::VEFrameLowering(const VESubtarget &ST) 131480093f4SDimitry Andric : TargetFrameLowering(TargetFrameLowering::StackGrowsDown, Align(16), 0, 1325ffd83dbSDimitry Andric Align(16)), 1335ffd83dbSDimitry Andric STI(ST) {} 134480093f4SDimitry Andric 135480093f4SDimitry Andric void VEFrameLowering::emitPrologueInsns(MachineFunction &MF, 136480093f4SDimitry Andric MachineBasicBlock &MBB, 137480093f4SDimitry Andric MachineBasicBlock::iterator MBBI, 1385ffd83dbSDimitry Andric uint64_t NumBytes, 139480093f4SDimitry Andric bool RequireFPUpdate) const { 140*e8d8bef9SDimitry Andric const VEMachineFunctionInfo *FuncInfo = MF.getInfo<VEMachineFunctionInfo>(); 141*e8d8bef9SDimitry Andric DebugLoc DL; 142*e8d8bef9SDimitry Andric const VEInstrInfo &TII = *STI.getInstrInfo(); 143480093f4SDimitry Andric 144480093f4SDimitry Andric // Insert following codes here as prologue 145480093f4SDimitry Andric // 146*e8d8bef9SDimitry Andric // st %fp, 0(, %sp) iff !isLeafProc 147*e8d8bef9SDimitry Andric // st %lr, 8(, %sp) iff !isLeafProc 148*e8d8bef9SDimitry Andric // st %got, 24(, %sp) iff hasGOT 149*e8d8bef9SDimitry Andric // st %plt, 32(, %sp) iff hasGOT 150*e8d8bef9SDimitry Andric // st %s17, 40(, %sp) iff hasBP 151*e8d8bef9SDimitry Andric if (!FuncInfo->isLeafProc()) { 152*e8d8bef9SDimitry Andric BuildMI(MBB, MBBI, DL, TII.get(VE::STrii)) 153480093f4SDimitry Andric .addReg(VE::SX11) 154480093f4SDimitry Andric .addImm(0) 1555ffd83dbSDimitry Andric .addImm(0) 156480093f4SDimitry Andric .addReg(VE::SX9); 157*e8d8bef9SDimitry Andric BuildMI(MBB, MBBI, DL, TII.get(VE::STrii)) 158480093f4SDimitry Andric .addReg(VE::SX11) 1595ffd83dbSDimitry Andric .addImm(0) 160480093f4SDimitry Andric .addImm(8) 161480093f4SDimitry Andric .addReg(VE::SX10); 162*e8d8bef9SDimitry Andric } 163*e8d8bef9SDimitry Andric if (hasGOT(MF)) { 164*e8d8bef9SDimitry Andric BuildMI(MBB, MBBI, DL, TII.get(VE::STrii)) 165480093f4SDimitry Andric .addReg(VE::SX11) 1665ffd83dbSDimitry Andric .addImm(0) 167480093f4SDimitry Andric .addImm(24) 168480093f4SDimitry Andric .addReg(VE::SX15); 169*e8d8bef9SDimitry Andric BuildMI(MBB, MBBI, DL, TII.get(VE::STrii)) 170480093f4SDimitry Andric .addReg(VE::SX11) 1715ffd83dbSDimitry Andric .addImm(0) 172480093f4SDimitry Andric .addImm(32) 173480093f4SDimitry Andric .addReg(VE::SX16); 174*e8d8bef9SDimitry Andric } 1755ffd83dbSDimitry Andric if (hasBP(MF)) 176*e8d8bef9SDimitry Andric BuildMI(MBB, MBBI, DL, TII.get(VE::STrii)) 1775ffd83dbSDimitry Andric .addReg(VE::SX11) 1785ffd83dbSDimitry Andric .addImm(0) 1795ffd83dbSDimitry Andric .addImm(40) 1805ffd83dbSDimitry Andric .addReg(VE::SX17); 181480093f4SDimitry Andric } 182480093f4SDimitry Andric 183480093f4SDimitry Andric void VEFrameLowering::emitEpilogueInsns(MachineFunction &MF, 184480093f4SDimitry Andric MachineBasicBlock &MBB, 185480093f4SDimitry Andric MachineBasicBlock::iterator MBBI, 1865ffd83dbSDimitry Andric uint64_t NumBytes, 187480093f4SDimitry Andric bool RequireFPUpdate) const { 188*e8d8bef9SDimitry Andric const VEMachineFunctionInfo *FuncInfo = MF.getInfo<VEMachineFunctionInfo>(); 189*e8d8bef9SDimitry Andric DebugLoc DL; 190*e8d8bef9SDimitry Andric const VEInstrInfo &TII = *STI.getInstrInfo(); 191480093f4SDimitry Andric 192480093f4SDimitry Andric // Insert following codes here as epilogue 193480093f4SDimitry Andric // 194*e8d8bef9SDimitry Andric // ld %s17, 40(, %sp) iff hasBP 195*e8d8bef9SDimitry Andric // ld %plt, 32(, %sp) iff hasGOT 196*e8d8bef9SDimitry Andric // ld %got, 24(, %sp) iff hasGOT 197*e8d8bef9SDimitry Andric // ld %lr, 8(, %sp) iff !isLeafProc 198*e8d8bef9SDimitry Andric // ld %fp, 0(, %sp) iff !isLeafProc 1995ffd83dbSDimitry Andric if (hasBP(MF)) 200*e8d8bef9SDimitry Andric BuildMI(MBB, MBBI, DL, TII.get(VE::LDrii), VE::SX17) 201480093f4SDimitry Andric .addReg(VE::SX11) 2025ffd83dbSDimitry Andric .addImm(0) 2035ffd83dbSDimitry Andric .addImm(40); 204*e8d8bef9SDimitry Andric if (hasGOT(MF)) { 205*e8d8bef9SDimitry Andric BuildMI(MBB, MBBI, DL, TII.get(VE::LDrii), VE::SX16) 2065ffd83dbSDimitry Andric .addReg(VE::SX11) 2075ffd83dbSDimitry Andric .addImm(0) 208480093f4SDimitry Andric .addImm(32); 209*e8d8bef9SDimitry Andric BuildMI(MBB, MBBI, DL, TII.get(VE::LDrii), VE::SX15) 210480093f4SDimitry Andric .addReg(VE::SX11) 2115ffd83dbSDimitry Andric .addImm(0) 212480093f4SDimitry Andric .addImm(24); 213*e8d8bef9SDimitry Andric } 214*e8d8bef9SDimitry Andric if (!FuncInfo->isLeafProc()) { 215*e8d8bef9SDimitry Andric BuildMI(MBB, MBBI, DL, TII.get(VE::LDrii), VE::SX10) 216480093f4SDimitry Andric .addReg(VE::SX11) 2175ffd83dbSDimitry Andric .addImm(0) 218480093f4SDimitry Andric .addImm(8); 219*e8d8bef9SDimitry Andric BuildMI(MBB, MBBI, DL, TII.get(VE::LDrii), VE::SX9) 220480093f4SDimitry Andric .addReg(VE::SX11) 2215ffd83dbSDimitry Andric .addImm(0) 222480093f4SDimitry Andric .addImm(0); 223480093f4SDimitry Andric } 224*e8d8bef9SDimitry Andric } 225480093f4SDimitry Andric 226480093f4SDimitry Andric void VEFrameLowering::emitSPAdjustment(MachineFunction &MF, 227480093f4SDimitry Andric MachineBasicBlock &MBB, 228480093f4SDimitry Andric MachineBasicBlock::iterator MBBI, 2295ffd83dbSDimitry Andric int64_t NumBytes, 2305ffd83dbSDimitry Andric MaybeAlign MaybeAlign) const { 231*e8d8bef9SDimitry Andric DebugLoc DL; 232*e8d8bef9SDimitry Andric const VEInstrInfo &TII = *STI.getInstrInfo(); 233480093f4SDimitry Andric 234*e8d8bef9SDimitry Andric if (NumBytes == 0) { 235*e8d8bef9SDimitry Andric // Nothing to do here. 236*e8d8bef9SDimitry Andric } else if (isInt<7>(NumBytes)) { 237*e8d8bef9SDimitry Andric // adds.l %s11, NumBytes@lo, %s11 238*e8d8bef9SDimitry Andric BuildMI(MBB, MBBI, DL, TII.get(VE::ADDSLri), VE::SX11) 239480093f4SDimitry Andric .addReg(VE::SX11) 240480093f4SDimitry Andric .addImm(NumBytes); 241*e8d8bef9SDimitry Andric } else if (isInt<32>(NumBytes)) { 242*e8d8bef9SDimitry Andric // lea %s11, NumBytes@lo(, %s11) 243*e8d8bef9SDimitry Andric BuildMI(MBB, MBBI, DL, TII.get(VE::LEArii), VE::SX11) 244*e8d8bef9SDimitry Andric .addReg(VE::SX11) 245*e8d8bef9SDimitry Andric .addImm(0) 246*e8d8bef9SDimitry Andric .addImm(Lo_32(NumBytes)); 247*e8d8bef9SDimitry Andric } else { 248480093f4SDimitry Andric // Emit following codes. This clobbers SX13 which we always know is 249480093f4SDimitry Andric // available here. 250*e8d8bef9SDimitry Andric // lea %s13, NumBytes@lo 251480093f4SDimitry Andric // and %s13, %s13, (32)0 252*e8d8bef9SDimitry Andric // lea.sl %sp, NumBytes@hi(%s13, %sp) 253*e8d8bef9SDimitry Andric BuildMI(MBB, MBBI, DL, TII.get(VE::LEAzii), VE::SX13) 2545ffd83dbSDimitry Andric .addImm(0) 2555ffd83dbSDimitry Andric .addImm(0) 2565ffd83dbSDimitry Andric .addImm(Lo_32(NumBytes)); 257*e8d8bef9SDimitry Andric BuildMI(MBB, MBBI, DL, TII.get(VE::ANDrm), VE::SX13) 258480093f4SDimitry Andric .addReg(VE::SX13) 2595ffd83dbSDimitry Andric .addImm(M0(32)); 260*e8d8bef9SDimitry Andric BuildMI(MBB, MBBI, DL, TII.get(VE::LEASLrri), VE::SX11) 261480093f4SDimitry Andric .addReg(VE::SX11) 262480093f4SDimitry Andric .addReg(VE::SX13) 2635ffd83dbSDimitry Andric .addImm(Hi_32(NumBytes)); 264*e8d8bef9SDimitry Andric } 2655ffd83dbSDimitry Andric 2665ffd83dbSDimitry Andric if (MaybeAlign) { 2675ffd83dbSDimitry Andric // and %sp, %sp, Align-1 268*e8d8bef9SDimitry Andric BuildMI(MBB, MBBI, DL, TII.get(VE::ANDrm), VE::SX11) 2695ffd83dbSDimitry Andric .addReg(VE::SX11) 2705ffd83dbSDimitry Andric .addImm(M1(64 - Log2_64(MaybeAlign.valueOrOne().value()))); 2715ffd83dbSDimitry Andric } 272480093f4SDimitry Andric } 273480093f4SDimitry Andric 274480093f4SDimitry Andric void VEFrameLowering::emitSPExtend(MachineFunction &MF, MachineBasicBlock &MBB, 2755ffd83dbSDimitry Andric MachineBasicBlock::iterator MBBI) const { 276*e8d8bef9SDimitry Andric DebugLoc DL; 277*e8d8bef9SDimitry Andric const VEInstrInfo &TII = *STI.getInstrInfo(); 278480093f4SDimitry Andric 279480093f4SDimitry Andric // Emit following codes. It is not possible to insert multiple 280480093f4SDimitry Andric // BasicBlocks in PEI pass, so we emit two pseudo instructions here. 281480093f4SDimitry Andric // 282480093f4SDimitry Andric // EXTEND_STACK // pseudo instrcution 283480093f4SDimitry Andric // EXTEND_STACK_GUARD // pseudo instrcution 284480093f4SDimitry Andric // 285480093f4SDimitry Andric // EXTEND_STACK pseudo will be converted by ExpandPostRA pass into 286480093f4SDimitry Andric // following instructions with multiple basic blocks later. 287480093f4SDimitry Andric // 288480093f4SDimitry Andric // thisBB: 289480093f4SDimitry Andric // brge.l.t %sp, %sl, sinkBB 290480093f4SDimitry Andric // syscallBB: 291480093f4SDimitry Andric // ld %s61, 0x18(, %tp) // load param area 292480093f4SDimitry Andric // or %s62, 0, %s0 // spill the value of %s0 293480093f4SDimitry Andric // lea %s63, 0x13b // syscall # of grow 294480093f4SDimitry Andric // shm.l %s63, 0x0(%s61) // store syscall # at addr:0 295480093f4SDimitry Andric // shm.l %sl, 0x8(%s61) // store old limit at addr:8 296480093f4SDimitry Andric // shm.l %sp, 0x10(%s61) // store new limit at addr:16 297480093f4SDimitry Andric // monc // call monitor 298480093f4SDimitry Andric // or %s0, 0, %s62 // restore the value of %s0 299480093f4SDimitry Andric // sinkBB: 300480093f4SDimitry Andric // 301480093f4SDimitry Andric // EXTEND_STACK_GUARD pseudo will be simply eliminated by ExpandPostRA 302480093f4SDimitry Andric // pass. This pseudo is required to be at the next of EXTEND_STACK 303480093f4SDimitry Andric // pseudo in order to protect iteration loop in ExpandPostRA. 304*e8d8bef9SDimitry Andric BuildMI(MBB, MBBI, DL, TII.get(VE::EXTEND_STACK)); 305*e8d8bef9SDimitry Andric BuildMI(MBB, MBBI, DL, TII.get(VE::EXTEND_STACK_GUARD)); 306480093f4SDimitry Andric } 307480093f4SDimitry Andric 308480093f4SDimitry Andric void VEFrameLowering::emitPrologue(MachineFunction &MF, 309480093f4SDimitry Andric MachineBasicBlock &MBB) const { 310*e8d8bef9SDimitry Andric const VEMachineFunctionInfo *FuncInfo = MF.getInfo<VEMachineFunctionInfo>(); 311480093f4SDimitry Andric assert(&MF.front() == &MBB && "Shrink-wrapping not yet supported"); 312480093f4SDimitry Andric MachineFrameInfo &MFI = MF.getFrameInfo(); 3135ffd83dbSDimitry Andric const VEInstrInfo &TII = *STI.getInstrInfo(); 3145ffd83dbSDimitry Andric const VERegisterInfo &RegInfo = *STI.getRegisterInfo(); 315480093f4SDimitry Andric MachineBasicBlock::iterator MBBI = MBB.begin(); 316*e8d8bef9SDimitry Andric bool NeedsStackRealignment = RegInfo.needsStackRealignment(MF); 317*e8d8bef9SDimitry Andric 318480093f4SDimitry Andric // Debug location must be unknown since the first debug location is used 319480093f4SDimitry Andric // to determine the end of the prologue. 320*e8d8bef9SDimitry Andric DebugLoc DL; 321480093f4SDimitry Andric 322480093f4SDimitry Andric // FIXME: unfortunately, returning false from canRealignStack 323480093f4SDimitry Andric // actually just causes needsStackRealignment to return false, 324480093f4SDimitry Andric // rather than reporting an error, as would be sensible. This is 325480093f4SDimitry Andric // poor, but fixing that bogosity is going to be a large project. 326480093f4SDimitry Andric // For now, just see if it's lied, and report an error here. 3275ffd83dbSDimitry Andric if (!NeedsStackRealignment && MFI.getMaxAlign() > getStackAlign()) 328480093f4SDimitry Andric report_fatal_error("Function \"" + Twine(MF.getName()) + 329480093f4SDimitry Andric "\" required " 330480093f4SDimitry Andric "stack re-alignment, but LLVM couldn't handle it " 331480093f4SDimitry Andric "(probably because it has a dynamic alloca)."); 332480093f4SDimitry Andric 333*e8d8bef9SDimitry Andric // Get the number of bytes to allocate from the FrameInfo. 334*e8d8bef9SDimitry Andric // This number of bytes is already aligned to ABI stack alignment. 3355ffd83dbSDimitry Andric uint64_t NumBytes = MFI.getStackSize(); 336480093f4SDimitry Andric 337*e8d8bef9SDimitry Andric // Adjust stack size if this function is not a leaf function since the 338*e8d8bef9SDimitry Andric // VE ABI requires a reserved area at the top of stack as described in 339*e8d8bef9SDimitry Andric // VEFrameLowering.cpp. 340*e8d8bef9SDimitry Andric if (!FuncInfo->isLeafProc()) { 341*e8d8bef9SDimitry Andric // NOTE: The number is aligned to ABI stack alignment after adjustment. 3425ffd83dbSDimitry Andric NumBytes = STI.getAdjustedFrameSize(NumBytes); 343*e8d8bef9SDimitry Andric } 344480093f4SDimitry Andric 345480093f4SDimitry Andric // Finally, ensure that the size is sufficiently aligned for the 346480093f4SDimitry Andric // data on the stack. 3475ffd83dbSDimitry Andric NumBytes = alignTo(NumBytes, MFI.getMaxAlign()); 348480093f4SDimitry Andric 349480093f4SDimitry Andric // Update stack size with corrected value. 350480093f4SDimitry Andric MFI.setStackSize(NumBytes); 351480093f4SDimitry Andric 352*e8d8bef9SDimitry Andric // Emit Prologue instructions to save multiple registers. 353480093f4SDimitry Andric emitPrologueInsns(MF, MBB, MBBI, NumBytes, true); 354480093f4SDimitry Andric 355*e8d8bef9SDimitry Andric // Emit instructions to save SP in FP as follows if this is not a leaf 356*e8d8bef9SDimitry Andric // function: 357*e8d8bef9SDimitry Andric // or %fp, 0, %sp 358*e8d8bef9SDimitry Andric if (!FuncInfo->isLeafProc()) 359*e8d8bef9SDimitry Andric BuildMI(MBB, MBBI, DL, TII.get(VE::ORri), VE::SX9) 360*e8d8bef9SDimitry Andric .addReg(VE::SX11) 361*e8d8bef9SDimitry Andric .addImm(0); 362*e8d8bef9SDimitry Andric 363480093f4SDimitry Andric // Emit stack adjust instructions 3645ffd83dbSDimitry Andric MaybeAlign RuntimeAlign = 3655ffd83dbSDimitry Andric NeedsStackRealignment ? MaybeAlign(MFI.getMaxAlign()) : None; 366*e8d8bef9SDimitry Andric assert((RuntimeAlign == None || !FuncInfo->isLeafProc()) && 367*e8d8bef9SDimitry Andric "SP has to be saved in order to align variable sized stack object!"); 3685ffd83dbSDimitry Andric emitSPAdjustment(MF, MBB, MBBI, -(int64_t)NumBytes, RuntimeAlign); 3695ffd83dbSDimitry Andric 3705ffd83dbSDimitry Andric if (hasBP(MF)) { 3715ffd83dbSDimitry Andric // Copy SP to BP. 372*e8d8bef9SDimitry Andric BuildMI(MBB, MBBI, DL, TII.get(VE::ORri), VE::SX17) 3735ffd83dbSDimitry Andric .addReg(VE::SX11) 3745ffd83dbSDimitry Andric .addImm(0); 3755ffd83dbSDimitry Andric } 376480093f4SDimitry Andric 377480093f4SDimitry Andric // Emit stack extend instructions 378*e8d8bef9SDimitry Andric if (NumBytes != 0) 3795ffd83dbSDimitry Andric emitSPExtend(MF, MBB, MBBI); 380480093f4SDimitry Andric } 381480093f4SDimitry Andric 382480093f4SDimitry Andric MachineBasicBlock::iterator VEFrameLowering::eliminateCallFramePseudoInstr( 383480093f4SDimitry Andric MachineFunction &MF, MachineBasicBlock &MBB, 384480093f4SDimitry Andric MachineBasicBlock::iterator I) const { 385480093f4SDimitry Andric if (!hasReservedCallFrame(MF)) { 386480093f4SDimitry Andric MachineInstr &MI = *I; 3875ffd83dbSDimitry Andric int64_t Size = MI.getOperand(0).getImm(); 388480093f4SDimitry Andric if (MI.getOpcode() == VE::ADJCALLSTACKDOWN) 389480093f4SDimitry Andric Size = -Size; 390480093f4SDimitry Andric 391480093f4SDimitry Andric if (Size) 392480093f4SDimitry Andric emitSPAdjustment(MF, MBB, I, Size); 393480093f4SDimitry Andric } 394480093f4SDimitry Andric return MBB.erase(I); 395480093f4SDimitry Andric } 396480093f4SDimitry Andric 397480093f4SDimitry Andric void VEFrameLowering::emitEpilogue(MachineFunction &MF, 398480093f4SDimitry Andric MachineBasicBlock &MBB) const { 399*e8d8bef9SDimitry Andric const VEMachineFunctionInfo *FuncInfo = MF.getInfo<VEMachineFunctionInfo>(); 400*e8d8bef9SDimitry Andric DebugLoc DL; 401480093f4SDimitry Andric MachineBasicBlock::iterator MBBI = MBB.getLastNonDebugInstr(); 402480093f4SDimitry Andric MachineFrameInfo &MFI = MF.getFrameInfo(); 403*e8d8bef9SDimitry Andric const VEInstrInfo &TII = *STI.getInstrInfo(); 404480093f4SDimitry Andric 4055ffd83dbSDimitry Andric uint64_t NumBytes = MFI.getStackSize(); 406480093f4SDimitry Andric 407*e8d8bef9SDimitry Andric // Emit instructions to retrieve original SP. 408*e8d8bef9SDimitry Andric if (!FuncInfo->isLeafProc()) { 409*e8d8bef9SDimitry Andric // If SP is saved in FP, retrieve it as follows: 410*e8d8bef9SDimitry Andric // or %sp, 0, %fp iff !isLeafProc 411*e8d8bef9SDimitry Andric BuildMI(MBB, MBBI, DL, TII.get(VE::ORri), VE::SX11) 412*e8d8bef9SDimitry Andric .addReg(VE::SX9) 413*e8d8bef9SDimitry Andric .addImm(0); 414*e8d8bef9SDimitry Andric } else { 415*e8d8bef9SDimitry Andric // Emit stack adjust instructions. 416*e8d8bef9SDimitry Andric emitSPAdjustment(MF, MBB, MBBI, NumBytes, None); 417*e8d8bef9SDimitry Andric } 418*e8d8bef9SDimitry Andric 419*e8d8bef9SDimitry Andric // Emit Epilogue instructions to restore multiple registers. 420480093f4SDimitry Andric emitEpilogueInsns(MF, MBB, MBBI, NumBytes, true); 421480093f4SDimitry Andric } 422480093f4SDimitry Andric 423480093f4SDimitry Andric // hasFP - Return true if the specified function should have a dedicated frame 4245ffd83dbSDimitry Andric // pointer register. This is true if the function has variable sized allocas 425*e8d8bef9SDimitry Andric // or if frame pointer elimination is disabled. 426480093f4SDimitry Andric bool VEFrameLowering::hasFP(const MachineFunction &MF) const { 427480093f4SDimitry Andric const TargetRegisterInfo *RegInfo = MF.getSubtarget().getRegisterInfo(); 428480093f4SDimitry Andric 429480093f4SDimitry Andric const MachineFrameInfo &MFI = MF.getFrameInfo(); 430480093f4SDimitry Andric return MF.getTarget().Options.DisableFramePointerElim(MF) || 431480093f4SDimitry Andric RegInfo->needsStackRealignment(MF) || MFI.hasVarSizedObjects() || 432480093f4SDimitry Andric MFI.isFrameAddressTaken(); 433480093f4SDimitry Andric } 434480093f4SDimitry Andric 4355ffd83dbSDimitry Andric bool VEFrameLowering::hasBP(const MachineFunction &MF) const { 4365ffd83dbSDimitry Andric const MachineFrameInfo &MFI = MF.getFrameInfo(); 4375ffd83dbSDimitry Andric const TargetRegisterInfo *TRI = STI.getRegisterInfo(); 4385ffd83dbSDimitry Andric 4395ffd83dbSDimitry Andric return MFI.hasVarSizedObjects() && TRI->needsStackRealignment(MF); 4405ffd83dbSDimitry Andric } 4415ffd83dbSDimitry Andric 442*e8d8bef9SDimitry Andric bool VEFrameLowering::hasGOT(const MachineFunction &MF) const { 443*e8d8bef9SDimitry Andric const VEMachineFunctionInfo *FuncInfo = MF.getInfo<VEMachineFunctionInfo>(); 444*e8d8bef9SDimitry Andric 445*e8d8bef9SDimitry Andric // If a global base register is assigned (!= 0), GOT is used. 446*e8d8bef9SDimitry Andric return FuncInfo->getGlobalBaseReg() != 0; 447*e8d8bef9SDimitry Andric } 448*e8d8bef9SDimitry Andric 449*e8d8bef9SDimitry Andric StackOffset VEFrameLowering::getFrameIndexReference(const MachineFunction &MF, 450*e8d8bef9SDimitry Andric int FI, 4515ffd83dbSDimitry Andric Register &FrameReg) const { 4525ffd83dbSDimitry Andric const MachineFrameInfo &MFI = MF.getFrameInfo(); 4535ffd83dbSDimitry Andric const VERegisterInfo *RegInfo = STI.getRegisterInfo(); 4545ffd83dbSDimitry Andric bool isFixed = MFI.isFixedObjectIndex(FI); 4555ffd83dbSDimitry Andric 456480093f4SDimitry Andric int64_t FrameOffset = MF.getFrameInfo().getObjectOffset(FI); 4575ffd83dbSDimitry Andric 458*e8d8bef9SDimitry Andric if (!hasFP(MF)) { 459*e8d8bef9SDimitry Andric // If FP is not used, frame indexies are based on a %sp regiter. 460480093f4SDimitry Andric FrameReg = VE::SX11; // %sp 461*e8d8bef9SDimitry Andric return StackOffset::getFixed(FrameOffset + 462*e8d8bef9SDimitry Andric MF.getFrameInfo().getStackSize()); 463480093f4SDimitry Andric } 4645ffd83dbSDimitry Andric if (RegInfo->needsStackRealignment(MF) && !isFixed) { 465*e8d8bef9SDimitry Andric // If data on stack require realignemnt, frame indexies are based on a %sp 466*e8d8bef9SDimitry Andric // or %s17 (bp) register. If there is a variable sized object, bp is used. 4675ffd83dbSDimitry Andric if (hasBP(MF)) 4685ffd83dbSDimitry Andric FrameReg = VE::SX17; // %bp 4695ffd83dbSDimitry Andric else 4705ffd83dbSDimitry Andric FrameReg = VE::SX11; // %sp 471*e8d8bef9SDimitry Andric return StackOffset::getFixed(FrameOffset + 472*e8d8bef9SDimitry Andric MF.getFrameInfo().getStackSize()); 4735ffd83dbSDimitry Andric } 474*e8d8bef9SDimitry Andric // Use %fp by default. 4755ffd83dbSDimitry Andric FrameReg = RegInfo->getFrameRegister(MF); 476*e8d8bef9SDimitry Andric return StackOffset::getFixed(FrameOffset); 4775ffd83dbSDimitry Andric } 478480093f4SDimitry Andric 479480093f4SDimitry Andric bool VEFrameLowering::isLeafProc(MachineFunction &MF) const { 480480093f4SDimitry Andric 481480093f4SDimitry Andric MachineRegisterInfo &MRI = MF.getRegInfo(); 482480093f4SDimitry Andric MachineFrameInfo &MFI = MF.getFrameInfo(); 483480093f4SDimitry Andric 484480093f4SDimitry Andric return !MFI.hasCalls() // No calls 485480093f4SDimitry Andric && !MRI.isPhysRegUsed(VE::SX18) // Registers within limits 486480093f4SDimitry Andric // (s18 is first CSR) 487480093f4SDimitry Andric && !MRI.isPhysRegUsed(VE::SX11) // %sp un-used 488480093f4SDimitry Andric && !hasFP(MF); // Don't need %fp 489480093f4SDimitry Andric } 490480093f4SDimitry Andric 491480093f4SDimitry Andric void VEFrameLowering::determineCalleeSaves(MachineFunction &MF, 492480093f4SDimitry Andric BitVector &SavedRegs, 493480093f4SDimitry Andric RegScavenger *RS) const { 494480093f4SDimitry Andric TargetFrameLowering::determineCalleeSaves(MF, SavedRegs, RS); 495480093f4SDimitry Andric 496*e8d8bef9SDimitry Andric // Functions having BP need to emit prologue and epilogue to allocate local 497*e8d8bef9SDimitry Andric // buffer on the stack even if the function is a leaf function. 498*e8d8bef9SDimitry Andric if (isLeafProc(MF) && !hasBP(MF)) { 499*e8d8bef9SDimitry Andric VEMachineFunctionInfo *FuncInfo = MF.getInfo<VEMachineFunctionInfo>(); 500*e8d8bef9SDimitry Andric FuncInfo->setLeafProc(true); 5015ffd83dbSDimitry Andric } 502480093f4SDimitry Andric } 503