Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2026-05-10 08:44:01

0001 //===- llvm/InlineAsm.h - Class to represent inline asm strings -*- C++ -*-===//
0002 //
0003 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
0004 // See https://llvm.org/LICENSE.txt for license information.
0005 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
0006 //
0007 //===----------------------------------------------------------------------===//
0008 //
0009 // This class represents the inline asm strings, which are Value*'s that are
0010 // used as the callee operand of call instructions.  InlineAsm's are uniqued
0011 // like constants, and created via InlineAsm::get(...).
0012 //
0013 //===----------------------------------------------------------------------===//
0014 
0015 #ifndef LLVM_IR_INLINEASM_H
0016 #define LLVM_IR_INLINEASM_H
0017 
0018 #include "llvm/ADT/Bitfields.h"
0019 #include "llvm/ADT/SmallVector.h"
0020 #include "llvm/ADT/StringRef.h"
0021 #include "llvm/IR/Value.h"
0022 #include "llvm/Support/ErrorHandling.h"
0023 #include <cassert>
0024 #include <string>
0025 #include <vector>
0026 
0027 namespace llvm {
0028 
0029 class Error;
0030 class FunctionType;
0031 class PointerType;
0032 template <class ConstantClass> class ConstantUniqueMap;
0033 
0034 class InlineAsm final : public Value {
0035 public:
0036   enum AsmDialect {
0037     AD_ATT,
0038     AD_Intel
0039   };
0040 
0041 private:
0042   friend struct InlineAsmKeyType;
0043   friend class ConstantUniqueMap<InlineAsm>;
0044 
0045   std::string AsmString, Constraints;
0046   FunctionType *FTy;
0047   bool HasSideEffects;
0048   bool IsAlignStack;
0049   AsmDialect Dialect;
0050   bool CanThrow;
0051 
0052   InlineAsm(FunctionType *Ty, const std::string &AsmString,
0053             const std::string &Constraints, bool hasSideEffects,
0054             bool isAlignStack, AsmDialect asmDialect, bool canThrow);
0055 
0056   /// When the ConstantUniqueMap merges two types and makes two InlineAsms
0057   /// identical, it destroys one of them with this method.
0058   void destroyConstant();
0059 
0060 public:
0061   InlineAsm(const InlineAsm &) = delete;
0062   InlineAsm &operator=(const InlineAsm &) = delete;
0063 
0064   /// InlineAsm::get - Return the specified uniqued inline asm string.
0065   ///
0066   static InlineAsm *get(FunctionType *Ty, StringRef AsmString,
0067                         StringRef Constraints, bool hasSideEffects,
0068                         bool isAlignStack = false,
0069                         AsmDialect asmDialect = AD_ATT, bool canThrow = false);
0070 
0071   bool hasSideEffects() const { return HasSideEffects; }
0072   bool isAlignStack() const { return IsAlignStack; }
0073   AsmDialect getDialect() const { return Dialect; }
0074   bool canThrow() const { return CanThrow; }
0075 
0076   /// getType - InlineAsm's are always pointers.
0077   ///
0078   PointerType *getType() const {
0079     return reinterpret_cast<PointerType*>(Value::getType());
0080   }
0081 
0082   /// getFunctionType - InlineAsm's are always pointers to functions.
0083   ///
0084   FunctionType *getFunctionType() const;
0085 
0086   const std::string &getAsmString() const { return AsmString; }
0087   const std::string &getConstraintString() const { return Constraints; }
0088   void collectAsmStrs(SmallVectorImpl<StringRef> &AsmStrs) const;
0089 
0090   /// This static method can be used by the parser to check to see if the
0091   /// specified constraint string is legal for the type.
0092   static Error verify(FunctionType *Ty, StringRef Constraints);
0093 
0094   // Constraint String Parsing
0095   enum ConstraintPrefix {
0096     isInput,            // 'x'
0097     isOutput,           // '=x'
0098     isClobber,          // '~x'
0099     isLabel,            // '!x'
0100   };
0101 
0102   using ConstraintCodeVector = std::vector<std::string>;
0103 
0104   struct SubConstraintInfo {
0105     /// MatchingInput - If this is not -1, this is an output constraint where an
0106     /// input constraint is required to match it (e.g. "0").  The value is the
0107     /// constraint number that matches this one (for example, if this is
0108     /// constraint #0 and constraint #4 has the value "0", this will be 4).
0109     int MatchingInput = -1;
0110 
0111     /// Code - The constraint code, either the register name (in braces) or the
0112     /// constraint letter/number.
0113     ConstraintCodeVector Codes;
0114 
0115     /// Default constructor.
0116     SubConstraintInfo() = default;
0117   };
0118 
0119   using SubConstraintInfoVector = std::vector<SubConstraintInfo>;
0120   struct ConstraintInfo;
0121   using ConstraintInfoVector = std::vector<ConstraintInfo>;
0122 
0123   struct ConstraintInfo {
0124     /// Type - The basic type of the constraint: input/output/clobber/label
0125     ///
0126     ConstraintPrefix Type = isInput;
0127 
0128     /// isEarlyClobber - "&": output operand writes result before inputs are all
0129     /// read.  This is only ever set for an output operand.
0130     bool isEarlyClobber = false;
0131 
0132     /// MatchingInput - If this is not -1, this is an output constraint where an
0133     /// input constraint is required to match it (e.g. "0").  The value is the
0134     /// constraint number that matches this one (for example, if this is
0135     /// constraint #0 and constraint #4 has the value "0", this will be 4).
0136     int MatchingInput = -1;
0137 
0138     /// hasMatchingInput - Return true if this is an output constraint that has
0139     /// a matching input constraint.
0140     bool hasMatchingInput() const { return MatchingInput != -1; }
0141 
0142     /// isCommutative - This is set to true for a constraint that is commutative
0143     /// with the next operand.
0144     bool isCommutative = false;
0145 
0146     /// isIndirect - True if this operand is an indirect operand.  This means
0147     /// that the address of the source or destination is present in the call
0148     /// instruction, instead of it being returned or passed in explicitly.  This
0149     /// is represented with a '*' in the asm string.
0150     bool isIndirect = false;
0151 
0152     /// Code - The constraint code, either the register name (in braces) or the
0153     /// constraint letter/number.
0154     ConstraintCodeVector Codes;
0155 
0156     /// isMultipleAlternative - '|': has multiple-alternative constraints.
0157     bool isMultipleAlternative = false;
0158 
0159     /// multipleAlternatives - If there are multiple alternative constraints,
0160     /// this array will contain them.  Otherwise it will be empty.
0161     SubConstraintInfoVector multipleAlternatives;
0162 
0163     /// The currently selected alternative constraint index.
0164     unsigned currentAlternativeIndex = 0;
0165 
0166     /// Default constructor.
0167     ConstraintInfo() = default;
0168 
0169     /// Parse - Analyze the specified string (e.g. "=*&{eax}") and fill in the
0170     /// fields in this structure.  If the constraint string is not understood,
0171     /// return true, otherwise return false.
0172     bool Parse(StringRef Str, ConstraintInfoVector &ConstraintsSoFar);
0173 
0174     /// selectAlternative - Point this constraint to the alternative constraint
0175     /// indicated by the index.
0176     void selectAlternative(unsigned index);
0177 
0178     /// Whether this constraint corresponds to an argument.
0179     bool hasArg() const {
0180       return Type == isInput || (Type == isOutput && isIndirect);
0181     }
0182   };
0183 
0184   /// ParseConstraints - Split up the constraint string into the specific
0185   /// constraints and their prefixes.  If this returns an empty vector, and if
0186   /// the constraint string itself isn't empty, there was an error parsing.
0187   static ConstraintInfoVector ParseConstraints(StringRef ConstraintString);
0188 
0189   /// ParseConstraints - Parse the constraints of this inlineasm object,
0190   /// returning them the same way that ParseConstraints(str) does.
0191   ConstraintInfoVector ParseConstraints() const {
0192     return ParseConstraints(Constraints);
0193   }
0194 
0195   // Methods for support type inquiry through isa, cast, and dyn_cast:
0196   static bool classof(const Value *V) {
0197     return V->getValueID() == Value::InlineAsmVal;
0198   }
0199 
0200   enum : uint32_t {
0201     // Fixed operands on an INLINEASM SDNode.
0202     Op_InputChain = 0,
0203     Op_AsmString = 1,
0204     Op_MDNode = 2,
0205     Op_ExtraInfo = 3, // HasSideEffects, IsAlignStack, AsmDialect.
0206     Op_FirstOperand = 4,
0207 
0208     // Fixed operands on an INLINEASM MachineInstr.
0209     MIOp_AsmString = 0,
0210     MIOp_ExtraInfo = 1, // HasSideEffects, IsAlignStack, AsmDialect.
0211     MIOp_FirstOperand = 2,
0212 
0213     // Interpretation of the MIOp_ExtraInfo bit field.
0214     Extra_HasSideEffects = 1,
0215     Extra_IsAlignStack = 2,
0216     Extra_AsmDialect = 4,
0217     Extra_MayLoad = 8,
0218     Extra_MayStore = 16,
0219     Extra_IsConvergent = 32,
0220   };
0221 
0222   // Inline asm operands map to multiple SDNode / MachineInstr operands.
0223   // The first operand is an immediate describing the asm operand, the low
0224   // bits is the kind:
0225   enum class Kind : uint8_t {
0226     RegUse = 1,             // Input register, "r".
0227     RegDef = 2,             // Output register, "=r".
0228     RegDefEarlyClobber = 3, // Early-clobber output register, "=&r".
0229     Clobber = 4,            // Clobbered register, "~r".
0230     Imm = 5,                // Immediate.
0231     Mem = 6,                // Memory operand, "m", or an address, "p".
0232     Func = 7,               // Address operand of function call
0233   };
0234 
0235   // Memory constraint codes.
0236   // Addresses are included here as they need to be treated the same by the
0237   // backend, the only difference is that they are not used to actaully
0238   // access memory by the instruction.
0239   enum class ConstraintCode : uint32_t {
0240     Unknown = 0,
0241     es,
0242     i,
0243     k,
0244     m,
0245     o,
0246     v,
0247     A,
0248     Q,
0249     R,
0250     S,
0251     T,
0252     Um,
0253     Un,
0254     Uq,
0255     Us,
0256     Ut,
0257     Uv,
0258     Uy,
0259     X,
0260     Z,
0261     ZB,
0262     ZC,
0263     Zy,
0264 
0265     // Address constraints
0266     p,
0267     ZQ,
0268     ZR,
0269     ZS,
0270     ZT,
0271 
0272     Max = ZT,
0273   };
0274 
0275   // This class is intentionally packed into a 32b value as it is used as a
0276   // MVT::i32 ConstantSDNode SDValue for SelectionDAG and as immediate operands
0277   // on INLINEASM and INLINEASM_BR MachineInstr's.
0278   //
0279   // The encoding of Flag is currently:
0280   //   Bits 2-0  - A Kind::* value indicating the kind of the operand.
0281   //               (KindField)
0282   //   Bits 15-3 - The number of SDNode operands associated with this inline
0283   //               assembly operand. Once lowered to MIR, this represents the
0284   //               number of MachineOperands necessary to refer to a
0285   //               MachineOperandType::MO_FrameIndex. (NumOperands)
0286   //   Bit 31    - Determines if this is a matched operand. (IsMatched)
0287   //   If bit 31 is set:
0288   //     Bits 30-16 - The operand number that this operand must match.
0289   //                  (MatchedOperandNo)
0290   //   Else if bits 2-0 are Kind::Mem:
0291   //     Bits 30-16 - A ConstraintCode:: value indicating the original
0292   //                  constraint code. (MemConstraintCode)
0293   //   Else:
0294   //     Bits 29-16 - The register class ID to use for the operand. (RegClass)
0295   //     Bit  30    - If the register is permitted to be spilled.
0296   //                  (RegMayBeFolded)
0297   //                  Defaults to false "r", may be set for constraints like
0298   //                  "rm" (or "g").
0299   //
0300   //   As such, MatchedOperandNo, MemConstraintCode, and
0301   //   (RegClass+RegMayBeFolded) are views of the same slice of bits, but are
0302   //   mutually exclusive depending on the fields IsMatched then KindField.
0303   class Flag {
0304     uint32_t Storage;
0305     using KindField = Bitfield::Element<Kind, 0, 3, Kind::Func>;
0306     using NumOperands = Bitfield::Element<unsigned, 3, 13>;
0307     using MatchedOperandNo = Bitfield::Element<unsigned, 16, 15>;
0308     using MemConstraintCode = Bitfield::Element<ConstraintCode, 16, 15, ConstraintCode::Max>;
0309     using RegClass = Bitfield::Element<unsigned, 16, 14>;
0310     using RegMayBeFolded = Bitfield::Element<bool, 30, 1>;
0311     using IsMatched = Bitfield::Element<bool, 31, 1>;
0312 
0313 
0314     unsigned getMatchedOperandNo() const { return Bitfield::get<MatchedOperandNo>(Storage); }
0315     unsigned getRegClass() const { return Bitfield::get<RegClass>(Storage); }
0316     bool isMatched() const { return Bitfield::get<IsMatched>(Storage); }
0317 
0318   public:
0319     Flag() : Storage(0) {}
0320     explicit Flag(uint32_t F) : Storage(F) {}
0321     Flag(enum Kind K, unsigned NumOps) : Storage(0) {
0322       Bitfield::set<KindField>(Storage, K);
0323       Bitfield::set<NumOperands>(Storage, NumOps);
0324     }
0325     operator uint32_t() { return Storage; }
0326     Kind getKind() const { return Bitfield::get<KindField>(Storage); }
0327     bool isRegUseKind() const { return getKind() == Kind::RegUse; }
0328     bool isRegDefKind() const { return getKind() == Kind::RegDef; }
0329     bool isRegDefEarlyClobberKind() const {
0330       return getKind() == Kind::RegDefEarlyClobber;
0331     }
0332     bool isClobberKind() const { return getKind() == Kind::Clobber; }
0333     bool isImmKind() const { return getKind() == Kind::Imm; }
0334     bool isMemKind() const { return getKind() == Kind::Mem; }
0335     bool isFuncKind() const { return getKind() == Kind::Func; }
0336     StringRef getKindName() const {
0337       switch (getKind()) {
0338       case Kind::RegUse:
0339         return "reguse";
0340       case Kind::RegDef:
0341         return "regdef";
0342       case Kind::RegDefEarlyClobber:
0343         return "regdef-ec";
0344       case Kind::Clobber:
0345         return "clobber";
0346       case Kind::Imm:
0347         return "imm";
0348       case Kind::Mem:
0349       case Kind::Func:
0350         return "mem";
0351       }
0352       llvm_unreachable("impossible kind");
0353     }
0354 
0355     /// getNumOperandRegisters - Extract the number of registers field from the
0356     /// inline asm operand flag.
0357     unsigned getNumOperandRegisters() const {
0358       return Bitfield::get<NumOperands>(Storage);
0359     }
0360 
0361     /// isUseOperandTiedToDef - Return true if the flag of the inline asm
0362     /// operand indicates it is an use operand that's matched to a def operand.
0363     bool isUseOperandTiedToDef(unsigned &Idx) const {
0364       if (!isMatched())
0365         return false;
0366       Idx = getMatchedOperandNo();
0367       return true;
0368     }
0369 
0370     /// hasRegClassConstraint - Returns true if the flag contains a register
0371     /// class constraint.  Sets RC to the register class ID.
0372     bool hasRegClassConstraint(unsigned &RC) const {
0373       if (isMatched())
0374         return false;
0375       // setRegClass() uses 0 to mean no register class, and otherwise stores
0376       // RC + 1.
0377       if (!getRegClass())
0378         return false;
0379       RC = getRegClass() - 1;
0380       return true;
0381     }
0382 
0383     ConstraintCode getMemoryConstraintID() const {
0384       assert((isMemKind() || isFuncKind()) &&
0385              "Not expected mem or function flag!");
0386       return Bitfield::get<MemConstraintCode>(Storage);
0387     }
0388 
0389     /// setMatchingOp - Augment an existing flag with information indicating
0390     /// that this input operand is tied to a previous output operand.
0391     void setMatchingOp(unsigned OperandNo) {
0392       assert(getMatchedOperandNo() == 0 && "Matching operand already set");
0393       Bitfield::set<MatchedOperandNo>(Storage, OperandNo);
0394       Bitfield::set<IsMatched>(Storage, true);
0395     }
0396 
0397     /// setRegClass - Augment an existing flag with the required register class
0398     /// for the following register operands. A tied use operand cannot have a
0399     /// register class, use the register class from the def operand instead.
0400     void setRegClass(unsigned RC) {
0401       assert(!isImmKind() && "Immediates cannot have a register class");
0402       assert(!isMemKind() && "Memory operand cannot have a register class");
0403       assert(getRegClass() == 0 && "Register class already set");
0404       // Store RC + 1, reserve the value 0 to mean 'no register class'.
0405       Bitfield::set<RegClass>(Storage, RC + 1);
0406     }
0407 
0408     /// setMemConstraint - Augment an existing flag with the constraint code for
0409     /// a memory constraint.
0410     void setMemConstraint(ConstraintCode C) {
0411       assert(getMemoryConstraintID() == ConstraintCode::Unknown && "Mem constraint already set");
0412       Bitfield::set<MemConstraintCode>(Storage, C);
0413     }
0414     /// clearMemConstraint - Similar to setMemConstraint(0), but without the
0415     /// assertion checking that the constraint has not been set previously.
0416     void clearMemConstraint() {
0417       assert((isMemKind() || isFuncKind()) &&
0418              "Flag is not a memory or function constraint!");
0419       Bitfield::set<MemConstraintCode>(Storage, ConstraintCode::Unknown);
0420     }
0421 
0422     /// Set a bit to denote that while this operand is some kind of register
0423     /// (use, def, ...), a memory flag did appear in the original constraint
0424     /// list.  This is set by the instruction selection framework, and consumed
0425     /// by the register allocator. While the register allocator is generally
0426     /// responsible for spilling registers, we need to be able to distinguish
0427     /// between registers that the register allocator has permission to fold
0428     /// ("rm") vs ones it does not ("r"). This is because the inline asm may use
0429     /// instructions which don't support memory addressing modes for that
0430     /// operand.
0431     void setRegMayBeFolded(bool B) {
0432       assert((isRegDefKind() || isRegDefEarlyClobberKind() || isRegUseKind()) &&
0433              "Must be reg");
0434       Bitfield::set<RegMayBeFolded>(Storage, B);
0435     }
0436     bool getRegMayBeFolded() const {
0437       assert((isRegDefKind() || isRegDefEarlyClobberKind() || isRegUseKind()) &&
0438              "Must be reg");
0439       return Bitfield::get<RegMayBeFolded>(Storage);
0440     }
0441   };
0442 
0443   static std::vector<StringRef> getExtraInfoNames(unsigned ExtraInfo) {
0444     std::vector<StringRef> Result;
0445     if (ExtraInfo & InlineAsm::Extra_HasSideEffects)
0446       Result.push_back("sideeffect");
0447     if (ExtraInfo & InlineAsm::Extra_MayLoad)
0448       Result.push_back("mayload");
0449     if (ExtraInfo & InlineAsm::Extra_MayStore)
0450       Result.push_back("maystore");
0451     if (ExtraInfo & InlineAsm::Extra_IsConvergent)
0452       Result.push_back("isconvergent");
0453     if (ExtraInfo & InlineAsm::Extra_IsAlignStack)
0454       Result.push_back("alignstack");
0455 
0456     AsmDialect Dialect =
0457         InlineAsm::AsmDialect((ExtraInfo & InlineAsm::Extra_AsmDialect));
0458 
0459     if (Dialect == InlineAsm::AD_ATT)
0460       Result.push_back("attdialect");
0461     if (Dialect == InlineAsm::AD_Intel)
0462       Result.push_back("inteldialect");
0463 
0464     return Result;
0465   }
0466 
0467   static StringRef getMemConstraintName(ConstraintCode C) {
0468     switch (C) {
0469     case ConstraintCode::es:
0470       return "es";
0471     case ConstraintCode::i:
0472       return "i";
0473     case ConstraintCode::k:
0474       return "k";
0475     case ConstraintCode::m:
0476       return "m";
0477     case ConstraintCode::o:
0478       return "o";
0479     case ConstraintCode::v:
0480       return "v";
0481     case ConstraintCode::A:
0482       return "A";
0483     case ConstraintCode::Q:
0484       return "Q";
0485     case ConstraintCode::R:
0486       return "R";
0487     case ConstraintCode::S:
0488       return "S";
0489     case ConstraintCode::T:
0490       return "T";
0491     case ConstraintCode::Um:
0492       return "Um";
0493     case ConstraintCode::Un:
0494       return "Un";
0495     case ConstraintCode::Uq:
0496       return "Uq";
0497     case ConstraintCode::Us:
0498       return "Us";
0499     case ConstraintCode::Ut:
0500       return "Ut";
0501     case ConstraintCode::Uv:
0502       return "Uv";
0503     case ConstraintCode::Uy:
0504       return "Uy";
0505     case ConstraintCode::X:
0506       return "X";
0507     case ConstraintCode::Z:
0508       return "Z";
0509     case ConstraintCode::ZB:
0510       return "ZB";
0511     case ConstraintCode::ZC:
0512       return "ZC";
0513     case ConstraintCode::Zy:
0514       return "Zy";
0515     case ConstraintCode::p:
0516       return "p";
0517     case ConstraintCode::ZQ:
0518       return "ZQ";
0519     case ConstraintCode::ZR:
0520       return "ZR";
0521     case ConstraintCode::ZS:
0522       return "ZS";
0523     case ConstraintCode::ZT:
0524       return "ZT";
0525     default:
0526       llvm_unreachable("Unknown memory constraint");
0527     }
0528   }
0529 };
0530 
0531 } // end namespace llvm
0532 
0533 #endif // LLVM_IR_INLINEASM_H