1*0fca6ea1SDimitry Andric //===- CodeGenTarget.h - Target Class Wrapper -------------------*- C++ -*-===// 2*0fca6ea1SDimitry Andric // 3*0fca6ea1SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4*0fca6ea1SDimitry Andric // See https://llvm.org/LICENSE.txt for license information. 5*0fca6ea1SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6*0fca6ea1SDimitry Andric // 7*0fca6ea1SDimitry Andric //===----------------------------------------------------------------------===// 8*0fca6ea1SDimitry Andric // 9*0fca6ea1SDimitry Andric // This file defines wrappers for the Target class and related global 10*0fca6ea1SDimitry Andric // functionality. This makes it easier to access the data and provides a single 11*0fca6ea1SDimitry Andric // place that needs to check it for validity. All of these classes abort 12*0fca6ea1SDimitry Andric // on error conditions. 13*0fca6ea1SDimitry Andric // 14*0fca6ea1SDimitry Andric //===----------------------------------------------------------------------===// 15*0fca6ea1SDimitry Andric 16*0fca6ea1SDimitry Andric #ifndef LLVM_UTILS_TABLEGEN_CODEGENTARGET_H 17*0fca6ea1SDimitry Andric #define LLVM_UTILS_TABLEGEN_CODEGENTARGET_H 18*0fca6ea1SDimitry Andric 19*0fca6ea1SDimitry Andric #include "Basic/SDNodeProperties.h" 20*0fca6ea1SDimitry Andric #include "CodeGenHwModes.h" 21*0fca6ea1SDimitry Andric #include "CodeGenInstruction.h" 22*0fca6ea1SDimitry Andric #include "InfoByHwMode.h" 23*0fca6ea1SDimitry Andric #include "llvm/ADT/ArrayRef.h" 24*0fca6ea1SDimitry Andric #include "llvm/ADT/DenseMap.h" 25*0fca6ea1SDimitry Andric #include "llvm/ADT/SmallVector.h" 26*0fca6ea1SDimitry Andric #include "llvm/ADT/StringRef.h" 27*0fca6ea1SDimitry Andric #include "llvm/CodeGenTypes/MachineValueType.h" 28*0fca6ea1SDimitry Andric #include <cassert> 29*0fca6ea1SDimitry Andric #include <memory> 30*0fca6ea1SDimitry Andric #include <optional> 31*0fca6ea1SDimitry Andric #include <string> 32*0fca6ea1SDimitry Andric #include <vector> 33*0fca6ea1SDimitry Andric 34*0fca6ea1SDimitry Andric namespace llvm { 35*0fca6ea1SDimitry Andric 36*0fca6ea1SDimitry Andric class RecordKeeper; 37*0fca6ea1SDimitry Andric class Record; 38*0fca6ea1SDimitry Andric class CodeGenRegBank; 39*0fca6ea1SDimitry Andric class CodeGenRegister; 40*0fca6ea1SDimitry Andric class CodeGenRegisterClass; 41*0fca6ea1SDimitry Andric class CodeGenSchedModels; 42*0fca6ea1SDimitry Andric class CodeGenSubRegIndex; 43*0fca6ea1SDimitry Andric 44*0fca6ea1SDimitry Andric /// getValueType - Return the MVT::SimpleValueType that the specified TableGen 45*0fca6ea1SDimitry Andric /// record corresponds to. 46*0fca6ea1SDimitry Andric MVT::SimpleValueType getValueType(const Record *Rec); 47*0fca6ea1SDimitry Andric 48*0fca6ea1SDimitry Andric StringRef getName(MVT::SimpleValueType T); 49*0fca6ea1SDimitry Andric StringRef getEnumName(MVT::SimpleValueType T); 50*0fca6ea1SDimitry Andric 51*0fca6ea1SDimitry Andric /// getQualifiedName - Return the name of the specified record, with a 52*0fca6ea1SDimitry Andric /// namespace qualifier if the record contains one. 53*0fca6ea1SDimitry Andric std::string getQualifiedName(const Record *R); 54*0fca6ea1SDimitry Andric 55*0fca6ea1SDimitry Andric /// CodeGenTarget - This class corresponds to the Target class in the .td files. 56*0fca6ea1SDimitry Andric /// 57*0fca6ea1SDimitry Andric class CodeGenTarget { 58*0fca6ea1SDimitry Andric RecordKeeper &Records; 59*0fca6ea1SDimitry Andric Record *TargetRec; 60*0fca6ea1SDimitry Andric 61*0fca6ea1SDimitry Andric mutable DenseMap<const Record *, std::unique_ptr<CodeGenInstruction>> 62*0fca6ea1SDimitry Andric Instructions; 63*0fca6ea1SDimitry Andric mutable std::unique_ptr<CodeGenRegBank> RegBank; 64*0fca6ea1SDimitry Andric mutable std::vector<Record *> RegAltNameIndices; 65*0fca6ea1SDimitry Andric mutable SmallVector<ValueTypeByHwMode, 8> LegalValueTypes; 66*0fca6ea1SDimitry Andric CodeGenHwModes CGH; 67*0fca6ea1SDimitry Andric std::vector<Record *> MacroFusions; 68*0fca6ea1SDimitry Andric mutable bool HasVariableLengthEncodings = false; 69*0fca6ea1SDimitry Andric 70*0fca6ea1SDimitry Andric void ReadRegAltNameIndices() const; 71*0fca6ea1SDimitry Andric void ReadInstructions() const; 72*0fca6ea1SDimitry Andric void ReadLegalValueTypes() const; 73*0fca6ea1SDimitry Andric 74*0fca6ea1SDimitry Andric mutable std::unique_ptr<CodeGenSchedModels> SchedModels; 75*0fca6ea1SDimitry Andric 76*0fca6ea1SDimitry Andric mutable StringRef InstNamespace; 77*0fca6ea1SDimitry Andric mutable std::vector<const CodeGenInstruction *> InstrsByEnum; 78*0fca6ea1SDimitry Andric mutable unsigned NumPseudoInstructions = 0; 79*0fca6ea1SDimitry Andric 80*0fca6ea1SDimitry Andric public: 81*0fca6ea1SDimitry Andric CodeGenTarget(RecordKeeper &Records); 82*0fca6ea1SDimitry Andric ~CodeGenTarget(); 83*0fca6ea1SDimitry Andric 84*0fca6ea1SDimitry Andric Record *getTargetRecord() const { return TargetRec; } 85*0fca6ea1SDimitry Andric StringRef getName() const; 86*0fca6ea1SDimitry Andric 87*0fca6ea1SDimitry Andric /// getInstNamespace - Return the target-specific instruction namespace. 88*0fca6ea1SDimitry Andric /// 89*0fca6ea1SDimitry Andric StringRef getInstNamespace() const; 90*0fca6ea1SDimitry Andric 91*0fca6ea1SDimitry Andric /// getRegNamespace - Return the target-specific register namespace. 92*0fca6ea1SDimitry Andric StringRef getRegNamespace() const; 93*0fca6ea1SDimitry Andric 94*0fca6ea1SDimitry Andric /// getInstructionSet - Return the InstructionSet object. 95*0fca6ea1SDimitry Andric /// 96*0fca6ea1SDimitry Andric Record *getInstructionSet() const; 97*0fca6ea1SDimitry Andric 98*0fca6ea1SDimitry Andric /// getAllowRegisterRenaming - Return the AllowRegisterRenaming flag value for 99*0fca6ea1SDimitry Andric /// this target. 100*0fca6ea1SDimitry Andric /// 101*0fca6ea1SDimitry Andric bool getAllowRegisterRenaming() const; 102*0fca6ea1SDimitry Andric 103*0fca6ea1SDimitry Andric /// getAsmParser - Return the AssemblyParser definition for this target. 104*0fca6ea1SDimitry Andric /// 105*0fca6ea1SDimitry Andric Record *getAsmParser() const; 106*0fca6ea1SDimitry Andric 107*0fca6ea1SDimitry Andric /// getAsmParserVariant - Return the AssemblyParserVariant definition for 108*0fca6ea1SDimitry Andric /// this target. 109*0fca6ea1SDimitry Andric /// 110*0fca6ea1SDimitry Andric Record *getAsmParserVariant(unsigned i) const; 111*0fca6ea1SDimitry Andric 112*0fca6ea1SDimitry Andric /// getAsmParserVariantCount - Return the AssemblyParserVariant definition 113*0fca6ea1SDimitry Andric /// available for this target. 114*0fca6ea1SDimitry Andric /// 115*0fca6ea1SDimitry Andric unsigned getAsmParserVariantCount() const; 116*0fca6ea1SDimitry Andric 117*0fca6ea1SDimitry Andric /// getAsmWriter - Return the AssemblyWriter definition for this target. 118*0fca6ea1SDimitry Andric /// 119*0fca6ea1SDimitry Andric Record *getAsmWriter() const; 120*0fca6ea1SDimitry Andric 121*0fca6ea1SDimitry Andric /// getRegBank - Return the register bank description. 122*0fca6ea1SDimitry Andric CodeGenRegBank &getRegBank() const; 123*0fca6ea1SDimitry Andric 124*0fca6ea1SDimitry Andric /// Return the largest register class on \p RegBank which supports \p Ty and 125*0fca6ea1SDimitry Andric /// covers \p SubIdx if it exists. 126*0fca6ea1SDimitry Andric std::optional<CodeGenRegisterClass *> 127*0fca6ea1SDimitry Andric getSuperRegForSubReg(const ValueTypeByHwMode &Ty, CodeGenRegBank &RegBank, 128*0fca6ea1SDimitry Andric const CodeGenSubRegIndex *SubIdx, 129*0fca6ea1SDimitry Andric bool MustBeAllocatable = false) const; 130*0fca6ea1SDimitry Andric 131*0fca6ea1SDimitry Andric /// getRegisterByName - If there is a register with the specific AsmName, 132*0fca6ea1SDimitry Andric /// return it. 133*0fca6ea1SDimitry Andric const CodeGenRegister *getRegisterByName(StringRef Name) const; 134*0fca6ea1SDimitry Andric 135*0fca6ea1SDimitry Andric const std::vector<Record *> &getRegAltNameIndices() const { 136*0fca6ea1SDimitry Andric if (RegAltNameIndices.empty()) 137*0fca6ea1SDimitry Andric ReadRegAltNameIndices(); 138*0fca6ea1SDimitry Andric return RegAltNameIndices; 139*0fca6ea1SDimitry Andric } 140*0fca6ea1SDimitry Andric 141*0fca6ea1SDimitry Andric const CodeGenRegisterClass &getRegisterClass(Record *R) const; 142*0fca6ea1SDimitry Andric 143*0fca6ea1SDimitry Andric /// getRegisterVTs - Find the union of all possible SimpleValueTypes for the 144*0fca6ea1SDimitry Andric /// specified physical register. 145*0fca6ea1SDimitry Andric std::vector<ValueTypeByHwMode> getRegisterVTs(Record *R) const; 146*0fca6ea1SDimitry Andric 147*0fca6ea1SDimitry Andric ArrayRef<ValueTypeByHwMode> getLegalValueTypes() const { 148*0fca6ea1SDimitry Andric if (LegalValueTypes.empty()) 149*0fca6ea1SDimitry Andric ReadLegalValueTypes(); 150*0fca6ea1SDimitry Andric return LegalValueTypes; 151*0fca6ea1SDimitry Andric } 152*0fca6ea1SDimitry Andric 153*0fca6ea1SDimitry Andric CodeGenSchedModels &getSchedModels() const; 154*0fca6ea1SDimitry Andric 155*0fca6ea1SDimitry Andric const CodeGenHwModes &getHwModes() const { return CGH; } 156*0fca6ea1SDimitry Andric 157*0fca6ea1SDimitry Andric bool hasMacroFusion() const { return !MacroFusions.empty(); } 158*0fca6ea1SDimitry Andric 159*0fca6ea1SDimitry Andric const std::vector<Record *> getMacroFusions() const { return MacroFusions; } 160*0fca6ea1SDimitry Andric 161*0fca6ea1SDimitry Andric private: 162*0fca6ea1SDimitry Andric DenseMap<const Record *, std::unique_ptr<CodeGenInstruction>> & 163*0fca6ea1SDimitry Andric getInstructions() const { 164*0fca6ea1SDimitry Andric if (Instructions.empty()) 165*0fca6ea1SDimitry Andric ReadInstructions(); 166*0fca6ea1SDimitry Andric return Instructions; 167*0fca6ea1SDimitry Andric } 168*0fca6ea1SDimitry Andric 169*0fca6ea1SDimitry Andric public: 170*0fca6ea1SDimitry Andric CodeGenInstruction &getInstruction(const Record *InstRec) const { 171*0fca6ea1SDimitry Andric if (Instructions.empty()) 172*0fca6ea1SDimitry Andric ReadInstructions(); 173*0fca6ea1SDimitry Andric auto I = Instructions.find(InstRec); 174*0fca6ea1SDimitry Andric assert(I != Instructions.end() && "Not an instruction"); 175*0fca6ea1SDimitry Andric return *I->second; 176*0fca6ea1SDimitry Andric } 177*0fca6ea1SDimitry Andric 178*0fca6ea1SDimitry Andric /// Returns the number of predefined instructions. 179*0fca6ea1SDimitry Andric static unsigned getNumFixedInstructions(); 180*0fca6ea1SDimitry Andric 181*0fca6ea1SDimitry Andric /// Returns the number of pseudo instructions. 182*0fca6ea1SDimitry Andric unsigned getNumPseudoInstructions() const { 183*0fca6ea1SDimitry Andric if (InstrsByEnum.empty()) 184*0fca6ea1SDimitry Andric ComputeInstrsByEnum(); 185*0fca6ea1SDimitry Andric return NumPseudoInstructions; 186*0fca6ea1SDimitry Andric } 187*0fca6ea1SDimitry Andric 188*0fca6ea1SDimitry Andric /// Return all of the instructions defined by the target, ordered by their 189*0fca6ea1SDimitry Andric /// enum value. 190*0fca6ea1SDimitry Andric /// The following order of instructions is also guaranteed: 191*0fca6ea1SDimitry Andric /// - fixed / generic instructions as declared in TargetOpcodes.def, in order; 192*0fca6ea1SDimitry Andric /// - pseudo instructions in lexicographical order sorted by name; 193*0fca6ea1SDimitry Andric /// - other instructions in lexicographical order sorted by name. 194*0fca6ea1SDimitry Andric ArrayRef<const CodeGenInstruction *> getInstructionsByEnumValue() const { 195*0fca6ea1SDimitry Andric if (InstrsByEnum.empty()) 196*0fca6ea1SDimitry Andric ComputeInstrsByEnum(); 197*0fca6ea1SDimitry Andric return InstrsByEnum; 198*0fca6ea1SDimitry Andric } 199*0fca6ea1SDimitry Andric 200*0fca6ea1SDimitry Andric /// Return the integer enum value corresponding to this instruction record. 201*0fca6ea1SDimitry Andric unsigned getInstrIntValue(const Record *R) const { 202*0fca6ea1SDimitry Andric if (InstrsByEnum.empty()) 203*0fca6ea1SDimitry Andric ComputeInstrsByEnum(); 204*0fca6ea1SDimitry Andric return getInstruction(R).EnumVal; 205*0fca6ea1SDimitry Andric } 206*0fca6ea1SDimitry Andric 207*0fca6ea1SDimitry Andric typedef ArrayRef<const CodeGenInstruction *>::const_iterator inst_iterator; 208*0fca6ea1SDimitry Andric inst_iterator inst_begin() const { 209*0fca6ea1SDimitry Andric return getInstructionsByEnumValue().begin(); 210*0fca6ea1SDimitry Andric } 211*0fca6ea1SDimitry Andric inst_iterator inst_end() const { return getInstructionsByEnumValue().end(); } 212*0fca6ea1SDimitry Andric 213*0fca6ea1SDimitry Andric /// Return whether instructions have variable length encodings on this target. 214*0fca6ea1SDimitry Andric bool hasVariableLengthEncodings() const { return HasVariableLengthEncodings; } 215*0fca6ea1SDimitry Andric 216*0fca6ea1SDimitry Andric /// isLittleEndianEncoding - are instruction bit patterns defined as [0..n]? 217*0fca6ea1SDimitry Andric /// 218*0fca6ea1SDimitry Andric bool isLittleEndianEncoding() const; 219*0fca6ea1SDimitry Andric 220*0fca6ea1SDimitry Andric /// reverseBitsForLittleEndianEncoding - For little-endian instruction bit 221*0fca6ea1SDimitry Andric /// encodings, reverse the bit order of all instructions. 222*0fca6ea1SDimitry Andric void reverseBitsForLittleEndianEncoding(); 223*0fca6ea1SDimitry Andric 224*0fca6ea1SDimitry Andric /// guessInstructionProperties - should we just guess unset instruction 225*0fca6ea1SDimitry Andric /// properties? 226*0fca6ea1SDimitry Andric bool guessInstructionProperties() const; 227*0fca6ea1SDimitry Andric 228*0fca6ea1SDimitry Andric private: 229*0fca6ea1SDimitry Andric void ComputeInstrsByEnum() const; 230*0fca6ea1SDimitry Andric }; 231*0fca6ea1SDimitry Andric 232*0fca6ea1SDimitry Andric /// ComplexPattern - ComplexPattern info, corresponding to the ComplexPattern 233*0fca6ea1SDimitry Andric /// tablegen class in TargetSelectionDAG.td 234*0fca6ea1SDimitry Andric class ComplexPattern { 235*0fca6ea1SDimitry Andric Record *Ty; 236*0fca6ea1SDimitry Andric unsigned NumOperands; 237*0fca6ea1SDimitry Andric std::string SelectFunc; 238*0fca6ea1SDimitry Andric std::vector<Record *> RootNodes; 239*0fca6ea1SDimitry Andric unsigned Properties; // Node properties 240*0fca6ea1SDimitry Andric unsigned Complexity; 241*0fca6ea1SDimitry Andric 242*0fca6ea1SDimitry Andric public: 243*0fca6ea1SDimitry Andric ComplexPattern(Record *R); 244*0fca6ea1SDimitry Andric 245*0fca6ea1SDimitry Andric Record *getValueType() const { return Ty; } 246*0fca6ea1SDimitry Andric unsigned getNumOperands() const { return NumOperands; } 247*0fca6ea1SDimitry Andric const std::string &getSelectFunc() const { return SelectFunc; } 248*0fca6ea1SDimitry Andric const std::vector<Record *> &getRootNodes() const { return RootNodes; } 249*0fca6ea1SDimitry Andric bool hasProperty(enum SDNP Prop) const { return Properties & (1 << Prop); } 250*0fca6ea1SDimitry Andric unsigned getComplexity() const { return Complexity; } 251*0fca6ea1SDimitry Andric }; 252*0fca6ea1SDimitry Andric 253*0fca6ea1SDimitry Andric } // namespace llvm 254*0fca6ea1SDimitry Andric 255*0fca6ea1SDimitry Andric #endif 256