xref: /freebsd/contrib/llvm-project/llvm/lib/Target/ARM/ARMCallLowering.cpp (revision 62987288060ff68c817b7056815aa9fb8ba8ecd7)
10b57cec5SDimitry Andric //===- llvm/lib/Target/ARM/ARMCallLowering.cpp - Call lowering ------------===//
20b57cec5SDimitry Andric //
30b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
40b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
50b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
60b57cec5SDimitry Andric //
70b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
80b57cec5SDimitry Andric //
90b57cec5SDimitry Andric /// \file
100b57cec5SDimitry Andric /// This file implements the lowering of LLVM calls to machine code calls for
110b57cec5SDimitry Andric /// GlobalISel.
120b57cec5SDimitry Andric //
130b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
140b57cec5SDimitry Andric 
150b57cec5SDimitry Andric #include "ARMCallLowering.h"
160b57cec5SDimitry Andric #include "ARMBaseInstrInfo.h"
170b57cec5SDimitry Andric #include "ARMISelLowering.h"
180b57cec5SDimitry Andric #include "ARMSubtarget.h"
190b57cec5SDimitry Andric #include "Utils/ARMBaseInfo.h"
200b57cec5SDimitry Andric #include "llvm/ADT/SmallVector.h"
210b57cec5SDimitry Andric #include "llvm/CodeGen/Analysis.h"
220b57cec5SDimitry Andric #include "llvm/CodeGen/CallingConvLower.h"
230b57cec5SDimitry Andric #include "llvm/CodeGen/GlobalISel/MachineIRBuilder.h"
240b57cec5SDimitry Andric #include "llvm/CodeGen/GlobalISel/Utils.h"
2506c3fb27SDimitry Andric #include "llvm/CodeGen/LowLevelTypeUtils.h"
260b57cec5SDimitry Andric #include "llvm/CodeGen/MachineBasicBlock.h"
270b57cec5SDimitry Andric #include "llvm/CodeGen/MachineFrameInfo.h"
280b57cec5SDimitry Andric #include "llvm/CodeGen/MachineFunction.h"
290b57cec5SDimitry Andric #include "llvm/CodeGen/MachineInstrBuilder.h"
300b57cec5SDimitry Andric #include "llvm/CodeGen/MachineMemOperand.h"
310b57cec5SDimitry Andric #include "llvm/CodeGen/MachineOperand.h"
320b57cec5SDimitry Andric #include "llvm/CodeGen/MachineRegisterInfo.h"
330b57cec5SDimitry Andric #include "llvm/CodeGen/TargetRegisterInfo.h"
340b57cec5SDimitry Andric #include "llvm/CodeGen/TargetSubtargetInfo.h"
350b57cec5SDimitry Andric #include "llvm/CodeGen/ValueTypes.h"
360fca6ea1SDimitry Andric #include "llvm/CodeGenTypes/LowLevelType.h"
370fca6ea1SDimitry Andric #include "llvm/CodeGenTypes/MachineValueType.h"
380b57cec5SDimitry Andric #include "llvm/IR/Attributes.h"
390b57cec5SDimitry Andric #include "llvm/IR/DataLayout.h"
400b57cec5SDimitry Andric #include "llvm/IR/DerivedTypes.h"
410b57cec5SDimitry Andric #include "llvm/IR/Function.h"
420b57cec5SDimitry Andric #include "llvm/IR/Type.h"
430b57cec5SDimitry Andric #include "llvm/IR/Value.h"
440b57cec5SDimitry Andric #include "llvm/Support/Casting.h"
450b57cec5SDimitry Andric #include <algorithm>
460b57cec5SDimitry Andric #include <cassert>
470b57cec5SDimitry Andric #include <cstdint>
48349cc55cSDimitry Andric #include <functional>
490b57cec5SDimitry Andric #include <utility>
500b57cec5SDimitry Andric 
510b57cec5SDimitry Andric using namespace llvm;
520b57cec5SDimitry Andric 
53*62987288SDimitry Andric // Whether Big-endian GISel is enabled, defaults to off, can be enabled for
54*62987288SDimitry Andric // testing.
55*62987288SDimitry Andric static cl::opt<bool>
56*62987288SDimitry Andric     EnableGISelBigEndian("enable-arm-gisel-bigendian", cl::Hidden,
57*62987288SDimitry Andric                          cl::init(false),
58*62987288SDimitry Andric                          cl::desc("Enable Global-ISel Big Endian Lowering"));
59*62987288SDimitry Andric 
ARMCallLowering(const ARMTargetLowering & TLI)600b57cec5SDimitry Andric ARMCallLowering::ARMCallLowering(const ARMTargetLowering &TLI)
610b57cec5SDimitry Andric     : CallLowering(&TLI) {}
620b57cec5SDimitry Andric 
isSupportedType(const DataLayout & DL,const ARMTargetLowering & TLI,Type * T)630b57cec5SDimitry Andric static bool isSupportedType(const DataLayout &DL, const ARMTargetLowering &TLI,
640b57cec5SDimitry Andric                             Type *T) {
650b57cec5SDimitry Andric   if (T->isArrayTy())
660b57cec5SDimitry Andric     return isSupportedType(DL, TLI, T->getArrayElementType());
670b57cec5SDimitry Andric 
680b57cec5SDimitry Andric   if (T->isStructTy()) {
690b57cec5SDimitry Andric     // For now we only allow homogeneous structs that we can manipulate with
700b57cec5SDimitry Andric     // G_MERGE_VALUES and G_UNMERGE_VALUES
710b57cec5SDimitry Andric     auto StructT = cast<StructType>(T);
720b57cec5SDimitry Andric     for (unsigned i = 1, e = StructT->getNumElements(); i != e; ++i)
730b57cec5SDimitry Andric       if (StructT->getElementType(i) != StructT->getElementType(0))
740b57cec5SDimitry Andric         return false;
750b57cec5SDimitry Andric     return isSupportedType(DL, TLI, StructT->getElementType(0));
760b57cec5SDimitry Andric   }
770b57cec5SDimitry Andric 
780b57cec5SDimitry Andric   EVT VT = TLI.getValueType(DL, T, true);
790b57cec5SDimitry Andric   if (!VT.isSimple() || VT.isVector() ||
800b57cec5SDimitry Andric       !(VT.isInteger() || VT.isFloatingPoint()))
810b57cec5SDimitry Andric     return false;
820b57cec5SDimitry Andric 
830b57cec5SDimitry Andric   unsigned VTSize = VT.getSimpleVT().getSizeInBits();
840b57cec5SDimitry Andric 
850b57cec5SDimitry Andric   if (VTSize == 64)
860b57cec5SDimitry Andric     // FIXME: Support i64 too
870b57cec5SDimitry Andric     return VT.isFloatingPoint();
880b57cec5SDimitry Andric 
890b57cec5SDimitry Andric   return VTSize == 1 || VTSize == 8 || VTSize == 16 || VTSize == 32;
900b57cec5SDimitry Andric }
910b57cec5SDimitry Andric 
920b57cec5SDimitry Andric namespace {
930b57cec5SDimitry Andric 
940b57cec5SDimitry Andric /// Helper class for values going out through an ABI boundary (used for handling
950b57cec5SDimitry Andric /// function return values and call parameters).
96e8d8bef9SDimitry Andric struct ARMOutgoingValueHandler : public CallLowering::OutgoingValueHandler {
ARMOutgoingValueHandler__anon5229aa980111::ARMOutgoingValueHandler97e8d8bef9SDimitry Andric   ARMOutgoingValueHandler(MachineIRBuilder &MIRBuilder,
98fe6060f1SDimitry Andric                           MachineRegisterInfo &MRI, MachineInstrBuilder &MIB)
99fe6060f1SDimitry Andric       : OutgoingValueHandler(MIRBuilder, MRI), MIB(MIB) {}
1008bcb0991SDimitry Andric 
getStackAddress__anon5229aa980111::ARMOutgoingValueHandler1010b57cec5SDimitry Andric   Register getStackAddress(uint64_t Size, int64_t Offset,
102fe6060f1SDimitry Andric                            MachinePointerInfo &MPO,
103fe6060f1SDimitry Andric                            ISD::ArgFlagsTy Flags) override {
1040b57cec5SDimitry Andric     assert((Size == 1 || Size == 2 || Size == 4 || Size == 8) &&
1050b57cec5SDimitry Andric            "Unsupported size");
1060b57cec5SDimitry Andric 
1070b57cec5SDimitry Andric     LLT p0 = LLT::pointer(0, 32);
1080b57cec5SDimitry Andric     LLT s32 = LLT::scalar(32);
1095ffd83dbSDimitry Andric     auto SPReg = MIRBuilder.buildCopy(p0, Register(ARM::SP));
1100b57cec5SDimitry Andric 
1115ffd83dbSDimitry Andric     auto OffsetReg = MIRBuilder.buildConstant(s32, Offset);
1120b57cec5SDimitry Andric 
1135ffd83dbSDimitry Andric     auto AddrReg = MIRBuilder.buildPtrAdd(p0, SPReg, OffsetReg);
1140b57cec5SDimitry Andric 
1150b57cec5SDimitry Andric     MPO = MachinePointerInfo::getStack(MIRBuilder.getMF(), Offset);
1165ffd83dbSDimitry Andric     return AddrReg.getReg(0);
1170b57cec5SDimitry Andric   }
1180b57cec5SDimitry Andric 
assignValueToReg__anon5229aa980111::ARMOutgoingValueHandler1190b57cec5SDimitry Andric   void assignValueToReg(Register ValVReg, Register PhysReg,
1205f757f3fSDimitry Andric                         const CCValAssign &VA) override {
1210b57cec5SDimitry Andric     assert(VA.isRegLoc() && "Value shouldn't be assigned to reg");
1220b57cec5SDimitry Andric     assert(VA.getLocReg() == PhysReg && "Assigning to the wrong reg?");
1230b57cec5SDimitry Andric 
1240b57cec5SDimitry Andric     assert(VA.getValVT().getSizeInBits() <= 64 && "Unsupported value size");
1250b57cec5SDimitry Andric     assert(VA.getLocVT().getSizeInBits() <= 64 && "Unsupported location size");
1260b57cec5SDimitry Andric 
1270b57cec5SDimitry Andric     Register ExtReg = extendRegister(ValVReg, VA);
1280b57cec5SDimitry Andric     MIRBuilder.buildCopy(PhysReg, ExtReg);
1290b57cec5SDimitry Andric     MIB.addUse(PhysReg, RegState::Implicit);
1300b57cec5SDimitry Andric   }
1310b57cec5SDimitry Andric 
assignValueToAddress__anon5229aa980111::ARMOutgoingValueHandler132fe6060f1SDimitry Andric   void assignValueToAddress(Register ValVReg, Register Addr, LLT MemTy,
1335f757f3fSDimitry Andric                             const MachinePointerInfo &MPO,
1345f757f3fSDimitry Andric                             const CCValAssign &VA) override {
1350b57cec5SDimitry Andric     Register ExtReg = extendRegister(ValVReg, VA);
1360b57cec5SDimitry Andric     auto MMO = MIRBuilder.getMF().getMachineMemOperand(
137fe6060f1SDimitry Andric         MPO, MachineMemOperand::MOStore, MemTy, Align(1));
1380b57cec5SDimitry Andric     MIRBuilder.buildStore(ExtReg, Addr, *MMO);
1390b57cec5SDimitry Andric   }
1400b57cec5SDimitry Andric 
assignCustomValue__anon5229aa980111::ARMOutgoingValueHandler141fe6060f1SDimitry Andric   unsigned assignCustomValue(CallLowering::ArgInfo &Arg,
142349cc55cSDimitry Andric                              ArrayRef<CCValAssign> VAs,
143349cc55cSDimitry Andric                              std::function<void()> *Thunk) override {
1440b57cec5SDimitry Andric     assert(Arg.Regs.size() == 1 && "Can't handle multple regs yet");
1450b57cec5SDimitry Andric 
1465f757f3fSDimitry Andric     const CCValAssign &VA = VAs[0];
1470b57cec5SDimitry Andric     assert(VA.needsCustom() && "Value doesn't need custom handling");
1485ffd83dbSDimitry Andric 
1495ffd83dbSDimitry Andric     // Custom lowering for other types, such as f16, is currently not supported
1505ffd83dbSDimitry Andric     if (VA.getValVT() != MVT::f64)
1515ffd83dbSDimitry Andric       return 0;
1520b57cec5SDimitry Andric 
1535f757f3fSDimitry Andric     const CCValAssign &NextVA = VAs[1];
1540b57cec5SDimitry Andric     assert(NextVA.needsCustom() && "Value doesn't need custom handling");
1550b57cec5SDimitry Andric     assert(NextVA.getValVT() == MVT::f64 && "Unsupported type");
1560b57cec5SDimitry Andric 
1570b57cec5SDimitry Andric     assert(VA.getValNo() == NextVA.getValNo() &&
1580b57cec5SDimitry Andric            "Values belong to different arguments");
1590b57cec5SDimitry Andric 
1600b57cec5SDimitry Andric     assert(VA.isRegLoc() && "Value should be in reg");
1610b57cec5SDimitry Andric     assert(NextVA.isRegLoc() && "Value should be in reg");
1620b57cec5SDimitry Andric 
1630b57cec5SDimitry Andric     Register NewRegs[] = {MRI.createGenericVirtualRegister(LLT::scalar(32)),
1640b57cec5SDimitry Andric                           MRI.createGenericVirtualRegister(LLT::scalar(32))};
1650b57cec5SDimitry Andric     MIRBuilder.buildUnmerge(NewRegs, Arg.Regs[0]);
1660b57cec5SDimitry Andric 
1670b57cec5SDimitry Andric     bool IsLittle = MIRBuilder.getMF().getSubtarget<ARMSubtarget>().isLittle();
1680b57cec5SDimitry Andric     if (!IsLittle)
1690b57cec5SDimitry Andric       std::swap(NewRegs[0], NewRegs[1]);
1700b57cec5SDimitry Andric 
171349cc55cSDimitry Andric     if (Thunk) {
172349cc55cSDimitry Andric       *Thunk = [=]() {
1730b57cec5SDimitry Andric         assignValueToReg(NewRegs[0], VA.getLocReg(), VA);
1740b57cec5SDimitry Andric         assignValueToReg(NewRegs[1], NextVA.getLocReg(), NextVA);
175349cc55cSDimitry Andric       };
1767a6dacacSDimitry Andric       return 2;
177349cc55cSDimitry Andric     }
178349cc55cSDimitry Andric     assignValueToReg(NewRegs[0], VA.getLocReg(), VA);
179349cc55cSDimitry Andric     assignValueToReg(NewRegs[1], NextVA.getLocReg(), NextVA);
1807a6dacacSDimitry Andric     return 2;
1810b57cec5SDimitry Andric   }
1820b57cec5SDimitry Andric 
183fe6060f1SDimitry Andric   MachineInstrBuilder MIB;
1840b57cec5SDimitry Andric };
1850b57cec5SDimitry Andric 
1860b57cec5SDimitry Andric } // end anonymous namespace
1870b57cec5SDimitry Andric 
1880b57cec5SDimitry Andric /// Lower the return value for the already existing \p Ret. This assumes that
1890b57cec5SDimitry Andric /// \p MIRBuilder's insertion point is correct.
lowerReturnVal(MachineIRBuilder & MIRBuilder,const Value * Val,ArrayRef<Register> VRegs,MachineInstrBuilder & Ret) const1900b57cec5SDimitry Andric bool ARMCallLowering::lowerReturnVal(MachineIRBuilder &MIRBuilder,
1910b57cec5SDimitry Andric                                      const Value *Val, ArrayRef<Register> VRegs,
1920b57cec5SDimitry Andric                                      MachineInstrBuilder &Ret) const {
1930b57cec5SDimitry Andric   if (!Val)
1940b57cec5SDimitry Andric     // Nothing to do here.
1950b57cec5SDimitry Andric     return true;
1960b57cec5SDimitry Andric 
1970b57cec5SDimitry Andric   auto &MF = MIRBuilder.getMF();
1980b57cec5SDimitry Andric   const auto &F = MF.getFunction();
1990b57cec5SDimitry Andric 
200fe6060f1SDimitry Andric   const auto &DL = MF.getDataLayout();
2010b57cec5SDimitry Andric   auto &TLI = *getTLI<ARMTargetLowering>();
2020b57cec5SDimitry Andric   if (!isSupportedType(DL, TLI, Val->getType()))
2030b57cec5SDimitry Andric     return false;
2040b57cec5SDimitry Andric 
205fe6060f1SDimitry Andric   ArgInfo OrigRetInfo(VRegs, Val->getType(), 0);
2060b57cec5SDimitry Andric   setArgFlags(OrigRetInfo, AttributeList::ReturnIndex, DL, F);
2070b57cec5SDimitry Andric 
2080b57cec5SDimitry Andric   SmallVector<ArgInfo, 4> SplitRetInfos;
209fe6060f1SDimitry Andric   splitToValueTypes(OrigRetInfo, SplitRetInfos, DL, F.getCallingConv());
2100b57cec5SDimitry Andric 
2110b57cec5SDimitry Andric   CCAssignFn *AssignFn =
2120b57cec5SDimitry Andric       TLI.CCAssignFnForReturn(F.getCallingConv(), F.isVarArg());
2130b57cec5SDimitry Andric 
214fe6060f1SDimitry Andric   OutgoingValueAssigner RetAssigner(AssignFn);
215fe6060f1SDimitry Andric   ARMOutgoingValueHandler RetHandler(MIRBuilder, MF.getRegInfo(), Ret);
216fe6060f1SDimitry Andric   return determineAndHandleAssignments(RetHandler, RetAssigner, SplitRetInfos,
217fe6060f1SDimitry Andric                                        MIRBuilder, F.getCallingConv(),
218fe6060f1SDimitry Andric                                        F.isVarArg());
2190b57cec5SDimitry Andric }
2200b57cec5SDimitry Andric 
lowerReturn(MachineIRBuilder & MIRBuilder,const Value * Val,ArrayRef<Register> VRegs,FunctionLoweringInfo & FLI) const2210b57cec5SDimitry Andric bool ARMCallLowering::lowerReturn(MachineIRBuilder &MIRBuilder,
222e8d8bef9SDimitry Andric                                   const Value *Val, ArrayRef<Register> VRegs,
223e8d8bef9SDimitry Andric                                   FunctionLoweringInfo &FLI) const {
2240b57cec5SDimitry Andric   assert(!Val == VRegs.empty() && "Return value without a vreg");
2250b57cec5SDimitry Andric 
2260b57cec5SDimitry Andric   auto const &ST = MIRBuilder.getMF().getSubtarget<ARMSubtarget>();
2270b57cec5SDimitry Andric   unsigned Opcode = ST.getReturnOpcode();
2280b57cec5SDimitry Andric   auto Ret = MIRBuilder.buildInstrNoInsert(Opcode).add(predOps(ARMCC::AL));
2290b57cec5SDimitry Andric 
2300b57cec5SDimitry Andric   if (!lowerReturnVal(MIRBuilder, Val, VRegs, Ret))
2310b57cec5SDimitry Andric     return false;
2320b57cec5SDimitry Andric 
2330b57cec5SDimitry Andric   MIRBuilder.insertInstr(Ret);
2340b57cec5SDimitry Andric   return true;
2350b57cec5SDimitry Andric }
2360b57cec5SDimitry Andric 
2370b57cec5SDimitry Andric namespace {
2380b57cec5SDimitry Andric 
2390b57cec5SDimitry Andric /// Helper class for values coming in through an ABI boundary (used for handling
2400b57cec5SDimitry Andric /// formal arguments and call return values).
241e8d8bef9SDimitry Andric struct ARMIncomingValueHandler : public CallLowering::IncomingValueHandler {
ARMIncomingValueHandler__anon5229aa980311::ARMIncomingValueHandler242e8d8bef9SDimitry Andric   ARMIncomingValueHandler(MachineIRBuilder &MIRBuilder,
243fe6060f1SDimitry Andric                           MachineRegisterInfo &MRI)
244fe6060f1SDimitry Andric       : IncomingValueHandler(MIRBuilder, MRI) {}
2450b57cec5SDimitry Andric 
getStackAddress__anon5229aa980311::ARMIncomingValueHandler2460b57cec5SDimitry Andric   Register getStackAddress(uint64_t Size, int64_t Offset,
247fe6060f1SDimitry Andric                            MachinePointerInfo &MPO,
248fe6060f1SDimitry Andric                            ISD::ArgFlagsTy Flags) override {
2490b57cec5SDimitry Andric     assert((Size == 1 || Size == 2 || Size == 4 || Size == 8) &&
2500b57cec5SDimitry Andric            "Unsupported size");
2510b57cec5SDimitry Andric 
2520b57cec5SDimitry Andric     auto &MFI = MIRBuilder.getMF().getFrameInfo();
2530b57cec5SDimitry Andric 
254fe6060f1SDimitry Andric     // Byval is assumed to be writable memory, but other stack passed arguments
255fe6060f1SDimitry Andric     // are not.
256fe6060f1SDimitry Andric     const bool IsImmutable = !Flags.isByVal();
257fe6060f1SDimitry Andric 
258fe6060f1SDimitry Andric     int FI = MFI.CreateFixedObject(Size, Offset, IsImmutable);
2590b57cec5SDimitry Andric     MPO = MachinePointerInfo::getFixedStack(MIRBuilder.getMF(), FI);
2600b57cec5SDimitry Andric 
2615ffd83dbSDimitry Andric     return MIRBuilder.buildFrameIndex(LLT::pointer(MPO.getAddrSpace(), 32), FI)
2625ffd83dbSDimitry Andric         .getReg(0);
2630b57cec5SDimitry Andric   }
2640b57cec5SDimitry Andric 
assignValueToAddress__anon5229aa980311::ARMIncomingValueHandler265fe6060f1SDimitry Andric   void assignValueToAddress(Register ValVReg, Register Addr, LLT MemTy,
2665f757f3fSDimitry Andric                             const MachinePointerInfo &MPO,
2675f757f3fSDimitry Andric                             const CCValAssign &VA) override {
2680b57cec5SDimitry Andric     if (VA.getLocInfo() == CCValAssign::SExt ||
2690b57cec5SDimitry Andric         VA.getLocInfo() == CCValAssign::ZExt) {
2700b57cec5SDimitry Andric       // If the value is zero- or sign-extended, its size becomes 4 bytes, so
2710b57cec5SDimitry Andric       // that's what we should load.
272fe6060f1SDimitry Andric       MemTy = LLT::scalar(32);
2730b57cec5SDimitry Andric       assert(MRI.getType(ValVReg).isScalar() && "Only scalars supported atm");
2740b57cec5SDimitry Andric 
275fe6060f1SDimitry Andric       auto LoadVReg = buildLoad(LLT::scalar(32), Addr, MemTy, MPO);
2760b57cec5SDimitry Andric       MIRBuilder.buildTrunc(ValVReg, LoadVReg);
2770b57cec5SDimitry Andric     } else {
2780b57cec5SDimitry Andric       // If the value is not extended, a simple load will suffice.
279fe6060f1SDimitry Andric       buildLoad(ValVReg, Addr, MemTy, MPO);
2800b57cec5SDimitry Andric     }
2810b57cec5SDimitry Andric   }
2820b57cec5SDimitry Andric 
buildLoad__anon5229aa980311::ARMIncomingValueHandler283fe6060f1SDimitry Andric   MachineInstrBuilder buildLoad(const DstOp &Res, Register Addr, LLT MemTy,
2845f757f3fSDimitry Andric                                 const MachinePointerInfo &MPO) {
2855ffd83dbSDimitry Andric     MachineFunction &MF = MIRBuilder.getMF();
2865ffd83dbSDimitry Andric 
287fe6060f1SDimitry Andric     auto MMO = MF.getMachineMemOperand(MPO, MachineMemOperand::MOLoad, MemTy,
2885ffd83dbSDimitry Andric                                        inferAlignFromPtrInfo(MF, MPO));
2895ffd83dbSDimitry Andric     return MIRBuilder.buildLoad(Res, Addr, *MMO);
2900b57cec5SDimitry Andric   }
2910b57cec5SDimitry Andric 
assignValueToReg__anon5229aa980311::ARMIncomingValueHandler2920b57cec5SDimitry Andric   void assignValueToReg(Register ValVReg, Register PhysReg,
2935f757f3fSDimitry Andric                         const CCValAssign &VA) override {
2940b57cec5SDimitry Andric     assert(VA.isRegLoc() && "Value shouldn't be assigned to reg");
2950b57cec5SDimitry Andric     assert(VA.getLocReg() == PhysReg && "Assigning to the wrong reg?");
2960b57cec5SDimitry Andric 
297e8d8bef9SDimitry Andric     uint64_t ValSize = VA.getValVT().getFixedSizeInBits();
298e8d8bef9SDimitry Andric     uint64_t LocSize = VA.getLocVT().getFixedSizeInBits();
2990b57cec5SDimitry Andric 
3000b57cec5SDimitry Andric     assert(ValSize <= 64 && "Unsupported value size");
3010b57cec5SDimitry Andric     assert(LocSize <= 64 && "Unsupported location size");
3020b57cec5SDimitry Andric 
3030b57cec5SDimitry Andric     markPhysRegUsed(PhysReg);
3040b57cec5SDimitry Andric     if (ValSize == LocSize) {
3050b57cec5SDimitry Andric       MIRBuilder.buildCopy(ValVReg, PhysReg);
3060b57cec5SDimitry Andric     } else {
3070b57cec5SDimitry Andric       assert(ValSize < LocSize && "Extensions not supported");
3080b57cec5SDimitry Andric 
3090b57cec5SDimitry Andric       // We cannot create a truncating copy, nor a trunc of a physical register.
3100b57cec5SDimitry Andric       // Therefore, we need to copy the content of the physical register into a
3110b57cec5SDimitry Andric       // virtual one and then truncate that.
3125ffd83dbSDimitry Andric       auto PhysRegToVReg = MIRBuilder.buildCopy(LLT::scalar(LocSize), PhysReg);
3130b57cec5SDimitry Andric       MIRBuilder.buildTrunc(ValVReg, PhysRegToVReg);
3140b57cec5SDimitry Andric     }
3150b57cec5SDimitry Andric   }
3160b57cec5SDimitry Andric 
assignCustomValue__anon5229aa980311::ARMIncomingValueHandler317fe6060f1SDimitry Andric   unsigned assignCustomValue(ARMCallLowering::ArgInfo &Arg,
318349cc55cSDimitry Andric                              ArrayRef<CCValAssign> VAs,
319349cc55cSDimitry Andric                              std::function<void()> *Thunk) override {
3200b57cec5SDimitry Andric     assert(Arg.Regs.size() == 1 && "Can't handle multple regs yet");
3210b57cec5SDimitry Andric 
3225f757f3fSDimitry Andric     const CCValAssign &VA = VAs[0];
3230b57cec5SDimitry Andric     assert(VA.needsCustom() && "Value doesn't need custom handling");
3245ffd83dbSDimitry Andric 
3255ffd83dbSDimitry Andric     // Custom lowering for other types, such as f16, is currently not supported
3265ffd83dbSDimitry Andric     if (VA.getValVT() != MVT::f64)
3275ffd83dbSDimitry Andric       return 0;
3280b57cec5SDimitry Andric 
3295f757f3fSDimitry Andric     const CCValAssign &NextVA = VAs[1];
3300b57cec5SDimitry Andric     assert(NextVA.needsCustom() && "Value doesn't need custom handling");
3310b57cec5SDimitry Andric     assert(NextVA.getValVT() == MVT::f64 && "Unsupported type");
3320b57cec5SDimitry Andric 
3330b57cec5SDimitry Andric     assert(VA.getValNo() == NextVA.getValNo() &&
3340b57cec5SDimitry Andric            "Values belong to different arguments");
3350b57cec5SDimitry Andric 
3360b57cec5SDimitry Andric     assert(VA.isRegLoc() && "Value should be in reg");
3370b57cec5SDimitry Andric     assert(NextVA.isRegLoc() && "Value should be in reg");
3380b57cec5SDimitry Andric 
3390b57cec5SDimitry Andric     Register NewRegs[] = {MRI.createGenericVirtualRegister(LLT::scalar(32)),
3400b57cec5SDimitry Andric                           MRI.createGenericVirtualRegister(LLT::scalar(32))};
3410b57cec5SDimitry Andric 
3420b57cec5SDimitry Andric     assignValueToReg(NewRegs[0], VA.getLocReg(), VA);
3430b57cec5SDimitry Andric     assignValueToReg(NewRegs[1], NextVA.getLocReg(), NextVA);
3440b57cec5SDimitry Andric 
3450b57cec5SDimitry Andric     bool IsLittle = MIRBuilder.getMF().getSubtarget<ARMSubtarget>().isLittle();
3460b57cec5SDimitry Andric     if (!IsLittle)
3470b57cec5SDimitry Andric       std::swap(NewRegs[0], NewRegs[1]);
3480b57cec5SDimitry Andric 
349bdd1243dSDimitry Andric     MIRBuilder.buildMergeLikeInstr(Arg.Regs[0], NewRegs);
3500b57cec5SDimitry Andric 
3517a6dacacSDimitry Andric     return 2;
3520b57cec5SDimitry Andric   }
3530b57cec5SDimitry Andric 
3540b57cec5SDimitry Andric   /// Marking a physical register as used is different between formal
3550b57cec5SDimitry Andric   /// parameters, where it's a basic block live-in, and call returns, where it's
3560b57cec5SDimitry Andric   /// an implicit-def of the call instruction.
3570b57cec5SDimitry Andric   virtual void markPhysRegUsed(unsigned PhysReg) = 0;
3580b57cec5SDimitry Andric };
3590b57cec5SDimitry Andric 
360e8d8bef9SDimitry Andric struct FormalArgHandler : public ARMIncomingValueHandler {
FormalArgHandler__anon5229aa980311::FormalArgHandler361fe6060f1SDimitry Andric   FormalArgHandler(MachineIRBuilder &MIRBuilder, MachineRegisterInfo &MRI)
362fe6060f1SDimitry Andric       : ARMIncomingValueHandler(MIRBuilder, MRI) {}
3630b57cec5SDimitry Andric 
markPhysRegUsed__anon5229aa980311::FormalArgHandler3640b57cec5SDimitry Andric   void markPhysRegUsed(unsigned PhysReg) override {
3658bcb0991SDimitry Andric     MIRBuilder.getMRI()->addLiveIn(PhysReg);
3660b57cec5SDimitry Andric     MIRBuilder.getMBB().addLiveIn(PhysReg);
3670b57cec5SDimitry Andric   }
3680b57cec5SDimitry Andric };
3690b57cec5SDimitry Andric 
3700b57cec5SDimitry Andric } // end anonymous namespace
3710b57cec5SDimitry Andric 
lowerFormalArguments(MachineIRBuilder & MIRBuilder,const Function & F,ArrayRef<ArrayRef<Register>> VRegs,FunctionLoweringInfo & FLI) const372e8d8bef9SDimitry Andric bool ARMCallLowering::lowerFormalArguments(MachineIRBuilder &MIRBuilder,
373e8d8bef9SDimitry Andric                                            const Function &F,
374e8d8bef9SDimitry Andric                                            ArrayRef<ArrayRef<Register>> VRegs,
375e8d8bef9SDimitry Andric                                            FunctionLoweringInfo &FLI) const {
3760b57cec5SDimitry Andric   auto &TLI = *getTLI<ARMTargetLowering>();
3770b57cec5SDimitry Andric   auto Subtarget = TLI.getSubtarget();
3780b57cec5SDimitry Andric 
3790b57cec5SDimitry Andric   if (Subtarget->isThumb1Only())
3800b57cec5SDimitry Andric     return false;
3810b57cec5SDimitry Andric 
3820b57cec5SDimitry Andric   // Quick exit if there aren't any args
3830b57cec5SDimitry Andric   if (F.arg_empty())
3840b57cec5SDimitry Andric     return true;
3850b57cec5SDimitry Andric 
3860b57cec5SDimitry Andric   if (F.isVarArg())
3870b57cec5SDimitry Andric     return false;
3880b57cec5SDimitry Andric 
3890b57cec5SDimitry Andric   auto &MF = MIRBuilder.getMF();
3900b57cec5SDimitry Andric   auto &MBB = MIRBuilder.getMBB();
391fe6060f1SDimitry Andric   const auto &DL = MF.getDataLayout();
3920b57cec5SDimitry Andric 
3930b57cec5SDimitry Andric   for (auto &Arg : F.args()) {
3940b57cec5SDimitry Andric     if (!isSupportedType(DL, TLI, Arg.getType()))
3950b57cec5SDimitry Andric       return false;
396e8d8bef9SDimitry Andric     if (Arg.hasPassPointeeByValueCopyAttr())
3970b57cec5SDimitry Andric       return false;
3980b57cec5SDimitry Andric   }
3990b57cec5SDimitry Andric 
4000b57cec5SDimitry Andric   CCAssignFn *AssignFn =
4010b57cec5SDimitry Andric       TLI.CCAssignFnForCall(F.getCallingConv(), F.isVarArg());
4020b57cec5SDimitry Andric 
403fe6060f1SDimitry Andric   OutgoingValueAssigner ArgAssigner(AssignFn);
404fe6060f1SDimitry Andric   FormalArgHandler ArgHandler(MIRBuilder, MIRBuilder.getMF().getRegInfo());
4050b57cec5SDimitry Andric 
4060b57cec5SDimitry Andric   SmallVector<ArgInfo, 8> SplitArgInfos;
4070b57cec5SDimitry Andric   unsigned Idx = 0;
4080b57cec5SDimitry Andric   for (auto &Arg : F.args()) {
409fe6060f1SDimitry Andric     ArgInfo OrigArgInfo(VRegs[Idx], Arg.getType(), Idx);
4100b57cec5SDimitry Andric 
4110b57cec5SDimitry Andric     setArgFlags(OrigArgInfo, Idx + AttributeList::FirstArgIndex, DL, F);
412fe6060f1SDimitry Andric     splitToValueTypes(OrigArgInfo, SplitArgInfos, DL, F.getCallingConv());
4130b57cec5SDimitry Andric 
4140b57cec5SDimitry Andric     Idx++;
4150b57cec5SDimitry Andric   }
4160b57cec5SDimitry Andric 
4170b57cec5SDimitry Andric   if (!MBB.empty())
4180b57cec5SDimitry Andric     MIRBuilder.setInstr(*MBB.begin());
4190b57cec5SDimitry Andric 
420fe6060f1SDimitry Andric   if (!determineAndHandleAssignments(ArgHandler, ArgAssigner, SplitArgInfos,
421fe6060f1SDimitry Andric                                      MIRBuilder, F.getCallingConv(),
422fe6060f1SDimitry Andric                                      F.isVarArg()))
4230b57cec5SDimitry Andric     return false;
4240b57cec5SDimitry Andric 
4250b57cec5SDimitry Andric   // Move back to the end of the basic block.
4260b57cec5SDimitry Andric   MIRBuilder.setMBB(MBB);
4270b57cec5SDimitry Andric   return true;
4280b57cec5SDimitry Andric }
4290b57cec5SDimitry Andric 
4300b57cec5SDimitry Andric namespace {
4310b57cec5SDimitry Andric 
432e8d8bef9SDimitry Andric struct CallReturnHandler : public ARMIncomingValueHandler {
CallReturnHandler__anon5229aa980411::CallReturnHandler4330b57cec5SDimitry Andric   CallReturnHandler(MachineIRBuilder &MIRBuilder, MachineRegisterInfo &MRI,
434fe6060f1SDimitry Andric                     MachineInstrBuilder MIB)
435fe6060f1SDimitry Andric       : ARMIncomingValueHandler(MIRBuilder, MRI), MIB(MIB) {}
4360b57cec5SDimitry Andric 
markPhysRegUsed__anon5229aa980411::CallReturnHandler4370b57cec5SDimitry Andric   void markPhysRegUsed(unsigned PhysReg) override {
4380b57cec5SDimitry Andric     MIB.addDef(PhysReg, RegState::Implicit);
4390b57cec5SDimitry Andric   }
4400b57cec5SDimitry Andric 
4410b57cec5SDimitry Andric   MachineInstrBuilder MIB;
4420b57cec5SDimitry Andric };
4430b57cec5SDimitry Andric 
4440b57cec5SDimitry Andric // FIXME: This should move to the ARMSubtarget when it supports all the opcodes.
getCallOpcode(const MachineFunction & MF,const ARMSubtarget & STI,bool isDirect)445e8d8bef9SDimitry Andric unsigned getCallOpcode(const MachineFunction &MF, const ARMSubtarget &STI,
446e8d8bef9SDimitry Andric                        bool isDirect) {
4470b57cec5SDimitry Andric   if (isDirect)
4480b57cec5SDimitry Andric     return STI.isThumb() ? ARM::tBL : ARM::BL;
4490b57cec5SDimitry Andric 
4500b57cec5SDimitry Andric   if (STI.isThumb())
451e8d8bef9SDimitry Andric     return gettBLXrOpcode(MF);
4520b57cec5SDimitry Andric 
4530b57cec5SDimitry Andric   if (STI.hasV5TOps())
454e8d8bef9SDimitry Andric     return getBLXOpcode(MF);
4550b57cec5SDimitry Andric 
4560b57cec5SDimitry Andric   if (STI.hasV4TOps())
4570b57cec5SDimitry Andric     return ARM::BX_CALL;
4580b57cec5SDimitry Andric 
4590b57cec5SDimitry Andric   return ARM::BMOVPCRX_CALL;
4600b57cec5SDimitry Andric }
4610b57cec5SDimitry Andric } // end anonymous namespace
4620b57cec5SDimitry Andric 
lowerCall(MachineIRBuilder & MIRBuilder,CallLoweringInfo & Info) const4638bcb0991SDimitry Andric bool ARMCallLowering::lowerCall(MachineIRBuilder &MIRBuilder, CallLoweringInfo &Info) const {
4640b57cec5SDimitry Andric   MachineFunction &MF = MIRBuilder.getMF();
4650b57cec5SDimitry Andric   const auto &TLI = *getTLI<ARMTargetLowering>();
4660b57cec5SDimitry Andric   const auto &DL = MF.getDataLayout();
4670b57cec5SDimitry Andric   const auto &STI = MF.getSubtarget<ARMSubtarget>();
4680b57cec5SDimitry Andric   const TargetRegisterInfo *TRI = STI.getRegisterInfo();
4690b57cec5SDimitry Andric   MachineRegisterInfo &MRI = MF.getRegInfo();
4700b57cec5SDimitry Andric 
4710b57cec5SDimitry Andric   if (STI.genLongCalls())
4720b57cec5SDimitry Andric     return false;
4730b57cec5SDimitry Andric 
4740b57cec5SDimitry Andric   if (STI.isThumb1Only())
4750b57cec5SDimitry Andric     return false;
4760b57cec5SDimitry Andric 
4770b57cec5SDimitry Andric   auto CallSeqStart = MIRBuilder.buildInstr(ARM::ADJCALLSTACKDOWN);
4780b57cec5SDimitry Andric 
4790b57cec5SDimitry Andric   // Create the call instruction so we can add the implicit uses of arg
4800b57cec5SDimitry Andric   // registers, but don't insert it yet.
4818bcb0991SDimitry Andric   bool IsDirect = !Info.Callee.isReg();
482e8d8bef9SDimitry Andric   auto CallOpcode = getCallOpcode(MF, STI, IsDirect);
4830b57cec5SDimitry Andric   auto MIB = MIRBuilder.buildInstrNoInsert(CallOpcode);
4840b57cec5SDimitry Andric 
4850b57cec5SDimitry Andric   bool IsThumb = STI.isThumb();
4860b57cec5SDimitry Andric   if (IsThumb)
4870b57cec5SDimitry Andric     MIB.add(predOps(ARMCC::AL));
4880b57cec5SDimitry Andric 
4898bcb0991SDimitry Andric   MIB.add(Info.Callee);
4900b57cec5SDimitry Andric   if (!IsDirect) {
4918bcb0991SDimitry Andric     auto CalleeReg = Info.Callee.getReg();
492bdd1243dSDimitry Andric     if (CalleeReg && !CalleeReg.isPhysical()) {
4930b57cec5SDimitry Andric       unsigned CalleeIdx = IsThumb ? 2 : 0;
4940b57cec5SDimitry Andric       MIB->getOperand(CalleeIdx).setReg(constrainOperandRegClass(
4950b57cec5SDimitry Andric           MF, *TRI, MRI, *STI.getInstrInfo(), *STI.getRegBankInfo(),
4968bcb0991SDimitry Andric           *MIB.getInstr(), MIB->getDesc(), Info.Callee, CalleeIdx));
4970b57cec5SDimitry Andric     }
4980b57cec5SDimitry Andric   }
4990b57cec5SDimitry Andric 
5008bcb0991SDimitry Andric   MIB.addRegMask(TRI->getCallPreservedMask(MF, Info.CallConv));
5010b57cec5SDimitry Andric 
5020b57cec5SDimitry Andric   SmallVector<ArgInfo, 8> ArgInfos;
5038bcb0991SDimitry Andric   for (auto Arg : Info.OrigArgs) {
5040b57cec5SDimitry Andric     if (!isSupportedType(DL, TLI, Arg.Ty))
5050b57cec5SDimitry Andric       return false;
5060b57cec5SDimitry Andric 
5078bcb0991SDimitry Andric     if (Arg.Flags[0].isByVal())
5080b57cec5SDimitry Andric       return false;
5090b57cec5SDimitry Andric 
510fe6060f1SDimitry Andric     splitToValueTypes(Arg, ArgInfos, DL, Info.CallConv);
5110b57cec5SDimitry Andric   }
5120b57cec5SDimitry Andric 
513e8d8bef9SDimitry Andric   auto ArgAssignFn = TLI.CCAssignFnForCall(Info.CallConv, Info.IsVarArg);
514fe6060f1SDimitry Andric   OutgoingValueAssigner ArgAssigner(ArgAssignFn);
515fe6060f1SDimitry Andric   ARMOutgoingValueHandler ArgHandler(MIRBuilder, MRI, MIB);
516fe6060f1SDimitry Andric   if (!determineAndHandleAssignments(ArgHandler, ArgAssigner, ArgInfos,
517fe6060f1SDimitry Andric                                      MIRBuilder, Info.CallConv, Info.IsVarArg))
5180b57cec5SDimitry Andric     return false;
5190b57cec5SDimitry Andric 
5200b57cec5SDimitry Andric   // Now we can add the actual call instruction to the correct basic block.
5210b57cec5SDimitry Andric   MIRBuilder.insertInstr(MIB);
5220b57cec5SDimitry Andric 
5238bcb0991SDimitry Andric   if (!Info.OrigRet.Ty->isVoidTy()) {
5248bcb0991SDimitry Andric     if (!isSupportedType(DL, TLI, Info.OrigRet.Ty))
5250b57cec5SDimitry Andric       return false;
5260b57cec5SDimitry Andric 
5270b57cec5SDimitry Andric     ArgInfos.clear();
528fe6060f1SDimitry Andric     splitToValueTypes(Info.OrigRet, ArgInfos, DL, Info.CallConv);
529e8d8bef9SDimitry Andric     auto RetAssignFn = TLI.CCAssignFnForReturn(Info.CallConv, Info.IsVarArg);
530fe6060f1SDimitry Andric     OutgoingValueAssigner Assigner(RetAssignFn);
531fe6060f1SDimitry Andric     CallReturnHandler RetHandler(MIRBuilder, MRI, MIB);
532fe6060f1SDimitry Andric     if (!determineAndHandleAssignments(RetHandler, Assigner, ArgInfos,
533fe6060f1SDimitry Andric                                        MIRBuilder, Info.CallConv,
534fe6060f1SDimitry Andric                                        Info.IsVarArg))
5350b57cec5SDimitry Andric       return false;
5360b57cec5SDimitry Andric   }
5370b57cec5SDimitry Andric 
5380b57cec5SDimitry Andric   // We now know the size of the stack - update the ADJCALLSTACKDOWN
5390b57cec5SDimitry Andric   // accordingly.
54006c3fb27SDimitry Andric   CallSeqStart.addImm(ArgAssigner.StackSize).addImm(0).add(predOps(ARMCC::AL));
5410b57cec5SDimitry Andric 
5420b57cec5SDimitry Andric   MIRBuilder.buildInstr(ARM::ADJCALLSTACKUP)
54306c3fb27SDimitry Andric       .addImm(ArgAssigner.StackSize)
54404eeddc0SDimitry Andric       .addImm(-1ULL)
5450b57cec5SDimitry Andric       .add(predOps(ARMCC::AL));
5460b57cec5SDimitry Andric 
5470b57cec5SDimitry Andric   return true;
5480b57cec5SDimitry Andric }
549*62987288SDimitry Andric 
enableBigEndian() const550*62987288SDimitry Andric bool ARMCallLowering::enableBigEndian() const { return EnableGISelBigEndian; }