Line data Source code
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 8103 : InlineAsm::InlineAsm(FunctionType *FTy, const std::string &asmString,
32 : const std::string &constraints, bool hasSideEffects,
33 8103 : bool isAlignStack, AsmDialect asmDialect)
34 : : Value(PointerType::getUnqual(FTy), Value::InlineAsmVal),
35 : AsmString(asmString), Constraints(constraints), FTy(FTy),
36 : HasSideEffects(hasSideEffects), IsAlignStack(isAlignStack),
37 8103 : Dialect(asmDialect) {
38 : // Do various checks on the constraint string and type.
39 : assert(Verify(getFunctionType(), constraints) &&
40 : "Function type not legal for constraints!");
41 8103 : }
42 :
43 19488 : InlineAsm *InlineAsm::get(FunctionType *FTy, StringRef AsmString,
44 : StringRef Constraints, bool hasSideEffects,
45 : bool isAlignStack, AsmDialect asmDialect) {
46 : InlineAsmKeyType Key(AsmString, Constraints, FTy, hasSideEffects,
47 : isAlignStack, asmDialect);
48 19488 : LLVMContextImpl *pImpl = FTy->getContext().pImpl;
49 19488 : return pImpl->InlineAsms.getOrCreate(PointerType::getUnqual(FTy), Key);
50 : }
51 :
52 0 : void InlineAsm::destroyConstant() {
53 0 : getType()->getContext().pImpl->InlineAsms.remove(this);
54 0 : delete this;
55 0 : }
56 :
57 14238 : FunctionType *InlineAsm::getFunctionType() const {
58 14238 : return FTy;
59 : }
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 270926 : bool InlineAsm::ConstraintInfo::Parse(StringRef Str,
65 : InlineAsm::ConstraintInfoVector &ConstraintsSoFar) {
66 : StringRef::iterator I = Str.begin(), E = Str.end();
67 270926 : unsigned multipleAlternativeCount = Str.count('|') + 1;
68 : unsigned multipleAlternativeIndex = 0;
69 270926 : ConstraintCodeVector *pCodes = &Codes;
70 :
71 : // Initialize
72 270926 : isMultipleAlternative = multipleAlternativeCount > 1;
73 270926 : if (isMultipleAlternative) {
74 1201 : multipleAlternatives.resize(multipleAlternativeCount);
75 1201 : pCodes = &multipleAlternatives[0].Codes;
76 : }
77 270926 : Type = isInput;
78 270926 : isEarlyClobber = false;
79 270926 : MatchingInput = -1;
80 270926 : isCommutative = false;
81 270926 : isIndirect = false;
82 270926 : currentAlternativeIndex = 0;
83 :
84 : // Parse prefixes.
85 270926 : if (*I == '~') {
86 209201 : Type = isClobber;
87 209201 : ++I;
88 :
89 : // '{' must immediately follow '~'.
90 209201 : if (I != E && *I != '{')
91 : return true;
92 61725 : } else if (*I == '=') {
93 17190 : ++I;
94 17190 : Type = isOutput;
95 : }
96 :
97 270925 : if (*I == '*') {
98 12378 : isIndirect = true;
99 12378 : ++I;
100 : }
101 :
102 270925 : if (I == E) return true; // Just a prefix, like "==" or "~".
103 :
104 : // Parse the modifiers.
105 : bool DoneWithModifiers = false;
106 542862 : while (!DoneWithModifiers) {
107 271937 : switch (*I) {
108 : default:
109 : DoneWithModifiers = true;
110 : break;
111 1003 : case '&': // Early clobber.
112 1003 : if (Type != isOutput || // Cannot early clobber anything but output.
113 1003 : isEarlyClobber) // Reject &&&&&&
114 : return true;
115 1003 : isEarlyClobber = true;
116 1003 : break;
117 9 : case '%': // Commutative.
118 9 : if (Type == isClobber || // Cannot commute clobbers.
119 9 : isCommutative) // Reject %%%%%
120 : return true;
121 9 : isCommutative = true;
122 9 : break;
123 : case '#': // Comment.
124 : case '*': // Register preferencing.
125 : return true; // Not supported.
126 : }
127 :
128 : if (!DoneWithModifiers) {
129 1012 : ++I;
130 1012 : if (I == E) return true; // Just prefixes and modifiers!
131 : }
132 : }
133 :
134 : // Parse the various constraints.
135 681177 : while (I != E) {
136 410253 : if (*I == '{') { // Physical register reference.
137 : // Find the end of the register name.
138 350175 : StringRef::iterator ConstraintEnd = std::find(I+1, E, '}');
139 350175 : if (ConstraintEnd == E) return true; // "{foo"
140 700350 : pCodes->push_back(StringRef(I, ConstraintEnd+1 - I));
141 : I = ConstraintEnd+1;
142 60078 : } else if (isdigit(static_cast<unsigned char>(*I))) { // Matching Constraint
143 : // Maximal munch numbers.
144 : StringRef::iterator NumStart = I;
145 3234 : while (I != E && isdigit(static_cast<unsigned char>(*I)))
146 1749 : ++I;
147 1485 : pCodes->push_back(StringRef(NumStart, I - NumStart));
148 : unsigned N = atoi(pCodes->back().c_str());
149 : // Check that this is a valid matching constraint!
150 2970 : if (N >= ConstraintsSoFar.size() || ConstraintsSoFar[N].Type != isOutput||
151 1485 : Type != isInput)
152 : return true; // Invalid constraint number.
153 :
154 : // If Operand N already has a matching input, reject this. An output
155 : // can't be constrained to the same value as multiple inputs.
156 1485 : if (isMultipleAlternative) {
157 1 : if (multipleAlternativeIndex >=
158 1 : ConstraintsSoFar[N].multipleAlternatives.size())
159 : return true;
160 : InlineAsm::SubConstraintInfo &scInfo =
161 : ConstraintsSoFar[N].multipleAlternatives[multipleAlternativeIndex];
162 0 : if (scInfo.MatchingInput != -1)
163 : return true;
164 : // Note that operand #n has a matching input.
165 0 : scInfo.MatchingInput = ConstraintsSoFar.size();
166 : assert(scInfo.MatchingInput >= 0);
167 : } else {
168 1484 : if (ConstraintsSoFar[N].hasMatchingInput() &&
169 4 : (size_t)ConstraintsSoFar[N].MatchingInput !=
170 : ConstraintsSoFar.size())
171 : return true;
172 : // Note that operand #n has a matching input.
173 1484 : ConstraintsSoFar[N].MatchingInput = ConstraintsSoFar.size();
174 : assert(ConstraintsSoFar[N].MatchingInput >= 0);
175 : }
176 58593 : } else if (*I == '|') {
177 1341 : multipleAlternativeIndex++;
178 1341 : pCodes = &multipleAlternatives[multipleAlternativeIndex].Codes;
179 1341 : ++I;
180 57252 : } else if (*I == '^') {
181 : // Multi-letter constraint
182 : // FIXME: For now assuming these are 2-character constraints.
183 432 : pCodes->push_back(StringRef(I+1, 2));
184 432 : I += 3;
185 : } else {
186 : // Single letter constraint.
187 56820 : pCodes->push_back(StringRef(I, 1));
188 56820 : ++I;
189 : }
190 : }
191 :
192 : return false;
193 : }
194 :
195 : /// selectAlternative - Point this constraint to the alternative constraint
196 : /// indicated by the index.
197 1001 : void InlineAsm::ConstraintInfo::selectAlternative(unsigned index) {
198 2002 : if (index < multipleAlternatives.size()) {
199 923 : currentAlternativeIndex = index;
200 : InlineAsm::SubConstraintInfo &scInfo =
201 : multipleAlternatives[currentAlternativeIndex];
202 923 : MatchingInput = scInfo.MatchingInput;
203 923 : Codes = scInfo.Codes;
204 : }
205 1001 : }
206 :
207 : InlineAsm::ConstraintInfoVector
208 64746 : InlineAsm::ParseConstraints(StringRef Constraints) {
209 : ConstraintInfoVector Result;
210 :
211 : // Scan the constraints string.
212 : for (StringRef::iterator I = Constraints.begin(),
213 335670 : E = Constraints.end(); I != E; ) {
214 : ConstraintInfo Info;
215 :
216 : // Find the end of this constraint.
217 270926 : StringRef::iterator ConstraintEnd = std::find(I, E, ',');
218 :
219 541852 : if (ConstraintEnd == I || // Empty constraint like ",,"
220 541854 : Info.Parse(StringRef(I, ConstraintEnd-I), Result)) {
221 : Result.clear(); // Erroneous constraint?
222 : break;
223 : }
224 :
225 270924 : Result.push_back(Info);
226 :
227 : // ConstraintEnd may be either the next comma or the end of the string. In
228 : // the former case, we skip the comma.
229 : I = ConstraintEnd;
230 270924 : if (I != E) {
231 227853 : ++I;
232 227853 : if (I == E) {
233 : Result.clear();
234 : break;
235 : } // don't allow "xyz,"
236 : }
237 : }
238 :
239 64746 : return Result;
240 : }
241 :
242 : /// Verify - Verify that the specified constraint string is reasonable for the
243 : /// specified function type, and otherwise validate the constraint string.
244 16763 : bool InlineAsm::Verify(FunctionType *Ty, StringRef ConstStr) {
245 16763 : if (Ty->isVarArg()) return false;
246 :
247 33526 : ConstraintInfoVector Constraints = ParseConstraints(ConstStr);
248 :
249 : // Error parsing constraints.
250 16763 : if (Constraints.empty() && !ConstStr.empty()) return false;
251 :
252 : unsigned NumOutputs = 0, NumInputs = 0, NumClobbers = 0;
253 : unsigned NumIndirect = 0;
254 :
255 83881 : for (unsigned i = 0, e = Constraints.size(); i != e; ++i) {
256 134240 : switch (Constraints[i].Type) {
257 4321 : case InlineAsm::isOutput:
258 4321 : if ((NumInputs-NumIndirect) != 0 || NumClobbers != 0)
259 : return false; // outputs before inputs and clobbers.
260 4321 : if (!Constraints[i].isIndirect) {
261 4087 : ++NumOutputs;
262 4087 : break;
263 : }
264 234 : ++NumIndirect;
265 : LLVM_FALLTHROUGH; // We fall through for Indirect Outputs.
266 11387 : case InlineAsm::isInput:
267 11387 : if (NumClobbers) return false; // inputs before clobbers.
268 11387 : ++NumInputs;
269 11387 : break;
270 51646 : case InlineAsm::isClobber:
271 51646 : ++NumClobbers;
272 51646 : break;
273 : }
274 : }
275 :
276 16761 : switch (NumOutputs) {
277 13084 : case 0:
278 26168 : if (!Ty->getReturnType()->isVoidTy()) return false;
279 : break;
280 3484 : case 1:
281 6968 : if (Ty->getReturnType()->isStructTy()) return false;
282 : break;
283 193 : default:
284 193 : StructType *STy = dyn_cast<StructType>(Ty->getReturnType());
285 193 : if (!STy || STy->getNumElements() != NumOutputs)
286 : return false;
287 : break;
288 : }
289 :
290 33522 : if (Ty->getNumParams() != NumInputs) return false;
291 : return true;
292 : }
|