LLVM  3.7.0
InlineAsm.cpp
Go to the documentation of this file.
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/IR/DerivedTypes.h"
18 #include <algorithm>
19 #include <cctype>
20 using namespace llvm;
21 
22 // Implement the first virtual method in this class in this file so the
23 // InlineAsm vtable is emitted here.
24 InlineAsm::~InlineAsm() {
25 }
26 
27 
29  StringRef Constraints, bool hasSideEffects,
30  bool isAlignStack, AsmDialect asmDialect) {
31  InlineAsmKeyType Key(AsmString, Constraints, hasSideEffects, isAlignStack,
32  asmDialect);
33  LLVMContextImpl *pImpl = Ty->getContext().pImpl;
34  return pImpl->InlineAsms.getOrCreate(PointerType::getUnqual(Ty), Key);
35 }
36 
37 InlineAsm::InlineAsm(PointerType *Ty, const std::string &asmString,
38  const std::string &constraints, bool hasSideEffects,
39  bool isAlignStack, AsmDialect asmDialect)
40  : Value(Ty, Value::InlineAsmVal),
41  AsmString(asmString), Constraints(constraints),
42  HasSideEffects(hasSideEffects), IsAlignStack(isAlignStack),
43  Dialect(asmDialect) {
44 
45  // Do various checks on the constraint string and type.
46  assert(Verify(getFunctionType(), constraints) &&
47  "Function type not legal for constraints!");
48 }
49 
50 void InlineAsm::destroyConstant() {
51  getType()->getContext().pImpl->InlineAsms.remove(this);
52  delete this;
53 }
54 
56  return cast<FunctionType>(getType()->getElementType());
57 }
58 
59 ///Default constructor.
61  Type(isInput), isEarlyClobber(false),
62  MatchingInput(-1), isCommutative(false),
63  isIndirect(false), isMultipleAlternative(false),
64  currentAlternativeIndex(0) {
65 }
66 
67 /// Parse - Analyze the specified string (e.g. "==&{eax}") and fill in the
68 /// fields in this structure. If the constraint string is not understood,
69 /// return true, otherwise return false.
71  InlineAsm::ConstraintInfoVector &ConstraintsSoFar) {
72  StringRef::iterator I = Str.begin(), E = Str.end();
73  unsigned multipleAlternativeCount = Str.count('|') + 1;
74  unsigned multipleAlternativeIndex = 0;
75  ConstraintCodeVector *pCodes = &Codes;
76 
77  // Initialize
78  isMultipleAlternative = multipleAlternativeCount > 1;
79  if (isMultipleAlternative) {
80  multipleAlternatives.resize(multipleAlternativeCount);
81  pCodes = &multipleAlternatives[0].Codes;
82  }
83  Type = isInput;
84  isEarlyClobber = false;
85  MatchingInput = -1;
86  isCommutative = false;
87  isIndirect = false;
88  currentAlternativeIndex = 0;
89 
90  // Parse prefixes.
91  if (*I == '~') {
92  Type = isClobber;
93  ++I;
94 
95  // '{' must immediately follow '~'.
96  if (I != E && *I != '{')
97  return true;
98  } else if (*I == '=') {
99  ++I;
100  Type = isOutput;
101  }
102 
103  if (*I == '*') {
104  isIndirect = true;
105  ++I;
106  }
107 
108  if (I == E) return true; // Just a prefix, like "==" or "~".
109 
110  // Parse the modifiers.
111  bool DoneWithModifiers = false;
112  while (!DoneWithModifiers) {
113  switch (*I) {
114  default:
115  DoneWithModifiers = true;
116  break;
117  case '&': // Early clobber.
118  if (Type != isOutput || // Cannot early clobber anything but output.
119  isEarlyClobber) // Reject &&&&&&
120  return true;
121  isEarlyClobber = true;
122  break;
123  case '%': // Commutative.
124  if (Type == isClobber || // Cannot commute clobbers.
125  isCommutative) // Reject %%%%%
126  return true;
127  isCommutative = true;
128  break;
129  case '#': // Comment.
130  case '*': // Register preferencing.
131  return true; // Not supported.
132  }
133 
134  if (!DoneWithModifiers) {
135  ++I;
136  if (I == E) return true; // Just prefixes and modifiers!
137  }
138  }
139 
140  // Parse the various constraints.
141  while (I != E) {
142  if (*I == '{') { // Physical register reference.
143  // Find the end of the register name.
144  StringRef::iterator ConstraintEnd = std::find(I+1, E, '}');
145  if (ConstraintEnd == E) return true; // "{foo"
146  pCodes->push_back(std::string(I, ConstraintEnd+1));
147  I = ConstraintEnd+1;
148  } else if (isdigit(static_cast<unsigned char>(*I))) { // Matching Constraint
149  // Maximal munch numbers.
150  StringRef::iterator NumStart = I;
151  while (I != E && isdigit(static_cast<unsigned char>(*I)))
152  ++I;
153  pCodes->push_back(std::string(NumStart, I));
154  unsigned N = atoi(pCodes->back().c_str());
155  // Check that this is a valid matching constraint!
156  if (N >= ConstraintsSoFar.size() || ConstraintsSoFar[N].Type != isOutput||
157  Type != isInput)
158  return true; // Invalid constraint number.
159 
160  // If Operand N already has a matching input, reject this. An output
161  // can't be constrained to the same value as multiple inputs.
162  if (isMultipleAlternative) {
164  ConstraintsSoFar[N].multipleAlternatives[multipleAlternativeIndex];
165  if (scInfo.MatchingInput != -1)
166  return true;
167  // Note that operand #n has a matching input.
168  scInfo.MatchingInput = ConstraintsSoFar.size();
169  } else {
170  if (ConstraintsSoFar[N].hasMatchingInput() &&
171  (size_t)ConstraintsSoFar[N].MatchingInput !=
172  ConstraintsSoFar.size())
173  return true;
174  // Note that operand #n has a matching input.
175  ConstraintsSoFar[N].MatchingInput = ConstraintsSoFar.size();
176  }
177  } else if (*I == '|') {
178  multipleAlternativeIndex++;
179  pCodes = &multipleAlternatives[multipleAlternativeIndex].Codes;
180  ++I;
181  } else if (*I == '^') {
182  // Multi-letter constraint
183  // FIXME: For now assuming these are 2-character constraints.
184  pCodes->push_back(std::string(I+1, I+3));
185  I += 3;
186  } else {
187  // Single letter constraint.
188  pCodes->push_back(std::string(I, I+1));
189  ++I;
190  }
191  }
192 
193  return false;
194 }
195 
196 /// selectAlternative - Point this constraint to the alternative constraint
197 /// indicated by the index.
199  if (index < multipleAlternatives.size()) {
200  currentAlternativeIndex = index;
202  multipleAlternatives[currentAlternativeIndex];
203  MatchingInput = scInfo.MatchingInput;
204  Codes = scInfo.Codes;
205  }
206 }
207 
210  ConstraintInfoVector Result;
211 
212  // Scan the constraints string.
213  for (StringRef::iterator I = Constraints.begin(),
214  E = Constraints.end(); I != E; ) {
215  ConstraintInfo Info;
216 
217  // Find the end of this constraint.
218  StringRef::iterator ConstraintEnd = std::find(I, E, ',');
219 
220  if (ConstraintEnd == I || // Empty constraint like ",,"
221  Info.Parse(StringRef(I, ConstraintEnd-I), Result)) {
222  Result.clear(); // Erroneous constraint?
223  break;
224  }
225 
226  Result.push_back(Info);
227 
228  // ConstraintEnd may be either the next comma or the end of the string. In
229  // the former case, we skip the comma.
230  I = ConstraintEnd;
231  if (I != E) {
232  ++I;
233  if (I == E) {
234  Result.clear();
235  break;
236  } // don't allow "xyz,"
237  }
238  }
239 
240  return Result;
241 }
242 
243 /// Verify - Verify that the specified constraint string is reasonable for the
244 /// specified function type, and otherwise validate the constraint string.
246  if (Ty->isVarArg()) return false;
247 
248  ConstraintInfoVector Constraints = ParseConstraints(ConstStr);
249 
250  // Error parsing constraints.
251  if (Constraints.empty() && !ConstStr.empty()) return false;
252 
253  unsigned NumOutputs = 0, NumInputs = 0, NumClobbers = 0;
254  unsigned NumIndirect = 0;
255 
256  for (unsigned i = 0, e = Constraints.size(); i != e; ++i) {
257  switch (Constraints[i].Type) {
258  case InlineAsm::isOutput:
259  if ((NumInputs-NumIndirect) != 0 || NumClobbers != 0)
260  return false; // outputs before inputs and clobbers.
261  if (!Constraints[i].isIndirect) {
262  ++NumOutputs;
263  break;
264  }
265  ++NumIndirect;
266  // FALLTHROUGH for Indirect Outputs.
267  case InlineAsm::isInput:
268  if (NumClobbers) return false; // inputs before clobbers.
269  ++NumInputs;
270  break;
272  ++NumClobbers;
273  break;
274  }
275  }
276 
277  switch (NumOutputs) {
278  case 0:
279  if (!Ty->getReturnType()->isVoidTy()) return false;
280  break;
281  case 1:
282  if (Ty->getReturnType()->isStructTy()) return false;
283  break;
284  default:
286  if (!STy || STy->getNumElements() != NumOutputs)
287  return false;
288  break;
289  }
290 
291  if (Ty->getNumParams() != NumInputs) return false;
292  return true;
293 }
294 
unsigned getNumParams() const
getNumParams - Return the number of fixed parameters this function type requires. ...
Definition: DerivedTypes.h:136
bool Parse(StringRef Str, ConstraintInfoVector &ConstraintsSoFar)
Parse - Analyze the specified string (e.g.
Definition: InlineAsm.cpp:70
static bool isInput(const llvm::StringSet<> &Prefixes, StringRef Arg)
Definition: OptTable.cpp:164
StructType - Class to represent struct types.
Definition: DerivedTypes.h:191
ConstraintInfoVector ParseConstraints() const
ParseConstraints - Parse the constraints of this inlineasm object, returning them the same way that P...
Definition: InlineAsm.h:180
#define false
Definition: ConvertUTF.c:65
ConstantUniqueMap< InlineAsm > InlineAsms
FunctionType - Class to represent function types.
Definition: DerivedTypes.h:96
LLVMContext & getContext() const
getContext - Return the LLVMContext in which this type was uniqued.
Definition: Type.h:125
static bool Verify(FunctionType *Ty, StringRef Constraints)
Verify - This static method can be used by the parser to check to see if the specified constraint str...
Definition: InlineAsm.cpp:245
Type * getElementType() const
Definition: DerivedTypes.h:323
PointerType - Class to represent pointers.
Definition: DerivedTypes.h:449
iterator begin() const
Definition: StringRef.h:90
The instances of the Type class are immutable: once they are created, they are never changed...
Definition: Type.h:45
ConstraintInfo()
Default constructor.
Definition: InlineAsm.cpp:60
size_t count(char C) const
Return the number of occurrences of C in the string.
Definition: StringRef.h:326
PointerType * getType() const
getType - InlineAsm's are always pointers.
Definition: InlineAsm.h:74
LLVMContextImpl *const pImpl
Definition: LLVMContext.h:43
signed char MatchingInput
MatchingInput - If this is not -1, this is an output constraint where an input constraint is required...
Definition: InlineAsm.h:105
const char * iterator
Definition: StringRef.h:42
FunctionType * getFunctionType() const
getFunctionType - InlineAsm's are always pointers to functions.
Definition: InlineAsm.cpp:55
std::vector< std::string > ConstraintCodeVector
Definition: InlineAsm.h:98
ConstraintCodeVector Codes
Code - The constraint code, either the register name (in braces) or the constraint letter/number...
Definition: InlineAsm.h:108
static PointerType * getUnqual(Type *ElementType)
PointerType::getUnqual - This constructs a pointer to an object of the specified type in the generic ...
Definition: DerivedTypes.h:460
LLVM_ATTRIBUTE_UNUSED_RESULT std::enable_if< !is_simple_type< Y >::value, typename cast_retty< X, const Y >::ret_type >::type dyn_cast(const Y &Val)
Definition: Casting.h:285
bool isStructTy() const
isStructTy - True if this is an instance of StructType.
Definition: Type.h:209
#define I(x, y, z)
Definition: MD5.cpp:54
#define N
static InlineAsm * get(FunctionType *Ty, StringRef AsmString, StringRef Constraints, bool hasSideEffects, bool isAlignStack=false, AsmDialect asmDialect=AD_ATT)
InlineAsm::get - Return the specified uniqued inline asm string.
Definition: InlineAsm.cpp:28
bool isVarArg() const
Definition: DerivedTypes.h:120
Type * getReturnType() const
Definition: DerivedTypes.h:121
LLVM Value Representation.
Definition: Value.h:69
iterator end() const
Definition: StringRef.h:92
StringRef - Represent a constant reference to a string, i.e.
Definition: StringRef.h:40
unsigned getNumElements() const
Random access to the elements.
Definition: DerivedTypes.h:290
std::vector< ConstraintInfo > ConstraintInfoVector
Definition: InlineAsm.h:114
bool isVoidTy() const
isVoidTy - Return true if this is 'void'.
Definition: Type.h:137
void selectAlternative(unsigned index)
selectAlternative - Point this constraint to the alternative constraint indicated by the index...
Definition: InlineAsm.cpp:198
bool empty() const
empty - Check if the string is empty.
Definition: StringRef.h:110