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