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/Bitfields.h"
19 #include "llvm/ADT/SmallVector.h"
20 #include "llvm/ADT/StringRef.h"
21 #include "llvm/IR/Value.h"
22 #include "llvm/Support/ErrorHandling.h"
23 #include <cassert>
24 #include <string>
25 #include <vector>
26 
27 namespace llvm {
28 
29 class Error;
30 class FunctionType;
31 class PointerType;
32 template <class ConstantClass> class ConstantUniqueMap;
33 
34 class InlineAsm final : public Value {
35 public:
36   enum AsmDialect {
37     AD_ATT,
38     AD_Intel
39   };
40 
41 private:
42   friend struct InlineAsmKeyType;
43   friend class ConstantUniqueMap<InlineAsm>;
44 
45   std::string AsmString, Constraints;
46   FunctionType *FTy;
47   bool HasSideEffects;
48   bool IsAlignStack;
49   AsmDialect Dialect;
50   bool CanThrow;
51 
52   InlineAsm(FunctionType *Ty, const std::string &AsmString,
53             const std::string &Constraints, bool hasSideEffects,
54             bool isAlignStack, AsmDialect asmDialect, bool canThrow);
55 
56   /// When the ConstantUniqueMap merges two types and makes two InlineAsms
57   /// identical, it destroys one of them with this method.
58   void destroyConstant();
59 
60 public:
61   InlineAsm(const InlineAsm &) = delete;
62   InlineAsm &operator=(const InlineAsm &) = delete;
63 
64   /// InlineAsm::get - Return the specified uniqued inline asm string.
65   ///
66   static InlineAsm *get(FunctionType *Ty, StringRef AsmString,
67                         StringRef Constraints, bool hasSideEffects,
68                         bool isAlignStack = false,
69                         AsmDialect asmDialect = AD_ATT, bool canThrow = false);
70 
hasSideEffects()71   bool hasSideEffects() const { return HasSideEffects; }
isAlignStack()72   bool isAlignStack() const { return IsAlignStack; }
getDialect()73   AsmDialect getDialect() const { return Dialect; }
canThrow()74   bool canThrow() const { return CanThrow; }
75 
76   /// getType - InlineAsm's are always pointers.
77   ///
getType()78   PointerType *getType() const {
79     return reinterpret_cast<PointerType*>(Value::getType());
80   }
81 
82   /// getFunctionType - InlineAsm's are always pointers to functions.
83   ///
84   FunctionType *getFunctionType() const;
85 
getAsmString()86   const std::string &getAsmString() const { return AsmString; }
getConstraintString()87   const std::string &getConstraintString() const { return Constraints; }
88   void collectAsmStrs(SmallVectorImpl<StringRef> &AsmStrs) const;
89 
90   /// This static method can be used by the parser to check to see if the
91   /// specified constraint string is legal for the type.
92   static Error verify(FunctionType *Ty, StringRef Constraints);
93 
94   // Constraint String Parsing
95   enum ConstraintPrefix {
96     isInput,            // 'x'
97     isOutput,           // '=x'
98     isClobber,          // '~x'
99     isLabel,            // '!x'
100   };
101 
102   using ConstraintCodeVector = std::vector<std::string>;
103 
104   struct SubConstraintInfo {
105     /// MatchingInput - If this is not -1, this is an output constraint where an
106     /// input constraint is required to match it (e.g. "0").  The value is the
107     /// constraint number that matches this one (for example, if this is
108     /// constraint #0 and constraint #4 has the value "0", this will be 4).
109     int MatchingInput = -1;
110 
111     /// Code - The constraint code, either the register name (in braces) or the
112     /// constraint letter/number.
113     ConstraintCodeVector Codes;
114 
115     /// Default constructor.
116     SubConstraintInfo() = default;
117   };
118 
119   using SubConstraintInfoVector = std::vector<SubConstraintInfo>;
120   struct ConstraintInfo;
121   using ConstraintInfoVector = std::vector<ConstraintInfo>;
122 
123   struct ConstraintInfo {
124     /// Type - The basic type of the constraint: input/output/clobber/label
125     ///
126     ConstraintPrefix Type = isInput;
127 
128     /// isEarlyClobber - "&": output operand writes result before inputs are all
129     /// read.  This is only ever set for an output operand.
130     bool isEarlyClobber = false;
131 
132     /// MatchingInput - If this is not -1, this is an output constraint where an
133     /// input constraint is required to match it (e.g. "0").  The value is the
134     /// constraint number that matches this one (for example, if this is
135     /// constraint #0 and constraint #4 has the value "0", this will be 4).
136     int MatchingInput = -1;
137 
138     /// hasMatchingInput - Return true if this is an output constraint that has
139     /// a matching input constraint.
hasMatchingInputConstraintInfo140     bool hasMatchingInput() const { return MatchingInput != -1; }
141 
142     /// isCommutative - This is set to true for a constraint that is commutative
143     /// with the next operand.
144     bool isCommutative = false;
145 
146     /// isIndirect - True if this operand is an indirect operand.  This means
147     /// that the address of the source or destination is present in the call
148     /// instruction, instead of it being returned or passed in explicitly.  This
149     /// is represented with a '*' in the asm string.
150     bool isIndirect = false;
151 
152     /// Code - The constraint code, either the register name (in braces) or the
153     /// constraint letter/number.
154     ConstraintCodeVector Codes;
155 
156     /// isMultipleAlternative - '|': has multiple-alternative constraints.
157     bool isMultipleAlternative = false;
158 
159     /// multipleAlternatives - If there are multiple alternative constraints,
160     /// this array will contain them.  Otherwise it will be empty.
161     SubConstraintInfoVector multipleAlternatives;
162 
163     /// The currently selected alternative constraint index.
164     unsigned currentAlternativeIndex = 0;
165 
166     /// Default constructor.
167     ConstraintInfo() = default;
168 
169     /// Parse - Analyze the specified string (e.g. "=*&{eax}") and fill in the
170     /// fields in this structure.  If the constraint string is not understood,
171     /// return true, otherwise return false.
172     bool Parse(StringRef Str, ConstraintInfoVector &ConstraintsSoFar);
173 
174     /// selectAlternative - Point this constraint to the alternative constraint
175     /// indicated by the index.
176     void selectAlternative(unsigned index);
177 
178     /// Whether this constraint corresponds to an argument.
hasArgConstraintInfo179     bool hasArg() const {
180       return Type == isInput || (Type == isOutput && isIndirect);
181     }
182   };
183 
184   /// ParseConstraints - Split up the constraint string into the specific
185   /// constraints and their prefixes.  If this returns an empty vector, and if
186   /// the constraint string itself isn't empty, there was an error parsing.
187   static ConstraintInfoVector ParseConstraints(StringRef ConstraintString);
188 
189   /// ParseConstraints - Parse the constraints of this inlineasm object,
190   /// returning them the same way that ParseConstraints(str) does.
ParseConstraints()191   ConstraintInfoVector ParseConstraints() const {
192     return ParseConstraints(Constraints);
193   }
194 
195   // Methods for support type inquiry through isa, cast, and dyn_cast:
classof(const Value * V)196   static bool classof(const Value *V) {
197     return V->getValueID() == Value::InlineAsmVal;
198   }
199 
200   enum : uint32_t {
201     // Fixed operands on an INLINEASM SDNode.
202     Op_InputChain = 0,
203     Op_AsmString = 1,
204     Op_MDNode = 2,
205     Op_ExtraInfo = 3, // HasSideEffects, IsAlignStack, AsmDialect.
206     Op_FirstOperand = 4,
207 
208     // Fixed operands on an INLINEASM MachineInstr.
209     MIOp_AsmString = 0,
210     MIOp_ExtraInfo = 1, // HasSideEffects, IsAlignStack, AsmDialect.
211     MIOp_FirstOperand = 2,
212 
213     // Interpretation of the MIOp_ExtraInfo bit field.
214     Extra_HasSideEffects = 1,
215     Extra_IsAlignStack = 2,
216     Extra_AsmDialect = 4,
217     Extra_MayLoad = 8,
218     Extra_MayStore = 16,
219     Extra_IsConvergent = 32,
220   };
221 
222   // Inline asm operands map to multiple SDNode / MachineInstr operands.
223   // The first operand is an immediate describing the asm operand, the low
224   // bits is the kind:
225   enum class Kind : uint8_t {
226     RegUse = 1,             // Input register, "r".
227     RegDef = 2,             // Output register, "=r".
228     RegDefEarlyClobber = 3, // Early-clobber output register, "=&r".
229     Clobber = 4,            // Clobbered register, "~r".
230     Imm = 5,                // Immediate.
231     Mem = 6,                // Memory operand, "m", or an address, "p".
232     Func = 7,               // Address operand of function call
233   };
234 
235   // Memory constraint codes.
236   // Addresses are included here as they need to be treated the same by the
237   // backend, the only difference is that they are not used to actaully
238   // access memory by the instruction.
239   enum class ConstraintCode : uint32_t {
240     Unknown = 0,
241     es,
242     i,
243     k,
244     m,
245     o,
246     v,
247     A,
248     Q,
249     R,
250     S,
251     T,
252     Um,
253     Un,
254     Uq,
255     Us,
256     Ut,
257     Uv,
258     Uy,
259     X,
260     Z,
261     ZB,
262     ZC,
263     Zy,
264 
265     // Address constraints
266     p,
267     ZQ,
268     ZR,
269     ZS,
270     ZT,
271 
272     Max = ZT,
273   };
274 
275   // This class is intentionally packed into a 32b value as it is used as a
276   // MVT::i32 ConstantSDNode SDValue for SelectionDAG and as immediate operands
277   // on INLINEASM and INLINEASM_BR MachineInstr's.
278   //
279   // The encoding of Flag is currently:
280   //   Bits 2-0  - A Kind::* value indicating the kind of the operand.
281   //               (KindField)
282   //   Bits 15-3 - The number of SDNode operands associated with this inline
283   //               assembly operand. Once lowered to MIR, this represents the
284   //               number of MachineOperands necessary to refer to a
285   //               MachineOperandType::MO_FrameIndex. (NumOperands)
286   //   Bit 31    - Determines if this is a matched operand. (IsMatched)
287   //   If bit 31 is set:
288   //     Bits 30-16 - The operand number that this operand must match.
289   //                  (MatchedOperandNo)
290   //   Else if bits 2-0 are Kind::Mem:
291   //     Bits 30-16 - A ConstraintCode:: value indicating the original
292   //                  constraint code. (MemConstraintCode)
293   //   Else:
294   //     Bits 29-16 - The register class ID to use for the operand. (RegClass)
295   //     Bit  30    - If the register is permitted to be spilled.
296   //                  (RegMayBeFolded)
297   //                  Defaults to false "r", may be set for constraints like
298   //                  "rm" (or "g").
299   //
300   //   As such, MatchedOperandNo, MemConstraintCode, and
301   //   (RegClass+RegMayBeFolded) are views of the same slice of bits, but are
302   //   mutually exclusive depending on the fields IsMatched then KindField.
303   class Flag {
304     uint32_t Storage;
305     using KindField = Bitfield::Element<Kind, 0, 3, Kind::Func>;
306     using NumOperands = Bitfield::Element<unsigned, 3, 13>;
307     using MatchedOperandNo = Bitfield::Element<unsigned, 16, 15>;
308     using MemConstraintCode = Bitfield::Element<ConstraintCode, 16, 15, ConstraintCode::Max>;
309     using RegClass = Bitfield::Element<unsigned, 16, 14>;
310     using RegMayBeFolded = Bitfield::Element<bool, 30, 1>;
311     using IsMatched = Bitfield::Element<bool, 31, 1>;
312 
313 
getMatchedOperandNo()314     unsigned getMatchedOperandNo() const { return Bitfield::get<MatchedOperandNo>(Storage); }
getRegClass()315     unsigned getRegClass() const { return Bitfield::get<RegClass>(Storage); }
isMatched()316     bool isMatched() const { return Bitfield::get<IsMatched>(Storage); }
317 
318   public:
Flag()319     Flag() : Storage(0) {}
Flag(uint32_t F)320     explicit Flag(uint32_t F) : Storage(F) {}
Flag(enum Kind K,unsigned NumOps)321     Flag(enum Kind K, unsigned NumOps) : Storage(0) {
322       Bitfield::set<KindField>(Storage, K);
323       Bitfield::set<NumOperands>(Storage, NumOps);
324     }
uint32_t()325     operator uint32_t() { return Storage; }
getKind()326     Kind getKind() const { return Bitfield::get<KindField>(Storage); }
isRegUseKind()327     bool isRegUseKind() const { return getKind() == Kind::RegUse; }
isRegDefKind()328     bool isRegDefKind() const { return getKind() == Kind::RegDef; }
isRegDefEarlyClobberKind()329     bool isRegDefEarlyClobberKind() const {
330       return getKind() == Kind::RegDefEarlyClobber;
331     }
isClobberKind()332     bool isClobberKind() const { return getKind() == Kind::Clobber; }
isImmKind()333     bool isImmKind() const { return getKind() == Kind::Imm; }
isMemKind()334     bool isMemKind() const { return getKind() == Kind::Mem; }
isFuncKind()335     bool isFuncKind() const { return getKind() == Kind::Func; }
getKindName()336     StringRef getKindName() const {
337       switch (getKind()) {
338       case Kind::RegUse:
339         return "reguse";
340       case Kind::RegDef:
341         return "regdef";
342       case Kind::RegDefEarlyClobber:
343         return "regdef-ec";
344       case Kind::Clobber:
345         return "clobber";
346       case Kind::Imm:
347         return "imm";
348       case Kind::Mem:
349       case Kind::Func:
350         return "mem";
351       }
352       llvm_unreachable("impossible kind");
353     }
354 
355     /// getNumOperandRegisters - Extract the number of registers field from the
356     /// inline asm operand flag.
getNumOperandRegisters()357     unsigned getNumOperandRegisters() const {
358       return Bitfield::get<NumOperands>(Storage);
359     }
360 
361     /// isUseOperandTiedToDef - Return true if the flag of the inline asm
362     /// operand indicates it is an use operand that's matched to a def operand.
isUseOperandTiedToDef(unsigned & Idx)363     bool isUseOperandTiedToDef(unsigned &Idx) const {
364       if (!isMatched())
365         return false;
366       Idx = getMatchedOperandNo();
367       return true;
368     }
369 
370     /// hasRegClassConstraint - Returns true if the flag contains a register
371     /// class constraint.  Sets RC to the register class ID.
hasRegClassConstraint(unsigned & RC)372     bool hasRegClassConstraint(unsigned &RC) const {
373       if (isMatched())
374         return false;
375       // setRegClass() uses 0 to mean no register class, and otherwise stores
376       // RC + 1.
377       if (!getRegClass())
378         return false;
379       RC = getRegClass() - 1;
380       return true;
381     }
382 
getMemoryConstraintID()383     ConstraintCode getMemoryConstraintID() const {
384       assert((isMemKind() || isFuncKind()) &&
385              "Not expected mem or function flag!");
386       return Bitfield::get<MemConstraintCode>(Storage);
387     }
388 
389     /// setMatchingOp - Augment an existing flag with information indicating
390     /// that this input operand is tied to a previous output operand.
setMatchingOp(unsigned OperandNo)391     void setMatchingOp(unsigned OperandNo) {
392       assert(getMatchedOperandNo() == 0 && "Matching operand already set");
393       Bitfield::set<MatchedOperandNo>(Storage, OperandNo);
394       Bitfield::set<IsMatched>(Storage, true);
395     }
396 
397     /// setRegClass - Augment an existing flag with the required register class
398     /// for the following register operands. A tied use operand cannot have a
399     /// register class, use the register class from the def operand instead.
setRegClass(unsigned RC)400     void setRegClass(unsigned RC) {
401       assert(!isImmKind() && "Immediates cannot have a register class");
402       assert(!isMemKind() && "Memory operand cannot have a register class");
403       assert(getRegClass() == 0 && "Register class already set");
404       // Store RC + 1, reserve the value 0 to mean 'no register class'.
405       Bitfield::set<RegClass>(Storage, RC + 1);
406     }
407 
408     /// setMemConstraint - Augment an existing flag with the constraint code for
409     /// a memory constraint.
setMemConstraint(ConstraintCode C)410     void setMemConstraint(ConstraintCode C) {
411       assert(getMemoryConstraintID() == ConstraintCode::Unknown && "Mem constraint already set");
412       Bitfield::set<MemConstraintCode>(Storage, C);
413     }
414     /// clearMemConstraint - Similar to setMemConstraint(0), but without the
415     /// assertion checking that the constraint has not been set previously.
clearMemConstraint()416     void clearMemConstraint() {
417       assert((isMemKind() || isFuncKind()) &&
418              "Flag is not a memory or function constraint!");
419       Bitfield::set<MemConstraintCode>(Storage, ConstraintCode::Unknown);
420     }
421 
422     /// Set a bit to denote that while this operand is some kind of register
423     /// (use, def, ...), a memory flag did appear in the original constraint
424     /// list.  This is set by the instruction selection framework, and consumed
425     /// by the register allocator. While the register allocator is generally
426     /// responsible for spilling registers, we need to be able to distinguish
427     /// between registers that the register allocator has permission to fold
428     /// ("rm") vs ones it does not ("r"). This is because the inline asm may use
429     /// instructions which don't support memory addressing modes for that
430     /// operand.
setRegMayBeFolded(bool B)431     void setRegMayBeFolded(bool B) {
432       assert((isRegDefKind() || isRegDefEarlyClobberKind() || isRegUseKind()) &&
433              "Must be reg");
434       Bitfield::set<RegMayBeFolded>(Storage, B);
435     }
getRegMayBeFolded()436     bool getRegMayBeFolded() const {
437       assert((isRegDefKind() || isRegDefEarlyClobberKind() || isRegUseKind()) &&
438              "Must be reg");
439       return Bitfield::get<RegMayBeFolded>(Storage);
440     }
441   };
442 
getExtraInfoNames(unsigned ExtraInfo)443   static std::vector<StringRef> getExtraInfoNames(unsigned ExtraInfo) {
444     std::vector<StringRef> Result;
445     if (ExtraInfo & InlineAsm::Extra_HasSideEffects)
446       Result.push_back("sideeffect");
447     if (ExtraInfo & InlineAsm::Extra_MayLoad)
448       Result.push_back("mayload");
449     if (ExtraInfo & InlineAsm::Extra_MayStore)
450       Result.push_back("maystore");
451     if (ExtraInfo & InlineAsm::Extra_IsConvergent)
452       Result.push_back("isconvergent");
453     if (ExtraInfo & InlineAsm::Extra_IsAlignStack)
454       Result.push_back("alignstack");
455 
456     AsmDialect Dialect =
457         InlineAsm::AsmDialect((ExtraInfo & InlineAsm::Extra_AsmDialect));
458 
459     if (Dialect == InlineAsm::AD_ATT)
460       Result.push_back("attdialect");
461     if (Dialect == InlineAsm::AD_Intel)
462       Result.push_back("inteldialect");
463 
464     return Result;
465   }
466 
getMemConstraintName(ConstraintCode C)467   static StringRef getMemConstraintName(ConstraintCode C) {
468     switch (C) {
469     case ConstraintCode::es:
470       return "es";
471     case ConstraintCode::i:
472       return "i";
473     case ConstraintCode::k:
474       return "k";
475     case ConstraintCode::m:
476       return "m";
477     case ConstraintCode::o:
478       return "o";
479     case ConstraintCode::v:
480       return "v";
481     case ConstraintCode::A:
482       return "A";
483     case ConstraintCode::Q:
484       return "Q";
485     case ConstraintCode::R:
486       return "R";
487     case ConstraintCode::S:
488       return "S";
489     case ConstraintCode::T:
490       return "T";
491     case ConstraintCode::Um:
492       return "Um";
493     case ConstraintCode::Un:
494       return "Un";
495     case ConstraintCode::Uq:
496       return "Uq";
497     case ConstraintCode::Us:
498       return "Us";
499     case ConstraintCode::Ut:
500       return "Ut";
501     case ConstraintCode::Uv:
502       return "Uv";
503     case ConstraintCode::Uy:
504       return "Uy";
505     case ConstraintCode::X:
506       return "X";
507     case ConstraintCode::Z:
508       return "Z";
509     case ConstraintCode::ZB:
510       return "ZB";
511     case ConstraintCode::ZC:
512       return "ZC";
513     case ConstraintCode::Zy:
514       return "Zy";
515     case ConstraintCode::p:
516       return "p";
517     case ConstraintCode::ZQ:
518       return "ZQ";
519     case ConstraintCode::ZR:
520       return "ZR";
521     case ConstraintCode::ZS:
522       return "ZS";
523     case ConstraintCode::ZT:
524       return "ZT";
525     default:
526       llvm_unreachable("Unknown memory constraint");
527     }
528   }
529 };
530 
531 } // end namespace llvm
532 
533 #endif // LLVM_IR_INLINEASM_H
534