127fd307bSReid Kleckner //=== ARMCallingConv.cpp - ARM Custom CC Routines ---------------*- C++ -*-===//
227fd307bSReid Kleckner //
327fd307bSReid Kleckner // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
427fd307bSReid Kleckner // See https://llvm.org/LICENSE.txt for license information.
527fd307bSReid Kleckner // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
627fd307bSReid Kleckner //
727fd307bSReid Kleckner //===----------------------------------------------------------------------===//
827fd307bSReid Kleckner //
927fd307bSReid Kleckner // This file contains the custom routines for the ARM Calling Convention that
1027fd307bSReid Kleckner // aren't done by tablegen, and includes the table generated implementations.
1127fd307bSReid Kleckner //
1227fd307bSReid Kleckner //===----------------------------------------------------------------------===//
1327fd307bSReid Kleckner 
1427fd307bSReid Kleckner #include "ARM.h"
1527fd307bSReid Kleckner #include "ARMCallingConv.h"
1627fd307bSReid Kleckner #include "ARMSubtarget.h"
1727fd307bSReid Kleckner #include "ARMRegisterInfo.h"
1827fd307bSReid Kleckner using namespace llvm;
1927fd307bSReid Kleckner 
2027fd307bSReid Kleckner // APCS f64 is in register pairs, possibly split to stack
f64AssignAPCS(unsigned ValNo,MVT ValVT,MVT LocVT,CCValAssign::LocInfo LocInfo,CCState & State,bool CanFail)2173c3137aSOliver Stannard static bool f64AssignAPCS(unsigned ValNo, MVT ValVT, MVT LocVT,
2273c3137aSOliver Stannard                           CCValAssign::LocInfo LocInfo,
2327fd307bSReid Kleckner                           CCState &State, bool CanFail) {
2427fd307bSReid Kleckner   static const MCPhysReg RegList[] = { ARM::R0, ARM::R1, ARM::R2, ARM::R3 };
2527fd307bSReid Kleckner 
2627fd307bSReid Kleckner   // Try to get the first register.
2727fd307bSReid Kleckner   if (unsigned Reg = State.AllocateReg(RegList))
2827fd307bSReid Kleckner     State.addLoc(CCValAssign::getCustomReg(ValNo, ValVT, Reg, LocVT, LocInfo));
2927fd307bSReid Kleckner   else {
3027fd307bSReid Kleckner     // For the 2nd half of a v2f64, do not fail.
3127fd307bSReid Kleckner     if (CanFail)
3227fd307bSReid Kleckner       return false;
3327fd307bSReid Kleckner 
3427fd307bSReid Kleckner     // Put the whole thing on the stack.
35be4f5061SGuillaume Chatelet     State.addLoc(CCValAssign::getCustomMem(
36be4f5061SGuillaume Chatelet         ValNo, ValVT, State.AllocateStack(8, Align(4)), LocVT, LocInfo));
3727fd307bSReid Kleckner     return true;
3827fd307bSReid Kleckner   }
3927fd307bSReid Kleckner 
4027fd307bSReid Kleckner   // Try to get the second register.
4127fd307bSReid Kleckner   if (unsigned Reg = State.AllocateReg(RegList))
4227fd307bSReid Kleckner     State.addLoc(CCValAssign::getCustomReg(ValNo, ValVT, Reg, LocVT, LocInfo));
4327fd307bSReid Kleckner   else
44be4f5061SGuillaume Chatelet     State.addLoc(CCValAssign::getCustomMem(
45be4f5061SGuillaume Chatelet         ValNo, ValVT, State.AllocateStack(4, Align(4)), LocVT, LocInfo));
4627fd307bSReid Kleckner   return true;
4727fd307bSReid Kleckner }
4827fd307bSReid Kleckner 
CC_ARM_APCS_Custom_f64(unsigned ValNo,MVT ValVT,MVT LocVT,CCValAssign::LocInfo LocInfo,ISD::ArgFlagsTy ArgFlags,CCState & State)4973c3137aSOliver Stannard static bool CC_ARM_APCS_Custom_f64(unsigned ValNo, MVT ValVT, MVT LocVT,
5073c3137aSOliver Stannard                                    CCValAssign::LocInfo LocInfo,
5173c3137aSOliver Stannard                                    ISD::ArgFlagsTy ArgFlags,
5227fd307bSReid Kleckner                                    CCState &State) {
5327fd307bSReid Kleckner   if (!f64AssignAPCS(ValNo, ValVT, LocVT, LocInfo, State, true))
5427fd307bSReid Kleckner     return false;
5527fd307bSReid Kleckner   if (LocVT == MVT::v2f64 &&
5627fd307bSReid Kleckner       !f64AssignAPCS(ValNo, ValVT, LocVT, LocInfo, State, false))
5727fd307bSReid Kleckner     return false;
5827fd307bSReid Kleckner   return true;  // we handled it
5927fd307bSReid Kleckner }
6027fd307bSReid Kleckner 
6127fd307bSReid Kleckner // AAPCS f64 is in aligned register pairs
f64AssignAAPCS(unsigned ValNo,MVT ValVT,MVT LocVT,CCValAssign::LocInfo LocInfo,CCState & State,bool CanFail)6273c3137aSOliver Stannard static bool f64AssignAAPCS(unsigned ValNo, MVT ValVT, MVT LocVT,
6373c3137aSOliver Stannard                            CCValAssign::LocInfo LocInfo,
6427fd307bSReid Kleckner                            CCState &State, bool CanFail) {
6527fd307bSReid Kleckner   static const MCPhysReg HiRegList[] = { ARM::R0, ARM::R2 };
6627fd307bSReid Kleckner   static const MCPhysReg LoRegList[] = { ARM::R1, ARM::R3 };
6727fd307bSReid Kleckner   static const MCPhysReg ShadowRegList[] = { ARM::R0, ARM::R1 };
6827fd307bSReid Kleckner   static const MCPhysReg GPRArgRegs[] = { ARM::R0, ARM::R1, ARM::R2, ARM::R3 };
6927fd307bSReid Kleckner 
7027fd307bSReid Kleckner   unsigned Reg = State.AllocateReg(HiRegList, ShadowRegList);
7127fd307bSReid Kleckner   if (Reg == 0) {
7227fd307bSReid Kleckner 
7327fd307bSReid Kleckner     // If we had R3 unallocated only, now we still must to waste it.
7427fd307bSReid Kleckner     Reg = State.AllocateReg(GPRArgRegs);
7527fd307bSReid Kleckner     assert((!Reg || Reg == ARM::R3) && "Wrong GPRs usage for f64");
7627fd307bSReid Kleckner 
7727fd307bSReid Kleckner     // For the 2nd half of a v2f64, do not just fail.
7827fd307bSReid Kleckner     if (CanFail)
7927fd307bSReid Kleckner       return false;
8027fd307bSReid Kleckner 
8127fd307bSReid Kleckner     // Put the whole thing on the stack.
82be4f5061SGuillaume Chatelet     State.addLoc(CCValAssign::getCustomMem(
83be4f5061SGuillaume Chatelet         ValNo, ValVT, State.AllocateStack(8, Align(8)), LocVT, LocInfo));
8427fd307bSReid Kleckner     return true;
8527fd307bSReid Kleckner   }
8627fd307bSReid Kleckner 
8727fd307bSReid Kleckner   unsigned i;
8827fd307bSReid Kleckner   for (i = 0; i < 2; ++i)
8927fd307bSReid Kleckner     if (HiRegList[i] == Reg)
9027fd307bSReid Kleckner       break;
9127fd307bSReid Kleckner 
9227fd307bSReid Kleckner   unsigned T = State.AllocateReg(LoRegList[i]);
9327fd307bSReid Kleckner   (void)T;
9427fd307bSReid Kleckner   assert(T == LoRegList[i] && "Could not allocate register");
9527fd307bSReid Kleckner 
9627fd307bSReid Kleckner   State.addLoc(CCValAssign::getCustomReg(ValNo, ValVT, Reg, LocVT, LocInfo));
9727fd307bSReid Kleckner   State.addLoc(CCValAssign::getCustomReg(ValNo, ValVT, LoRegList[i],
9827fd307bSReid Kleckner                                          LocVT, LocInfo));
9927fd307bSReid Kleckner   return true;
10027fd307bSReid Kleckner }
10127fd307bSReid Kleckner 
CC_ARM_AAPCS_Custom_f64(unsigned ValNo,MVT ValVT,MVT LocVT,CCValAssign::LocInfo LocInfo,ISD::ArgFlagsTy ArgFlags,CCState & State)10273c3137aSOliver Stannard static bool CC_ARM_AAPCS_Custom_f64(unsigned ValNo, MVT ValVT, MVT LocVT,
10373c3137aSOliver Stannard                                     CCValAssign::LocInfo LocInfo,
10473c3137aSOliver Stannard                                     ISD::ArgFlagsTy ArgFlags,
10527fd307bSReid Kleckner                                     CCState &State) {
10627fd307bSReid Kleckner   if (!f64AssignAAPCS(ValNo, ValVT, LocVT, LocInfo, State, true))
10727fd307bSReid Kleckner     return false;
10827fd307bSReid Kleckner   if (LocVT == MVT::v2f64 &&
10927fd307bSReid Kleckner       !f64AssignAAPCS(ValNo, ValVT, LocVT, LocInfo, State, false))
11027fd307bSReid Kleckner     return false;
11127fd307bSReid Kleckner   return true;  // we handled it
11227fd307bSReid Kleckner }
11327fd307bSReid Kleckner 
f64RetAssign(unsigned ValNo,MVT ValVT,MVT LocVT,CCValAssign::LocInfo LocInfo,CCState & State)11473c3137aSOliver Stannard static bool f64RetAssign(unsigned ValNo, MVT ValVT, MVT LocVT,
11573c3137aSOliver Stannard                          CCValAssign::LocInfo LocInfo, CCState &State) {
11627fd307bSReid Kleckner   static const MCPhysReg HiRegList[] = { ARM::R0, ARM::R2 };
11727fd307bSReid Kleckner   static const MCPhysReg LoRegList[] = { ARM::R1, ARM::R3 };
11827fd307bSReid Kleckner 
11927fd307bSReid Kleckner   unsigned Reg = State.AllocateReg(HiRegList, LoRegList);
12027fd307bSReid Kleckner   if (Reg == 0)
12127fd307bSReid Kleckner     return false; // we didn't handle it
12227fd307bSReid Kleckner 
12327fd307bSReid Kleckner   unsigned i;
12427fd307bSReid Kleckner   for (i = 0; i < 2; ++i)
12527fd307bSReid Kleckner     if (HiRegList[i] == Reg)
12627fd307bSReid Kleckner       break;
12727fd307bSReid Kleckner 
12827fd307bSReid Kleckner   State.addLoc(CCValAssign::getCustomReg(ValNo, ValVT, Reg, LocVT, LocInfo));
12927fd307bSReid Kleckner   State.addLoc(CCValAssign::getCustomReg(ValNo, ValVT, LoRegList[i],
13027fd307bSReid Kleckner                                          LocVT, LocInfo));
13127fd307bSReid Kleckner   return true;
13227fd307bSReid Kleckner }
13327fd307bSReid Kleckner 
RetCC_ARM_APCS_Custom_f64(unsigned ValNo,MVT ValVT,MVT LocVT,CCValAssign::LocInfo LocInfo,ISD::ArgFlagsTy ArgFlags,CCState & State)13473c3137aSOliver Stannard static bool RetCC_ARM_APCS_Custom_f64(unsigned ValNo, MVT ValVT, MVT LocVT,
13573c3137aSOliver Stannard                                       CCValAssign::LocInfo LocInfo,
13673c3137aSOliver Stannard                                       ISD::ArgFlagsTy ArgFlags,
13727fd307bSReid Kleckner                                       CCState &State) {
13827fd307bSReid Kleckner   if (!f64RetAssign(ValNo, ValVT, LocVT, LocInfo, State))
13927fd307bSReid Kleckner     return false;
14027fd307bSReid Kleckner   if (LocVT == MVT::v2f64 && !f64RetAssign(ValNo, ValVT, LocVT, LocInfo, State))
14127fd307bSReid Kleckner     return false;
14227fd307bSReid Kleckner   return true;  // we handled it
14327fd307bSReid Kleckner }
14427fd307bSReid Kleckner 
RetCC_ARM_AAPCS_Custom_f64(unsigned ValNo,MVT ValVT,MVT LocVT,CCValAssign::LocInfo LocInfo,ISD::ArgFlagsTy ArgFlags,CCState & State)14573c3137aSOliver Stannard static bool RetCC_ARM_AAPCS_Custom_f64(unsigned ValNo, MVT ValVT, MVT LocVT,
14673c3137aSOliver Stannard                                        CCValAssign::LocInfo LocInfo,
14773c3137aSOliver Stannard                                        ISD::ArgFlagsTy ArgFlags,
14827fd307bSReid Kleckner                                        CCState &State) {
14927fd307bSReid Kleckner   return RetCC_ARM_APCS_Custom_f64(ValNo, ValVT, LocVT, LocInfo, ArgFlags,
15027fd307bSReid Kleckner                                    State);
15127fd307bSReid Kleckner }
15227fd307bSReid Kleckner 
15327fd307bSReid Kleckner static const MCPhysReg RRegList[] = { ARM::R0,  ARM::R1,  ARM::R2,  ARM::R3 };
15427fd307bSReid Kleckner 
15527fd307bSReid Kleckner static const MCPhysReg SRegList[] = { ARM::S0,  ARM::S1,  ARM::S2,  ARM::S3,
15627fd307bSReid Kleckner                                       ARM::S4,  ARM::S5,  ARM::S6,  ARM::S7,
15727fd307bSReid Kleckner                                       ARM::S8,  ARM::S9,  ARM::S10, ARM::S11,
15827fd307bSReid Kleckner                                       ARM::S12, ARM::S13, ARM::S14,  ARM::S15 };
15927fd307bSReid Kleckner static const MCPhysReg DRegList[] = { ARM::D0, ARM::D1, ARM::D2, ARM::D3,
16027fd307bSReid Kleckner                                       ARM::D4, ARM::D5, ARM::D6, ARM::D7 };
16127fd307bSReid Kleckner static const MCPhysReg QRegList[] = { ARM::Q0, ARM::Q1, ARM::Q2, ARM::Q3 };
16227fd307bSReid Kleckner 
16327fd307bSReid Kleckner 
16427fd307bSReid Kleckner // Allocate part of an AAPCS HFA or HVA. We assume that each member of the HA
16527fd307bSReid Kleckner // has InConsecutiveRegs set, and that the last member also has
16627fd307bSReid Kleckner // InConsecutiveRegsLast set. We must process all members of the HA before
16727fd307bSReid Kleckner // we can allocate it, as we need to know the total number of registers that
16827fd307bSReid Kleckner // will be needed in order to (attempt to) allocate a contiguous block.
CC_ARM_AAPCS_Custom_Aggregate(unsigned ValNo,MVT ValVT,MVT LocVT,CCValAssign::LocInfo LocInfo,ISD::ArgFlagsTy ArgFlags,CCState & State)16973c3137aSOliver Stannard static bool CC_ARM_AAPCS_Custom_Aggregate(unsigned ValNo, MVT ValVT,
17073c3137aSOliver Stannard                                           MVT LocVT,
17173c3137aSOliver Stannard                                           CCValAssign::LocInfo LocInfo,
17273c3137aSOliver Stannard                                           ISD::ArgFlagsTy ArgFlags,
17327fd307bSReid Kleckner                                           CCState &State) {
17427fd307bSReid Kleckner   SmallVectorImpl<CCValAssign> &PendingMembers = State.getPendingLocs();
17527fd307bSReid Kleckner 
17627fd307bSReid Kleckner   // AAPCS HFAs must have 1-4 elements, all of the same type
17727fd307bSReid Kleckner   if (PendingMembers.size() > 0)
17827fd307bSReid Kleckner     assert(PendingMembers[0].getLocVT() == LocVT);
17927fd307bSReid Kleckner 
18027fd307bSReid Kleckner   // Add the argument to the list to be allocated once we know the size of the
181d68904f9SJames Henderson   // aggregate. Store the type's required alignment as extra info for later: in
18227fd307bSReid Kleckner   // the [N x i64] case all trace has been removed by the time we actually get
18327fd307bSReid Kleckner   // to do allocation.
1842e7bba69SGuillaume Chatelet   PendingMembers.push_back(CCValAssign::getPending(
1852e7bba69SGuillaume Chatelet       ValNo, ValVT, LocVT, LocInfo, ArgFlags.getNonZeroOrigAlign().value()));
18627fd307bSReid Kleckner 
18727fd307bSReid Kleckner   if (!ArgFlags.isInConsecutiveRegsLast())
18827fd307bSReid Kleckner     return true;
18927fd307bSReid Kleckner 
19027fd307bSReid Kleckner   // Try to allocate a contiguous block of registers, each of the correct
19127fd307bSReid Kleckner   // size to hold one member.
19227fd307bSReid Kleckner   auto &DL = State.getMachineFunction().getDataLayout();
193be4f5061SGuillaume Chatelet   const Align StackAlign = DL.getStackAlignment();
194be4f5061SGuillaume Chatelet   const Align FirstMemberAlign(PendingMembers[0].getExtraInfo());
195be4f5061SGuillaume Chatelet   Align Alignment = std::min(FirstMemberAlign, StackAlign);
19627fd307bSReid Kleckner 
19727fd307bSReid Kleckner   ArrayRef<MCPhysReg> RegList;
19827fd307bSReid Kleckner   switch (LocVT.SimpleTy) {
19927fd307bSReid Kleckner   case MVT::i32: {
20027fd307bSReid Kleckner     RegList = RRegList;
20127fd307bSReid Kleckner     unsigned RegIdx = State.getFirstUnallocated(RegList);
20227fd307bSReid Kleckner 
20327fd307bSReid Kleckner     // First consume all registers that would give an unaligned object. Whether
20427fd307bSReid Kleckner     // we go on stack or in regs, no-one will be using them in future.
205be4f5061SGuillaume Chatelet     unsigned RegAlign = alignTo(Alignment.value(), 4) / 4;
20627fd307bSReid Kleckner     while (RegIdx % RegAlign != 0 && RegIdx < RegList.size())
20727fd307bSReid Kleckner       State.AllocateReg(RegList[RegIdx++]);
20827fd307bSReid Kleckner 
20927fd307bSReid Kleckner     break;
21027fd307bSReid Kleckner   }
21127fd307bSReid Kleckner   case MVT::f16:
212ecdf48f1SAlexandros Lamprineas   case MVT::bf16:
21327fd307bSReid Kleckner   case MVT::f32:
21427fd307bSReid Kleckner     RegList = SRegList;
21527fd307bSReid Kleckner     break;
21627fd307bSReid Kleckner   case MVT::v4f16:
217ecdf48f1SAlexandros Lamprineas   case MVT::v4bf16:
21827fd307bSReid Kleckner   case MVT::f64:
21927fd307bSReid Kleckner     RegList = DRegList;
22027fd307bSReid Kleckner     break;
22127fd307bSReid Kleckner   case MVT::v8f16:
222ecdf48f1SAlexandros Lamprineas   case MVT::v8bf16:
22327fd307bSReid Kleckner   case MVT::v2f64:
22427fd307bSReid Kleckner     RegList = QRegList;
22527fd307bSReid Kleckner     break;
22627fd307bSReid Kleckner   default:
22727fd307bSReid Kleckner     llvm_unreachable("Unexpected member type for block aggregate");
22827fd307bSReid Kleckner     break;
22927fd307bSReid Kleckner   }
23027fd307bSReid Kleckner 
23127fd307bSReid Kleckner   unsigned RegResult = State.AllocateRegBlock(RegList, PendingMembers.size());
23227fd307bSReid Kleckner   if (RegResult) {
233*c5cf7d91SKazu Hirata     for (CCValAssign &PendingMember : PendingMembers) {
234*c5cf7d91SKazu Hirata       PendingMember.convertToReg(RegResult);
235*c5cf7d91SKazu Hirata       State.addLoc(PendingMember);
23627fd307bSReid Kleckner       ++RegResult;
23727fd307bSReid Kleckner     }
23827fd307bSReid Kleckner     PendingMembers.clear();
23927fd307bSReid Kleckner     return true;
24027fd307bSReid Kleckner   }
24127fd307bSReid Kleckner 
24227fd307bSReid Kleckner   // Register allocation failed, we'll be needing the stack
24327fd307bSReid Kleckner   unsigned Size = LocVT.getSizeInBits() / 8;
24427fd307bSReid Kleckner   if (LocVT == MVT::i32 && State.getNextStackOffset() == 0) {
24527fd307bSReid Kleckner     // If nothing else has used the stack until this point, a non-HFA aggregate
24627fd307bSReid Kleckner     // can be split between regs and stack.
24727fd307bSReid Kleckner     unsigned RegIdx = State.getFirstUnallocated(RegList);
24827fd307bSReid Kleckner     for (auto &It : PendingMembers) {
24927fd307bSReid Kleckner       if (RegIdx >= RegList.size())
250be4f5061SGuillaume Chatelet         It.convertToMem(State.AllocateStack(Size, Align(Size)));
25127fd307bSReid Kleckner       else
25227fd307bSReid Kleckner         It.convertToReg(State.AllocateReg(RegList[RegIdx++]));
25327fd307bSReid Kleckner 
25427fd307bSReid Kleckner       State.addLoc(It);
25527fd307bSReid Kleckner     }
25627fd307bSReid Kleckner     PendingMembers.clear();
25727fd307bSReid Kleckner     return true;
2585c7b43aaSMomchil Velikov   }
2595c7b43aaSMomchil Velikov 
2605c7b43aaSMomchil Velikov   if (LocVT != MVT::i32)
26127fd307bSReid Kleckner     RegList = SRegList;
26227fd307bSReid Kleckner 
26327fd307bSReid Kleckner   // Mark all regs as unavailable (AAPCS rule C.2.vfp for VFP, C.6 for core)
26427fd307bSReid Kleckner   for (auto Reg : RegList)
26527fd307bSReid Kleckner     State.AllocateReg(Reg);
26627fd307bSReid Kleckner 
2675c7b43aaSMomchil Velikov   // Clamp the alignment between 4 and 8.
2685c7b43aaSMomchil Velikov   if (State.getMachineFunction().getSubtarget<ARMSubtarget>().isTargetAEABI())
2695c7b43aaSMomchil Velikov     Alignment = ArgFlags.getNonZeroMemAlign() <= 4 ? Align(4) : Align(8);
2705c7b43aaSMomchil Velikov 
27127fd307bSReid Kleckner   // After the first item has been allocated, the rest are packed as tightly as
27227fd307bSReid Kleckner   // possible. (E.g. an incoming i64 would have starting Align of 8, but we'll
27327fd307bSReid Kleckner   // be allocating a bunch of i32 slots).
27427fd307bSReid Kleckner   for (auto &It : PendingMembers) {
275be4f5061SGuillaume Chatelet     It.convertToMem(State.AllocateStack(Size, Alignment));
27627fd307bSReid Kleckner     State.addLoc(It);
2775c7b43aaSMomchil Velikov     Alignment = Align(1);
27827fd307bSReid Kleckner   }
27927fd307bSReid Kleckner 
28027fd307bSReid Kleckner   // All pending members have now been allocated
28127fd307bSReid Kleckner   PendingMembers.clear();
28227fd307bSReid Kleckner 
28327fd307bSReid Kleckner   // This will be allocated by the last member of the aggregate
28427fd307bSReid Kleckner   return true;
28527fd307bSReid Kleckner }
28627fd307bSReid Kleckner 
CustomAssignInRegList(unsigned ValNo,MVT ValVT,MVT LocVT,CCValAssign::LocInfo LocInfo,CCState & State,ArrayRef<MCPhysReg> RegList)287a255931cSLucas Prates static bool CustomAssignInRegList(unsigned ValNo, MVT ValVT, MVT LocVT,
288a255931cSLucas Prates                                   CCValAssign::LocInfo LocInfo, CCState &State,
289a255931cSLucas Prates                                   ArrayRef<MCPhysReg> RegList) {
290a255931cSLucas Prates   unsigned Reg = State.AllocateReg(RegList);
291a255931cSLucas Prates   if (Reg) {
292a255931cSLucas Prates     State.addLoc(CCValAssign::getCustomReg(ValNo, ValVT, Reg, LocVT, LocInfo));
293a255931cSLucas Prates     return true;
294a255931cSLucas Prates   }
295a255931cSLucas Prates   return false;
296a255931cSLucas Prates }
297a255931cSLucas Prates 
CC_ARM_AAPCS_Custom_f16(unsigned ValNo,MVT ValVT,MVT LocVT,CCValAssign::LocInfo LocInfo,ISD::ArgFlagsTy ArgFlags,CCState & State)298a255931cSLucas Prates static bool CC_ARM_AAPCS_Custom_f16(unsigned ValNo, MVT ValVT, MVT LocVT,
299a255931cSLucas Prates                                     CCValAssign::LocInfo LocInfo,
300a255931cSLucas Prates                                     ISD::ArgFlagsTy ArgFlags, CCState &State) {
301a255931cSLucas Prates   // f16 arguments are extended to i32 and assigned to a register in [r0, r3]
302a255931cSLucas Prates   return CustomAssignInRegList(ValNo, ValVT, MVT::i32, LocInfo, State,
303a255931cSLucas Prates                                RRegList);
304a255931cSLucas Prates }
305a255931cSLucas Prates 
CC_ARM_AAPCS_VFP_Custom_f16(unsigned ValNo,MVT ValVT,MVT LocVT,CCValAssign::LocInfo LocInfo,ISD::ArgFlagsTy ArgFlags,CCState & State)306a255931cSLucas Prates static bool CC_ARM_AAPCS_VFP_Custom_f16(unsigned ValNo, MVT ValVT, MVT LocVT,
307a255931cSLucas Prates                                         CCValAssign::LocInfo LocInfo,
308a255931cSLucas Prates                                         ISD::ArgFlagsTy ArgFlags,
309a255931cSLucas Prates                                         CCState &State) {
310a255931cSLucas Prates   // f16 arguments are extended to f32 and assigned to a register in [s0, s15]
311a255931cSLucas Prates   return CustomAssignInRegList(ValNo, ValVT, MVT::f32, LocInfo, State,
312a255931cSLucas Prates                                SRegList);
313a255931cSLucas Prates }
314a255931cSLucas Prates 
31527fd307bSReid Kleckner // Include the table generated calling convention implementations.
31627fd307bSReid Kleckner #include "ARMGenCallingConv.inc"
317