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