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