]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - contrib/llvm/lib/Target/X86/X86CallingConv.cpp
MFV 316897
[FreeBSD/FreeBSD.git] / contrib / llvm / lib / Target / X86 / X86CallingConv.cpp
1 //=== X86CallingConv.cpp - X86 Custom Calling Convention Impl   -*- C++ -*-===//\r
2 //\r
3 //                     The LLVM Compiler Infrastructure\r
4 //\r
5 // This file is distributed under the University of Illinois Open Source\r
6 // License. See LICENSE.TXT for details.\r
7 //\r
8 //===----------------------------------------------------------------------===//\r
9 //\r
10 // This file contains the implementation of custom routines for the X86\r
11 // Calling Convention that aren't done by tablegen.\r
12 //\r
13 //===----------------------------------------------------------------------===//\r
14 \r
15 #include "MCTargetDesc/X86MCTargetDesc.h"\r
16 #include "X86Subtarget.h"\r
17 #include "llvm/CodeGen/CallingConvLower.h"\r
18 #include "llvm/IR/CallingConv.h"\r
19 \r
20 namespace llvm {\r
21 \r
22 bool CC_X86_32_RegCall_Assign2Regs(unsigned &ValNo, MVT &ValVT, MVT &LocVT,\r
23                                    CCValAssign::LocInfo &LocInfo,\r
24                                    ISD::ArgFlagsTy &ArgFlags, CCState &State) {\r
25   // List of GPR registers that are available to store values in regcall\r
26   // calling convention.\r
27   static const MCPhysReg RegList[] = {X86::EAX, X86::ECX, X86::EDX, X86::EDI,\r
28                                       X86::ESI};\r
29 \r
30   // The vector will save all the available registers for allocation.\r
31   SmallVector<unsigned, 5> AvailableRegs;\r
32 \r
33   // searching for the available registers.\r
34   for (auto Reg : RegList) {\r
35     if (!State.isAllocated(Reg))\r
36       AvailableRegs.push_back(Reg);\r
37   }\r
38 \r
39   const size_t RequiredGprsUponSplit = 2;\r
40   if (AvailableRegs.size() < RequiredGprsUponSplit)\r
41     return false; // Not enough free registers - continue the search.\r
42 \r
43   // Allocating the available registers.\r
44   for (unsigned I = 0; I < RequiredGprsUponSplit; I++) {\r
45 \r
46     // Marking the register as located.\r
47     unsigned Reg = State.AllocateReg(AvailableRegs[I]);\r
48 \r
49     // Since we previously made sure that 2 registers are available\r
50     // we expect that a real register number will be returned.\r
51     assert(Reg && "Expecting a register will be available");\r
52 \r
53     // Assign the value to the allocated register\r
54     State.addLoc(CCValAssign::getCustomReg(ValNo, ValVT, Reg, LocVT, LocInfo));\r
55   }\r
56 \r
57   // Successful in allocating regsiters - stop scanning next rules.\r
58   return true;\r
59 }\r
60 \r
61 static ArrayRef<MCPhysReg> CC_X86_VectorCallGetSSEs(const MVT &ValVT) {\r
62   if (ValVT.is512BitVector()) {\r
63     static const MCPhysReg RegListZMM[] = {X86::ZMM0, X86::ZMM1, X86::ZMM2,\r
64                                            X86::ZMM3, X86::ZMM4, X86::ZMM5};\r
65     return makeArrayRef(std::begin(RegListZMM), std::end(RegListZMM));\r
66   }\r
67 \r
68   if (ValVT.is256BitVector()) {\r
69     static const MCPhysReg RegListYMM[] = {X86::YMM0, X86::YMM1, X86::YMM2,\r
70                                            X86::YMM3, X86::YMM4, X86::YMM5};\r
71     return makeArrayRef(std::begin(RegListYMM), std::end(RegListYMM));\r
72   }\r
73 \r
74   static const MCPhysReg RegListXMM[] = {X86::XMM0, X86::XMM1, X86::XMM2,\r
75                                          X86::XMM3, X86::XMM4, X86::XMM5};\r
76   return makeArrayRef(std::begin(RegListXMM), std::end(RegListXMM));\r
77 }\r
78 \r
79 static ArrayRef<MCPhysReg> CC_X86_64_VectorCallGetGPRs() {\r
80   static const MCPhysReg RegListGPR[] = {X86::RCX, X86::RDX, X86::R8, X86::R9};\r
81   return makeArrayRef(std::begin(RegListGPR), std::end(RegListGPR));\r
82 }\r
83 \r
84 static bool CC_X86_VectorCallAssignRegister(unsigned &ValNo, MVT &ValVT,\r
85                                             MVT &LocVT,\r
86                                             CCValAssign::LocInfo &LocInfo,\r
87                                             ISD::ArgFlagsTy &ArgFlags,\r
88                                             CCState &State) {\r
89 \r
90   ArrayRef<MCPhysReg> RegList = CC_X86_VectorCallGetSSEs(ValVT);\r
91   bool Is64bit = static_cast<const X86Subtarget &>(\r
92                      State.getMachineFunction().getSubtarget())\r
93                      .is64Bit();\r
94 \r
95   for (auto Reg : RegList) {\r
96     // If the register is not marked as allocated - assign to it.\r
97     if (!State.isAllocated(Reg)) {\r
98       unsigned AssigedReg = State.AllocateReg(Reg);\r
99       assert(AssigedReg == Reg && "Expecting a valid register allocation");\r
100       State.addLoc(\r
101           CCValAssign::getReg(ValNo, ValVT, AssigedReg, LocVT, LocInfo));\r
102       return true;\r
103     }\r
104     // If the register is marked as shadow allocated - assign to it.\r
105     if (Is64bit && State.IsShadowAllocatedReg(Reg)) {\r
106       State.addLoc(CCValAssign::getReg(ValNo, ValVT, Reg, LocVT, LocInfo));\r
107       return true;\r
108     }\r
109   }\r
110 \r
111   llvm_unreachable("Clang should ensure that hva marked vectors will have "\r
112                    "an available register.");\r
113   return false;\r
114 }\r
115 \r
116 bool CC_X86_64_VectorCall(unsigned &ValNo, MVT &ValVT, MVT &LocVT,\r
117                           CCValAssign::LocInfo &LocInfo,\r
118                           ISD::ArgFlagsTy &ArgFlags, CCState &State) {\r
119   // On the second pass, go through the HVAs only.\r
120   if (ArgFlags.isSecArgPass()) {\r
121     if (ArgFlags.isHva())\r
122       return CC_X86_VectorCallAssignRegister(ValNo, ValVT, LocVT, LocInfo,\r
123                                              ArgFlags, State);\r
124     return true;\r
125   }\r
126 \r
127   // Process only vector types as defined by vectorcall spec:\r
128   // "A vector type is either a floating-point type, for example,\r
129   //  a float or double, or an SIMD vector type, for example, __m128 or __m256".\r
130   if (!(ValVT.isFloatingPoint() ||\r
131         (ValVT.isVector() && ValVT.getSizeInBits() >= 128))) {\r
132     // If R9 was already assigned it means that we are after the fourth element\r
133     // and because this is not an HVA / Vector type, we need to allocate\r
134     // shadow XMM register.\r
135     if (State.isAllocated(X86::R9)) {\r
136       // Assign shadow XMM register.\r
137       (void)State.AllocateReg(CC_X86_VectorCallGetSSEs(ValVT));\r
138     }\r
139 \r
140     return false;\r
141   }\r
142 \r
143   if (!ArgFlags.isHva() || ArgFlags.isHvaStart()) {\r
144     // Assign shadow GPR register.\r
145     (void)State.AllocateReg(CC_X86_64_VectorCallGetGPRs());\r
146 \r
147     // Assign XMM register - (shadow for HVA and non-shadow for non HVA).\r
148     if (unsigned Reg = State.AllocateReg(CC_X86_VectorCallGetSSEs(ValVT))) {\r
149       // In Vectorcall Calling convention, additional shadow stack can be\r
150       // created on top of the basic 32 bytes of win64.\r
151       // It can happen if the fifth or sixth argument is vector type or HVA.\r
152       // At that case for each argument a shadow stack of 8 bytes is allocated.\r
153       if (Reg == X86::XMM4 || Reg == X86::XMM5)\r
154         State.AllocateStack(8, 8);\r
155 \r
156       if (!ArgFlags.isHva()) {\r
157         State.addLoc(CCValAssign::getReg(ValNo, ValVT, Reg, LocVT, LocInfo));\r
158         return true; // Allocated a register - Stop the search.\r
159       }\r
160     }\r
161   }\r
162 \r
163   // If this is an HVA - Stop the search,\r
164   // otherwise continue the search.\r
165   return ArgFlags.isHva();\r
166 }\r
167 \r
168 bool CC_X86_32_VectorCall(unsigned &ValNo, MVT &ValVT, MVT &LocVT,\r
169                           CCValAssign::LocInfo &LocInfo,\r
170                           ISD::ArgFlagsTy &ArgFlags, CCState &State) {\r
171   // On the second pass, go through the HVAs only.\r
172   if (ArgFlags.isSecArgPass()) {\r
173     if (ArgFlags.isHva())\r
174       return CC_X86_VectorCallAssignRegister(ValNo, ValVT, LocVT, LocInfo,\r
175                                              ArgFlags, State);\r
176     return true;\r
177   }\r
178 \r
179   // Process only vector types as defined by vectorcall spec:\r
180   // "A vector type is either a floating point type, for example,\r
181   //  a float or double, or an SIMD vector type, for example, __m128 or __m256".\r
182   if (!(ValVT.isFloatingPoint() ||\r
183         (ValVT.isVector() && ValVT.getSizeInBits() >= 128))) {\r
184     return false;\r
185   }\r
186 \r
187   if (ArgFlags.isHva())\r
188     return true; // If this is an HVA - Stop the search.\r
189 \r
190   // Assign XMM register.\r
191   if (unsigned Reg = State.AllocateReg(CC_X86_VectorCallGetSSEs(ValVT))) {\r
192     State.addLoc(CCValAssign::getReg(ValNo, ValVT, Reg, LocVT, LocInfo));\r
193     return true;\r
194   }\r
195 \r
196   // In case we did not find an available XMM register for a vector -\r
197   // pass it indirectly.\r
198   // It is similar to CCPassIndirect, with the addition of inreg.\r
199   if (!ValVT.isFloatingPoint()) {\r
200     LocVT = MVT::i32;\r
201     LocInfo = CCValAssign::Indirect;\r
202     ArgFlags.setInReg();\r
203   }\r
204 \r
205   return false; // No register was assigned - Continue the search.\r
206 }\r
207 \r
208 } // End llvm namespace\r