/Users/buildslave/jenkins/sharedspace/clang-stage2-coverage-R@2/llvm/lib/IR/InlineAsm.cpp
Line | Count | Source (jump to first uncovered line) |
1 | | //===- InlineAsm.cpp - Implement the InlineAsm class ----------------------===// |
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 implements the InlineAsm class. |
11 | | // |
12 | | //===----------------------------------------------------------------------===// |
13 | | |
14 | | #include "llvm/IR/InlineAsm.h" |
15 | | #include "ConstantsContext.h" |
16 | | #include "LLVMContextImpl.h" |
17 | | #include "llvm/ADT/StringRef.h" |
18 | | #include "llvm/IR/DerivedTypes.h" |
19 | | #include "llvm/IR/LLVMContext.h" |
20 | | #include "llvm/IR/Value.h" |
21 | | #include "llvm/Support/Casting.h" |
22 | | #include "llvm/Support/Compiler.h" |
23 | | #include <algorithm> |
24 | | #include <cassert> |
25 | | #include <cctype> |
26 | | #include <cstddef> |
27 | | #include <cstdlib> |
28 | | |
29 | | using namespace llvm; |
30 | | |
31 | | InlineAsm::InlineAsm(FunctionType *FTy, const std::string &asmString, |
32 | | const std::string &constraints, bool hasSideEffects, |
33 | | bool isAlignStack, AsmDialect asmDialect) |
34 | | : Value(PointerType::getUnqual(FTy), Value::InlineAsmVal), |
35 | | AsmString(asmString), Constraints(constraints), FTy(FTy), |
36 | | HasSideEffects(hasSideEffects), IsAlignStack(isAlignStack), |
37 | 4.62k | Dialect(asmDialect) { |
38 | 4.62k | // Do various checks on the constraint string and type. |
39 | 4.62k | assert(Verify(getFunctionType(), constraints) && |
40 | 4.62k | "Function type not legal for constraints!"); |
41 | 4.62k | } |
42 | | |
43 | | InlineAsm *InlineAsm::get(FunctionType *FTy, StringRef AsmString, |
44 | | StringRef Constraints, bool hasSideEffects, |
45 | 12.8k | bool isAlignStack, AsmDialect asmDialect) { |
46 | 12.8k | InlineAsmKeyType Key(AsmString, Constraints, FTy, hasSideEffects, |
47 | 12.8k | isAlignStack, asmDialect); |
48 | 12.8k | LLVMContextImpl *pImpl = FTy->getContext().pImpl; |
49 | 12.8k | return pImpl->InlineAsms.getOrCreate(PointerType::getUnqual(FTy), Key); |
50 | 12.8k | } |
51 | | |
52 | 0 | void InlineAsm::destroyConstant() { |
53 | 0 | getType()->getContext().pImpl->InlineAsms.remove(this); |
54 | 0 | delete this; |
55 | 0 | } |
56 | | |
57 | 10.7k | FunctionType *InlineAsm::getFunctionType() const { |
58 | 10.7k | return FTy; |
59 | 10.7k | } |
60 | | |
61 | | /// Parse - Analyze the specified string (e.g. "==&{eax}") and fill in the |
62 | | /// fields in this structure. If the constraint string is not understood, |
63 | | /// return true, otherwise return false. |
64 | | bool InlineAsm::ConstraintInfo::Parse(StringRef Str, |
65 | 249k | InlineAsm::ConstraintInfoVector &ConstraintsSoFar) { |
66 | 249k | StringRef::iterator I = Str.begin(), E = Str.end(); |
67 | 249k | unsigned multipleAlternativeCount = Str.count('|') + 1; |
68 | 249k | unsigned multipleAlternativeIndex = 0; |
69 | 249k | ConstraintCodeVector *pCodes = &Codes; |
70 | 249k | |
71 | 249k | // Initialize |
72 | 249k | isMultipleAlternative = multipleAlternativeCount > 1; |
73 | 249k | if (isMultipleAlternative249k ) { |
74 | 1.10k | multipleAlternatives.resize(multipleAlternativeCount); |
75 | 1.10k | pCodes = &multipleAlternatives[0].Codes; |
76 | 1.10k | } |
77 | 249k | Type = isInput; |
78 | 249k | isEarlyClobber = false; |
79 | 249k | MatchingInput = -1; |
80 | 249k | isCommutative = false; |
81 | 249k | isIndirect = false; |
82 | 249k | currentAlternativeIndex = 0; |
83 | 249k | |
84 | 249k | // Parse prefixes. |
85 | 249k | if (*I == '~'249k ) { |
86 | 221k | Type = isClobber; |
87 | 221k | ++I; |
88 | 221k | |
89 | 221k | // '{' must immediately follow '~'. |
90 | 221k | if (I != E && 221k *I != '{'221k ) |
91 | 1 | return true; |
92 | 27.9k | } else if (27.9k *I == '='27.9k ) { |
93 | 15.5k | ++I; |
94 | 15.5k | Type = isOutput; |
95 | 15.5k | } |
96 | 249k | |
97 | 249k | if (249k *I == '*'249k ) { |
98 | 1.59k | isIndirect = true; |
99 | 1.59k | ++I; |
100 | 1.59k | } |
101 | 249k | |
102 | 249k | if (I == E249k ) return true0 ; // Just a prefix, like "==" or "~". |
103 | 249k | |
104 | 249k | // Parse the modifiers. |
105 | 249k | bool DoneWithModifiers = false; |
106 | 500k | while (!DoneWithModifiers500k ) { |
107 | 250k | switch (*I) { |
108 | 249k | default: |
109 | 249k | DoneWithModifiers = true; |
110 | 249k | break; |
111 | 797 | case '&': // Early clobber. |
112 | 797 | if (Type != isOutput || // Cannot early clobber anything but output. |
113 | 797 | isEarlyClobber) // Reject &&&&&& |
114 | 0 | return true; |
115 | 797 | isEarlyClobber = true; |
116 | 797 | break; |
117 | 9 | case '%': // Commutative. |
118 | 9 | if (Type == isClobber || // Cannot commute clobbers. |
119 | 9 | isCommutative) // Reject %%%%% |
120 | 0 | return true; |
121 | 9 | isCommutative = true; |
122 | 9 | break; |
123 | 0 | case '#': // Comment. |
124 | 0 | case '*': // Register preferencing. |
125 | 0 | return true; // Not supported. |
126 | 250k | } |
127 | 250k | |
128 | 250k | if (250k !DoneWithModifiers250k ) { |
129 | 806 | ++I; |
130 | 806 | if (I == E806 ) return true0 ; // Just prefixes and modifiers! |
131 | 806 | } |
132 | 250k | } |
133 | 249k | |
134 | 249k | // Parse the various constraints. |
135 | 638k | while (249k I != E638k ) { |
136 | 388k | if (*I == '{'388k ) { // Physical register reference. |
137 | 362k | // Find the end of the register name. |
138 | 362k | StringRef::iterator ConstraintEnd = std::find(I+1, E, '}'); |
139 | 362k | if (ConstraintEnd == E362k ) return true0 ; // "{foo" |
140 | 362k | pCodes->push_back(StringRef(I, ConstraintEnd+1 - I)); |
141 | 362k | I = ConstraintEnd+1; |
142 | 388k | } else if (25.8k isdigit(static_cast<unsigned char>(*I))25.8k ) { // Matching Constraint |
143 | 879 | // Maximal munch numbers. |
144 | 879 | StringRef::iterator NumStart = I; |
145 | 1.79k | while (I != E && 1.79k isdigit(static_cast<unsigned char>(*I))927 ) |
146 | 919 | ++I; |
147 | 879 | pCodes->push_back(StringRef(NumStart, I - NumStart)); |
148 | 879 | unsigned N = atoi(pCodes->back().c_str()); |
149 | 879 | // Check that this is a valid matching constraint! |
150 | 879 | if (N >= ConstraintsSoFar.size() || 879 ConstraintsSoFar[N].Type != isOutput879 || |
151 | 879 | Type != isInput) |
152 | 0 | return true; // Invalid constraint number. |
153 | 879 | |
154 | 879 | // If Operand N already has a matching input, reject this. An output |
155 | 879 | // can't be constrained to the same value as multiple inputs. |
156 | 879 | if (879 isMultipleAlternative879 ) { |
157 | 1 | if (multipleAlternativeIndex >= |
158 | 1 | ConstraintsSoFar[N].multipleAlternatives.size()) |
159 | 1 | return true; |
160 | 0 | InlineAsm::SubConstraintInfo &scInfo = |
161 | 0 | ConstraintsSoFar[N].multipleAlternatives[multipleAlternativeIndex]; |
162 | 0 | if (scInfo.MatchingInput != -1) |
163 | 0 | return true; |
164 | 0 | // Note that operand #n has a matching input. |
165 | 0 | scInfo.MatchingInput = ConstraintsSoFar.size(); |
166 | 879 | } else { |
167 | 878 | if (ConstraintsSoFar[N].hasMatchingInput() && |
168 | 4 | (size_t)ConstraintsSoFar[N].MatchingInput != |
169 | 4 | ConstraintsSoFar.size()) |
170 | 0 | return true; |
171 | 878 | // Note that operand #n has a matching input. |
172 | 878 | ConstraintsSoFar[N].MatchingInput = ConstraintsSoFar.size(); |
173 | 878 | } |
174 | 25.8k | } else if (25.0k *I == '|'25.0k ) { |
175 | 1.24k | multipleAlternativeIndex++; |
176 | 1.24k | pCodes = &multipleAlternatives[multipleAlternativeIndex].Codes; |
177 | 1.24k | ++I; |
178 | 25.0k | } else if (23.7k *I == '^'23.7k ) { |
179 | 396 | // Multi-letter constraint |
180 | 396 | // FIXME: For now assuming these are 2-character constraints. |
181 | 396 | pCodes->push_back(StringRef(I+1, 2)); |
182 | 396 | I += 3; |
183 | 23.7k | } else { |
184 | 23.3k | // Single letter constraint. |
185 | 23.3k | pCodes->push_back(StringRef(I, 1)); |
186 | 23.3k | ++I; |
187 | 23.3k | } |
188 | 388k | } |
189 | 249k | |
190 | 249k | return false; |
191 | 249k | } |
192 | | |
193 | | /// selectAlternative - Point this constraint to the alternative constraint |
194 | | /// indicated by the index. |
195 | 831 | void InlineAsm::ConstraintInfo::selectAlternative(unsigned index) { |
196 | 831 | if (index < multipleAlternatives.size()831 ) { |
197 | 831 | currentAlternativeIndex = index; |
198 | 831 | InlineAsm::SubConstraintInfo &scInfo = |
199 | 831 | multipleAlternatives[currentAlternativeIndex]; |
200 | 831 | MatchingInput = scInfo.MatchingInput; |
201 | 831 | Codes = scInfo.Codes; |
202 | 831 | } |
203 | 831 | } |
204 | | |
205 | | InlineAsm::ConstraintInfoVector |
206 | 42.7k | InlineAsm::ParseConstraints(StringRef Constraints) { |
207 | 42.7k | ConstraintInfoVector Result; |
208 | 42.7k | |
209 | 42.7k | // Scan the constraints string. |
210 | 42.7k | for (StringRef::iterator I = Constraints.begin(), |
211 | 292k | E = Constraints.end(); I != E292k ; ) { |
212 | 249k | ConstraintInfo Info; |
213 | 249k | |
214 | 249k | // Find the end of this constraint. |
215 | 249k | StringRef::iterator ConstraintEnd = std::find(I, E, ','); |
216 | 249k | |
217 | 249k | if (ConstraintEnd == I || // Empty constraint like ",," |
218 | 249k | Info.Parse(StringRef(I, ConstraintEnd-I), Result)249k ) { |
219 | 2 | Result.clear(); // Erroneous constraint? |
220 | 2 | break; |
221 | 2 | } |
222 | 249k | |
223 | 249k | Result.push_back(Info); |
224 | 249k | |
225 | 249k | // ConstraintEnd may be either the next comma or the end of the string. In |
226 | 249k | // the former case, we skip the comma. |
227 | 249k | I = ConstraintEnd; |
228 | 249k | if (I != E249k ) { |
229 | 208k | ++I; |
230 | 208k | if (I == E208k ) { |
231 | 0 | Result.clear(); |
232 | 0 | break; |
233 | 0 | } // don't allow "xyz," |
234 | 208k | } |
235 | 249k | } |
236 | 42.7k | |
237 | 42.7k | return Result; |
238 | 42.7k | } |
239 | | |
240 | | /// Verify - Verify that the specified constraint string is reasonable for the |
241 | | /// specified function type, and otherwise validate the constraint string. |
242 | 8.69k | bool InlineAsm::Verify(FunctionType *Ty, StringRef ConstStr) { |
243 | 8.69k | if (Ty->isVarArg()8.69k ) return false0 ; |
244 | 8.69k | |
245 | 8.69k | ConstraintInfoVector Constraints = ParseConstraints(ConstStr); |
246 | 8.69k | |
247 | 8.69k | // Error parsing constraints. |
248 | 8.69k | if (Constraints.empty() && 8.69k !ConstStr.empty()435 ) return false2 ; |
249 | 8.69k | |
250 | 8.69k | unsigned NumOutputs = 0, NumInputs = 0, NumClobbers = 0; |
251 | 8.69k | unsigned NumIndirect = 0; |
252 | 8.69k | |
253 | 62.9k | for (unsigned i = 0, e = Constraints.size(); i != e62.9k ; ++i54.3k ) { |
254 | 54.3k | switch (Constraints[i].Type) { |
255 | 3.69k | case InlineAsm::isOutput: |
256 | 3.69k | if ((NumInputs-NumIndirect) != 0 || 3.69k NumClobbers != 03.69k ) |
257 | 0 | return false; // outputs before inputs and clobbers. |
258 | 3.69k | if (3.69k !Constraints[i].isIndirect3.69k ) { |
259 | 3.47k | ++NumOutputs; |
260 | 3.47k | break; |
261 | 3.47k | } |
262 | 220 | ++NumIndirect; |
263 | 220 | LLVM_FALLTHROUGH; // We fall through for Indirect Outputs. |
264 | 3.23k | case InlineAsm::isInput: |
265 | 3.23k | if (NumClobbers3.23k ) return false0 ; // inputs before clobbers. |
266 | 3.23k | ++NumInputs; |
267 | 3.23k | break; |
268 | 47.5k | case InlineAsm::isClobber: |
269 | 47.5k | ++NumClobbers; |
270 | 47.5k | break; |
271 | 54.3k | } |
272 | 54.3k | } |
273 | 8.69k | |
274 | 8.69k | switch (NumOutputs) { |
275 | 5.47k | case 0: |
276 | 5.47k | if (!Ty->getReturnType()->isVoidTy()5.47k ) return false0 ; |
277 | 5.47k | break; |
278 | 3.12k | case 1: |
279 | 3.12k | if (Ty->getReturnType()->isStructTy()3.12k ) return false0 ; |
280 | 3.12k | break; |
281 | 100 | default: |
282 | 100 | StructType *STy = dyn_cast<StructType>(Ty->getReturnType()); |
283 | 100 | if (!STy || 100 STy->getNumElements() != NumOutputs100 ) |
284 | 0 | return false; |
285 | 100 | break; |
286 | 8.69k | } |
287 | 8.69k | |
288 | 8.69k | if (8.69k Ty->getNumParams() != NumInputs8.69k ) return false0 ; |
289 | 8.69k | return true; |
290 | 8.69k | } |