brintos

brintos / llvm-project-archived public Read only

0
0
Text · 17.6 KiB · 35194e7 Raw
507 lines · cpp
1//===- MipsCallLowering.cpp -------------------------------------*- C++ -*-===//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-exception6//7//===----------------------------------------------------------------------===//8//9/// \file10/// This file implements the lowering of LLVM calls to machine code calls for11/// GlobalISel.12//13//===----------------------------------------------------------------------===//14 15#include "MipsCallLowering.h"16#include "MipsCCState.h"17#include "MipsMachineFunction.h"18#include "MipsTargetMachine.h"19#include "llvm/CodeGen/Analysis.h"20#include "llvm/CodeGen/GlobalISel/MachineIRBuilder.h"21#include "llvm/CodeGen/MachineFrameInfo.h"22 23using namespace llvm;24 25MipsCallLowering::MipsCallLowering(const MipsTargetLowering &TLI)26    : CallLowering(&TLI) {}27 28namespace {29class MipsIncomingValueHandler : public CallLowering::IncomingValueHandler {30  const MipsSubtarget &STI;31 32public:33  MipsIncomingValueHandler(MachineIRBuilder &MIRBuilder,34                           MachineRegisterInfo &MRI)35      : IncomingValueHandler(MIRBuilder, MRI),36        STI(MIRBuilder.getMF().getSubtarget<MipsSubtarget>()) {}37 38private:39  void assignValueToReg(Register ValVReg, Register PhysReg,40                        const CCValAssign &VA) override;41 42  Register getStackAddress(uint64_t Size, int64_t Offset,43                           MachinePointerInfo &MPO,44                           ISD::ArgFlagsTy Flags) override;45  void assignValueToAddress(Register ValVReg, Register Addr, LLT MemTy,46                            const MachinePointerInfo &MPO,47                            const CCValAssign &VA) override;48 49  unsigned assignCustomValue(CallLowering::ArgInfo &Arg,50                             ArrayRef<CCValAssign> VAs,51                             std::function<void()> *Thunk = nullptr) override;52 53  virtual void markPhysRegUsed(unsigned PhysReg) {54    MIRBuilder.getMRI()->addLiveIn(PhysReg);55    MIRBuilder.getMBB().addLiveIn(PhysReg);56  }57};58 59class CallReturnHandler : public MipsIncomingValueHandler {60public:61  CallReturnHandler(MachineIRBuilder &MIRBuilder, MachineRegisterInfo &MRI,62                    MachineInstrBuilder &MIB)63      : MipsIncomingValueHandler(MIRBuilder, MRI), MIB(MIB) {}64 65private:66  void markPhysRegUsed(unsigned PhysReg) override {67    MIB.addDef(PhysReg, RegState::Implicit);68  }69 70  MachineInstrBuilder &MIB;71};72 73} // end anonymous namespace74 75void MipsIncomingValueHandler::assignValueToReg(Register ValVReg,76                                                Register PhysReg,77                                                const CCValAssign &VA) {78  markPhysRegUsed(PhysReg);79  IncomingValueHandler::assignValueToReg(ValVReg, PhysReg, VA);80}81 82Register MipsIncomingValueHandler::getStackAddress(uint64_t Size,83                                                   int64_t Offset,84                                                   MachinePointerInfo &MPO,85                                                   ISD::ArgFlagsTy Flags) {86 87  MachineFunction &MF = MIRBuilder.getMF();88  MachineFrameInfo &MFI = MF.getFrameInfo();89 90  // FIXME: This should only be immutable for non-byval memory arguments.91  int FI = MFI.CreateFixedObject(Size, Offset, true);92  MPO = MachinePointerInfo::getFixedStack(MIRBuilder.getMF(), FI);93 94  return MIRBuilder.buildFrameIndex(LLT::pointer(0, 32), FI).getReg(0);95}96 97void MipsIncomingValueHandler::assignValueToAddress(98    Register ValVReg, Register Addr, LLT MemTy, const MachinePointerInfo &MPO,99    const CCValAssign &VA) {100  MachineFunction &MF = MIRBuilder.getMF();101  auto MMO = MF.getMachineMemOperand(MPO, MachineMemOperand::MOLoad, MemTy,102                                     inferAlignFromPtrInfo(MF, MPO));103  MIRBuilder.buildLoad(ValVReg, Addr, *MMO);104}105 106/// Handle cases when f64 is split into 2 32-bit GPRs. This is a custom107/// assignment because generic code assumes getNumRegistersForCallingConv is108/// accurate. In this case it is not because the type/number are context109/// dependent on other arguments.110unsigned111MipsIncomingValueHandler::assignCustomValue(CallLowering::ArgInfo &Arg,112                                            ArrayRef<CCValAssign> VAs,113                                            std::function<void()> *Thunk) {114  const CCValAssign &VALo = VAs[0];115  const CCValAssign &VAHi = VAs[1];116 117  assert(VALo.getLocVT() == MVT::i32 && VAHi.getLocVT() == MVT::i32 &&118         VALo.getValVT() == MVT::f64 && VAHi.getValVT() == MVT::f64 &&119         "unexpected custom value");120 121  auto CopyLo = MIRBuilder.buildCopy(LLT::scalar(32), VALo.getLocReg());122  auto CopyHi = MIRBuilder.buildCopy(LLT::scalar(32), VAHi.getLocReg());123  if (!STI.isLittle())124    std::swap(CopyLo, CopyHi);125 126  Arg.OrigRegs.assign(Arg.Regs.begin(), Arg.Regs.end());127  Arg.Regs = { CopyLo.getReg(0), CopyHi.getReg(0) };128  MIRBuilder.buildMergeLikeInstr(Arg.OrigRegs[0], {CopyLo, CopyHi});129 130  markPhysRegUsed(VALo.getLocReg());131  markPhysRegUsed(VAHi.getLocReg());132  return 2;133}134 135namespace {136class MipsOutgoingValueHandler : public CallLowering::OutgoingValueHandler {137  const MipsSubtarget &STI;138 139public:140  MipsOutgoingValueHandler(MachineIRBuilder &MIRBuilder,141                           MachineRegisterInfo &MRI, MachineInstrBuilder &MIB)142      : OutgoingValueHandler(MIRBuilder, MRI),143        STI(MIRBuilder.getMF().getSubtarget<MipsSubtarget>()), MIB(MIB) {}144 145private:146  void assignValueToReg(Register ValVReg, Register PhysReg,147                        const CCValAssign &VA) override;148 149  Register getStackAddress(uint64_t Size, int64_t Offset,150                           MachinePointerInfo &MPO,151                           ISD::ArgFlagsTy Flags) override;152 153  void assignValueToAddress(Register ValVReg, Register Addr, LLT MemTy,154                            const MachinePointerInfo &MPO,155                            const CCValAssign &VA) override;156  unsigned assignCustomValue(CallLowering::ArgInfo &Arg,157                             ArrayRef<CCValAssign> VAs,158                             std::function<void()> *Thunk) override;159 160  MachineInstrBuilder &MIB;161};162} // end anonymous namespace163 164void MipsOutgoingValueHandler::assignValueToReg(Register ValVReg,165                                                Register PhysReg,166                                                const CCValAssign &VA) {167  Register ExtReg = extendRegister(ValVReg, VA);168  MIRBuilder.buildCopy(PhysReg, ExtReg);169  MIB.addUse(PhysReg, RegState::Implicit);170}171 172Register MipsOutgoingValueHandler::getStackAddress(uint64_t Size,173                                                   int64_t Offset,174                                                   MachinePointerInfo &MPO,175                                                   ISD::ArgFlagsTy Flags) {176  MachineFunction &MF = MIRBuilder.getMF();177  MPO = MachinePointerInfo::getStack(MF, Offset);178 179  LLT p0 = LLT::pointer(0, 32);180  LLT s32 = LLT::scalar(32);181  auto SPReg = MIRBuilder.buildCopy(p0, Register(Mips::SP));182 183  auto OffsetReg = MIRBuilder.buildConstant(s32, Offset);184  auto AddrReg = MIRBuilder.buildPtrAdd(p0, SPReg, OffsetReg);185  return AddrReg.getReg(0);186}187 188void MipsOutgoingValueHandler::assignValueToAddress(189    Register ValVReg, Register Addr, LLT MemTy, const MachinePointerInfo &MPO,190    const CCValAssign &VA) {191  MachineFunction &MF = MIRBuilder.getMF();192  uint64_t LocMemOffset = VA.getLocMemOffset();193 194  auto MMO = MF.getMachineMemOperand(195      MPO, MachineMemOperand::MOStore, MemTy,196      commonAlignment(STI.getStackAlignment(), LocMemOffset));197 198  Register ExtReg = extendRegister(ValVReg, VA);199  MIRBuilder.buildStore(ExtReg, Addr, *MMO);200}201 202unsigned203MipsOutgoingValueHandler::assignCustomValue(CallLowering::ArgInfo &Arg,204                                            ArrayRef<CCValAssign> VAs,205                                            std::function<void()> *Thunk) {206  const CCValAssign &VALo = VAs[0];207  const CCValAssign &VAHi = VAs[1];208 209  assert(VALo.getLocVT() == MVT::i32 && VAHi.getLocVT() == MVT::i32 &&210         VALo.getValVT() == MVT::f64 && VAHi.getValVT() == MVT::f64 &&211         "unexpected custom value");212 213  auto Unmerge =214      MIRBuilder.buildUnmerge({LLT::scalar(32), LLT::scalar(32)}, Arg.Regs[0]);215  Register Lo = Unmerge.getReg(0);216  Register Hi = Unmerge.getReg(1);217 218  Arg.OrigRegs.assign(Arg.Regs.begin(), Arg.Regs.end());219  Arg.Regs = { Lo, Hi };220  if (!STI.isLittle())221    std::swap(Lo, Hi);222 223  // If we can return a thunk, just include the register copies. The unmerge can224  // be emitted earlier.225  if (Thunk) {226    *Thunk = [=]() {227      MIRBuilder.buildCopy(VALo.getLocReg(), Lo);228      MIRBuilder.buildCopy(VAHi.getLocReg(), Hi);229    };230    return 2;231  }232  MIRBuilder.buildCopy(VALo.getLocReg(), Lo);233  MIRBuilder.buildCopy(VAHi.getLocReg(), Hi);234  return 2;235}236 237static bool isSupportedArgumentType(Type *T) {238  if (T->isIntegerTy())239    return true;240  if (T->isPointerTy())241    return true;242  if (T->isFloatingPointTy())243    return true;244  return false;245}246 247static bool isSupportedReturnType(Type *T) {248  if (T->isIntegerTy())249    return true;250  if (T->isPointerTy())251    return true;252  if (T->isFloatingPointTy())253    return true;254  if (T->isAggregateType())255    return true;256  return false;257}258 259bool MipsCallLowering::lowerReturn(MachineIRBuilder &MIRBuilder,260                                   const Value *Val, ArrayRef<Register> VRegs,261                                   FunctionLoweringInfo &FLI) const {262 263  MachineInstrBuilder Ret = MIRBuilder.buildInstrNoInsert(Mips::RetRA);264 265  if (Val != nullptr && !isSupportedReturnType(Val->getType()))266    return false;267 268  if (!VRegs.empty()) {269    MachineFunction &MF = MIRBuilder.getMF();270    const Function &F = MF.getFunction();271    const DataLayout &DL = MF.getDataLayout();272    const MipsTargetLowering &TLI = *getTLI<MipsTargetLowering>();273 274    SmallVector<ArgInfo, 8> RetInfos;275 276    ArgInfo ArgRetInfo(VRegs, *Val, 0);277    setArgFlags(ArgRetInfo, AttributeList::ReturnIndex, DL, F);278    splitToValueTypes(ArgRetInfo, RetInfos, DL, F.getCallingConv());279 280    SmallVector<CCValAssign, 16> ArgLocs;281 282    MipsCCState CCInfo(F.getCallingConv(), F.isVarArg(), MF, ArgLocs,283                       F.getContext());284 285    MipsOutgoingValueHandler RetHandler(MIRBuilder, MF.getRegInfo(), Ret);286    OutgoingValueAssigner Assigner(TLI.CCAssignFnForReturn());287 288    if (!determineAssignments(Assigner, RetInfos, CCInfo))289      return false;290 291    if (!handleAssignments(RetHandler, RetInfos, CCInfo, ArgLocs, MIRBuilder))292      return false;293  }294 295  MIRBuilder.insertInstr(Ret);296  return true;297}298 299bool MipsCallLowering::lowerFormalArguments(MachineIRBuilder &MIRBuilder,300                                            const Function &F,301                                            ArrayRef<ArrayRef<Register>> VRegs,302                                            FunctionLoweringInfo &FLI) const {303 304  // Quick exit if there aren't any args.305  if (F.arg_empty())306    return true;307 308  for (auto &Arg : F.args()) {309    if (!isSupportedArgumentType(Arg.getType()))310      return false;311  }312 313  MachineFunction &MF = MIRBuilder.getMF();314  const DataLayout &DL = MF.getDataLayout();315  const MipsTargetLowering &TLI = *getTLI<MipsTargetLowering>();316 317  SmallVector<ArgInfo, 8> ArgInfos;318  unsigned i = 0;319  for (auto &Arg : F.args()) {320    ArgInfo AInfo(VRegs[i], Arg, i);321    setArgFlags(AInfo, i + AttributeList::FirstArgIndex, DL, F);322 323    splitToValueTypes(AInfo, ArgInfos, DL, F.getCallingConv());324    ++i;325  }326 327  SmallVector<CCValAssign, 16> ArgLocs;328  MipsCCState CCInfo(F.getCallingConv(), F.isVarArg(), MF, ArgLocs,329                     F.getContext());330 331  const MipsTargetMachine &TM =332      static_cast<const MipsTargetMachine &>(MF.getTarget());333  const MipsABIInfo &ABI = TM.getABI();334  CCInfo.AllocateStack(ABI.GetCalleeAllocdArgSizeInBytes(F.getCallingConv()),335                       Align(1));336 337  IncomingValueAssigner Assigner(TLI.CCAssignFnForCall());338  if (!determineAssignments(Assigner, ArgInfos, CCInfo))339    return false;340 341  MipsIncomingValueHandler Handler(MIRBuilder, MF.getRegInfo());342  if (!handleAssignments(Handler, ArgInfos, CCInfo, ArgLocs, MIRBuilder))343    return false;344 345  if (F.isVarArg()) {346    ArrayRef<MCPhysReg> ArgRegs =347        ABI.getVarArgRegs(MF.getSubtarget<MipsSubtarget>().isGP64bit());348    unsigned Idx = CCInfo.getFirstUnallocated(ArgRegs);349 350    int VaArgOffset;351    unsigned RegSize = 4;352    if (ArgRegs.size() == Idx)353      VaArgOffset = alignTo(CCInfo.getStackSize(), RegSize);354    else {355      VaArgOffset =356          (int)ABI.GetCalleeAllocdArgSizeInBytes(CCInfo.getCallingConv()) -357          (int)(RegSize * (ArgRegs.size() - Idx));358    }359 360    MachineFrameInfo &MFI = MF.getFrameInfo();361    int FI = MFI.CreateFixedObject(RegSize, VaArgOffset, true);362    MF.getInfo<MipsFunctionInfo>()->setVarArgsFrameIndex(FI);363 364    for (unsigned I = Idx; I < ArgRegs.size(); ++I, VaArgOffset += RegSize) {365      MIRBuilder.getMBB().addLiveIn(ArgRegs[I]);366      LLT RegTy = LLT::scalar(RegSize * 8);367      MachineInstrBuilder Copy =368          MIRBuilder.buildCopy(RegTy, Register(ArgRegs[I]));369      FI = MFI.CreateFixedObject(RegSize, VaArgOffset, true);370      MachinePointerInfo MPO = MachinePointerInfo::getFixedStack(MF, FI);371 372      const LLT PtrTy = LLT::pointer(MPO.getAddrSpace(), 32);373      auto FrameIndex = MIRBuilder.buildFrameIndex(PtrTy, FI);374      MachineMemOperand *MMO = MF.getMachineMemOperand(375          MPO, MachineMemOperand::MOStore, RegTy, Align(RegSize));376      MIRBuilder.buildStore(Copy, FrameIndex, *MMO);377    }378  }379 380  return true;381}382 383bool MipsCallLowering::lowerCall(MachineIRBuilder &MIRBuilder,384                                 CallLoweringInfo &Info) const {385 386  if (Info.CallConv != CallingConv::C)387    return false;388 389  for (auto &Arg : Info.OrigArgs) {390    if (!isSupportedArgumentType(Arg.Ty))391      return false;392    if (Arg.Flags[0].isByVal())393      return false;394    if (Arg.Flags[0].isSRet() && !Arg.Ty->isPointerTy())395      return false;396  }397 398  if (!Info.OrigRet.Ty->isVoidTy() && !isSupportedReturnType(Info.OrigRet.Ty))399    return false;400 401  MachineFunction &MF = MIRBuilder.getMF();402  const Function &F = MF.getFunction();403  const DataLayout &DL = MF.getDataLayout();404  const MipsTargetLowering &TLI = *getTLI<MipsTargetLowering>();405  const MipsTargetMachine &TM =406      static_cast<const MipsTargetMachine &>(MF.getTarget());407  const MipsABIInfo &ABI = TM.getABI();408 409  MachineInstrBuilder CallSeqStart =410      MIRBuilder.buildInstr(Mips::ADJCALLSTACKDOWN);411 412  const bool IsCalleeGlobalPIC =413      Info.Callee.isGlobal() && TM.isPositionIndependent();414 415  MachineInstrBuilder MIB = MIRBuilder.buildInstrNoInsert(416      Info.Callee.isReg() || IsCalleeGlobalPIC ? Mips::JALRPseudo : Mips::JAL);417  MIB.addDef(Mips::SP, RegState::Implicit);418  if (IsCalleeGlobalPIC) {419    Register CalleeReg =420        MF.getRegInfo().createGenericVirtualRegister(LLT::pointer(0, 32));421    MachineInstr *CalleeGlobalValue =422        MIRBuilder.buildGlobalValue(CalleeReg, Info.Callee.getGlobal());423    if (!Info.Callee.getGlobal()->hasLocalLinkage())424      CalleeGlobalValue->getOperand(1).setTargetFlags(MipsII::MO_GOT_CALL);425    MIB.addUse(CalleeReg);426  } else427    MIB.add(Info.Callee);428  const TargetRegisterInfo *TRI = MF.getSubtarget().getRegisterInfo();429  MIB.addRegMask(TRI->getCallPreservedMask(MF, Info.CallConv));430 431  TargetLowering::ArgListTy FuncOrigArgs;432  FuncOrigArgs.reserve(Info.OrigArgs.size());433 434  SmallVector<ArgInfo, 8> ArgInfos;435  for (auto &Arg : Info.OrigArgs)436    splitToValueTypes(Arg, ArgInfos, DL, Info.CallConv);437 438  SmallVector<CCValAssign, 8> ArgLocs;439  bool IsCalleeVarArg = false;440  if (Info.Callee.isGlobal()) {441    const Function *CF = static_cast<const Function *>(Info.Callee.getGlobal());442    IsCalleeVarArg = CF->isVarArg();443  }444 445  // FIXME: Should use MipsCCState::getSpecialCallingConvForCallee, but it446  // depends on looking directly at the call target.447  MipsCCState CCInfo(Info.CallConv, IsCalleeVarArg, MF, ArgLocs,448                     F.getContext());449 450  CCInfo.AllocateStack(ABI.GetCalleeAllocdArgSizeInBytes(Info.CallConv),451                       Align(1));452 453  OutgoingValueAssigner Assigner(TLI.CCAssignFnForCall());454  if (!determineAssignments(Assigner, ArgInfos, CCInfo))455    return false;456 457  MipsOutgoingValueHandler ArgHandler(MIRBuilder, MF.getRegInfo(), MIB);458  if (!handleAssignments(ArgHandler, ArgInfos, CCInfo, ArgLocs, MIRBuilder))459    return false;460 461  unsigned StackSize = CCInfo.getStackSize();462  unsigned StackAlignment = F.getParent()->getOverrideStackAlignment();463  if (!StackAlignment) {464    const TargetFrameLowering *TFL = MF.getSubtarget().getFrameLowering();465    StackAlignment = TFL->getStackAlignment();466  }467  StackSize = alignTo(StackSize, StackAlignment);468  CallSeqStart.addImm(StackSize).addImm(0);469 470  if (IsCalleeGlobalPIC) {471    MIRBuilder.buildCopy(472      Register(Mips::GP),473      MF.getInfo<MipsFunctionInfo>()->getGlobalBaseRegForGlobalISel(MF));474    MIB.addDef(Mips::GP, RegState::Implicit);475  }476  MIRBuilder.insertInstr(MIB);477  if (MIB->getOpcode() == Mips::JALRPseudo) {478    const MipsSubtarget &STI = MIRBuilder.getMF().getSubtarget<MipsSubtarget>();479    MIB.constrainAllUses(MIRBuilder.getTII(), *STI.getRegisterInfo(),480                         *STI.getRegBankInfo());481  }482 483  if (!Info.OrigRet.Ty->isVoidTy()) {484    ArgInfos.clear();485 486    CallLowering::splitToValueTypes(Info.OrigRet, ArgInfos, DL,487                                    F.getCallingConv());488 489    SmallVector<CCValAssign, 8> ArgLocs;490    IncomingValueAssigner Assigner(TLI.CCAssignFnForReturn());491    CallReturnHandler RetHandler(MIRBuilder, MF.getRegInfo(), MIB);492 493    MipsCCState CCInfo(F.getCallingConv(), F.isVarArg(), MF, ArgLocs,494                       F.getContext());495 496    if (!determineAssignments(Assigner, ArgInfos, CCInfo))497      return false;498 499    if (!handleAssignments(RetHandler, ArgInfos, CCInfo, ArgLocs, MIRBuilder))500      return false;501  }502 503  MIRBuilder.buildInstr(Mips::ADJCALLSTACKUP).addImm(StackSize).addImm(0);504 505  return true;506}507