ARMCallingConv.h revision 218893
1//===-- ARMCallingConv.h - ARM Custom Calling Convention Routines ---------===//
2//
3//                     The LLVM Compiler Infrastructure
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9//
10// This file contains the custom routines for the ARM Calling Convention that
11// aren't done by tablegen.
12//
13//===----------------------------------------------------------------------===//
14
15#ifndef ARMCALLINGCONV_H
16#define ARMCALLINGCONV_H
17
18#include "llvm/CallingConv.h"
19#include "llvm/CodeGen/CallingConvLower.h"
20#include "llvm/Target/TargetInstrInfo.h"
21#include "ARMBaseInstrInfo.h"
22#include "ARMRegisterInfo.h"
23#include "ARMSubtarget.h"
24#include "ARM.h"
25
26namespace llvm {
27
28// APCS f64 is in register pairs, possibly split to stack
29static bool f64AssignAPCS(unsigned &ValNo, MVT &ValVT, MVT &LocVT,
30                          CCValAssign::LocInfo &LocInfo,
31                          CCState &State, bool CanFail) {
32  static const unsigned RegList[] = { ARM::R0, ARM::R1, ARM::R2, ARM::R3 };
33
34  // Try to get the first register.
35  if (unsigned Reg = State.AllocateReg(RegList, 4))
36    State.addLoc(CCValAssign::getCustomReg(ValNo, ValVT, Reg, LocVT, LocInfo));
37  else {
38    // For the 2nd half of a v2f64, do not fail.
39    if (CanFail)
40      return false;
41
42    // Put the whole thing on the stack.
43    State.addLoc(CCValAssign::getCustomMem(ValNo, ValVT,
44                                           State.AllocateStack(8, 4),
45                                           LocVT, LocInfo));
46    return true;
47  }
48
49  // Try to get the second register.
50  if (unsigned Reg = State.AllocateReg(RegList, 4))
51    State.addLoc(CCValAssign::getCustomReg(ValNo, ValVT, Reg, LocVT, LocInfo));
52  else
53    State.addLoc(CCValAssign::getCustomMem(ValNo, ValVT,
54                                           State.AllocateStack(4, 4),
55                                           LocVT, LocInfo));
56  return true;
57}
58
59static bool CC_ARM_APCS_Custom_f64(unsigned &ValNo, MVT &ValVT, MVT &LocVT,
60                                   CCValAssign::LocInfo &LocInfo,
61                                   ISD::ArgFlagsTy &ArgFlags,
62                                   CCState &State) {
63  if (!f64AssignAPCS(ValNo, ValVT, LocVT, LocInfo, State, true))
64    return false;
65  if (LocVT == MVT::v2f64 &&
66      !f64AssignAPCS(ValNo, ValVT, LocVT, LocInfo, State, false))
67    return false;
68  return true;  // we handled it
69}
70
71// AAPCS f64 is in aligned register pairs
72static bool f64AssignAAPCS(unsigned &ValNo, MVT &ValVT, MVT &LocVT,
73                           CCValAssign::LocInfo &LocInfo,
74                           CCState &State, bool CanFail) {
75  static const unsigned HiRegList[] = { ARM::R0, ARM::R2 };
76  static const unsigned LoRegList[] = { ARM::R1, ARM::R3 };
77  static const unsigned ShadowRegList[] = { ARM::R0, ARM::R1 };
78
79  unsigned Reg = State.AllocateReg(HiRegList, ShadowRegList, 2);
80  if (Reg == 0) {
81    // For the 2nd half of a v2f64, do not just fail.
82    if (CanFail)
83      return false;
84
85    // Put the whole thing on the stack.
86    State.addLoc(CCValAssign::getCustomMem(ValNo, ValVT,
87                                           State.AllocateStack(8, 8),
88                                           LocVT, LocInfo));
89    return true;
90  }
91
92  unsigned i;
93  for (i = 0; i < 2; ++i)
94    if (HiRegList[i] == Reg)
95      break;
96
97  unsigned T = State.AllocateReg(LoRegList[i]);
98  (void)T;
99  assert(T == LoRegList[i] && "Could not allocate register");
100
101  State.addLoc(CCValAssign::getCustomReg(ValNo, ValVT, Reg, LocVT, LocInfo));
102  State.addLoc(CCValAssign::getCustomReg(ValNo, ValVT, LoRegList[i],
103                                         LocVT, LocInfo));
104  return true;
105}
106
107static bool CC_ARM_AAPCS_Custom_f64(unsigned &ValNo, MVT &ValVT, MVT &LocVT,
108                                    CCValAssign::LocInfo &LocInfo,
109                                    ISD::ArgFlagsTy &ArgFlags,
110                                    CCState &State) {
111  if (!f64AssignAAPCS(ValNo, ValVT, LocVT, LocInfo, State, true))
112    return false;
113  if (LocVT == MVT::v2f64 &&
114      !f64AssignAAPCS(ValNo, ValVT, LocVT, LocInfo, State, false))
115    return false;
116  return true;  // we handled it
117}
118
119static bool f64RetAssign(unsigned &ValNo, MVT &ValVT, MVT &LocVT,
120                         CCValAssign::LocInfo &LocInfo, CCState &State) {
121  static const unsigned HiRegList[] = { ARM::R0, ARM::R2 };
122  static const unsigned LoRegList[] = { ARM::R1, ARM::R3 };
123
124  unsigned Reg = State.AllocateReg(HiRegList, LoRegList, 2);
125  if (Reg == 0)
126    return false; // we didn't handle it
127
128  unsigned i;
129  for (i = 0; i < 2; ++i)
130    if (HiRegList[i] == Reg)
131      break;
132
133  State.addLoc(CCValAssign::getCustomReg(ValNo, ValVT, Reg, LocVT, LocInfo));
134  State.addLoc(CCValAssign::getCustomReg(ValNo, ValVT, LoRegList[i],
135                                         LocVT, LocInfo));
136  return true;
137}
138
139static bool RetCC_ARM_APCS_Custom_f64(unsigned &ValNo, MVT &ValVT, MVT &LocVT,
140                                      CCValAssign::LocInfo &LocInfo,
141                                      ISD::ArgFlagsTy &ArgFlags,
142                                      CCState &State) {
143  if (!f64RetAssign(ValNo, ValVT, LocVT, LocInfo, State))
144    return false;
145  if (LocVT == MVT::v2f64 && !f64RetAssign(ValNo, ValVT, LocVT, LocInfo, State))
146    return false;
147  return true;  // we handled it
148}
149
150static bool RetCC_ARM_AAPCS_Custom_f64(unsigned &ValNo, MVT &ValVT, MVT &LocVT,
151                                       CCValAssign::LocInfo &LocInfo,
152                                       ISD::ArgFlagsTy &ArgFlags,
153                                       CCState &State) {
154  return RetCC_ARM_APCS_Custom_f64(ValNo, ValVT, LocVT, LocInfo, ArgFlags,
155                                   State);
156}
157
158} // End llvm namespace
159
160#endif
161