//===- CodeGenInstruction.h - Instruction Class Wrapper ---------*- 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 file defines a wrapper class for the 'Instruction' TableGen class. // //===----------------------------------------------------------------------===// #ifndef LLVM_UTILS_TABLEGEN_CODEGENINSTRUCTION_H #define LLVM_UTILS_TABLEGEN_CODEGENINSTRUCTION_H #include "llvm/ADT/BitVector.h" #include "llvm/ADT/StringMap.h" #include "llvm/ADT/StringRef.h" #include "llvm/Support/MachineValueType.h" #include #include #include #include namespace llvm { class SMLoc; template class ArrayRef; class Record; class DagInit; class CodeGenTarget; class CGIOperandList { public: class ConstraintInfo { enum { None, EarlyClobber, Tied } Kind = None; unsigned OtherTiedOperand = 0; public: ConstraintInfo() = default; static ConstraintInfo getEarlyClobber() { ConstraintInfo I; I.Kind = EarlyClobber; I.OtherTiedOperand = 0; return I; } static ConstraintInfo getTied(unsigned Op) { ConstraintInfo I; I.Kind = Tied; I.OtherTiedOperand = Op; return I; } bool isNone() const { return Kind == None; } bool isEarlyClobber() const { return Kind == EarlyClobber; } bool isTied() const { return Kind == Tied; } unsigned getTiedOperand() const { assert(isTied()); return OtherTiedOperand; } bool operator==(const ConstraintInfo &RHS) const { if (Kind != RHS.Kind) return false; if (Kind == Tied && OtherTiedOperand != RHS.OtherTiedOperand) return false; return true; } bool operator!=(const ConstraintInfo &RHS) const { return !(*this == RHS); } }; /// OperandInfo - The information we keep track of for each operand in the /// operand list for a tablegen instruction. struct OperandInfo { /// Rec - The definition this operand is declared as. /// Record *Rec; /// Name - If this operand was assigned a symbolic name, this is it, /// otherwise, it's empty. std::string Name; /// The names of sub-operands, if given, otherwise empty. std::vector SubOpNames; /// PrinterMethodName - The method used to print operands of this type in /// the asmprinter. std::string PrinterMethodName; /// The method used to get the machine operand value for binary /// encoding, per sub-operand. If empty, uses "getMachineOpValue". std::vector EncoderMethodNames; /// OperandType - A value from MCOI::OperandType representing the type of /// the operand. std::string OperandType; /// MIOperandNo - Currently (this is meant to be phased out), some logical /// operands correspond to multiple MachineInstr operands. In the X86 /// target for example, one address operand is represented as 4 /// MachineOperands. Because of this, the operand number in the /// OperandList may not match the MachineInstr operand num. Until it /// does, this contains the MI operand index of this operand. unsigned MIOperandNo; unsigned MINumOperands; // The number of operands. /// DoNotEncode - Bools are set to true in this vector for each operand in /// the DisableEncoding list. These should not be emitted by the code /// emitter. BitVector DoNotEncode; /// MIOperandInfo - Default MI operand type. Note an operand may be made /// up of multiple MI operands. DagInit *MIOperandInfo; /// Constraint info for this operand. This operand can have pieces, so we /// track constraint info for each. std::vector Constraints; OperandInfo(Record *R, const std::string &N, const std::string &PMN, const std::string &OT, unsigned MION, unsigned MINO, DagInit *MIOI) : Rec(R), Name(N), SubOpNames(MINO), PrinterMethodName(PMN), EncoderMethodNames(MINO), OperandType(OT), MIOperandNo(MION), MINumOperands(MINO), DoNotEncode(MINO), MIOperandInfo(MIOI), Constraints(MINO) {} /// getTiedOperand - If this operand is tied to another one, return the /// other operand number. Otherwise, return -1. int getTiedRegister() const { for (unsigned j = 0, e = Constraints.size(); j != e; ++j) { const CGIOperandList::ConstraintInfo &CI = Constraints[j]; if (CI.isTied()) return CI.getTiedOperand(); } return -1; } }; CGIOperandList(Record *D); Record *TheDef; // The actual record containing this OperandList. /// NumDefs - Number of def operands declared, this is the number of /// elements in the instruction's (outs) list. /// unsigned NumDefs; /// OperandList - The list of declared operands, along with their declared /// type (which is a record). std::vector OperandList; /// SubOpAliases - List of alias names for suboperands. StringMap> SubOpAliases; // Information gleaned from the operand list. bool isPredicable; bool hasOptionalDef; bool isVariadic; // Provide transparent accessors to the operand list. bool empty() const { return OperandList.empty(); } unsigned size() const { return OperandList.size(); } const OperandInfo &operator[](unsigned i) const { return OperandList[i]; } OperandInfo &operator[](unsigned i) { return OperandList[i]; } OperandInfo &back() { return OperandList.back(); } const OperandInfo &back() const { return OperandList.back(); } typedef std::vector::iterator iterator; typedef std::vector::const_iterator const_iterator; iterator begin() { return OperandList.begin(); } const_iterator begin() const { return OperandList.begin(); } iterator end() { return OperandList.end(); } const_iterator end() const { return OperandList.end(); } /// getOperandNamed - Return the index of the operand with the specified /// non-empty name. If the instruction does not have an operand with the /// specified name, abort. unsigned getOperandNamed(StringRef Name) const; /// hasOperandNamed - Query whether the instruction has an operand of the /// given name. If so, return true and set OpIdx to the index of the /// operand. Otherwise, return false. bool hasOperandNamed(StringRef Name, unsigned &OpIdx) const; bool hasSubOperandAlias(StringRef Name, std::pair &SubOp) const; /// ParseOperandName - Parse an operand name like "$foo" or "$foo.bar", /// where $foo is a whole operand and $foo.bar refers to a suboperand. /// This aborts if the name is invalid. If AllowWholeOp is true, references /// to operands with suboperands are allowed, otherwise not. std::pair ParseOperandName(StringRef Op, bool AllowWholeOp = true); /// getFlattenedOperandNumber - Flatten a operand/suboperand pair into a /// flat machineinstr operand #. unsigned getFlattenedOperandNumber(std::pair Op) const { return OperandList[Op.first].MIOperandNo + Op.second; } /// getSubOperandNumber - Unflatten a operand number into an /// operand/suboperand pair. std::pair getSubOperandNumber(unsigned Op) const { for (unsigned i = 0; ; ++i) { assert(i < OperandList.size() && "Invalid flat operand #"); if (OperandList[i].MIOperandNo+OperandList[i].MINumOperands > Op) return std::make_pair(i, Op-OperandList[i].MIOperandNo); } } /// isFlatOperandNotEmitted - Return true if the specified flat operand # /// should not be emitted with the code emitter. bool isFlatOperandNotEmitted(unsigned FlatOpNo) const { std::pair Op = getSubOperandNumber(FlatOpNo); if (OperandList[Op.first].DoNotEncode.size() > Op.second) return OperandList[Op.first].DoNotEncode[Op.second]; return false; } void ProcessDisableEncoding(StringRef Value); }; class CodeGenInstruction { public: Record *TheDef; // The actual record defining this instruction. StringRef Namespace; // The namespace the instruction is in. /// AsmString - The format string used to emit a .s file for the /// instruction. std::string AsmString; /// Operands - This is information about the (ins) and (outs) list specified /// to the instruction. CGIOperandList Operands; /// ImplicitDefs/ImplicitUses - These are lists of registers that are /// implicitly defined and used by the instruction. std::vector ImplicitDefs, ImplicitUses; // Various boolean values we track for the instruction. bool isPreISelOpcode : 1; bool isReturn : 1; bool isEHScopeReturn : 1; bool isBranch : 1; bool isIndirectBranch : 1; bool isCompare : 1; bool isMoveImm : 1; bool isMoveReg : 1; bool isBitcast : 1; bool isSelect : 1; bool isBarrier : 1; bool isCall : 1; bool isAdd : 1; bool isTrap : 1; bool canFoldAsLoad : 1; bool mayLoad : 1; bool mayLoad_Unset : 1; bool mayStore : 1; bool mayStore_Unset : 1; bool mayRaiseFPException : 1; bool isPredicable : 1; bool isConvertibleToThreeAddress : 1; bool isCommutable : 1; bool isTerminator : 1; bool isReMaterializable : 1; bool hasDelaySlot : 1; bool usesCustomInserter : 1; bool hasPostISelHook : 1; bool hasCtrlDep : 1; bool isNotDuplicable : 1; bool hasSideEffects : 1; bool hasSideEffects_Unset : 1; bool isAsCheapAsAMove : 1; bool hasExtraSrcRegAllocReq : 1; bool hasExtraDefRegAllocReq : 1; bool isCodeGenOnly : 1; bool isPseudo : 1; bool isMeta : 1; bool isRegSequence : 1; bool isExtractSubreg : 1; bool isInsertSubreg : 1; bool isConvergent : 1; bool hasNoSchedulingInfo : 1; bool FastISelShouldIgnore : 1; bool hasChain : 1; bool hasChain_Inferred : 1; bool variadicOpsAreDefs : 1; bool isAuthenticated : 1; std::string DeprecatedReason; bool HasComplexDeprecationPredicate; /// Are there any undefined flags? bool hasUndefFlags() const { return mayLoad_Unset || mayStore_Unset || hasSideEffects_Unset; } // The record used to infer instruction flags, or NULL if no flag values // have been inferred. Record *InferredFrom; CodeGenInstruction(Record *R); /// HasOneImplicitDefWithKnownVT - If the instruction has at least one /// implicit def and it has a known VT, return the VT, otherwise return /// MVT::Other. MVT::SimpleValueType HasOneImplicitDefWithKnownVT(const CodeGenTarget &TargetInfo) const; /// FlattenAsmStringVariants - Flatten the specified AsmString to only /// include text from the specified variant, returning the new string. static std::string FlattenAsmStringVariants(StringRef AsmString, unsigned Variant); // Is the specified operand in a generic instruction implicitly a pointer. // This can be used on intructions that use typeN or ptypeN to identify // operands that should be considered as pointers even though SelectionDAG // didn't make a distinction between integer and pointers. bool isInOperandAPointer(unsigned i) const { return isOperandImpl("InOperandList", i, "IsPointer"); } bool isOutOperandAPointer(unsigned i) const { return isOperandImpl("OutOperandList", i, "IsPointer"); } /// Check if the operand is required to be an immediate. bool isInOperandImmArg(unsigned i) const { return isOperandImpl("InOperandList", i, "IsImmediate"); } private: bool isOperandImpl(StringRef OpListName, unsigned i, StringRef PropertyName) const; }; /// CodeGenInstAlias - This represents an InstAlias definition. class CodeGenInstAlias { public: Record *TheDef; // The actual record defining this InstAlias. /// AsmString - The format string used to emit a .s file for the /// instruction. std::string AsmString; /// Result - The result instruction. DagInit *Result; /// ResultInst - The instruction generated by the alias (decoded from /// Result). CodeGenInstruction *ResultInst; struct ResultOperand { private: std::string Name; Record *R = nullptr; int64_t Imm = 0; public: enum { K_Record, K_Imm, K_Reg } Kind; ResultOperand(std::string N, Record *r) : Name(std::move(N)), R(r), Kind(K_Record) {} ResultOperand(int64_t I) : Imm(I), Kind(K_Imm) {} ResultOperand(Record *r) : R(r), Kind(K_Reg) {} bool isRecord() const { return Kind == K_Record; } bool isImm() const { return Kind == K_Imm; } bool isReg() const { return Kind == K_Reg; } StringRef getName() const { assert(isRecord()); return Name; } Record *getRecord() const { assert(isRecord()); return R; } int64_t getImm() const { assert(isImm()); return Imm; } Record *getRegister() const { assert(isReg()); return R; } unsigned getMINumOperands() const; }; /// ResultOperands - The decoded operands for the result instruction. std::vector ResultOperands; /// ResultInstOperandIndex - For each operand, this vector holds a pair of /// indices to identify the corresponding operand in the result /// instruction. The first index specifies the operand and the second /// index specifies the suboperand. If there are no suboperands or if all /// of them are matched by the operand, the second value should be -1. std::vector > ResultInstOperandIndex; CodeGenInstAlias(Record *R, CodeGenTarget &T); bool tryAliasOpMatch(DagInit *Result, unsigned AliasOpNo, Record *InstOpRec, bool hasSubOps, ArrayRef Loc, CodeGenTarget &T, ResultOperand &ResOp); }; } #endif