LLVM  16.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 "llvm/Support/Errc.h"
23 #include <algorithm>
24 #include <cassert>
25 #include <cctype>
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 #ifndef NDEBUG
38  // Do various checks on the constraint string and type.
39  cantFail(verify(getFunctionType(), constraints));
40 #endif
41 }
42 
44  StringRef Constraints, bool hasSideEffects,
45  bool isAlignStack, AsmDialect asmDialect,
46  bool canThrow) {
47  InlineAsmKeyType Key(AsmString, Constraints, FTy, hasSideEffects,
48  isAlignStack, asmDialect, canThrow);
49  LLVMContextImpl *pImpl = FTy->getContext().pImpl;
50  return pImpl->InlineAsms.getOrCreate(PointerType::getUnqual(FTy), Key);
51 }
52 
53 void InlineAsm::destroyConstant() {
54  getType()->getContext().pImpl->InlineAsms.remove(this);
55  delete this;
56 }
57 
59  return FTy;
60 }
61 
63  StringRef AsmStr(AsmString);
64  AsmStrs.clear();
65 
66  // TODO: 1) Unify delimiter for inline asm, we also meet other delimiters
67  // for example "\0A", ";".
68  // 2) Enhance StringRef. Some of the special delimiter ("\0") can't be
69  // split in StringRef. Also empty StringRef can not call split (will stuck).
70  if (AsmStr.empty())
71  return;
72  AsmStr.split(AsmStrs, "\n\t", -1, false);
73 }
74 
75 /// Parse - Analyze the specified string (e.g. "==&{eax}") and fill in the
76 /// fields in this structure. If the constraint string is not understood,
77 /// return true, otherwise return false.
79  InlineAsm::ConstraintInfoVector &ConstraintsSoFar) {
80  StringRef::iterator I = Str.begin(), E = Str.end();
81  unsigned multipleAlternativeCount = Str.count('|') + 1;
82  unsigned multipleAlternativeIndex = 0;
83  ConstraintCodeVector *pCodes = &Codes;
84 
85  // Initialize
86  isMultipleAlternative = multipleAlternativeCount > 1;
88  multipleAlternatives.resize(multipleAlternativeCount);
89  pCodes = &multipleAlternatives[0].Codes;
90  }
91  Type = isInput;
92  isEarlyClobber = false;
93  MatchingInput = -1;
94  isCommutative = false;
95  isIndirect = false;
97 
98  // Parse prefixes.
99  if (*I == '~') {
100  Type = isClobber;
101  ++I;
102 
103  // '{' must immediately follow '~'.
104  if (I != E && *I != '{')
105  return true;
106  } else if (*I == '=') {
107  ++I;
108  Type = isOutput;
109  } else if (*I == '!') {
110  ++I;
111  Type = isLabel;
112  }
113 
114  if (*I == '*') {
115  isIndirect = true;
116  ++I;
117  }
118 
119  if (I == E) return true; // Just a prefix, like "==" or "~".
120 
121  // Parse the modifiers.
122  bool DoneWithModifiers = false;
123  while (!DoneWithModifiers) {
124  switch (*I) {
125  default:
126  DoneWithModifiers = true;
127  break;
128  case '&': // Early clobber.
129  if (Type != isOutput || // Cannot early clobber anything but output.
130  isEarlyClobber) // Reject &&&&&&
131  return true;
132  isEarlyClobber = true;
133  break;
134  case '%': // Commutative.
135  if (Type == isClobber || // Cannot commute clobbers.
136  isCommutative) // Reject %%%%%
137  return true;
138  isCommutative = true;
139  break;
140  case '#': // Comment.
141  case '*': // Register preferencing.
142  return true; // Not supported.
143  }
144 
145  if (!DoneWithModifiers) {
146  ++I;
147  if (I == E) return true; // Just prefixes and modifiers!
148  }
149  }
150 
151  // Parse the various constraints.
152  while (I != E) {
153  if (*I == '{') { // Physical register reference.
154  // Find the end of the register name.
155  StringRef::iterator ConstraintEnd = std::find(I+1, E, '}');
156  if (ConstraintEnd == E) return true; // "{foo"
157  pCodes->push_back(std::string(StringRef(I, ConstraintEnd + 1 - I)));
158  I = ConstraintEnd+1;
159  } else if (isdigit(static_cast<unsigned char>(*I))) { // Matching Constraint
160  // Maximal munch numbers.
161  StringRef::iterator NumStart = I;
162  while (I != E && isdigit(static_cast<unsigned char>(*I)))
163  ++I;
164  pCodes->push_back(std::string(StringRef(NumStart, I - NumStart)));
165  unsigned N = atoi(pCodes->back().c_str());
166  // Check that this is a valid matching constraint!
167  if (N >= ConstraintsSoFar.size() || ConstraintsSoFar[N].Type != isOutput||
168  Type != isInput)
169  return true; // Invalid constraint number.
170 
171  // If Operand N already has a matching input, reject this. An output
172  // can't be constrained to the same value as multiple inputs.
173  if (isMultipleAlternative) {
174  if (multipleAlternativeIndex >=
175  ConstraintsSoFar[N].multipleAlternatives.size())
176  return true;
178  ConstraintsSoFar[N].multipleAlternatives[multipleAlternativeIndex];
179  if (scInfo.MatchingInput != -1)
180  return true;
181  // Note that operand #n has a matching input.
182  scInfo.MatchingInput = ConstraintsSoFar.size();
183  assert(scInfo.MatchingInput >= 0);
184  } else {
185  if (ConstraintsSoFar[N].hasMatchingInput() &&
186  (size_t)ConstraintsSoFar[N].MatchingInput !=
187  ConstraintsSoFar.size())
188  return true;
189  // Note that operand #n has a matching input.
190  ConstraintsSoFar[N].MatchingInput = ConstraintsSoFar.size();
191  assert(ConstraintsSoFar[N].MatchingInput >= 0);
192  }
193  } else if (*I == '|') {
194  multipleAlternativeIndex++;
195  pCodes = &multipleAlternatives[multipleAlternativeIndex].Codes;
196  ++I;
197  } else if (*I == '^') {
198  // Multi-letter constraint
199  // FIXME: For now assuming these are 2-character constraints.
200  pCodes->push_back(std::string(StringRef(I + 1, 2)));
201  I += 3;
202  } else if (*I == '@') {
203  // Multi-letter constraint
204  ++I;
205  unsigned char C = static_cast<unsigned char>(*I);
206  assert(isdigit(C) && "Expected a digit!");
207  int N = C - '0';
208  assert(N > 0 && "Found a zero letter constraint!");
209  ++I;
210  pCodes->push_back(std::string(StringRef(I, N)));
211  I += N;
212  } else {
213  // Single letter constraint.
214  pCodes->push_back(std::string(StringRef(I, 1)));
215  ++I;
216  }
217  }
218 
219  return false;
220 }
221 
222 /// selectAlternative - Point this constraint to the alternative constraint
223 /// indicated by the index.
225  if (index < multipleAlternatives.size()) {
226  currentAlternativeIndex = index;
228  multipleAlternatives[currentAlternativeIndex];
229  MatchingInput = scInfo.MatchingInput;
230  Codes = scInfo.Codes;
231  }
232 }
233 
236  ConstraintInfoVector Result;
237 
238  // Scan the constraints string.
239  for (StringRef::iterator I = Constraints.begin(),
240  E = Constraints.end(); I != E; ) {
242 
243  // Find the end of this constraint.
244  StringRef::iterator ConstraintEnd = std::find(I, E, ',');
245 
246  if (ConstraintEnd == I || // Empty constraint like ",,"
247  Info.Parse(StringRef(I, ConstraintEnd-I), Result)) {
248  Result.clear(); // Erroneous constraint?
249  break;
250  }
251 
252  Result.push_back(Info);
253 
254  // ConstraintEnd may be either the next comma or the end of the string. In
255  // the former case, we skip the comma.
256  I = ConstraintEnd;
257  if (I != E) {
258  ++I;
259  if (I == E) {
260  Result.clear();
261  break;
262  } // don't allow "xyz,"
263  }
264  }
265 
266  return Result;
267 }
268 
269 static Error makeStringError(const char *Msg) {
271 }
272 
274  if (Ty->isVarArg())
275  return makeStringError("inline asm cannot be variadic");
276 
277  ConstraintInfoVector Constraints = ParseConstraints(ConstStr);
278 
279  // Error parsing constraints.
280  if (Constraints.empty() && !ConstStr.empty())
281  return makeStringError("failed to parse constraints");
282 
283  unsigned NumOutputs = 0, NumInputs = 0, NumClobbers = 0;
284  unsigned NumIndirect = 0, NumLabels = 0;
285 
286  for (const ConstraintInfo &Constraint : Constraints) {
287  switch (Constraint.Type) {
288  case InlineAsm::isOutput:
289  if ((NumInputs-NumIndirect) != 0 || NumClobbers != 0 || NumLabels != 0)
290  return makeStringError("output constraint occurs after input, "
291  "clobber or label constraint");
292 
293  if (!Constraint.isIndirect) {
294  ++NumOutputs;
295  break;
296  }
297  ++NumIndirect;
298  [[fallthrough]]; // We fall through for Indirect Outputs.
299  case InlineAsm::isInput:
300  if (NumClobbers)
301  return makeStringError("input constraint occurs after clobber "
302  "constraint");
303  ++NumInputs;
304  break;
306  ++NumClobbers;
307  break;
308  case InlineAsm::isLabel:
309  if (NumClobbers)
310  return makeStringError("label constraint occurs after clobber "
311  "constraint");
312 
313  ++NumLabels;
314  break;
315  }
316  }
317 
318  switch (NumOutputs) {
319  case 0:
320  if (!Ty->getReturnType()->isVoidTy())
321  return makeStringError("inline asm without outputs must return void");
322  break;
323  case 1:
324  if (Ty->getReturnType()->isStructTy())
325  return makeStringError("inline asm with one output cannot return struct");
326  break;
327  default:
328  StructType *STy = dyn_cast<StructType>(Ty->getReturnType());
329  if (!STy || STy->getNumElements() != NumOutputs)
330  return makeStringError("number of output constraints does not match "
331  "number of return struct elements");
332  break;
333  }
334 
335  if (Ty->getNumParams() != NumInputs)
336  return makeStringError("number of input constraints does not match number "
337  "of parameters");
338 
339  // We don't have access to labels here, NumLabels will be checked separately.
340  return Error::success();
341 }
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:135
llvm::LLVMContext::pImpl
LLVMContextImpl *const pImpl
Definition: LLVMContext.h:69
llvm::errc::invalid_argument
@ invalid_argument
llvm::LLVMContextImpl::InlineAsms
ConstantUniqueMap< InlineAsm > InlineAsms
Definition: LLVMContextImpl.h:1459
llvm
This is an optimization pass for GlobalISel generic memory operations.
Definition: AddressRanges.h:18
llvm::InlineAsm::AsmDialect
AsmDialect
Definition: InlineAsm.h:35
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:143
llvm::InlineAsm::ConstraintInfoVector
std::vector< ConstraintInfo > ConstraintInfoVector
Definition: InlineAsm.h:120
StringRef.h
llvm::InlineAsm::isAlignStack
bool isAlignStack() const
Definition: InlineAsm.h:71
llvm::InlineAsm::ConstraintInfo::isIndirect
bool isIndirect
isIndirect - True if this operand is an indirect operand.
Definition: InlineAsm.h:149
InlineAsm.h
llvm::Error::success
static ErrorSuccess success()
Create a success value.
Definition: Error.h:329
Errc.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:78
llvm::InlineAsm::getFunctionType
FunctionType * getFunctionType() const
getFunctionType - InlineAsm's are always pointers to functions.
Definition: InlineAsm.cpp:58
llvm::InlineAsm::getType
PointerType * getType() const
getType - InlineAsm's are always pointers.
Definition: InlineAsm.h:77
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:163
E
static GCRegistry::Add< CoreCLRGC > E("coreclr", "CoreCLR-compatible GC")
llvm::InlineAsmKeyType
Definition: ConstantsContext.h:380
llvm::InlineAsm::hasSideEffects
bool hasSideEffects() const
Definition: InlineAsm.h:70
C
(vector float) vec_cmpeq(*A, *B) C
Definition: README_ALTIVEC.txt:86
llvm::LLVMContextImpl
Definition: LLVMContextImpl.h:1355
canThrow
static bool canThrow(const Value *V)
Definition: WebAssemblyLowerEmscriptenEHSjLj.cpp:394
llvm::StringRef::iterator
const char * iterator
Definition: StringRef.h:54
llvm::AMDGPU::PALMD::Key
Key
PAL metadata keys.
Definition: AMDGPUMetadata.h:486
llvm::InlineAsm::isInput
@ isInput
Definition: InlineAsm.h:95
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:43
llvm::InlineAsm::verify
static Error verify(FunctionType *Ty, StringRef Constraints)
This static method can be used by the parser to check to see if the specified constraint string is le...
Definition: InlineAsm.cpp:273
llvm::StringRef::empty
constexpr bool empty() const
empty - Check if the string is empty.
Definition: StringRef.h:134
llvm::InlineAsm
Definition: InlineAsm.h:33
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:73
index
splat index
Definition: README_ALTIVEC.txt:181
llvm::StringRef::end
iterator end() const
Definition: StringRef.h:113
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:1729
I
#define I(x, y, z)
Definition: MD5.cpp:58
llvm::InlineAsm::ConstraintInfo::isEarlyClobber
bool isEarlyClobber
isEarlyClobber - "&": output operand writes result before inputs are all read.
Definition: InlineAsm.h:129
llvm::PointerType
Class to represent pointers.
Definition: DerivedTypes.h:632
llvm::InlineAsm::ConstraintInfo
Definition: InlineAsm.h:122
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:153
ConstantsContext.h
llvm::InlineAsm::collectAsmStrs
void collectAsmStrs(SmallVectorImpl< StringRef > &AsmStrs) const
Definition: InlineAsm.cpp:62
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:108
llvm::InlineAsm::SubConstraintInfo::Codes
ConstraintCodeVector Codes
Code - The constraint code, either the register name (in braces) or the constraint letter/number.
Definition: InlineAsm.h:112
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:50
llvm::cantFail
void cantFail(Error Err, const char *Msg=nullptr)
Report a fatal error if Err is a failure value.
Definition: Error.h:744
Compiler.h
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:327
llvm::AMDGPU::SendMsg::Msg
const CustomOperand< const MCSubtargetInfo & > Msg[]
Definition: AMDGPUAsmUtils.cpp:39
llvm::InlineAsm::ConstraintInfo::multipleAlternatives
SubConstraintInfoVector multipleAlternatives
multipleAlternatives - If there are multiple alternative constraints, this array will contain them.
Definition: InlineAsm.h:160
llvm::InlineAsm::ConstraintInfo::selectAlternative
void selectAlternative(unsigned index)
selectAlternative - Point this constraint to the alternative constraint indicated by the index.
Definition: InlineAsm.cpp:224
llvm::createStringError
Error createStringError(std::error_code EC, char const *Fmt, const Ts &... Vals)
Create formatted StringError object.
Definition: Error.h:1238
llvm::InlineAsm::ConstraintInfo::isMultipleAlternative
bool isMultipleAlternative
isMultipleAlternative - '|': has multiple-alternative constraints.
Definition: InlineAsm.h:156
llvm::InlineAsm::isClobber
@ isClobber
Definition: InlineAsm.h:97
llvm::Error
Lightweight error class with error context and mandatory checking.
Definition: Error.h:155
Casting.h
verify
ppc ctr loops verify
Definition: PPCCTRLoopsVerify.cpp:76
llvm::SmallVectorImpl::clear
void clear()
Definition: SmallVector.h:614
llvm::InlineAsm::isOutput
@ isOutput
Definition: InlineAsm.h:96
llvm::InlineAsm::ParseConstraints
ConstraintInfoVector ParseConstraints() const
ParseConstraints - Parse the constraints of this inlineasm object, returning them the same way that P...
Definition: InlineAsm.h:190
llvm::Type::isStructTy
bool isStructTy() const
True if this is an instance of StructType.
Definition: Type.h:231
N
#define N
llvm::InlineAsm::ConstraintCodeVector
std::vector< std::string > ConstraintCodeVector
Definition: InlineAsm.h:101
llvm::SmallVectorImpl< StringRef >
DerivedTypes.h
llvm::InlineAsm::SubConstraintInfo
Definition: InlineAsm.h:103
LLVMContext.h
makeStringError
static Error makeStringError(const char *Msg)
Definition: InlineAsm.cpp:269
llvm::StringRef::begin
iterator begin() const
Definition: StringRef.h:111
llvm::InlineAsm::isLabel
@ isLabel
Definition: InlineAsm.h:98
Value.h
llvm::StringRef::split
std::pair< StringRef, StringRef > split(char Separator) const
Split into two substrings around the first occurrence of a separator character.
Definition: StringRef.h:692
llvm::FunctionType::getReturnType
Type * getReturnType() const
Definition: DerivedTypes.h:124
llvm::Value
LLVM Value Representation.
Definition: Value.h:74
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:139
llvm::FunctionType
Class to represent function types.
Definition: DerivedTypes.h:103