]> CyberLeo.Net >> Repos - FreeBSD/releng/10.0.git/blob - contrib/llvm/lib/Target/ARM/ARMCallingConv.h
- Copy stable/10 (r259064) to releng/10.0 as part of the
[FreeBSD/releng/10.0.git] / contrib / llvm / 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   static const uint16_t GPRArgRegs[] = { ARM::R0, ARM::R1, ARM::R2, ARM::R3 };
78
79   unsigned Reg = State.AllocateReg(HiRegList, ShadowRegList, 2);
80   if (Reg == 0) {
81
82     // If we had R3 unallocated only, now we still must to waste it.
83     Reg = State.AllocateReg(GPRArgRegs, 4);
84     assert((!Reg || Reg == ARM::R3) && "Wrong GPRs usage for f64");
85
86     // For the 2nd half of a v2f64, do not just fail.
87     if (CanFail)
88       return false;
89
90     // Put the whole thing on the stack.
91     State.addLoc(CCValAssign::getCustomMem(ValNo, ValVT,
92                                            State.AllocateStack(8, 8),
93                                            LocVT, LocInfo));
94     return true;
95   }
96
97   unsigned i;
98   for (i = 0; i < 2; ++i)
99     if (HiRegList[i] == Reg)
100       break;
101
102   unsigned T = State.AllocateReg(LoRegList[i]);
103   (void)T;
104   assert(T == LoRegList[i] && "Could not allocate register");
105
106   State.addLoc(CCValAssign::getCustomReg(ValNo, ValVT, Reg, LocVT, LocInfo));
107   State.addLoc(CCValAssign::getCustomReg(ValNo, ValVT, LoRegList[i],
108                                          LocVT, LocInfo));
109   return true;
110 }
111
112 static bool CC_ARM_AAPCS_Custom_f64(unsigned &ValNo, MVT &ValVT, MVT &LocVT,
113                                     CCValAssign::LocInfo &LocInfo,
114                                     ISD::ArgFlagsTy &ArgFlags,
115                                     CCState &State) {
116   if (!f64AssignAAPCS(ValNo, ValVT, LocVT, LocInfo, State, true))
117     return false;
118   if (LocVT == MVT::v2f64 &&
119       !f64AssignAAPCS(ValNo, ValVT, LocVT, LocInfo, State, false))
120     return false;
121   return true;  // we handled it
122 }
123
124 static bool f64RetAssign(unsigned &ValNo, MVT &ValVT, MVT &LocVT,
125                          CCValAssign::LocInfo &LocInfo, CCState &State) {
126   static const uint16_t HiRegList[] = { ARM::R0, ARM::R2 };
127   static const uint16_t LoRegList[] = { ARM::R1, ARM::R3 };
128
129   unsigned Reg = State.AllocateReg(HiRegList, LoRegList, 2);
130   if (Reg == 0)
131     return false; // we didn't handle it
132
133   unsigned i;
134   for (i = 0; i < 2; ++i)
135     if (HiRegList[i] == Reg)
136       break;
137
138   State.addLoc(CCValAssign::getCustomReg(ValNo, ValVT, Reg, LocVT, LocInfo));
139   State.addLoc(CCValAssign::getCustomReg(ValNo, ValVT, LoRegList[i],
140                                          LocVT, LocInfo));
141   return true;
142 }
143
144 static bool RetCC_ARM_APCS_Custom_f64(unsigned &ValNo, MVT &ValVT, MVT &LocVT,
145                                       CCValAssign::LocInfo &LocInfo,
146                                       ISD::ArgFlagsTy &ArgFlags,
147                                       CCState &State) {
148   if (!f64RetAssign(ValNo, ValVT, LocVT, LocInfo, State))
149     return false;
150   if (LocVT == MVT::v2f64 && !f64RetAssign(ValNo, ValVT, LocVT, LocInfo, State))
151     return false;
152   return true;  // we handled it
153 }
154
155 static bool RetCC_ARM_AAPCS_Custom_f64(unsigned &ValNo, MVT &ValVT, MVT &LocVT,
156                                        CCValAssign::LocInfo &LocInfo,
157                                        ISD::ArgFlagsTy &ArgFlags,
158                                        CCState &State) {
159   return RetCC_ARM_APCS_Custom_f64(ValNo, ValVT, LocVT, LocInfo, ArgFlags,
160                                    State);
161 }
162
163 } // End llvm namespace
164
165 #endif