|  | //===-------- CompressInstEmitter.cpp - Generator for Compression ---------===// | 
|  | // | 
|  | // 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 | 
|  | // | 
|  | // CompressInstEmitter implements a tablegen-driven CompressPat based | 
|  | // Instruction Compression mechanism. | 
|  | // | 
|  | //===----------------------------------------------------------------------===// | 
|  | // | 
|  | // CompressInstEmitter implements a tablegen-driven CompressPat Instruction | 
|  | // Compression mechanism for generating compressed instructions from the | 
|  | // expanded instruction form. | 
|  |  | 
|  | // This tablegen backend processes CompressPat declarations in a | 
|  | // td file and generates all the required checks to validate the pattern | 
|  | // declarations; validate the input and output operands to generate the correct | 
|  | // compressed instructions. The checks include validating different types of | 
|  | // operands; register operands, immediate operands, fixed register and fixed | 
|  | // immediate inputs. | 
|  | // | 
|  | // Example: | 
|  | // /// Defines a Pat match between compressed and uncompressed instruction. | 
|  | // /// The relationship and helper function generation are handled by | 
|  | // /// CompressInstEmitter backend. | 
|  | // class CompressPat<dag input, dag output, list<Predicate> predicates = []> { | 
|  | //   /// Uncompressed instruction description. | 
|  | //   dag Input = input; | 
|  | //   /// Compressed instruction description. | 
|  | //   dag Output = output; | 
|  | //   /// Predicates that must be true for this to match. | 
|  | //   list<Predicate> Predicates = predicates; | 
|  | //   /// Duplicate match when tied operand is just different. | 
|  | //   bit isCompressOnly = false; | 
|  | // } | 
|  | // | 
|  | // let Predicates = [HasStdExtC] in { | 
|  | // def : CompressPat<(ADD GPRNoX0:$rs1, GPRNoX0:$rs1, GPRNoX0:$rs2), | 
|  | //                   (C_ADD GPRNoX0:$rs1, GPRNoX0:$rs2)>; | 
|  | // } | 
|  | // | 
|  | // The <TargetName>GenCompressInstEmitter.inc is an auto-generated header | 
|  | // file which exports two functions for compressing/uncompressing MCInst | 
|  | // instructions, plus some helper functions: | 
|  | // | 
|  | // bool compressInst(MCInst &OutInst, const MCInst &MI, | 
|  | //                   const MCSubtargetInfo &STI); | 
|  | // | 
|  | // bool uncompressInst(MCInst &OutInst, const MCInst &MI, | 
|  | //                     const MCSubtargetInfo &STI); | 
|  | // | 
|  | // In addition, it exports a function for checking whether | 
|  | // an instruction is compressable: | 
|  | // | 
|  | // bool isCompressibleInst(const MachineInstr& MI, | 
|  | //                         const <TargetName>Subtarget &STI); | 
|  | // | 
|  | // The clients that include this auto-generated header file and | 
|  | // invoke these functions can compress an instruction before emitting | 
|  | // it in the target-specific ASM or ELF streamer or can uncompress | 
|  | // an instruction before printing it when the expanded instruction | 
|  | // format aliases is favored. | 
|  |  | 
|  | //===----------------------------------------------------------------------===// | 
|  |  | 
|  | #include "Common/CodeGenInstruction.h" | 
|  | #include "Common/CodeGenRegisters.h" | 
|  | #include "Common/CodeGenTarget.h" | 
|  | #include "llvm/ADT/IndexedMap.h" | 
|  | #include "llvm/ADT/SmallVector.h" | 
|  | #include "llvm/ADT/StringMap.h" | 
|  | #include "llvm/Support/Debug.h" | 
|  | #include "llvm/Support/ErrorHandling.h" | 
|  | #include "llvm/TableGen/Error.h" | 
|  | #include "llvm/TableGen/Record.h" | 
|  | #include "llvm/TableGen/TableGenBackend.h" | 
|  | #include <limits> | 
|  | #include <set> | 
|  | #include <vector> | 
|  | using namespace llvm; | 
|  |  | 
|  | #define DEBUG_TYPE "compress-inst-emitter" | 
|  |  | 
|  | namespace { | 
|  | class CompressInstEmitter { | 
|  | struct OpData { | 
|  | enum MapKind { Operand, Imm, Reg } Kind; | 
|  | // Info for an operand. | 
|  | struct OpndInfo { | 
|  | // Record from the Dag. | 
|  | const Record *DagRec; | 
|  | // Operand number mapped to. | 
|  | unsigned Idx; | 
|  | // Tied operand index within the instruction. | 
|  | int TiedOpIdx; | 
|  | }; | 
|  | union { | 
|  | OpndInfo OpInfo; | 
|  | // Integer immediate value. | 
|  | int64_t ImmVal; | 
|  | // Physical register. | 
|  | const Record *RegRec; | 
|  | }; | 
|  | }; | 
|  | struct ArgData { | 
|  | unsigned DAGOpNo; | 
|  | unsigned MIOpNo; | 
|  | }; | 
|  | struct CompressPat { | 
|  | // The source instruction definition. | 
|  | CodeGenInstruction Source; | 
|  | // The destination instruction to transform to. | 
|  | CodeGenInstruction Dest; | 
|  | // Required target features to enable pattern. | 
|  | std::vector<const Record *> PatReqFeatures; | 
|  | // Maps operands in the Source Instruction to | 
|  | // the corresponding Dest instruction operand. | 
|  | IndexedMap<OpData> SourceOperandMap; | 
|  | // Maps operands in the Dest Instruction | 
|  | // to the corresponding Source instruction operand. | 
|  | IndexedMap<OpData> DestOperandMap; | 
|  |  | 
|  | bool IsCompressOnly; | 
|  | CompressPat(const CodeGenInstruction &S, const CodeGenInstruction &D, | 
|  | std::vector<const Record *> RF, | 
|  | const IndexedMap<OpData> &SourceMap, | 
|  | const IndexedMap<OpData> &DestMap, bool IsCompressOnly) | 
|  | : Source(S), Dest(D), PatReqFeatures(std::move(RF)), | 
|  | SourceOperandMap(SourceMap), DestOperandMap(DestMap), | 
|  | IsCompressOnly(IsCompressOnly) {} | 
|  | }; | 
|  | enum EmitterType { Compress, Uncompress, CheckCompress }; | 
|  | const RecordKeeper &Records; | 
|  | const CodeGenTarget Target; | 
|  | std::vector<CompressPat> CompressPatterns; | 
|  | void addDagOperandMapping(const Record *Rec, const DagInit *Dag, | 
|  | const CodeGenInstruction &Inst, | 
|  | IndexedMap<OpData> &OperandMap, | 
|  | StringMap<ArgData> &Operands, bool IsSourceInst); | 
|  | void evaluateCompressPat(const Record *Compress); | 
|  | void emitCompressInstEmitter(raw_ostream &OS, EmitterType EType); | 
|  | bool validateTypes(const Record *DagOpType, const Record *InstOpType, | 
|  | bool IsSourceInst); | 
|  | bool validateRegister(const Record *Reg, const Record *RegClass); | 
|  | void checkDagOperandMapping(const Record *Rec, | 
|  | const StringMap<ArgData> &DestOperands, | 
|  | const DagInit *SourceDag, const DagInit *DestDag); | 
|  |  | 
|  | void createInstOperandMapping(const Record *Rec, const DagInit *SourceDag, | 
|  | const DagInit *DestDag, | 
|  | IndexedMap<OpData> &SourceOperandMap, | 
|  | IndexedMap<OpData> &DestOperandMap, | 
|  | StringMap<ArgData> &SourceOperands, | 
|  | const CodeGenInstruction &DestInst); | 
|  |  | 
|  | public: | 
|  | CompressInstEmitter(const RecordKeeper &R) : Records(R), Target(R) {} | 
|  |  | 
|  | void run(raw_ostream &OS); | 
|  | }; | 
|  | } // End anonymous namespace. | 
|  |  | 
|  | bool CompressInstEmitter::validateRegister(const Record *Reg, | 
|  | const Record *RegClass) { | 
|  | assert(Reg->isSubClassOf("Register") && "Reg record should be a Register"); | 
|  | assert(RegClass->isSubClassOf("RegisterClass") && | 
|  | "RegClass record should be a RegisterClass"); | 
|  | const CodeGenRegisterClass &RC = Target.getRegisterClass(RegClass); | 
|  | const CodeGenRegister *R = Target.getRegisterByName(Reg->getName().lower()); | 
|  | assert(R != nullptr && "Register not defined!!"); | 
|  | return RC.contains(R); | 
|  | } | 
|  |  | 
|  | bool CompressInstEmitter::validateTypes(const Record *DagOpType, | 
|  | const Record *InstOpType, | 
|  | bool IsSourceInst) { | 
|  | if (DagOpType == InstOpType) | 
|  | return true; | 
|  |  | 
|  | if (DagOpType->isSubClassOf("RegisterClass") && | 
|  | InstOpType->isSubClassOf("RegisterClass")) { | 
|  | const CodeGenRegisterClass &RC = Target.getRegisterClass(InstOpType); | 
|  | const CodeGenRegisterClass &SubRC = Target.getRegisterClass(DagOpType); | 
|  | return RC.hasSubClass(&SubRC); | 
|  | } | 
|  |  | 
|  | // At this point either or both types are not registers, reject the pattern. | 
|  | if (DagOpType->isSubClassOf("RegisterClass") || | 
|  | InstOpType->isSubClassOf("RegisterClass")) | 
|  | return false; | 
|  |  | 
|  | // Let further validation happen when compress()/uncompress() functions are | 
|  | // invoked. | 
|  | LLVM_DEBUG(dbgs() << (IsSourceInst ? "Input" : "Output") | 
|  | << " Dag Operand Type: '" << DagOpType->getName() | 
|  | << "' and " | 
|  | << "Instruction Operand Type: '" << InstOpType->getName() | 
|  | << "' can't be checked at pattern validation time!\n"); | 
|  | return true; | 
|  | } | 
|  |  | 
|  | static bool validateArgsTypes(const Init *Arg1, const Init *Arg2) { | 
|  | return cast<DefInit>(Arg1)->getDef() == cast<DefInit>(Arg2)->getDef(); | 
|  | } | 
|  |  | 
|  | /// The patterns in the Dag contain different types of operands: | 
|  | /// Register operands, e.g.: GPRC:$rs1; Fixed registers, e.g: X1; Immediate | 
|  | /// operands, e.g.: simm6:$imm; Fixed immediate operands, e.g.: 0. This function | 
|  | /// maps Dag operands to its corresponding instruction operands. For register | 
|  | /// operands and fixed registers it expects the Dag operand type to be contained | 
|  | /// in the instantiated instruction operand type. For immediate operands and | 
|  | /// immediates no validation checks are enforced at pattern validation time. | 
|  | void CompressInstEmitter::addDagOperandMapping(const Record *Rec, | 
|  | const DagInit *Dag, | 
|  | const CodeGenInstruction &Inst, | 
|  | IndexedMap<OpData> &OperandMap, | 
|  | StringMap<ArgData> &Operands, | 
|  | bool IsSourceInst) { | 
|  | unsigned NumMIOperands = 0; | 
|  | if (!Inst.Operands.empty()) | 
|  | NumMIOperands = | 
|  | Inst.Operands.back().MIOperandNo + Inst.Operands.back().MINumOperands; | 
|  | OperandMap.grow(NumMIOperands); | 
|  |  | 
|  | // Tied operands are not represented in the DAG so we count them separately. | 
|  | unsigned DAGOpNo = 0; | 
|  | unsigned OpNo = 0; | 
|  | for (const auto &Opnd : Inst.Operands) { | 
|  | int TiedOpIdx = Opnd.getTiedRegister(); | 
|  | if (-1 != TiedOpIdx) { | 
|  | assert((unsigned)TiedOpIdx < OpNo); | 
|  | // Set the entry in OperandMap for the tied operand we're skipping. | 
|  | OperandMap[OpNo] = OperandMap[TiedOpIdx]; | 
|  | ++OpNo; | 
|  |  | 
|  | // Source instructions can have at most 1 tied operand. | 
|  | if (IsSourceInst && (OpNo - DAGOpNo > 1)) | 
|  | PrintFatalError(Rec->getLoc(), | 
|  | "Input operands for Inst '" + Inst.TheDef->getName() + | 
|  | "' and input Dag operand count mismatch"); | 
|  |  | 
|  | continue; | 
|  | } | 
|  | for (unsigned SubOp = 0; SubOp != Opnd.MINumOperands; | 
|  | ++SubOp, ++OpNo, ++DAGOpNo) { | 
|  | const Record *OpndRec = Opnd.Rec; | 
|  | if (Opnd.MINumOperands > 1) | 
|  | OpndRec = cast<DefInit>(Opnd.MIOperandInfo->getArg(SubOp))->getDef(); | 
|  |  | 
|  | if (DAGOpNo >= Dag->getNumArgs()) | 
|  | PrintFatalError(Rec->getLoc(), "Inst '" + Inst.TheDef->getName() + | 
|  | "' and Dag operand count mismatch"); | 
|  |  | 
|  | if (const auto *DI = dyn_cast<DefInit>(Dag->getArg(DAGOpNo))) { | 
|  | if (DI->getDef()->isSubClassOf("Register")) { | 
|  | // Check if the fixed register belongs to the Register class. | 
|  | if (!validateRegister(DI->getDef(), OpndRec)) | 
|  | PrintFatalError(Rec->getLoc(), | 
|  | "Error in Dag '" + Dag->getAsString() + | 
|  | "'Register: '" + DI->getDef()->getName() + | 
|  | "' is not in register class '" + | 
|  | OpndRec->getName() + "'"); | 
|  | OperandMap[OpNo].Kind = OpData::Reg; | 
|  | OperandMap[OpNo].RegRec = DI->getDef(); | 
|  | continue; | 
|  | } | 
|  | // Validate that Dag operand type matches the type defined in the | 
|  | // corresponding instruction. Operands in the input and output Dag | 
|  | // patterns are allowed to be a subclass of the type specified in the | 
|  | // corresponding instruction operand instead of being an exact match. | 
|  | if (!validateTypes(DI->getDef(), OpndRec, IsSourceInst)) | 
|  | PrintFatalError(Rec->getLoc(), | 
|  | "Error in Dag '" + Dag->getAsString() + | 
|  | "'. Operand '" + Dag->getArgNameStr(DAGOpNo) + | 
|  | "' has type '" + DI->getDef()->getName() + | 
|  | "' which does not match the type '" + | 
|  | OpndRec->getName() + | 
|  | "' in the corresponding instruction operand!"); | 
|  |  | 
|  | OperandMap[OpNo].Kind = OpData::Operand; | 
|  | OperandMap[OpNo].OpInfo.DagRec = DI->getDef(); | 
|  | OperandMap[OpNo].OpInfo.TiedOpIdx = -1; | 
|  |  | 
|  | // Create a mapping between the operand name in the Dag (e.g. $rs1) and | 
|  | // its index in the list of Dag operands and check that operands with | 
|  | // the same name have the same type. For example in 'C_ADD $rs1, $rs2' | 
|  | // we generate the mapping $rs1 --> 0, $rs2 ---> 1. If the operand | 
|  | // appears twice in the same Dag (tied in the compressed instruction), | 
|  | // we note the previous index in the TiedOpIdx field. | 
|  | StringRef ArgName = Dag->getArgNameStr(DAGOpNo); | 
|  | if (ArgName.empty()) | 
|  | continue; | 
|  |  | 
|  | if (IsSourceInst) { | 
|  | auto It = Operands.find(ArgName); | 
|  | if (It != Operands.end()) { | 
|  | OperandMap[OpNo].OpInfo.TiedOpIdx = It->getValue().MIOpNo; | 
|  | if (OperandMap[It->getValue().MIOpNo].OpInfo.DagRec != DI->getDef()) | 
|  | PrintFatalError(Rec->getLoc(), | 
|  | "Input Operand '" + ArgName + | 
|  | "' has a mismatched tied operand!"); | 
|  | } | 
|  | } | 
|  |  | 
|  | Operands[ArgName] = {DAGOpNo, OpNo}; | 
|  | } else if (const auto *II = dyn_cast<IntInit>(Dag->getArg(DAGOpNo))) { | 
|  | // Validate that corresponding instruction operand expects an immediate. | 
|  | if (!OpndRec->isSubClassOf("Operand")) | 
|  | PrintFatalError(Rec->getLoc(), "Error in Dag '" + Dag->getAsString() + | 
|  | "' Found immediate: '" + | 
|  | II->getAsString() + | 
|  | "' but corresponding instruction " | 
|  | "operand expected a register!"); | 
|  | // No pattern validation check possible for values of fixed immediate. | 
|  | OperandMap[OpNo].Kind = OpData::Imm; | 
|  | OperandMap[OpNo].ImmVal = II->getValue(); | 
|  | LLVM_DEBUG( | 
|  | dbgs() << "  Found immediate '" << II->getValue() << "' at " | 
|  | << (IsSourceInst ? "input " : "output ") | 
|  | << "Dag. No validation time check possible for values of " | 
|  | "fixed immediate.\n"); | 
|  | } else { | 
|  | llvm_unreachable("Unhandled CompressPat argument type!"); | 
|  | } | 
|  | } | 
|  | } | 
|  |  | 
|  | // We shouldn't have extra Dag operands. | 
|  | if (DAGOpNo != Dag->getNumArgs()) | 
|  | PrintFatalError(Rec->getLoc(), "Inst '" + Inst.TheDef->getName() + | 
|  | "' and Dag operand count mismatch"); | 
|  | } | 
|  |  | 
|  | // Check that all names in the source DAG appear in the destionation DAG. | 
|  | void CompressInstEmitter::checkDagOperandMapping( | 
|  | const Record *Rec, const StringMap<ArgData> &DestOperands, | 
|  | const DagInit *SourceDag, const DagInit *DestDag) { | 
|  |  | 
|  | for (unsigned I = 0; I < SourceDag->getNumArgs(); ++I) { | 
|  | // Skip fixed immediates and registers, they were handled in | 
|  | // addDagOperandMapping. | 
|  | StringRef ArgName = SourceDag->getArgNameStr(I); | 
|  | if (ArgName.empty()) | 
|  | continue; | 
|  |  | 
|  | auto It = DestOperands.find(ArgName); | 
|  | if (It == DestOperands.end()) | 
|  | PrintFatalError(Rec->getLoc(), "Operand " + ArgName + | 
|  | " defined in Input Dag but not used in" | 
|  | " Output Dag!"); | 
|  | // Input Dag operand types must match output Dag operand type. | 
|  | if (!validateArgsTypes(DestDag->getArg(It->getValue().DAGOpNo), | 
|  | SourceDag->getArg(I))) | 
|  | PrintFatalError(Rec->getLoc(), "Type mismatch between Input and " | 
|  | "Output Dag operand '" + | 
|  | ArgName + "'!"); | 
|  | } | 
|  | } | 
|  |  | 
|  | /// Map operand names in the Dag to their index in both corresponding input and | 
|  | /// output instructions. Validate that operands defined in the input are | 
|  | /// used in the output pattern while populating the maps. | 
|  | void CompressInstEmitter::createInstOperandMapping( | 
|  | const Record *Rec, const DagInit *SourceDag, const DagInit *DestDag, | 
|  | IndexedMap<OpData> &SourceOperandMap, IndexedMap<OpData> &DestOperandMap, | 
|  | StringMap<ArgData> &SourceOperands, const CodeGenInstruction &DestInst) { | 
|  | // TiedCount keeps track of the number of operands skipped in Inst | 
|  | // operands list to get to the corresponding Dag operand. | 
|  | unsigned TiedCount = 0; | 
|  | LLVM_DEBUG(dbgs() << "  Operand mapping:\n  Source   Dest\n"); | 
|  | unsigned OpNo = 0; | 
|  | for (const auto &Operand : DestInst.Operands) { | 
|  | int TiedInstOpIdx = Operand.getTiedRegister(); | 
|  | if (TiedInstOpIdx != -1) { | 
|  | ++TiedCount; | 
|  | assert((unsigned)TiedInstOpIdx < OpNo); | 
|  | DestOperandMap[OpNo] = DestOperandMap[TiedInstOpIdx]; | 
|  | if (DestOperandMap[OpNo].Kind == OpData::Operand) | 
|  | // No need to fill the SourceOperandMap here since it was mapped to | 
|  | // destination operand 'TiedInstOpIdx' in a previous iteration. | 
|  | LLVM_DEBUG(dbgs() << "    " << DestOperandMap[OpNo].OpInfo.Idx | 
|  | << " ====> " << OpNo | 
|  | << "  Dest operand tied with operand '" | 
|  | << TiedInstOpIdx << "'\n"); | 
|  | ++OpNo; | 
|  | continue; | 
|  | } | 
|  |  | 
|  | for (unsigned SubOp = 0; SubOp != Operand.MINumOperands; ++SubOp, ++OpNo) { | 
|  | // Skip fixed immediates and registers, they were handled in | 
|  | // addDagOperandMapping. | 
|  | if (DestOperandMap[OpNo].Kind != OpData::Operand) | 
|  | continue; | 
|  |  | 
|  | unsigned DagArgIdx = OpNo - TiedCount; | 
|  | StringRef ArgName = DestDag->getArgNameStr(DagArgIdx); | 
|  | auto SourceOp = SourceOperands.find(ArgName); | 
|  | if (SourceOp == SourceOperands.end()) | 
|  | PrintFatalError(Rec->getLoc(), | 
|  | "Output Dag operand '" + ArgName + | 
|  | "' has no matching input Dag operand."); | 
|  |  | 
|  | assert(ArgName == | 
|  | SourceDag->getArgNameStr(SourceOp->getValue().DAGOpNo) && | 
|  | "Incorrect operand mapping detected!\n"); | 
|  |  | 
|  | unsigned SourceOpNo = SourceOp->getValue().MIOpNo; | 
|  | DestOperandMap[OpNo].OpInfo.Idx = SourceOpNo; | 
|  | SourceOperandMap[SourceOpNo].OpInfo.Idx = OpNo; | 
|  | LLVM_DEBUG(dbgs() << "    " << SourceOpNo << " ====> " << OpNo << "\n"); | 
|  | } | 
|  | } | 
|  | } | 
|  |  | 
|  | /// Validates the CompressPattern and create operand mapping. | 
|  | /// These are the checks to validate a CompressPat pattern declarations. | 
|  | /// Error out with message under these conditions: | 
|  | /// - Dag Input opcode is an expanded instruction and Dag Output opcode is a | 
|  | ///   compressed instruction. | 
|  | /// - Operands in Dag Input must be all used in Dag Output. | 
|  | ///   Register Operand type in Dag Input Type must be contained in the | 
|  | ///   corresponding Source Instruction type. | 
|  | /// - Register Operand type in Dag Input must be the same as in Dag Ouput. | 
|  | /// - Register Operand type in Dag Output must be the same as the | 
|  | ///   corresponding Destination Inst type. | 
|  | /// - Immediate Operand type in Dag Input must be the same as in Dag Ouput. | 
|  | /// - Immediate Operand type in Dag Ouput must be the same as the corresponding | 
|  | ///   Destination Instruction type. | 
|  | /// - Fixed register must be contained in the corresponding Source Instruction | 
|  | ///   type. | 
|  | /// - Fixed register must be contained in the corresponding Destination | 
|  | ///   Instruction type. | 
|  | /// Warning message printed under these conditions: | 
|  | /// - Fixed immediate in Dag Input or Dag Ouput cannot be checked at this time | 
|  | ///   and generate warning. | 
|  | /// - Immediate operand type in Dag Input differs from the corresponding Source | 
|  | ///   Instruction type and generate a warning. | 
|  | void CompressInstEmitter::evaluateCompressPat(const Record *Rec) { | 
|  | // Validate input Dag operands. | 
|  | const DagInit *SourceDag = Rec->getValueAsDag("Input"); | 
|  | assert(SourceDag && "Missing 'Input' in compress pattern!"); | 
|  | LLVM_DEBUG(dbgs() << "Input: " << *SourceDag << "\n"); | 
|  |  | 
|  | // Checking we are transforming from compressed to uncompressed instructions. | 
|  | const Record *SourceOperator = SourceDag->getOperatorAsDef(Rec->getLoc()); | 
|  | CodeGenInstruction SourceInst(SourceOperator); | 
|  |  | 
|  | // Validate output Dag operands. | 
|  | const DagInit *DestDag = Rec->getValueAsDag("Output"); | 
|  | assert(DestDag && "Missing 'Output' in compress pattern!"); | 
|  | LLVM_DEBUG(dbgs() << "Output: " << *DestDag << "\n"); | 
|  |  | 
|  | const Record *DestOperator = DestDag->getOperatorAsDef(Rec->getLoc()); | 
|  | CodeGenInstruction DestInst(DestOperator); | 
|  |  | 
|  | if (SourceOperator->getValueAsInt("Size") <= | 
|  | DestOperator->getValueAsInt("Size")) | 
|  | PrintFatalError( | 
|  | Rec->getLoc(), | 
|  | "Compressed instruction '" + DestOperator->getName() + | 
|  | "'is not strictly smaller than the uncompressed instruction '" + | 
|  | SourceOperator->getName() + "' !"); | 
|  |  | 
|  | // Fill the mapping from the source to destination instructions. | 
|  |  | 
|  | IndexedMap<OpData> SourceOperandMap; | 
|  | // Map from arg name to DAG operand number and MI operand number. | 
|  | StringMap<ArgData> SourceOperands; | 
|  | // Create a mapping between source Dag operands and source Inst operands. | 
|  | addDagOperandMapping(Rec, SourceDag, SourceInst, SourceOperandMap, | 
|  | SourceOperands, /*IsSourceInst*/ true); | 
|  |  | 
|  | IndexedMap<OpData> DestOperandMap; | 
|  | // Map from arg name to DAG operand number and MI operand number. | 
|  | StringMap<ArgData> DestOperands; | 
|  | // Create a mapping between destination Dag operands and destination Inst | 
|  | // operands. | 
|  | addDagOperandMapping(Rec, DestDag, DestInst, DestOperandMap, DestOperands, | 
|  | /*IsSourceInst*/ false); | 
|  |  | 
|  | checkDagOperandMapping(Rec, DestOperands, SourceDag, DestDag); | 
|  | // Create operand mapping between the source and destination instructions. | 
|  | createInstOperandMapping(Rec, SourceDag, DestDag, SourceOperandMap, | 
|  | DestOperandMap, SourceOperands, DestInst); | 
|  |  | 
|  | // Get the target features for the CompressPat. | 
|  | std::vector<const Record *> PatReqFeatures; | 
|  | std::vector<const Record *> RF = Rec->getValueAsListOfDefs("Predicates"); | 
|  | copy_if(RF, std::back_inserter(PatReqFeatures), [](const Record *R) { | 
|  | return R->getValueAsBit("AssemblerMatcherPredicate"); | 
|  | }); | 
|  |  | 
|  | CompressPatterns.emplace_back(SourceInst, DestInst, std::move(PatReqFeatures), | 
|  | SourceOperandMap, DestOperandMap, | 
|  | Rec->getValueAsBit("isCompressOnly")); | 
|  | } | 
|  |  | 
|  | static void | 
|  | getReqFeatures(std::set<std::pair<bool, StringRef>> &FeaturesSet, | 
|  | std::set<std::set<std::pair<bool, StringRef>>> &AnyOfFeatureSets, | 
|  | ArrayRef<const Record *> ReqFeatures) { | 
|  | for (const Record *R : ReqFeatures) { | 
|  | const DagInit *D = R->getValueAsDag("AssemblerCondDag"); | 
|  | std::string CombineType = D->getOperator()->getAsString(); | 
|  | if (CombineType != "any_of" && CombineType != "all_of") | 
|  | PrintFatalError(R->getLoc(), "Invalid AssemblerCondDag!"); | 
|  | if (D->getNumArgs() == 0) | 
|  | PrintFatalError(R->getLoc(), "Invalid AssemblerCondDag!"); | 
|  | bool IsOr = CombineType == "any_of"; | 
|  | std::set<std::pair<bool, StringRef>> AnyOfSet; | 
|  |  | 
|  | for (auto *Arg : D->getArgs()) { | 
|  | bool IsNot = false; | 
|  | if (auto *NotArg = dyn_cast<DagInit>(Arg)) { | 
|  | if (NotArg->getOperator()->getAsString() != "not" || | 
|  | NotArg->getNumArgs() != 1) | 
|  | PrintFatalError(R->getLoc(), "Invalid AssemblerCondDag!"); | 
|  | Arg = NotArg->getArg(0); | 
|  | IsNot = true; | 
|  | } | 
|  | if (!isa<DefInit>(Arg) || | 
|  | !cast<DefInit>(Arg)->getDef()->isSubClassOf("SubtargetFeature")) | 
|  | PrintFatalError(R->getLoc(), "Invalid AssemblerCondDag!"); | 
|  | if (IsOr) | 
|  | AnyOfSet.emplace(IsNot, cast<DefInit>(Arg)->getDef()->getName()); | 
|  | else | 
|  | FeaturesSet.emplace(IsNot, cast<DefInit>(Arg)->getDef()->getName()); | 
|  | } | 
|  |  | 
|  | if (IsOr) | 
|  | AnyOfFeatureSets.insert(std::move(AnyOfSet)); | 
|  | } | 
|  | } | 
|  |  | 
|  | static unsigned getPredicates(DenseMap<const Record *, unsigned> &PredicateMap, | 
|  | std::vector<const Record *> &Predicates, | 
|  | const Record *Rec, StringRef Name) { | 
|  | unsigned &Entry = PredicateMap[Rec]; | 
|  | if (Entry) | 
|  | return Entry; | 
|  |  | 
|  | if (!Rec->isValueUnset(Name)) { | 
|  | Predicates.push_back(Rec); | 
|  | Entry = Predicates.size(); | 
|  | return Entry; | 
|  | } | 
|  |  | 
|  | PrintFatalError(Rec->getLoc(), "No " + Name + | 
|  | " predicate on this operand at all: '" + | 
|  | Rec->getName() + "'"); | 
|  | return 0; | 
|  | } | 
|  |  | 
|  | static void printPredicates(ArrayRef<const Record *> Predicates, StringRef Name, | 
|  | raw_ostream &OS) { | 
|  | for (unsigned I = 0; I < Predicates.size(); ++I) { | 
|  | StringRef Pred = Predicates[I]->getValueAsString(Name); | 
|  | Pred = Pred.trim(); | 
|  | OS.indent(2) << "case " << I + 1 << ": {\n"; | 
|  | OS.indent(4) << "// " << Predicates[I]->getName() << "\n"; | 
|  | OS.indent(4) << Pred << "\n"; | 
|  | OS.indent(2) << "}\n"; | 
|  | } | 
|  | } | 
|  |  | 
|  | static void mergeCondAndCode(raw_ostream &CombinedStream, StringRef CondStr, | 
|  | StringRef CodeStr) { | 
|  | CombinedStream.indent(4) << "if (" << CondStr << ") {\n"; | 
|  | CombinedStream << CodeStr; | 
|  | CombinedStream.indent(4) << "  return true;\n"; | 
|  | CombinedStream.indent(4) << "} // if\n"; | 
|  | } | 
|  |  | 
|  | void CompressInstEmitter::emitCompressInstEmitter(raw_ostream &OS, | 
|  | EmitterType EType) { | 
|  | const Record *AsmWriter = Target.getAsmWriter(); | 
|  | if (!AsmWriter->getValueAsInt("PassSubtarget")) | 
|  | PrintFatalError(AsmWriter->getLoc(), | 
|  | "'PassSubtarget' is false. SubTargetInfo object is needed " | 
|  | "for target features."); | 
|  |  | 
|  | StringRef TargetName = Target.getName(); | 
|  |  | 
|  | // Sort entries in CompressPatterns to handle instructions that can have more | 
|  | // than one candidate for compression\uncompression, e.g ADD can be | 
|  | // transformed to a C_ADD or a C_MV. When emitting 'uncompress()' function the | 
|  | // source and destination are flipped and the sort key needs to change | 
|  | // accordingly. | 
|  | llvm::stable_sort(CompressPatterns, [EType](const CompressPat &LHS, | 
|  | const CompressPat &RHS) { | 
|  | if (EType == EmitterType::Compress || EType == EmitterType::CheckCompress) | 
|  | return (LHS.Source.TheDef->getName() < RHS.Source.TheDef->getName()); | 
|  | return (LHS.Dest.TheDef->getName() < RHS.Dest.TheDef->getName()); | 
|  | }); | 
|  |  | 
|  | // A list of MCOperandPredicates for all operands in use, and the reverse map. | 
|  | std::vector<const Record *> MCOpPredicates; | 
|  | DenseMap<const Record *, unsigned> MCOpPredicateMap; | 
|  | // A list of ImmLeaf Predicates for all operands in use, and the reverse map. | 
|  | std::vector<const Record *> ImmLeafPredicates; | 
|  | DenseMap<const Record *, unsigned> ImmLeafPredicateMap; | 
|  |  | 
|  | std::string F; | 
|  | std::string FH; | 
|  | raw_string_ostream Func(F); | 
|  | raw_string_ostream FuncH(FH); | 
|  |  | 
|  | if (EType == EmitterType::Compress) | 
|  | OS << "\n#ifdef GEN_COMPRESS_INSTR\n" | 
|  | << "#undef GEN_COMPRESS_INSTR\n\n"; | 
|  | else if (EType == EmitterType::Uncompress) | 
|  | OS << "\n#ifdef GEN_UNCOMPRESS_INSTR\n" | 
|  | << "#undef GEN_UNCOMPRESS_INSTR\n\n"; | 
|  | else if (EType == EmitterType::CheckCompress) | 
|  | OS << "\n#ifdef GEN_CHECK_COMPRESS_INSTR\n" | 
|  | << "#undef GEN_CHECK_COMPRESS_INSTR\n\n"; | 
|  |  | 
|  | if (EType == EmitterType::Compress) { | 
|  | FuncH << "static bool compressInst(MCInst &OutInst,\n"; | 
|  | FuncH.indent(25) << "const MCInst &MI,\n"; | 
|  | FuncH.indent(25) << "const MCSubtargetInfo &STI) {\n"; | 
|  | } else if (EType == EmitterType::Uncompress) { | 
|  | FuncH << "static bool uncompressInst(MCInst &OutInst,\n"; | 
|  | FuncH.indent(27) << "const MCInst &MI,\n"; | 
|  | FuncH.indent(27) << "const MCSubtargetInfo &STI) {\n"; | 
|  | } else if (EType == EmitterType::CheckCompress) { | 
|  | FuncH << "static bool isCompressibleInst(const MachineInstr &MI,\n"; | 
|  | FuncH.indent(31) << "const " << TargetName << "Subtarget &STI) {\n"; | 
|  | } | 
|  |  | 
|  | if (CompressPatterns.empty()) { | 
|  | OS << FH; | 
|  | OS.indent(2) << "return false;\n}\n"; | 
|  | if (EType == EmitterType::Compress) | 
|  | OS << "\n#endif //GEN_COMPRESS_INSTR\n"; | 
|  | else if (EType == EmitterType::Uncompress) | 
|  | OS << "\n#endif //GEN_UNCOMPRESS_INSTR\n\n"; | 
|  | else if (EType == EmitterType::CheckCompress) | 
|  | OS << "\n#endif //GEN_CHECK_COMPRESS_INSTR\n\n"; | 
|  | return; | 
|  | } | 
|  |  | 
|  | std::string CaseString; | 
|  | raw_string_ostream CaseStream(CaseString); | 
|  | StringRef PrevOp; | 
|  | StringRef CurOp; | 
|  | CaseStream << "  switch (MI.getOpcode()) {\n"; | 
|  | CaseStream << "  default: return false;\n"; | 
|  |  | 
|  | bool CompressOrCheck = | 
|  | EType == EmitterType::Compress || EType == EmitterType::CheckCompress; | 
|  | bool CompressOrUncompress = | 
|  | EType == EmitterType::Compress || EType == EmitterType::Uncompress; | 
|  | std::string ValidatorName = | 
|  | CompressOrUncompress | 
|  | ? (TargetName + "ValidateMCOperandFor" + | 
|  | (EType == EmitterType::Compress ? "Compress" : "Uncompress")) | 
|  | .str() | 
|  | : ""; | 
|  |  | 
|  | for (const auto &CompressPat : CompressPatterns) { | 
|  | if (EType == EmitterType::Uncompress && CompressPat.IsCompressOnly) | 
|  | continue; | 
|  |  | 
|  | std::string CondString; | 
|  | std::string CodeString; | 
|  | raw_string_ostream CondStream(CondString); | 
|  | raw_string_ostream CodeStream(CodeString); | 
|  | const CodeGenInstruction &Source = | 
|  | CompressOrCheck ? CompressPat.Source : CompressPat.Dest; | 
|  | const CodeGenInstruction &Dest = | 
|  | CompressOrCheck ? CompressPat.Dest : CompressPat.Source; | 
|  | const IndexedMap<OpData> &SourceOperandMap = | 
|  | CompressOrCheck ? CompressPat.SourceOperandMap | 
|  | : CompressPat.DestOperandMap; | 
|  | const IndexedMap<OpData> &DestOperandMap = | 
|  | CompressOrCheck ? CompressPat.DestOperandMap | 
|  | : CompressPat.SourceOperandMap; | 
|  |  | 
|  | CurOp = Source.TheDef->getName(); | 
|  | // Check current and previous opcode to decide to continue or end a case. | 
|  | if (CurOp != PrevOp) { | 
|  | if (!PrevOp.empty()) { | 
|  | CaseStream.indent(4) << "break;\n"; | 
|  | CaseStream.indent(2) << "} // case " + PrevOp + "\n"; | 
|  | } | 
|  | CaseStream.indent(2) << "case " + TargetName + "::" + CurOp + ": {\n"; | 
|  | } | 
|  |  | 
|  | std::set<std::pair<bool, StringRef>> FeaturesSet; | 
|  | std::set<std::set<std::pair<bool, StringRef>>> AnyOfFeatureSets; | 
|  | // Add CompressPat required features. | 
|  | getReqFeatures(FeaturesSet, AnyOfFeatureSets, CompressPat.PatReqFeatures); | 
|  |  | 
|  | // Add Dest instruction required features. | 
|  | std::vector<const Record *> ReqFeatures; | 
|  | std::vector<const Record *> RF = | 
|  | Dest.TheDef->getValueAsListOfDefs("Predicates"); | 
|  | copy_if(RF, std::back_inserter(ReqFeatures), [](const Record *R) { | 
|  | return R->getValueAsBit("AssemblerMatcherPredicate"); | 
|  | }); | 
|  | getReqFeatures(FeaturesSet, AnyOfFeatureSets, ReqFeatures); | 
|  |  | 
|  | ListSeparator CondSep(" &&\n        "); | 
|  |  | 
|  | // Emit checks for all required features. | 
|  | for (auto &Op : FeaturesSet) { | 
|  | StringRef Not = Op.first ? "!" : ""; | 
|  | CondStream << CondSep << Not << "STI.getFeatureBits()[" << TargetName | 
|  | << "::" << Op.second << "]"; | 
|  | } | 
|  |  | 
|  | // Emit checks for all required feature groups. | 
|  | for (auto &Set : AnyOfFeatureSets) { | 
|  | CondStream << CondSep << "("; | 
|  | for (auto &Op : Set) { | 
|  | bool IsLast = &Op == &*Set.rbegin(); | 
|  | StringRef Not = Op.first ? "!" : ""; | 
|  | CondStream << Not << "STI.getFeatureBits()[" << TargetName | 
|  | << "::" << Op.second << "]"; | 
|  | if (!IsLast) | 
|  | CondStream << " || "; | 
|  | } | 
|  | CondStream << ")"; | 
|  | } | 
|  |  | 
|  | // Start Source Inst operands validation. | 
|  | unsigned OpNo = 0; | 
|  | for (const auto &SourceOperand : Source.Operands) { | 
|  | for (unsigned SubOp = 0; SubOp != SourceOperand.MINumOperands; ++SubOp) { | 
|  | // Check for fixed immediates\registers in the source instruction. | 
|  | switch (SourceOperandMap[OpNo].Kind) { | 
|  | case OpData::Operand: | 
|  | if (SourceOperandMap[OpNo].OpInfo.TiedOpIdx != -1) { | 
|  | if (Source.Operands[OpNo].Rec->isSubClassOf("RegisterClass")) | 
|  | CondStream << CondSep << "MI.getOperand(" << OpNo | 
|  | << ").isReg() && MI.getOperand(" | 
|  | << SourceOperandMap[OpNo].OpInfo.TiedOpIdx | 
|  | << ").isReg()" << CondSep << "(MI.getOperand(" << OpNo | 
|  | << ").getReg() == MI.getOperand(" | 
|  | << SourceOperandMap[OpNo].OpInfo.TiedOpIdx | 
|  | << ").getReg())"; | 
|  | else | 
|  | PrintFatalError("Unexpected tied operand types!"); | 
|  | } | 
|  |  | 
|  | // We don't need to do anything for source instruction operand checks. | 
|  | break; | 
|  | case OpData::Imm: | 
|  | CondStream << CondSep << "MI.getOperand(" << OpNo << ").isImm()" | 
|  | << CondSep << "(MI.getOperand(" << OpNo | 
|  | << ").getImm() == " << SourceOperandMap[OpNo].ImmVal | 
|  | << ")"; | 
|  | break; | 
|  | case OpData::Reg: { | 
|  | const Record *Reg = SourceOperandMap[OpNo].RegRec; | 
|  | CondStream << CondSep << "MI.getOperand(" << OpNo << ").isReg()" | 
|  | << CondSep << "(MI.getOperand(" << OpNo | 
|  | << ").getReg() == " << TargetName << "::" << Reg->getName() | 
|  | << ")"; | 
|  | break; | 
|  | } | 
|  | } | 
|  | ++OpNo; | 
|  | } | 
|  | } | 
|  | CodeStream.indent(6) << "// " << Dest.AsmString << "\n"; | 
|  | if (CompressOrUncompress) | 
|  | CodeStream.indent(6) << "OutInst.setOpcode(" << TargetName | 
|  | << "::" << Dest.TheDef->getName() << ");\n"; | 
|  | OpNo = 0; | 
|  | for (const auto &DestOperand : Dest.Operands) { | 
|  | CodeStream.indent(6) << "// Operand: " << DestOperand.Name << "\n"; | 
|  |  | 
|  | for (unsigned SubOp = 0; SubOp != DestOperand.MINumOperands; ++SubOp) { | 
|  | const Record *DestRec = DestOperand.Rec; | 
|  |  | 
|  | if (DestOperand.MINumOperands > 1) | 
|  | DestRec = | 
|  | cast<DefInit>(DestOperand.MIOperandInfo->getArg(SubOp))->getDef(); | 
|  |  | 
|  | switch (DestOperandMap[OpNo].Kind) { | 
|  | case OpData::Operand: { | 
|  | unsigned OpIdx = DestOperandMap[OpNo].OpInfo.Idx; | 
|  | const Record *DagRec = DestOperandMap[OpNo].OpInfo.DagRec; | 
|  | // Check that the operand in the Source instruction fits | 
|  | // the type for the Dest instruction. | 
|  | if (DagRec->isSubClassOf("RegisterClass") || | 
|  | DagRec->isSubClassOf("RegisterOperand")) { | 
|  | auto *ClassRec = DagRec->isSubClassOf("RegisterClass") | 
|  | ? DagRec | 
|  | : DagRec->getValueAsDef("RegClass"); | 
|  | // This is a register operand. Check the register class. | 
|  | // Don't check register class if this is a tied operand, it was done | 
|  | // for the operand it's tied to. | 
|  | if (DestOperand.getTiedRegister() == -1) { | 
|  | CondStream << CondSep << "MI.getOperand(" << OpIdx << ").isReg()"; | 
|  | if (EType == EmitterType::CheckCompress) | 
|  | CondStream << " && MI.getOperand(" << OpIdx | 
|  | << ").getReg().isPhysical()"; | 
|  | CondStream << CondSep << TargetName << "MCRegisterClasses[" | 
|  | << TargetName << "::" << ClassRec->getName() | 
|  | << "RegClassID].contains(MI.getOperand(" << OpIdx | 
|  | << ").getReg())"; | 
|  | } | 
|  |  | 
|  | if (CompressOrUncompress) | 
|  | CodeStream.indent(6) | 
|  | << "OutInst.addOperand(MI.getOperand(" << OpIdx << "));\n"; | 
|  | } else { | 
|  | // Handling immediate operands. | 
|  | if (CompressOrUncompress) { | 
|  | unsigned Entry = getPredicates(MCOpPredicateMap, MCOpPredicates, | 
|  | DagRec, "MCOperandPredicate"); | 
|  | CondStream << CondSep << ValidatorName << "(" | 
|  | << "MI.getOperand(" << OpIdx << "), STI, " << Entry | 
|  | << " /* " << DagRec->getName() << " */)"; | 
|  | // Also check DestRec if different than DagRec. | 
|  | if (DagRec != DestRec) { | 
|  | Entry = getPredicates(MCOpPredicateMap, MCOpPredicates, DestRec, | 
|  | "MCOperandPredicate"); | 
|  | CondStream << CondSep << ValidatorName << "(" | 
|  | << "MI.getOperand(" << OpIdx << "), STI, " << Entry | 
|  | << " /* " << DestRec->getName() << " */)"; | 
|  | } | 
|  | } else { | 
|  | unsigned Entry = | 
|  | getPredicates(ImmLeafPredicateMap, ImmLeafPredicates, DagRec, | 
|  | "ImmediateCode"); | 
|  | CondStream << CondSep << "MI.getOperand(" << OpIdx << ").isImm()"; | 
|  | CondStream << CondSep << TargetName << "ValidateMachineOperand(" | 
|  | << "MI.getOperand(" << OpIdx << "), &STI, " << Entry | 
|  | << " /* " << DagRec->getName() << " */)"; | 
|  | if (DagRec != DestRec) { | 
|  | Entry = getPredicates(ImmLeafPredicateMap, ImmLeafPredicates, | 
|  | DestRec, "ImmediateCode"); | 
|  | CondStream << CondSep << "MI.getOperand(" << OpIdx | 
|  | << ").isImm()"; | 
|  | CondStream << CondSep << TargetName << "ValidateMachineOperand(" | 
|  | << "MI.getOperand(" << OpIdx << "), &STI, " << Entry | 
|  | << " /* " << DestRec->getName() << " */)"; | 
|  | } | 
|  | } | 
|  | if (CompressOrUncompress) | 
|  | CodeStream.indent(6) | 
|  | << "OutInst.addOperand(MI.getOperand(" << OpIdx << "));\n"; | 
|  | } | 
|  | break; | 
|  | } | 
|  | case OpData::Imm: { | 
|  | if (CompressOrUncompress) { | 
|  | unsigned Entry = getPredicates(MCOpPredicateMap, MCOpPredicates, | 
|  | DestRec, "MCOperandPredicate"); | 
|  | CondStream << CondSep << ValidatorName << "(" | 
|  | << "MCOperand::createImm(" << DestOperandMap[OpNo].ImmVal | 
|  | << "), STI, " << Entry << " /* " << DestRec->getName() | 
|  | << " */)"; | 
|  | } else { | 
|  | unsigned Entry = | 
|  | getPredicates(ImmLeafPredicateMap, ImmLeafPredicates, DestRec, | 
|  | "ImmediateCode"); | 
|  | CondStream << CondSep << TargetName | 
|  | << "ValidateMachineOperand(MachineOperand::CreateImm(" | 
|  | << DestOperandMap[OpNo].ImmVal << "), &STI, " << Entry | 
|  | << " /* " << DestRec->getName() << " */)"; | 
|  | } | 
|  | if (CompressOrUncompress) | 
|  | CodeStream.indent(6) << "OutInst.addOperand(MCOperand::createImm(" | 
|  | << DestOperandMap[OpNo].ImmVal << "));\n"; | 
|  | } break; | 
|  | case OpData::Reg: { | 
|  | if (CompressOrUncompress) { | 
|  | // Fixed register has been validated at pattern validation time. | 
|  | const Record *Reg = DestOperandMap[OpNo].RegRec; | 
|  | CodeStream.indent(6) | 
|  | << "OutInst.addOperand(MCOperand::createReg(" << TargetName | 
|  | << "::" << Reg->getName() << "));\n"; | 
|  | } | 
|  | } break; | 
|  | } | 
|  | ++OpNo; | 
|  | } | 
|  | } | 
|  | if (CompressOrUncompress) | 
|  | CodeStream.indent(6) << "OutInst.setLoc(MI.getLoc());\n"; | 
|  | mergeCondAndCode(CaseStream, CondString, CodeString); | 
|  | PrevOp = CurOp; | 
|  | } | 
|  | Func << CaseString; | 
|  | Func.indent(4) << "break;\n"; | 
|  | // Close brace for the last case. | 
|  | Func.indent(2) << "} // case " << CurOp << "\n"; | 
|  | Func.indent(2) << "} // switch\n"; | 
|  | Func.indent(2) << "return false;\n}\n"; | 
|  |  | 
|  | if (!MCOpPredicates.empty()) { | 
|  | auto IndentLength = ValidatorName.size() + 13; | 
|  | OS << "static bool " << ValidatorName << "(const MCOperand &MCOp,\n"; | 
|  | OS.indent(IndentLength) << "const MCSubtargetInfo &STI,\n"; | 
|  | OS.indent(IndentLength) << "unsigned PredicateIndex) {\n"; | 
|  | OS << "  switch (PredicateIndex) {\n" | 
|  | << "  default:\n" | 
|  | << "    llvm_unreachable(\"Unknown MCOperandPredicate kind\");\n" | 
|  | << "    break;\n"; | 
|  |  | 
|  | printPredicates(MCOpPredicates, "MCOperandPredicate", OS); | 
|  |  | 
|  | OS << "  }\n" | 
|  | << "}\n\n"; | 
|  | } | 
|  |  | 
|  | if (!ImmLeafPredicates.empty()) { | 
|  | auto IndentLength = TargetName.size() + 35; | 
|  | OS << "static bool " << TargetName | 
|  | << "ValidateMachineOperand(const MachineOperand &MO,\n"; | 
|  | OS.indent(IndentLength) | 
|  | << "const " << TargetName << "Subtarget *Subtarget,\n"; | 
|  | OS.indent(IndentLength) | 
|  | << "unsigned PredicateIndex) {\n" | 
|  | << "  int64_t Imm = MO.getImm();\n" | 
|  | << "  switch (PredicateIndex) {\n" | 
|  | << "  default:\n" | 
|  | << "    llvm_unreachable(\"Unknown ImmLeaf Predicate kind\");\n" | 
|  | << "    break;\n"; | 
|  |  | 
|  | printPredicates(ImmLeafPredicates, "ImmediateCode", OS); | 
|  |  | 
|  | OS << "  }\n" | 
|  | << "}\n\n"; | 
|  | } | 
|  |  | 
|  | OS << FH; | 
|  | OS << F; | 
|  |  | 
|  | if (EType == EmitterType::Compress) | 
|  | OS << "\n#endif //GEN_COMPRESS_INSTR\n"; | 
|  | else if (EType == EmitterType::Uncompress) | 
|  | OS << "\n#endif //GEN_UNCOMPRESS_INSTR\n\n"; | 
|  | else if (EType == EmitterType::CheckCompress) | 
|  | OS << "\n#endif //GEN_CHECK_COMPRESS_INSTR\n\n"; | 
|  | } | 
|  |  | 
|  | void CompressInstEmitter::run(raw_ostream &OS) { | 
|  | // Process the CompressPat definitions, validating them as we do so. | 
|  | for (const Record *Pat : Records.getAllDerivedDefinitions("CompressPat")) | 
|  | evaluateCompressPat(Pat); | 
|  |  | 
|  | // Emit file header. | 
|  | emitSourceFileHeader("Compress instruction Source Fragment", OS, Records); | 
|  | // Generate compressInst() function. | 
|  | emitCompressInstEmitter(OS, EmitterType::Compress); | 
|  | // Generate uncompressInst() function. | 
|  | emitCompressInstEmitter(OS, EmitterType::Uncompress); | 
|  | // Generate isCompressibleInst() function. | 
|  | emitCompressInstEmitter(OS, EmitterType::CheckCompress); | 
|  | } | 
|  |  | 
|  | static TableGen::Emitter::OptClass<CompressInstEmitter> | 
|  | X("gen-compress-inst-emitter", "Generate compressed instructions."); |