LLVM  13.0.0git
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;
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;
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(std::string(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(std::string(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(std::string(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(std::string(StringRef(I, N)));
193  I += N;
194  } else {
195  // Single letter constraint.
196  pCodes->push_back(std::string(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:
293  StructType *STy = dyn_cast<StructType>(Ty->getReturnType());
294  if (!STy || STy->getNumElements() != NumOutputs)
295  return false;
296  break;
297  }
298 
299  if (Ty->getNumParams() != NumInputs) return false;
300  return true;
301 }
i
i
Definition: README.txt:29
llvm::InlineAsm::ConstraintInfo::MatchingInput
int MatchingInput
MatchingInput - If this is not -1, this is an output constraint where an input constraint is required...
Definition: InlineAsm.h:131
llvm::LLVMContext::pImpl
LLVMContextImpl *const pImpl
Definition: LLVMContext.h:70
llvm::LLVMContextImpl::InlineAsms
ConstantUniqueMap< InlineAsm > InlineAsms
Definition: LLVMContextImpl.h:1421
llvm
Definition: AllocatorList.h:23
llvm::InlineAsm::AsmDialect
AsmDialect
Definition: InlineAsm.h:33
llvm::StringRef::empty
LLVM_NODISCARD bool empty() const
empty - Check if the string is empty.
Definition: StringRef.h:156
llvm::InlineAsm::ConstraintInfo::isCommutative
bool isCommutative
isCommutative - This is set to true for a constraint that is commutative with the next operand.
Definition: InlineAsm.h:139
llvm::StringRef::count
LLVM_NODISCARD size_t count(char C) const
Return the number of occurrences of C in the string.
Definition: StringRef.h:490
llvm::InlineAsm::ConstraintInfoVector
std::vector< ConstraintInfo > ConstraintInfoVector
Definition: InlineAsm.h:116
StringRef.h
llvm::InlineAsm::isAlignStack
bool isAlignStack() const
Definition: InlineAsm.h:68
llvm::InlineAsm::ConstraintInfo::isIndirect
bool isIndirect
isIndirect - True if this operand is an indirect operand.
Definition: InlineAsm.h:145
InlineAsm.h
llvm::Type
The instances of the Type class are immutable: once they are created, they are never changed.
Definition: Type.h:46
llvm::InlineAsm::ConstraintInfo::Parse
bool Parse(StringRef Str, ConstraintInfoVector &ConstraintsSoFar)
Parse - Analyze the specified string (e.g.
Definition: InlineAsm.cpp:63
llvm::InlineAsm::getFunctionType
FunctionType * getFunctionType() const
getFunctionType - InlineAsm's are always pointers to functions.
Definition: InlineAsm.cpp:56
llvm::InlineAsm::getType
PointerType * getType() const
getType - InlineAsm's are always pointers.
Definition: InlineAsm.h:73
llvm::FunctionType::getNumParams
unsigned getNumParams() const
Return the number of fixed parameters this function type requires.
Definition: DerivedTypes.h:138
llvm::FunctionType::isVarArg
bool isVarArg() const
Definition: DerivedTypes.h:122
llvm::InlineAsm::ConstraintInfo::currentAlternativeIndex
unsigned currentAlternativeIndex
The currently selected alternative constraint index.
Definition: InlineAsm.h:159
E
static GCRegistry::Add< CoreCLRGC > E("coreclr", "CoreCLR-compatible GC")
llvm::InlineAsmKeyType
Definition: ConstantsContext.h:459
llvm::InlineAsm::hasSideEffects
bool hasSideEffects() const
Definition: InlineAsm.h:67
C
(vector float) vec_cmpeq(*A, *B) C
Definition: README_ALTIVEC.txt:86
llvm::LLVMContextImpl
Definition: LLVMContextImpl.h:1324
llvm::StringRef::iterator
const char * iterator
Definition: StringRef.h:61
llvm::AMDGPU::PALMD::Key
Key
PAL metadata keys.
Definition: AMDGPUMetadata.h:481
llvm::InlineAsm::isInput
@ isInput
Definition: InlineAsm.h:92
LLVMContextImpl.h
Info
Analysis containing CSE Info
Definition: CSEInfo.cpp:26
llvm::InlineAsm::get
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
llvm::InlineAsm
Definition: InlineAsm.h:31
Verify
ppc ctr loops PowerPC CTR Loops Verify
Definition: PPCCTRLoops.cpp:77
llvm::PointerType::getUnqual
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:649
index
splat index
Definition: README_ALTIVEC.txt:181
llvm::StringRef::end
iterator end() const
Definition: StringRef.h:133
llvm::find
auto find(R &&Range, const T &Val)
Provide wrappers to std::find which take ranges instead of having to pass begin/end explicitly.
Definition: STLExtras.h:1525
llvm::numbers::e
constexpr double e
Definition: MathExtras.h:57
I
#define I(x, y, z)
Definition: MD5.cpp:59
llvm::InlineAsm::ConstraintInfo::isEarlyClobber
bool isEarlyClobber
isEarlyClobber - "&": output operand writes result before inputs are all read.
Definition: InlineAsm.h:125
llvm::PointerType
Class to represent pointers.
Definition: DerivedTypes.h:634
llvm::InlineAsm::ConstraintInfo
Definition: InlineAsm.h:118
assert
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
llvm::InlineAsm::ConstraintInfo::Codes
ConstraintCodeVector Codes
Code - The constraint code, either the register name (in braces) or the constraint letter/number.
Definition: InlineAsm.h:149
ConstantsContext.h
llvm::Type::isVoidTy
bool isVoidTy() const
Return true if this is 'void'.
Definition: Type.h:139
llvm::InlineAsm::SubConstraintInfo::MatchingInput
int MatchingInput
MatchingInput - If this is not -1, this is an output constraint where an input constraint is required...
Definition: InlineAsm.h:104
llvm::InlineAsm::SubConstraintInfo::Codes
ConstraintCodeVector Codes
Code - The constraint code, either the register name (in braces) or the constraint letter/number.
Definition: InlineAsm.h:108
llvm::StructType
Class to represent struct types.
Definition: DerivedTypes.h:212
llvm::StringRef
StringRef - Represent a constant reference to a string, i.e.
Definition: StringRef.h:57
Compiler.h
LLVM_FALLTHROUGH
#define LLVM_FALLTHROUGH
LLVM_FALLTHROUGH - Mark fallthrough cases in switch statements.
Definition: Compiler.h:281
llvm::Type::getContext
LLVMContext & getContext() const
Return the LLVMContext in which this type was uniqued.
Definition: Type.h:128
llvm::StructType::getNumElements
unsigned getNumElements() const
Random access to the elements.
Definition: DerivedTypes.h:329
llvm::InlineAsm::ConstraintInfo::multipleAlternatives
SubConstraintInfoVector multipleAlternatives
multipleAlternatives - If there are multiple alternative constraints, this array will contain them.
Definition: InlineAsm.h:156
llvm::InlineAsm::ConstraintInfo::selectAlternative
void selectAlternative(unsigned index)
selectAlternative - Point this constraint to the alternative constraint indicated by the index.
Definition: InlineAsm.cpp:206
llvm::InlineAsm::ConstraintInfo::isMultipleAlternative
bool isMultipleAlternative
isMultipleAlternative - '|': has multiple-alternative constraints.
Definition: InlineAsm.h:152
llvm::InlineAsm::isClobber
@ isClobber
Definition: InlineAsm.h:94
Casting.h
llvm::InlineAsm::isOutput
@ isOutput
Definition: InlineAsm.h:93
llvm::InlineAsm::ParseConstraints
ConstraintInfoVector ParseConstraints() const
ParseConstraints - Parse the constraints of this inlineasm object, returning them the same way that P...
Definition: InlineAsm.h:181
llvm::Type::isStructTy
bool isStructTy() const
True if this is an instance of StructType.
Definition: Type.h:223
N
#define N
llvm::InlineAsm::ConstraintCodeVector
std::vector< std::string > ConstraintCodeVector
Definition: InlineAsm.h:97
DerivedTypes.h
llvm::InlineAsm::SubConstraintInfo
Definition: InlineAsm.h:99
LLVMContext.h
llvm::StringRef::begin
iterator begin() const
Definition: StringRef.h:131
Value.h
llvm::FunctionType::getReturnType
Type * getReturnType() const
Definition: DerivedTypes.h:123
llvm::Value
LLVM Value Representation.
Definition: Value.h:75
llvm::InlineAsm::Verify
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
llvm::InlineAsm::ConstraintInfo::hasMatchingInput
bool hasMatchingInput() const
hasMatchingInput - Return true if this is an output constraint that has a matching input constraint.
Definition: InlineAsm.h:135
llvm::FunctionType
Class to represent function types.
Definition: DerivedTypes.h:102