LLVM  14.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, bool canThrow)
33  : Value(PointerType::getUnqual(FTy), Value::InlineAsmVal),
34  AsmString(asmString), Constraints(constraints), FTy(FTy),
35  HasSideEffects(hasSideEffects), IsAlignStack(isAlignStack),
36  Dialect(asmDialect), CanThrow(canThrow) {
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  bool canThrow) {
46  InlineAsmKeyType Key(AsmString, Constraints, FTy, hasSideEffects,
47  isAlignStack, asmDialect, canThrow);
48  LLVMContextImpl *pImpl = FTy->getContext().pImpl;
49  return pImpl->InlineAsms.getOrCreate(PointerType::getUnqual(FTy), Key);
50 }
51 
52 void InlineAsm::destroyConstant() {
53  getType()->getContext().pImpl->InlineAsms.remove(this);
54  delete this;
55 }
56 
58  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.
65  InlineAsm::ConstraintInfoVector &ConstraintsSoFar) {
66  StringRef::iterator I = Str.begin(), E = Str.end();
67  unsigned multipleAlternativeCount = Str.count('|') + 1;
68  unsigned multipleAlternativeIndex = 0;
69  ConstraintCodeVector *pCodes = &Codes;
70 
71  // Initialize
72  isMultipleAlternative = multipleAlternativeCount > 1;
74  multipleAlternatives.resize(multipleAlternativeCount);
75  pCodes = &multipleAlternatives[0].Codes;
76  }
77  Type = isInput;
78  isEarlyClobber = false;
79  MatchingInput = -1;
80  isCommutative = false;
81  isIndirect = false;
83 
84  // Parse prefixes.
85  if (*I == '~') {
86  Type = isClobber;
87  ++I;
88 
89  // '{' must immediately follow '~'.
90  if (I != E && *I != '{')
91  return true;
92  } else if (*I == '=') {
93  ++I;
94  Type = isOutput;
95  }
96 
97  if (*I == '*') {
98  isIndirect = true;
99  ++I;
100  }
101 
102  if (I == E) return true; // Just a prefix, like "==" or "~".
103 
104  // Parse the modifiers.
105  bool DoneWithModifiers = false;
106  while (!DoneWithModifiers) {
107  switch (*I) {
108  default:
109  DoneWithModifiers = true;
110  break;
111  case '&': // Early clobber.
112  if (Type != isOutput || // Cannot early clobber anything but output.
113  isEarlyClobber) // Reject &&&&&&
114  return true;
115  isEarlyClobber = true;
116  break;
117  case '%': // Commutative.
118  if (Type == isClobber || // Cannot commute clobbers.
119  isCommutative) // Reject %%%%%
120  return true;
121  isCommutative = true;
122  break;
123  case '#': // Comment.
124  case '*': // Register preferencing.
125  return true; // Not supported.
126  }
127 
128  if (!DoneWithModifiers) {
129  ++I;
130  if (I == E) return true; // Just prefixes and modifiers!
131  }
132  }
133 
134  // Parse the various constraints.
135  while (I != E) {
136  if (*I == '{') { // Physical register reference.
137  // Find the end of the register name.
138  StringRef::iterator ConstraintEnd = std::find(I+1, E, '}');
139  if (ConstraintEnd == E) return true; // "{foo"
140  pCodes->push_back(std::string(StringRef(I, ConstraintEnd + 1 - I)));
141  I = ConstraintEnd+1;
142  } else if (isdigit(static_cast<unsigned char>(*I))) { // Matching Constraint
143  // Maximal munch numbers.
144  StringRef::iterator NumStart = I;
145  while (I != E && isdigit(static_cast<unsigned char>(*I)))
146  ++I;
147  pCodes->push_back(std::string(StringRef(NumStart, I - NumStart)));
148  unsigned N = atoi(pCodes->back().c_str());
149  // Check that this is a valid matching constraint!
150  if (N >= ConstraintsSoFar.size() || ConstraintsSoFar[N].Type != isOutput||
151  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  if (isMultipleAlternative) {
157  if (multipleAlternativeIndex >=
158  ConstraintsSoFar[N].multipleAlternatives.size())
159  return true;
161  ConstraintsSoFar[N].multipleAlternatives[multipleAlternativeIndex];
162  if (scInfo.MatchingInput != -1)
163  return true;
164  // Note that operand #n has a matching input.
165  scInfo.MatchingInput = ConstraintsSoFar.size();
166  assert(scInfo.MatchingInput >= 0);
167  } else {
168  if (ConstraintsSoFar[N].hasMatchingInput() &&
169  (size_t)ConstraintsSoFar[N].MatchingInput !=
170  ConstraintsSoFar.size())
171  return true;
172  // Note that operand #n has a matching input.
173  ConstraintsSoFar[N].MatchingInput = ConstraintsSoFar.size();
174  assert(ConstraintsSoFar[N].MatchingInput >= 0);
175  }
176  } else if (*I == '|') {
177  multipleAlternativeIndex++;
178  pCodes = &multipleAlternatives[multipleAlternativeIndex].Codes;
179  ++I;
180  } else if (*I == '^') {
181  // Multi-letter constraint
182  // FIXME: For now assuming these are 2-character constraints.
183  pCodes->push_back(std::string(StringRef(I + 1, 2)));
184  I += 3;
185  } else if (*I == '@') {
186  // Multi-letter constraint
187  ++I;
188  unsigned char C = static_cast<unsigned char>(*I);
189  assert(isdigit(C) && "Expected a digit!");
190  int N = C - '0';
191  assert(N > 0 && "Found a zero letter constraint!");
192  ++I;
193  pCodes->push_back(std::string(StringRef(I, N)));
194  I += N;
195  } else {
196  // Single letter constraint.
197  pCodes->push_back(std::string(StringRef(I, 1)));
198  ++I;
199  }
200  }
201 
202  return false;
203 }
204 
205 /// selectAlternative - Point this constraint to the alternative constraint
206 /// indicated by the index.
208  if (index < multipleAlternatives.size()) {
209  currentAlternativeIndex = index;
211  multipleAlternatives[currentAlternativeIndex];
212  MatchingInput = scInfo.MatchingInput;
213  Codes = scInfo.Codes;
214  }
215 }
216 
219  ConstraintInfoVector Result;
220 
221  // Scan the constraints string.
222  for (StringRef::iterator I = Constraints.begin(),
223  E = Constraints.end(); I != E; ) {
225 
226  // Find the end of this constraint.
227  StringRef::iterator ConstraintEnd = std::find(I, E, ',');
228 
229  if (ConstraintEnd == I || // Empty constraint like ",,"
230  Info.Parse(StringRef(I, ConstraintEnd-I), Result)) {
231  Result.clear(); // Erroneous constraint?
232  break;
233  }
234 
235  Result.push_back(Info);
236 
237  // ConstraintEnd may be either the next comma or the end of the string. In
238  // the former case, we skip the comma.
239  I = ConstraintEnd;
240  if (I != E) {
241  ++I;
242  if (I == E) {
243  Result.clear();
244  break;
245  } // don't allow "xyz,"
246  }
247  }
248 
249  return Result;
250 }
251 
252 /// Verify - Verify that the specified constraint string is reasonable for the
253 /// specified function type, and otherwise validate the constraint string.
255  if (Ty->isVarArg()) return false;
256 
257  ConstraintInfoVector Constraints = ParseConstraints(ConstStr);
258 
259  // Error parsing constraints.
260  if (Constraints.empty() && !ConstStr.empty()) return false;
261 
262  unsigned NumOutputs = 0, NumInputs = 0, NumClobbers = 0;
263  unsigned NumIndirect = 0;
264 
265  for (unsigned i = 0, e = Constraints.size(); i != e; ++i) {
266  switch (Constraints[i].Type) {
267  case InlineAsm::isOutput:
268  if ((NumInputs-NumIndirect) != 0 || NumClobbers != 0)
269  return false; // outputs before inputs and clobbers.
270  if (!Constraints[i].isIndirect) {
271  ++NumOutputs;
272  break;
273  }
274  ++NumIndirect;
275  LLVM_FALLTHROUGH; // We fall through for Indirect Outputs.
276  case InlineAsm::isInput:
277  if (NumClobbers) return false; // inputs before clobbers.
278  ++NumInputs;
279  break;
281  ++NumClobbers;
282  break;
283  }
284  }
285 
286  switch (NumOutputs) {
287  case 0:
288  if (!Ty->getReturnType()->isVoidTy()) return false;
289  break;
290  case 1:
291  if (Ty->getReturnType()->isStructTy()) return false;
292  break;
293  default:
294  StructType *STy = dyn_cast<StructType>(Ty->getReturnType());
295  if (!STy || STy->getNumElements() != NumOutputs)
296  return false;
297  break;
298  }
299 
300  if (Ty->getNumParams() != NumInputs) return false;
301  return true;
302 }
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:133
llvm::LLVMContext::pImpl
LLVMContextImpl *const pImpl
Definition: LLVMContext.h:70
llvm::LLVMContextImpl::InlineAsms
ConstantUniqueMap< InlineAsm > InlineAsms
Definition: LLVMContextImpl.h:1438
llvm
This file implements support for optimizing divisions by a constant.
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:153
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:141
llvm::InlineAsm::ConstraintInfoVector
std::vector< ConstraintInfo > ConstraintInfoVector
Definition: InlineAsm.h:118
StringRef.h
llvm::InlineAsm::isAlignStack
bool isAlignStack() const
Definition: InlineAsm.h:69
llvm::InlineAsm::ConstraintInfo::isIndirect
bool isIndirect
isIndirect - True if this operand is an indirect operand.
Definition: InlineAsm.h:147
InlineAsm.h
llvm::Type
The instances of the Type class are immutable: once they are created, they are never changed.
Definition: Type.h:45
llvm::InlineAsm::ConstraintInfo::Parse
bool Parse(StringRef Str, ConstraintInfoVector &ConstraintsSoFar)
Parse - Analyze the specified string (e.g.
Definition: InlineAsm.cpp:64
llvm::InlineAsm::getFunctionType
FunctionType * getFunctionType() const
getFunctionType - InlineAsm's are always pointers to functions.
Definition: InlineAsm.cpp:57
llvm::InlineAsm::getType
PointerType * getType() const
getType - InlineAsm's are always pointers.
Definition: InlineAsm.h:75
llvm::FunctionType::getNumParams
unsigned getNumParams() const
Return the number of fixed parameters this function type requires.
Definition: DerivedTypes.h:139
llvm::FunctionType::isVarArg
bool isVarArg() const
Definition: DerivedTypes.h:123
llvm::InlineAsm::ConstraintInfo::currentAlternativeIndex
unsigned currentAlternativeIndex
The currently selected alternative constraint index.
Definition: InlineAsm.h:161
E
static GCRegistry::Add< CoreCLRGC > E("coreclr", "CoreCLR-compatible GC")
llvm::InlineAsmKeyType
Definition: ConstantsContext.h:452
llvm::InlineAsm::hasSideEffects
bool hasSideEffects() const
Definition: InlineAsm.h:68
C
(vector float) vec_cmpeq(*A, *B) C
Definition: README_ALTIVEC.txt:86
llvm::LLVMContextImpl
Definition: LLVMContextImpl.h:1341
canThrow
static bool canThrow(const Value *V)
Definition: WebAssemblyLowerEmscriptenEHSjLj.cpp:398
llvm::StringRef::iterator
const char * iterator
Definition: StringRef.h:62
llvm::AMDGPU::PALMD::Key
Key
PAL metadata keys.
Definition: AMDGPUMetadata.h:481
llvm::InlineAsm::isInput
@ isInput
Definition: InlineAsm.h:94
LLVMContextImpl.h
Info
Analysis containing CSE Info
Definition: CSEInfo.cpp:27
llvm::InlineAsm::get
static InlineAsm * get(FunctionType *Ty, StringRef AsmString, StringRef Constraints, bool hasSideEffects, bool isAlignStack=false, AsmDialect asmDialect=AD_ATT, bool canThrow=false)
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 default address space (address sp...
Definition: DerivedTypes.h:651
llvm::InlineAsm::canThrow
bool canThrow() const
Definition: InlineAsm.h:71
index
splat index
Definition: README_ALTIVEC.txt:181
llvm::StringRef::end
iterator end() const
Definition: StringRef.h:130
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:1571
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:127
llvm::PointerType
Class to represent pointers.
Definition: DerivedTypes.h:632
llvm::InlineAsm::ConstraintInfo
Definition: InlineAsm.h:120
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:151
ConstantsContext.h
llvm::Type::isVoidTy
bool isVoidTy() const
Return true if this is 'void'.
Definition: Type.h:138
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:106
llvm::InlineAsm::SubConstraintInfo::Codes
ConstraintCodeVector Codes
Code - The constraint code, either the register name (in braces) or the constraint letter/number.
Definition: InlineAsm.h:110
llvm::StructType
Class to represent struct types.
Definition: DerivedTypes.h:213
llvm::StringRef
StringRef - Represent a constant reference to a string, i.e.
Definition: StringRef.h:58
Compiler.h
LLVM_FALLTHROUGH
#define LLVM_FALLTHROUGH
LLVM_FALLTHROUGH - Mark fallthrough cases in switch statements.
Definition: Compiler.h:286
llvm::Type::getContext
LLVMContext & getContext() const
Return the LLVMContext in which this type was uniqued.
Definition: Type.h:127
llvm::StructType::getNumElements
unsigned getNumElements() const
Random access to the elements.
Definition: DerivedTypes.h:327
llvm::InlineAsm::ConstraintInfo::multipleAlternatives
SubConstraintInfoVector multipleAlternatives
multipleAlternatives - If there are multiple alternative constraints, this array will contain them.
Definition: InlineAsm.h:158
llvm::InlineAsm::ConstraintInfo::selectAlternative
void selectAlternative(unsigned index)
selectAlternative - Point this constraint to the alternative constraint indicated by the index.
Definition: InlineAsm.cpp:207
llvm::InlineAsm::ConstraintInfo::isMultipleAlternative
bool isMultipleAlternative
isMultipleAlternative - '|': has multiple-alternative constraints.
Definition: InlineAsm.h:154
llvm::InlineAsm::isClobber
@ isClobber
Definition: InlineAsm.h:96
Casting.h
llvm::InlineAsm::isOutput
@ isOutput
Definition: InlineAsm.h:95
llvm::InlineAsm::ParseConstraints
ConstraintInfoVector ParseConstraints() const
ParseConstraints - Parse the constraints of this inlineasm object, returning them the same way that P...
Definition: InlineAsm.h:183
llvm::Type::isStructTy
bool isStructTy() const
True if this is an instance of StructType.
Definition: Type.h:211
N
#define N
llvm::InlineAsm::ConstraintCodeVector
std::vector< std::string > ConstraintCodeVector
Definition: InlineAsm.h:99
DerivedTypes.h
llvm::InlineAsm::SubConstraintInfo
Definition: InlineAsm.h:101
LLVMContext.h
llvm::StringRef::begin
iterator begin() const
Definition: StringRef.h:128
Value.h
llvm::FunctionType::getReturnType
Type * getReturnType() const
Definition: DerivedTypes.h:124
llvm::Value
LLVM Value Representation.
Definition: Value.h:74
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:254
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:137
llvm::FunctionType
Class to represent function types.
Definition: DerivedTypes.h:103