1//===- llvm/InlineAsm.h - Class to represent inline asm strings -*- C++ -*-===//
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 class represents the inline asm strings, which are Value*'s that are
10// used as the callee operand of call instructions. InlineAsm's are uniqued
11// like constants, and created via InlineAsm::get(...).
12//
13//===----------------------------------------------------------------------===//
14
15#ifndef LLVM_IR_INLINEASM_H
16#define LLVM_IR_INLINEASM_H
17
18#include "llvm/ADT/StringRef.h"
19#include "llvm/IR/Value.h"
20#include "llvm/Support/ErrorHandling.h"
21#include <cassert>
22#include <string>
23#include <vector>
24
25namespace llvm {
26
27class FunctionType;
28class PointerType;
29template <class ConstantClass> class ConstantUniqueMap;
30
31class InlineAsm final : public Value {
32public:
33 enum AsmDialect {
34 AD_ATT,
35 AD_Intel
36 };
37
38private:
39 friend struct InlineAsmKeyType;
40 friend class ConstantUniqueMap<InlineAsm>;
41
42 std::string AsmString, Constraints;
43 FunctionType *FTy;
44 bool HasSideEffects;
45 bool IsAlignStack;
46 AsmDialect Dialect;
47 bool CanThrow;
48
49 InlineAsm(FunctionType *Ty, const std::string &AsmString,
50 const std::string &Constraints, bool hasSideEffects,
51 bool isAlignStack, AsmDialect asmDialect, bool canThrow);
52
53 /// When the ConstantUniqueMap merges two types and makes two InlineAsms
54 /// identical, it destroys one of them with this method.
55 void destroyConstant();
56
57public:
58 InlineAsm(const InlineAsm &) = delete;
59 InlineAsm &operator=(const InlineAsm &) = delete;
60
61 /// InlineAsm::get - Return the specified uniqued inline asm string.
62 ///
63 static InlineAsm *get(FunctionType *Ty, StringRef AsmString,
64 StringRef Constraints, bool hasSideEffects,
65 bool isAlignStack = false,
66 AsmDialect asmDialect = AD_ATT, bool canThrow = false);
67
68 bool hasSideEffects() const { return HasSideEffects; }
69 bool isAlignStack() const { return IsAlignStack; }
70 AsmDialect getDialect() const { return Dialect; }
71 bool canThrow() const { return CanThrow; }
72
73 /// getType - InlineAsm's are always pointers.
74 ///
75 PointerType *getType() const {
76 return reinterpret_cast<PointerType*>(Value::getType());
77 }
78
79 /// getFunctionType - InlineAsm's are always pointers to functions.
80 ///
81 FunctionType *getFunctionType() const;
82
83 const std::string &getAsmString() const { return AsmString; }
84 const std::string &getConstraintString() const { return Constraints; }
85
86 /// Verify - This static method can be used by the parser to check to see if
87 /// the specified constraint string is legal for the type. This returns true
88 /// if legal, false if not.
89 ///
90 static bool Verify(FunctionType *Ty, StringRef Constraints);
91
92 // Constraint String Parsing
93 enum ConstraintPrefix {
94 isInput, // 'x'
95 isOutput, // '=x'
96 isClobber // '~x'
97 };
98
99 using ConstraintCodeVector = std::vector<std::string>;
100
101 struct SubConstraintInfo {
102 /// MatchingInput - If this is not -1, this is an output constraint where an
103 /// input constraint is required to match it (e.g. "0"). The value is the
104 /// constraint number that matches this one (for example, if this is
105 /// constraint #0 and constraint #4 has the value "0", this will be 4).
106 int MatchingInput = -1;
107
108 /// Code - The constraint code, either the register name (in braces) or the
109 /// constraint letter/number.
110 ConstraintCodeVector Codes;
111
112 /// Default constructor.
113 SubConstraintInfo() = default;
114 };
115
116 using SubConstraintInfoVector = std::vector<SubConstraintInfo>;
117 struct ConstraintInfo;
118 using ConstraintInfoVector = std::vector<ConstraintInfo>;
119
120 struct ConstraintInfo {
121 /// Type - The basic type of the constraint: input/output/clobber
122 ///
123 ConstraintPrefix Type = isInput;
124
125 /// isEarlyClobber - "&": output operand writes result before inputs are all
126 /// read. This is only ever set for an output operand.
127 bool isEarlyClobber = false;
128
129 /// MatchingInput - If this is not -1, this is an output constraint where an
130 /// input constraint is required to match it (e.g. "0"). The value is the
131 /// constraint number that matches this one (for example, if this is
132 /// constraint #0 and constraint #4 has the value "0", this will be 4).
133 int MatchingInput = -1;
134
135 /// hasMatchingInput - Return true if this is an output constraint that has
136 /// a matching input constraint.
137 bool hasMatchingInput() const { return MatchingInput != -1; }
138
139 /// isCommutative - This is set to true for a constraint that is commutative
140 /// with the next operand.
141 bool isCommutative = false;
142
143 /// isIndirect - True if this operand is an indirect operand. This means
144 /// that the address of the source or destination is present in the call
145 /// instruction, instead of it being returned or passed in explicitly. This
146 /// is represented with a '*' in the asm string.
147 bool isIndirect = false;
148
149 /// Code - The constraint code, either the register name (in braces) or the
150 /// constraint letter/number.
151 ConstraintCodeVector Codes;
152
153 /// isMultipleAlternative - '|': has multiple-alternative constraints.
154 bool isMultipleAlternative = false;
155
156 /// multipleAlternatives - If there are multiple alternative constraints,
157 /// this array will contain them. Otherwise it will be empty.
158 SubConstraintInfoVector multipleAlternatives;
159
160 /// The currently selected alternative constraint index.
161 unsigned currentAlternativeIndex = 0;
162
163 /// Default constructor.
164 ConstraintInfo() = default;
165
166 /// Parse - Analyze the specified string (e.g. "=*&{eax}") and fill in the
167 /// fields in this structure. If the constraint string is not understood,
168 /// return true, otherwise return false.
169 bool Parse(StringRef Str, ConstraintInfoVector &ConstraintsSoFar);
170
171 /// selectAlternative - Point this constraint to the alternative constraint
172 /// indicated by the index.
173 void selectAlternative(unsigned index);
174
175 /// Whether this constraint corresponds to an argument.
176 bool hasArg() const {
177 return Type == isInput || (Type == isOutput && isIndirect);
178 }
179 };
180
181 /// ParseConstraints - Split up the constraint string into the specific
182 /// constraints and their prefixes. If this returns an empty vector, and if
183 /// the constraint string itself isn't empty, there was an error parsing.
184 static ConstraintInfoVector ParseConstraints(StringRef ConstraintString);
185
186 /// ParseConstraints - Parse the constraints of this inlineasm object,
187 /// returning them the same way that ParseConstraints(str) does.
188 ConstraintInfoVector ParseConstraints() const {
189 return ParseConstraints(Constraints);
190 }
191
192 // Methods for support type inquiry through isa, cast, and dyn_cast:
193 static bool classof(const Value *V) {
194 return V->getValueID() == Value::InlineAsmVal;
195 }
196
197 // These are helper methods for dealing with flags in the INLINEASM SDNode
198 // in the backend.
199 //
200 // The encoding of the flag word is currently:
201 // Bits 2-0 - A Kind_* value indicating the kind of the operand.
202 // Bits 15-3 - The number of SDNode operands associated with this inline
203 // assembly operand.
204 // If bit 31 is set:
205 // Bit 30-16 - The operand number that this operand must match.
206 // When bits 2-0 are Kind_Mem, the Constraint_* value must be
207 // obtained from the flags for this operand number.
208 // Else if bits 2-0 are Kind_Mem:
209 // Bit 30-16 - A Constraint_* value indicating the original constraint
210 // code.
211 // Else:
212 // Bit 30-16 - The register class ID to use for the operand.
213
214 enum : uint32_t {
215 // Fixed operands on an INLINEASM SDNode.
216 Op_InputChain = 0,
217 Op_AsmString = 1,
218 Op_MDNode = 2,
219 Op_ExtraInfo = 3, // HasSideEffects, IsAlignStack, AsmDialect.
220 Op_FirstOperand = 4,
221
222 // Fixed operands on an INLINEASM MachineInstr.
223 MIOp_AsmString = 0,
224 MIOp_ExtraInfo = 1, // HasSideEffects, IsAlignStack, AsmDialect.
225 MIOp_FirstOperand = 2,
226
227 // Interpretation of the MIOp_ExtraInfo bit field.
228 Extra_HasSideEffects = 1,
229 Extra_IsAlignStack = 2,
230 Extra_AsmDialect = 4,
231 Extra_MayLoad = 8,
232 Extra_MayStore = 16,
233 Extra_IsConvergent = 32,
234
235 // Inline asm operands map to multiple SDNode / MachineInstr operands.
236 // The first operand is an immediate describing the asm operand, the low
237 // bits is the kind:
238 Kind_RegUse = 1, // Input register, "r".
239 Kind_RegDef = 2, // Output register, "=r".
240 Kind_RegDefEarlyClobber = 3, // Early-clobber output register, "=&r".
241 Kind_Clobber = 4, // Clobbered register, "~r".
242 Kind_Imm = 5, // Immediate.
243 Kind_Mem = 6, // Memory operand, "m".
244
245 // Memory constraint codes.
246 // These could be tablegenerated but there's little need to do that since
247 // there's plenty of space in the encoding to support the union of all
248 // constraint codes for all targets.
249 Constraint_Unknown = 0,
250 Constraint_es,
251 Constraint_i,
252 Constraint_m,
253 Constraint_o,
254 Constraint_v,
255 Constraint_A,
256 Constraint_Q,
257 Constraint_R,
258 Constraint_S,
259 Constraint_T,
260 Constraint_Um,
261 Constraint_Un,
262 Constraint_Uq,
263 Constraint_Us,
264 Constraint_Ut,
265 Constraint_Uv,
266 Constraint_Uy,
267 Constraint_X,
268 Constraint_Z,
269 Constraint_ZC,
270 Constraint_Zy,
271 Constraints_Max = Constraint_Zy,
272 Constraints_ShiftAmount = 16,
273
274 Flag_MatchingOperand = 0x80000000
275 };
276
277 static unsigned getFlagWord(unsigned Kind, unsigned NumOps) {
278 assert(((NumOps << 3) & ~0xffff) == 0 && "Too many inline asm operands!");
279 assert(Kind >= Kind_RegUse && Kind <= Kind_Mem && "Invalid Kind");
280 return Kind | (NumOps << 3);
281 }
282
283 static bool isRegDefKind(unsigned Flag){ return getKind(Flag) == Kind_RegDef;}
284 static bool isImmKind(unsigned Flag) { return getKind(Flag) == Kind_Imm; }
285 static bool isMemKind(unsigned Flag) { return getKind(Flag) == Kind_Mem; }
286 static bool isRegDefEarlyClobberKind(unsigned Flag) {
287 return getKind(Flag) == Kind_RegDefEarlyClobber;
288 }
289 static bool isClobberKind(unsigned Flag) {
290 return getKind(Flag) == Kind_Clobber;
291 }
292
293 /// getFlagWordForMatchingOp - Augment an existing flag word returned by
294 /// getFlagWord with information indicating that this input operand is tied
295 /// to a previous output operand.
296 static unsigned getFlagWordForMatchingOp(unsigned InputFlag,
297 unsigned MatchedOperandNo) {
298 assert(MatchedOperandNo <= 0x7fff && "Too big matched operand");
299 assert((InputFlag & ~0xffff) == 0 && "High bits already contain data");
300 return InputFlag | Flag_MatchingOperand | (MatchedOperandNo << 16);
301 }
302
303 /// getFlagWordForRegClass - Augment an existing flag word returned by
304 /// getFlagWord with the required register class for the following register
305 /// operands.
306 /// A tied use operand cannot have a register class, use the register class
307 /// from the def operand instead.
308 static unsigned getFlagWordForRegClass(unsigned InputFlag, unsigned RC) {
309 // Store RC + 1, reserve the value 0 to mean 'no register class'.
310 ++RC;
311 assert(!isImmKind(InputFlag) && "Immediates cannot have a register class");
312 assert(!isMemKind(InputFlag) && "Memory operand cannot have a register class");
313 assert(RC <= 0x7fff && "Too large register class ID");
314 assert((InputFlag & ~0xffff) == 0 && "High bits already contain data");
315 return InputFlag | (RC << 16);
316 }
317
318 /// Augment an existing flag word returned by getFlagWord with the constraint
319 /// code for a memory constraint.
320 static unsigned getFlagWordForMem(unsigned InputFlag, unsigned Constraint) {
321 assert(isMemKind(InputFlag) && "InputFlag is not a memory constraint!");
322 assert(Constraint <= 0x7fff && "Too large a memory constraint ID");
323 assert(Constraint <= Constraints_Max && "Unknown constraint ID");
324 assert((InputFlag & ~0xffff) == 0 && "High bits already contain data");
325 return InputFlag | (Constraint << Constraints_ShiftAmount);
326 }
327
328 static unsigned convertMemFlagWordToMatchingFlagWord(unsigned InputFlag) {
329 assert(isMemKind(InputFlag));
330 return InputFlag & ~(0x7fff << Constraints_ShiftAmount);
331 }
332
333 static unsigned getKind(unsigned Flags) {
334 return Flags & 7;
335 }
336
337 static unsigned getMemoryConstraintID(unsigned Flag) {
338 assert(isMemKind(Flag));
339 return (Flag >> Constraints_ShiftAmount) & 0x7fff;
340 }
341
342 /// getNumOperandRegisters - Extract the number of registers field from the
343 /// inline asm operand flag.
344 static unsigned getNumOperandRegisters(unsigned Flag) {
345 return (Flag & 0xffff) >> 3;
346 }
347
348 /// isUseOperandTiedToDef - Return true if the flag of the inline asm
349 /// operand indicates it is an use operand that's matched to a def operand.
350 static bool isUseOperandTiedToDef(unsigned Flag, unsigned &Idx) {
351 if ((Flag & Flag_MatchingOperand) == 0)
352 return false;
353 Idx = (Flag & ~Flag_MatchingOperand) >> 16;
354 return true;
355 }
356
357 /// hasRegClassConstraint - Returns true if the flag contains a register
358 /// class constraint. Sets RC to the register class ID.
359 static bool hasRegClassConstraint(unsigned Flag, unsigned &RC) {
360 if (Flag & Flag_MatchingOperand)
361 return false;
362 unsigned High = Flag >> 16;
363 // getFlagWordForRegClass() uses 0 to mean no register class, and otherwise
364 // stores RC + 1.
365 if (!High)
366 return false;
367 RC = High - 1;
368 return true;
369 }
370
371 static std::vector<StringRef> getExtraInfoNames(unsigned ExtraInfo) {
372 std::vector<StringRef> Result;
373 if (ExtraInfo & InlineAsm::Extra_HasSideEffects)
374 Result.push_back("sideeffect");
375 if (ExtraInfo & InlineAsm::Extra_MayLoad)
376 Result.push_back("mayload");
377 if (ExtraInfo & InlineAsm::Extra_MayStore)
378 Result.push_back("maystore");
379 if (ExtraInfo & InlineAsm::Extra_IsConvergent)
380 Result.push_back("isconvergent");
381 if (ExtraInfo & InlineAsm::Extra_IsAlignStack)
382 Result.push_back("alignstack");
383
384 AsmDialect Dialect =
385 InlineAsm::AsmDialect((ExtraInfo & InlineAsm::Extra_AsmDialect));
386
387 if (Dialect == InlineAsm::AD_ATT)
388 Result.push_back("attdialect");
389 if (Dialect == InlineAsm::AD_Intel)
390 Result.push_back("inteldialect");
391
392 return Result;
393 }
394
395 static StringRef getKindName(unsigned Kind) {
396 switch (Kind) {
397 case InlineAsm::Kind_RegUse:
398 return "reguse";
399 case InlineAsm::Kind_RegDef:
400 return "regdef";
401 case InlineAsm::Kind_RegDefEarlyClobber:
402 return "regdef-ec";
403 case InlineAsm::Kind_Clobber:
404 return "clobber";
405 case InlineAsm::Kind_Imm:
406 return "imm";
407 case InlineAsm::Kind_Mem:
408 return "mem";
409 default:
410 llvm_unreachable("Unknown operand kind");
411 }
412 }
413
414 static StringRef getMemConstraintName(unsigned Constraint) {
415 switch (Constraint) {
416 case InlineAsm::Constraint_es:
417 return "es";
418 case InlineAsm::Constraint_i:
419 return "i";
420 case InlineAsm::Constraint_m:
421 return "m";
422 case InlineAsm::Constraint_o:
423 return "o";
424 case InlineAsm::Constraint_v:
425 return "v";
426 case InlineAsm::Constraint_Q:
427 return "Q";
428 case InlineAsm::Constraint_R:
429 return "R";
430 case InlineAsm::Constraint_S:
431 return "S";
432 case InlineAsm::Constraint_T:
433 return "T";
434 case InlineAsm::Constraint_Um:
435 return "Um";
436 case InlineAsm::Constraint_Un:
437 return "Un";
438 case InlineAsm::Constraint_Uq:
439 return "Uq";
440 case InlineAsm::Constraint_Us:
441 return "Us";
442 case InlineAsm::Constraint_Ut:
443 return "Ut";
444 case InlineAsm::Constraint_Uv:
445 return "Uv";
446 case InlineAsm::Constraint_Uy:
447 return "Uy";
448 case InlineAsm::Constraint_X:
449 return "X";
450 case InlineAsm::Constraint_Z:
451 return "Z";
452 case InlineAsm::Constraint_ZC:
453 return "ZC";
454 case InlineAsm::Constraint_Zy:
455 return "Zy";
456 default:
457 llvm_unreachable("Unknown memory constraint");
458 }
459 }
460};
461
462} // end namespace llvm
463
464#endif // LLVM_IR_INLINEASM_H
465