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