- //===- llvm/InlineAsm.h - Class to represent inline asm strings -*- C++ -*-===// 
- // 
- // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 
- // See https://llvm.org/LICENSE.txt for license information. 
- // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 
- // 
- //===----------------------------------------------------------------------===// 
- // 
- // This class represents the inline asm strings, which are Value*'s that are 
- // used as the callee operand of call instructions.  InlineAsm's are uniqued 
- // like constants, and created via InlineAsm::get(...). 
- // 
- //===----------------------------------------------------------------------===// 
-   
- #ifndef LLVM_IR_INLINEASM_H 
- #define LLVM_IR_INLINEASM_H 
-   
- #include "llvm/ADT/SmallVector.h" 
- #include "llvm/ADT/StringRef.h" 
- #include "llvm/IR/Value.h" 
- #include "llvm/Support/ErrorHandling.h" 
- #include <cassert> 
- #include <string> 
- #include <vector> 
-   
- namespace llvm { 
-   
- class Error; 
- class FunctionType; 
- class PointerType; 
- template <class ConstantClass> class ConstantUniqueMap; 
-   
- class InlineAsm final : public Value { 
- public: 
-   enum AsmDialect { 
-     AD_ATT, 
-     AD_Intel 
-   }; 
-   
- private: 
-   friend struct InlineAsmKeyType; 
-   friend class ConstantUniqueMap<InlineAsm>; 
-   
-   std::string AsmString, Constraints; 
-   FunctionType *FTy; 
-   bool HasSideEffects; 
-   bool IsAlignStack; 
-   AsmDialect Dialect; 
-   bool CanThrow; 
-   
-   InlineAsm(FunctionType *Ty, const std::string &AsmString, 
-             const std::string &Constraints, bool hasSideEffects, 
-             bool isAlignStack, AsmDialect asmDialect, bool canThrow); 
-   
-   /// When the ConstantUniqueMap merges two types and makes two InlineAsms 
-   /// identical, it destroys one of them with this method. 
-   void destroyConstant(); 
-   
- public: 
-   InlineAsm(const InlineAsm &) = delete; 
-   InlineAsm &operator=(const InlineAsm &) = delete; 
-   
-   /// InlineAsm::get - Return the specified uniqued inline asm string. 
-   /// 
-   static InlineAsm *get(FunctionType *Ty, StringRef AsmString, 
-                         StringRef Constraints, bool hasSideEffects, 
-                         bool isAlignStack = false, 
-                         AsmDialect asmDialect = AD_ATT, bool canThrow = false); 
-   
-   bool hasSideEffects() const { return HasSideEffects; } 
-   bool isAlignStack() const { return IsAlignStack; } 
-   AsmDialect getDialect() const { return Dialect; } 
-   bool canThrow() const { return CanThrow; } 
-   
-   /// getType - InlineAsm's are always pointers. 
-   /// 
-   PointerType *getType() const { 
-     return reinterpret_cast<PointerType*>(Value::getType()); 
-   } 
-   
-   /// getFunctionType - InlineAsm's are always pointers to functions. 
-   /// 
-   FunctionType *getFunctionType() const; 
-   
-   const std::string &getAsmString() const { return AsmString; } 
-   const std::string &getConstraintString() const { return Constraints; } 
-   void collectAsmStrs(SmallVectorImpl<StringRef> &AsmStrs) const; 
-   
-   /// This static method can be used by the parser to check to see if the 
-   /// specified constraint string is legal for the type. 
-   static Error verify(FunctionType *Ty, StringRef Constraints); 
-   
-   // Constraint String Parsing 
-   enum ConstraintPrefix { 
-     isInput,            // 'x' 
-     isOutput,           // '=x' 
-     isClobber,          // '~x' 
-     isLabel,            // '!x' 
-   }; 
-   
-   using ConstraintCodeVector = std::vector<std::string>; 
-   
-   struct SubConstraintInfo { 
-     /// MatchingInput - If this is not -1, this is an output constraint where an 
-     /// input constraint is required to match it (e.g. "0").  The value is the 
-     /// constraint number that matches this one (for example, if this is 
-     /// constraint #0 and constraint #4 has the value "0", this will be 4). 
-     int MatchingInput = -1; 
-   
-     /// Code - The constraint code, either the register name (in braces) or the 
-     /// constraint letter/number. 
-     ConstraintCodeVector Codes; 
-   
-     /// Default constructor. 
-     SubConstraintInfo() = default; 
-   }; 
-   
-   using SubConstraintInfoVector = std::vector<SubConstraintInfo>; 
-   struct ConstraintInfo; 
-   using ConstraintInfoVector = std::vector<ConstraintInfo>; 
-   
-   struct ConstraintInfo { 
-     /// Type - The basic type of the constraint: input/output/clobber/label 
-     /// 
-     ConstraintPrefix Type = isInput; 
-   
-     /// isEarlyClobber - "&": output operand writes result before inputs are all 
-     /// read.  This is only ever set for an output operand. 
-     bool isEarlyClobber = false; 
-   
-     /// MatchingInput - If this is not -1, this is an output constraint where an 
-     /// input constraint is required to match it (e.g. "0").  The value is the 
-     /// constraint number that matches this one (for example, if this is 
-     /// constraint #0 and constraint #4 has the value "0", this will be 4). 
-     int MatchingInput = -1; 
-   
-     /// hasMatchingInput - Return true if this is an output constraint that has 
-     /// a matching input constraint. 
-     bool hasMatchingInput() const { return MatchingInput != -1; } 
-   
-     /// isCommutative - This is set to true for a constraint that is commutative 
-     /// with the next operand. 
-     bool isCommutative = false; 
-   
-     /// isIndirect - True if this operand is an indirect operand.  This means 
-     /// that the address of the source or destination is present in the call 
-     /// instruction, instead of it being returned or passed in explicitly.  This 
-     /// is represented with a '*' in the asm string. 
-     bool isIndirect = false; 
-   
-     /// Code - The constraint code, either the register name (in braces) or the 
-     /// constraint letter/number. 
-     ConstraintCodeVector Codes; 
-   
-     /// isMultipleAlternative - '|': has multiple-alternative constraints. 
-     bool isMultipleAlternative = false; 
-   
-     /// multipleAlternatives - If there are multiple alternative constraints, 
-     /// this array will contain them.  Otherwise it will be empty. 
-     SubConstraintInfoVector multipleAlternatives; 
-   
-     /// The currently selected alternative constraint index. 
-     unsigned currentAlternativeIndex = 0; 
-   
-     /// Default constructor. 
-     ConstraintInfo() = default; 
-   
-     /// Parse - Analyze the specified string (e.g. "=*&{eax}") and fill in the 
-     /// fields in this structure.  If the constraint string is not understood, 
-     /// return true, otherwise return false. 
-     bool Parse(StringRef Str, ConstraintInfoVector &ConstraintsSoFar); 
-   
-     /// selectAlternative - Point this constraint to the alternative constraint 
-     /// indicated by the index. 
-     void selectAlternative(unsigned index); 
-   
-     /// Whether this constraint corresponds to an argument. 
-     bool hasArg() const { 
-       return Type == isInput || (Type == isOutput && isIndirect); 
-     } 
-   }; 
-   
-   /// ParseConstraints - Split up the constraint string into the specific 
-   /// constraints and their prefixes.  If this returns an empty vector, and if 
-   /// the constraint string itself isn't empty, there was an error parsing. 
-   static ConstraintInfoVector ParseConstraints(StringRef ConstraintString); 
-   
-   /// ParseConstraints - Parse the constraints of this inlineasm object, 
-   /// returning them the same way that ParseConstraints(str) does. 
-   ConstraintInfoVector ParseConstraints() const { 
-     return ParseConstraints(Constraints); 
-   } 
-   
-   // Methods for support type inquiry through isa, cast, and dyn_cast: 
-   static bool classof(const Value *V) { 
-     return V->getValueID() == Value::InlineAsmVal; 
-   } 
-   
-   // These are helper methods for dealing with flags in the INLINEASM SDNode 
-   // in the backend. 
-   // 
-   // The encoding of the flag word is currently: 
-   //   Bits 2-0 - A Kind_* value indicating the kind of the operand. 
-   //   Bits 15-3 - The number of SDNode operands associated with this inline 
-   //               assembly operand. 
-   //   If bit 31 is set: 
-   //     Bit 30-16 - The operand number that this operand must match. 
-   //                 When bits 2-0 are Kind_Mem, the Constraint_* value must be 
-   //                 obtained from the flags for this operand number. 
-   //   Else if bits 2-0 are Kind_Mem: 
-   //     Bit 30-16 - A Constraint_* value indicating the original constraint 
-   //                 code. 
-   //   Else: 
-   //     Bit 30-16 - The register class ID to use for the operand. 
-   
-   enum : uint32_t { 
-     // Fixed operands on an INLINEASM SDNode. 
-     Op_InputChain = 0, 
-     Op_AsmString = 1, 
-     Op_MDNode = 2, 
-     Op_ExtraInfo = 3,    // HasSideEffects, IsAlignStack, AsmDialect. 
-     Op_FirstOperand = 4, 
-   
-     // Fixed operands on an INLINEASM MachineInstr. 
-     MIOp_AsmString = 0, 
-     MIOp_ExtraInfo = 1,    // HasSideEffects, IsAlignStack, AsmDialect. 
-     MIOp_FirstOperand = 2, 
-   
-     // Interpretation of the MIOp_ExtraInfo bit field. 
-     Extra_HasSideEffects = 1, 
-     Extra_IsAlignStack = 2, 
-     Extra_AsmDialect = 4, 
-     Extra_MayLoad = 8, 
-     Extra_MayStore = 16, 
-     Extra_IsConvergent = 32, 
-   
-     // Inline asm operands map to multiple SDNode / MachineInstr operands. 
-     // The first operand is an immediate describing the asm operand, the low 
-     // bits is the kind: 
-     Kind_RegUse = 1,             // Input register, "r". 
-     Kind_RegDef = 2,             // Output register, "=r". 
-     Kind_RegDefEarlyClobber = 3, // Early-clobber output register, "=&r". 
-     Kind_Clobber = 4,            // Clobbered register, "~r". 
-     Kind_Imm = 5,                // Immediate. 
-     Kind_Mem = 6,                // Memory operand, "m", or an address, "p". 
-     Kind_Func = 7,               // Address operand of function call 
-   
-     // Memory constraint codes. 
-     // These could be tablegenerated but there's little need to do that since 
-     // there's plenty of space in the encoding to support the union of all 
-     // constraint codes for all targets. 
-     // Addresses are included here as they need to be treated the same by the 
-     // backend, the only difference is that they are not used to actaully 
-     // access memory by the instruction. 
-     Constraint_Unknown = 0, 
-     Constraint_es, 
-     Constraint_i, 
-     Constraint_k, 
-     Constraint_m, 
-     Constraint_o, 
-     Constraint_v, 
-     Constraint_A, 
-     Constraint_Q, 
-     Constraint_R, 
-     Constraint_S, 
-     Constraint_T, 
-     Constraint_Um, 
-     Constraint_Un, 
-     Constraint_Uq, 
-     Constraint_Us, 
-     Constraint_Ut, 
-     Constraint_Uv, 
-     Constraint_Uy, 
-     Constraint_X, 
-     Constraint_Z, 
-     Constraint_ZB, 
-     Constraint_ZC, 
-     Constraint_Zy, 
-   
-     // Address constraints 
-     Constraint_p, 
-     Constraint_ZQ, 
-     Constraint_ZR, 
-     Constraint_ZS, 
-     Constraint_ZT, 
-   
-     Constraints_Max = Constraint_ZT, 
-     Constraints_ShiftAmount = 16, 
-   
-     Flag_MatchingOperand = 0x80000000 
-   }; 
-   
-   static unsigned getFlagWord(unsigned Kind, unsigned NumOps) { 
-     assert(((NumOps << 3) & ~0xffff) == 0 && "Too many inline asm operands!"); 
-     assert(Kind >= Kind_RegUse && Kind <= Kind_Func && "Invalid Kind"); 
-     return Kind | (NumOps << 3); 
-   } 
-   
-   static bool isRegDefKind(unsigned Flag){ return getKind(Flag) == Kind_RegDef;} 
-   static bool isImmKind(unsigned Flag) { return getKind(Flag) == Kind_Imm; } 
-   static bool isMemKind(unsigned Flag) { return getKind(Flag) == Kind_Mem; } 
-   static bool isFuncKind(unsigned Flag) { return getKind(Flag) == Kind_Func; } 
-   static bool isRegDefEarlyClobberKind(unsigned Flag) { 
-     return getKind(Flag) == Kind_RegDefEarlyClobber; 
-   } 
-   static bool isClobberKind(unsigned Flag) { 
-     return getKind(Flag) == Kind_Clobber; 
-   } 
-   
-   /// getFlagWordForMatchingOp - Augment an existing flag word returned by 
-   /// getFlagWord with information indicating that this input operand is tied 
-   /// to a previous output operand. 
-   static unsigned getFlagWordForMatchingOp(unsigned InputFlag, 
-                                            unsigned MatchedOperandNo) { 
-     assert(MatchedOperandNo <= 0x7fff && "Too big matched operand"); 
-     assert((InputFlag & ~0xffff) == 0 && "High bits already contain data"); 
-     return InputFlag | Flag_MatchingOperand | (MatchedOperandNo << 16); 
-   } 
-   
-   /// getFlagWordForRegClass - Augment an existing flag word returned by 
-   /// getFlagWord with the required register class for the following register 
-   /// operands. 
-   /// A tied use operand cannot have a register class, use the register class 
-   /// from the def operand instead. 
-   static unsigned getFlagWordForRegClass(unsigned InputFlag, unsigned RC) { 
-     // Store RC + 1, reserve the value 0 to mean 'no register class'. 
-     ++RC; 
-     assert(!isImmKind(InputFlag) && "Immediates cannot have a register class"); 
-     assert(!isMemKind(InputFlag) && "Memory operand cannot have a register class"); 
-     assert(RC <= 0x7fff && "Too large register class ID"); 
-     assert((InputFlag & ~0xffff) == 0 && "High bits already contain data"); 
-     return InputFlag | (RC << 16); 
-   } 
-   
-   /// Augment an existing flag word returned by getFlagWord with the constraint 
-   /// code for a memory constraint. 
-   static unsigned getFlagWordForMem(unsigned InputFlag, unsigned Constraint) { 
-     assert((isMemKind(InputFlag) || isFuncKind(InputFlag)) && 
-            "InputFlag is not a memory (include function) constraint!"); 
-     assert(Constraint <= 0x7fff && "Too large a memory constraint ID"); 
-     assert(Constraint <= Constraints_Max && "Unknown constraint ID"); 
-     assert((InputFlag & ~0xffff) == 0 && "High bits already contain data"); 
-     return InputFlag | (Constraint << Constraints_ShiftAmount); 
-   } 
-   
-   static unsigned convertMemFlagWordToMatchingFlagWord(unsigned InputFlag) { 
-     assert(isMemKind(InputFlag)); 
-     return InputFlag & ~(0x7fff << Constraints_ShiftAmount); 
-   } 
-   
-   static unsigned getKind(unsigned Flags) { 
-     return Flags & 7; 
-   } 
-   
-   static unsigned getMemoryConstraintID(unsigned Flag) { 
-     assert((isMemKind(Flag) || isFuncKind(Flag)) && 
-            "Not expected mem or function flang!"); 
-     return (Flag >> Constraints_ShiftAmount) & 0x7fff; 
-   } 
-   
-   /// getNumOperandRegisters - Extract the number of registers field from the 
-   /// inline asm operand flag. 
-   static unsigned getNumOperandRegisters(unsigned Flag) { 
-     return (Flag & 0xffff) >> 3; 
-   } 
-   
-   /// isUseOperandTiedToDef - Return true if the flag of the inline asm 
-   /// operand indicates it is an use operand that's matched to a def operand. 
-   static bool isUseOperandTiedToDef(unsigned Flag, unsigned &Idx) { 
-     if ((Flag & Flag_MatchingOperand) == 0) 
-       return false; 
-     Idx = (Flag & ~Flag_MatchingOperand) >> 16; 
-     return true; 
-   } 
-   
-   /// hasRegClassConstraint - Returns true if the flag contains a register 
-   /// class constraint.  Sets RC to the register class ID. 
-   static bool hasRegClassConstraint(unsigned Flag, unsigned &RC) { 
-     if (Flag & Flag_MatchingOperand) 
-       return false; 
-     unsigned High = Flag >> 16; 
-     // getFlagWordForRegClass() uses 0 to mean no register class, and otherwise 
-     // stores RC + 1. 
-     if (!High) 
-       return false; 
-     RC = High - 1; 
-     return true; 
-   } 
-   
-   static std::vector<StringRef> getExtraInfoNames(unsigned ExtraInfo) { 
-     std::vector<StringRef> Result; 
-     if (ExtraInfo & InlineAsm::Extra_HasSideEffects) 
-       Result.push_back("sideeffect"); 
-     if (ExtraInfo & InlineAsm::Extra_MayLoad) 
-       Result.push_back("mayload"); 
-     if (ExtraInfo & InlineAsm::Extra_MayStore) 
-       Result.push_back("maystore"); 
-     if (ExtraInfo & InlineAsm::Extra_IsConvergent) 
-       Result.push_back("isconvergent"); 
-     if (ExtraInfo & InlineAsm::Extra_IsAlignStack) 
-       Result.push_back("alignstack"); 
-   
-     AsmDialect Dialect = 
-         InlineAsm::AsmDialect((ExtraInfo & InlineAsm::Extra_AsmDialect)); 
-   
-     if (Dialect == InlineAsm::AD_ATT) 
-       Result.push_back("attdialect"); 
-     if (Dialect == InlineAsm::AD_Intel) 
-       Result.push_back("inteldialect"); 
-   
-     return Result; 
-   } 
-   
-   static StringRef getKindName(unsigned Kind) { 
-     switch (Kind) { 
-     case InlineAsm::Kind_RegUse: 
-       return "reguse"; 
-     case InlineAsm::Kind_RegDef: 
-       return "regdef"; 
-     case InlineAsm::Kind_RegDefEarlyClobber: 
-       return "regdef-ec"; 
-     case InlineAsm::Kind_Clobber: 
-       return "clobber"; 
-     case InlineAsm::Kind_Imm: 
-       return "imm"; 
-     case InlineAsm::Kind_Mem: 
-     case InlineAsm::Kind_Func: 
-       return "mem"; 
-     default: 
-       llvm_unreachable("Unknown operand kind"); 
-     } 
-   } 
-   
-   static StringRef getMemConstraintName(unsigned Constraint) { 
-     switch (Constraint) { 
-     case InlineAsm::Constraint_es: 
-       return "es"; 
-     case InlineAsm::Constraint_i: 
-       return "i"; 
-     case InlineAsm::Constraint_k: 
-       return "k"; 
-     case InlineAsm::Constraint_m: 
-       return "m"; 
-     case InlineAsm::Constraint_o: 
-       return "o"; 
-     case InlineAsm::Constraint_v: 
-       return "v"; 
-     case InlineAsm::Constraint_Q: 
-       return "Q"; 
-     case InlineAsm::Constraint_R: 
-       return "R"; 
-     case InlineAsm::Constraint_S: 
-       return "S"; 
-     case InlineAsm::Constraint_T: 
-       return "T"; 
-     case InlineAsm::Constraint_Um: 
-       return "Um"; 
-     case InlineAsm::Constraint_Un: 
-       return "Un"; 
-     case InlineAsm::Constraint_Uq: 
-       return "Uq"; 
-     case InlineAsm::Constraint_Us: 
-       return "Us"; 
-     case InlineAsm::Constraint_Ut: 
-       return "Ut"; 
-     case InlineAsm::Constraint_Uv: 
-       return "Uv"; 
-     case InlineAsm::Constraint_Uy: 
-       return "Uy"; 
-     case InlineAsm::Constraint_X: 
-       return "X"; 
-     case InlineAsm::Constraint_Z: 
-       return "Z"; 
-     case InlineAsm::Constraint_ZB: 
-       return "ZB"; 
-     case InlineAsm::Constraint_ZC: 
-       return "ZC"; 
-     case InlineAsm::Constraint_Zy: 
-       return "Zy"; 
-     case InlineAsm::Constraint_p: 
-       return "p"; 
-     case InlineAsm::Constraint_ZQ: 
-       return "ZQ"; 
-     case InlineAsm::Constraint_ZR: 
-       return "ZR"; 
-     case InlineAsm::Constraint_ZS: 
-       return "ZS"; 
-     case InlineAsm::Constraint_ZT: 
-       return "ZT"; 
-     default: 
-       llvm_unreachable("Unknown memory constraint"); 
-     } 
-   } 
- }; 
-   
- } // end namespace llvm 
-   
- #endif // LLVM_IR_INLINEASM_H 
-