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