131f9519dSMin-Yih Hsu //===- VarLenCodeEmitterGen.cpp - CEG for variable-length insts -----------===// 231f9519dSMin-Yih Hsu // 331f9519dSMin-Yih Hsu // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 431f9519dSMin-Yih Hsu // See https://llvm.org/LICENSE.txt for license information. 531f9519dSMin-Yih Hsu // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 631f9519dSMin-Yih Hsu // 731f9519dSMin-Yih Hsu //===----------------------------------------------------------------------===// 831f9519dSMin-Yih Hsu // 931f9519dSMin-Yih Hsu // The CodeEmitterGen component for variable-length instructions. 1031f9519dSMin-Yih Hsu // 1131f9519dSMin-Yih Hsu // The basic CodeEmitterGen is almost exclusively designed for fixed- 1231f9519dSMin-Yih Hsu // length instructions. A good analogy for its encoding scheme is how printf 1331f9519dSMin-Yih Hsu // works: The (immutable) formatting string represent the fixed values in the 1431f9519dSMin-Yih Hsu // encoded instruction. Placeholders (i.e. %something), on the other hand, 1531f9519dSMin-Yih Hsu // represent encoding for instruction operands. 1631f9519dSMin-Yih Hsu // ``` 1731f9519dSMin-Yih Hsu // printf("1101 %src 1001 %dst", <encoded value for operand `src`>, 1831f9519dSMin-Yih Hsu // <encoded value for operand `dst`>); 1931f9519dSMin-Yih Hsu // ``` 2031f9519dSMin-Yih Hsu // VarLenCodeEmitterGen in this file provides an alternative encoding scheme 2131f9519dSMin-Yih Hsu // that works more like a C++ stream operator: 2231f9519dSMin-Yih Hsu // ``` 2331f9519dSMin-Yih Hsu // OS << 0b1101; 2431f9519dSMin-Yih Hsu // if (Cond) 2531f9519dSMin-Yih Hsu // OS << OperandEncoding0; 2631f9519dSMin-Yih Hsu // OS << 0b1001 << OperandEncoding1; 2731f9519dSMin-Yih Hsu // ``` 2831f9519dSMin-Yih Hsu // You are free to concatenate arbitrary types (and sizes) of encoding 2931f9519dSMin-Yih Hsu // fragments on any bit position, bringing more flexibilities on defining 3031f9519dSMin-Yih Hsu // encoding for variable-length instructions. 3131f9519dSMin-Yih Hsu // 3231f9519dSMin-Yih Hsu // In a more specific way, instruction encoding is represented by a DAG type 3331f9519dSMin-Yih Hsu // `Inst` field. Here is an example: 3431f9519dSMin-Yih Hsu // ``` 3531f9519dSMin-Yih Hsu // dag Inst = (descend 0b1101, (operand "$src", 4), 0b1001, 3631f9519dSMin-Yih Hsu // (operand "$dst", 4)); 3731f9519dSMin-Yih Hsu // ``` 3831f9519dSMin-Yih Hsu // It represents the following instruction encoding: 3931f9519dSMin-Yih Hsu // ``` 4031f9519dSMin-Yih Hsu // MSB LSB 4131f9519dSMin-Yih Hsu // 1101<encoding for operand src>1001<encoding for operand dst> 4231f9519dSMin-Yih Hsu // ``` 4331f9519dSMin-Yih Hsu // For more details about DAG operators in the above snippet, please 4431f9519dSMin-Yih Hsu // refer to \file include/llvm/Target/Target.td. 4531f9519dSMin-Yih Hsu // 4631f9519dSMin-Yih Hsu // VarLenCodeEmitter will convert the above DAG into the same helper function 4731f9519dSMin-Yih Hsu // generated by CodeEmitter, `MCCodeEmitter::getBinaryCodeForInstr` (except 4831f9519dSMin-Yih Hsu // for few details). 4931f9519dSMin-Yih Hsu // 5031f9519dSMin-Yih Hsu //===----------------------------------------------------------------------===// 5131f9519dSMin-Yih Hsu 5231f9519dSMin-Yih Hsu #include "VarLenCodeEmitterGen.h" 53*fbbc41f8Sserge-sans-paille #include "CodeGenHwModes.h" 5431f9519dSMin-Yih Hsu #include "CodeGenInstruction.h" 5531f9519dSMin-Yih Hsu #include "CodeGenTarget.h" 56*fbbc41f8Sserge-sans-paille #include "InfoByHwMode.h" 5731f9519dSMin-Yih Hsu #include "llvm/ADT/ArrayRef.h" 5831f9519dSMin-Yih Hsu #include "llvm/ADT/DenseMap.h" 5931f9519dSMin-Yih Hsu #include "llvm/Support/raw_ostream.h" 6031f9519dSMin-Yih Hsu #include "llvm/TableGen/Error.h" 6131f9519dSMin-Yih Hsu #include "llvm/TableGen/Record.h" 6231f9519dSMin-Yih Hsu 6331f9519dSMin-Yih Hsu using namespace llvm; 6431f9519dSMin-Yih Hsu 6531f9519dSMin-Yih Hsu namespace { 6631f9519dSMin-Yih Hsu 6731f9519dSMin-Yih Hsu class VarLenCodeEmitterGen { 6831f9519dSMin-Yih Hsu RecordKeeper &Records; 6931f9519dSMin-Yih Hsu 70b99365a7SMin-Yih Hsu struct EncodingSegment { 71b99365a7SMin-Yih Hsu unsigned BitWidth; 72b99365a7SMin-Yih Hsu const Init *Value; 73b99365a7SMin-Yih Hsu StringRef CustomEncoder = ""; 74b99365a7SMin-Yih Hsu }; 75b99365a7SMin-Yih Hsu 7631f9519dSMin-Yih Hsu class VarLenInst { 77314155ebSSheng RecordVal *TheDef; 7831f9519dSMin-Yih Hsu size_t NumBits; 7931f9519dSMin-Yih Hsu 8031f9519dSMin-Yih Hsu // Set if any of the segment is not fixed value. 8131f9519dSMin-Yih Hsu bool HasDynamicSegment; 8231f9519dSMin-Yih Hsu 83b99365a7SMin-Yih Hsu SmallVector<EncodingSegment, 4> Segments; 8431f9519dSMin-Yih Hsu 8531f9519dSMin-Yih Hsu void buildRec(const DagInit *DI); 8631f9519dSMin-Yih Hsu 87b99365a7SMin-Yih Hsu StringRef getCustomEncoderName(const Init *EI) const { 88b99365a7SMin-Yih Hsu if (const auto *DI = dyn_cast<DagInit>(EI)) { 89b99365a7SMin-Yih Hsu if (DI->getNumArgs() && isa<StringInit>(DI->getArg(0))) 90b99365a7SMin-Yih Hsu return cast<StringInit>(DI->getArg(0))->getValue(); 91b99365a7SMin-Yih Hsu } 92b99365a7SMin-Yih Hsu return ""; 93b99365a7SMin-Yih Hsu } 94b99365a7SMin-Yih Hsu 9531f9519dSMin-Yih Hsu public: 96314155ebSSheng VarLenInst() : TheDef(nullptr), NumBits(0U), HasDynamicSegment(false) {} 9731f9519dSMin-Yih Hsu 98314155ebSSheng explicit VarLenInst(const DagInit *DI, RecordVal *TheDef); 9931f9519dSMin-Yih Hsu 10031f9519dSMin-Yih Hsu /// Number of bits 10131f9519dSMin-Yih Hsu size_t size() const { return NumBits; } 10231f9519dSMin-Yih Hsu 10331f9519dSMin-Yih Hsu using const_iterator = decltype(Segments)::const_iterator; 10431f9519dSMin-Yih Hsu 10531f9519dSMin-Yih Hsu const_iterator begin() const { return Segments.begin(); } 10631f9519dSMin-Yih Hsu const_iterator end() const { return Segments.end(); } 10731f9519dSMin-Yih Hsu size_t getNumSegments() const { return Segments.size(); } 10831f9519dSMin-Yih Hsu 10931f9519dSMin-Yih Hsu bool isFixedValueOnly() const { return !HasDynamicSegment; } 11031f9519dSMin-Yih Hsu }; 11131f9519dSMin-Yih Hsu 11231f9519dSMin-Yih Hsu DenseMap<Record *, VarLenInst> VarLenInsts; 11331f9519dSMin-Yih Hsu 11431f9519dSMin-Yih Hsu // Emit based values (i.e. fixed bits in the encoded instructions) 11531f9519dSMin-Yih Hsu void emitInstructionBaseValues( 11631f9519dSMin-Yih Hsu raw_ostream &OS, 11731f9519dSMin-Yih Hsu ArrayRef<const CodeGenInstruction *> NumberedInstructions, 11831f9519dSMin-Yih Hsu CodeGenTarget &Target, int HwMode = -1); 11931f9519dSMin-Yih Hsu 12031f9519dSMin-Yih Hsu std::string getInstructionCase(Record *R, CodeGenTarget &Target); 12131f9519dSMin-Yih Hsu std::string getInstructionCaseForEncoding(Record *R, Record *EncodingDef, 12231f9519dSMin-Yih Hsu CodeGenTarget &Target); 12331f9519dSMin-Yih Hsu 12431f9519dSMin-Yih Hsu public: 12531f9519dSMin-Yih Hsu explicit VarLenCodeEmitterGen(RecordKeeper &R) : Records(R) {} 12631f9519dSMin-Yih Hsu 12731f9519dSMin-Yih Hsu void run(raw_ostream &OS); 12831f9519dSMin-Yih Hsu }; 12931f9519dSMin-Yih Hsu 13031f9519dSMin-Yih Hsu } // end anonymous namespace 13131f9519dSMin-Yih Hsu 132314155ebSSheng VarLenCodeEmitterGen::VarLenInst::VarLenInst(const DagInit *DI, 133314155ebSSheng RecordVal *TheDef) 134314155ebSSheng : TheDef(TheDef), NumBits(0U) { 13531f9519dSMin-Yih Hsu buildRec(DI); 13631f9519dSMin-Yih Hsu for (const auto &S : Segments) 137b99365a7SMin-Yih Hsu NumBits += S.BitWidth; 13831f9519dSMin-Yih Hsu } 13931f9519dSMin-Yih Hsu 14031f9519dSMin-Yih Hsu void VarLenCodeEmitterGen::VarLenInst::buildRec(const DagInit *DI) { 141314155ebSSheng assert(TheDef && "The def record is nullptr ?"); 142314155ebSSheng 14331f9519dSMin-Yih Hsu std::string Op = DI->getOperator()->getAsString(); 14431f9519dSMin-Yih Hsu 14531f9519dSMin-Yih Hsu if (Op == "ascend" || Op == "descend") { 14631f9519dSMin-Yih Hsu bool Reverse = Op == "descend"; 14731f9519dSMin-Yih Hsu int i = Reverse ? DI->getNumArgs() - 1 : 0; 14831f9519dSMin-Yih Hsu int e = Reverse ? -1 : DI->getNumArgs(); 14931f9519dSMin-Yih Hsu int s = Reverse ? -1 : 1; 15031f9519dSMin-Yih Hsu for (; i != e; i += s) { 15131f9519dSMin-Yih Hsu const Init *Arg = DI->getArg(i); 15231f9519dSMin-Yih Hsu if (const auto *BI = dyn_cast<BitsInit>(Arg)) { 15331f9519dSMin-Yih Hsu if (!BI->isComplete()) 154314155ebSSheng PrintFatalError(TheDef->getLoc(), 155314155ebSSheng "Expecting complete bits init in `" + Op + "`"); 15631f9519dSMin-Yih Hsu Segments.push_back({BI->getNumBits(), BI}); 15731f9519dSMin-Yih Hsu } else if (const auto *BI = dyn_cast<BitInit>(Arg)) { 15831f9519dSMin-Yih Hsu if (!BI->isConcrete()) 159314155ebSSheng PrintFatalError(TheDef->getLoc(), 160314155ebSSheng "Expecting concrete bit init in `" + Op + "`"); 16131f9519dSMin-Yih Hsu Segments.push_back({1, BI}); 16231f9519dSMin-Yih Hsu } else if (const auto *SubDI = dyn_cast<DagInit>(Arg)) { 16331f9519dSMin-Yih Hsu buildRec(SubDI); 16431f9519dSMin-Yih Hsu } else { 165314155ebSSheng PrintFatalError(TheDef->getLoc(), "Unrecognized type of argument in `" + 166314155ebSSheng Op + "`: " + Arg->getAsString()); 16731f9519dSMin-Yih Hsu } 16831f9519dSMin-Yih Hsu } 16931f9519dSMin-Yih Hsu } else if (Op == "operand") { 170b99365a7SMin-Yih Hsu // (operand <operand name>, <# of bits>, [(encoder <custom encoder>)]) 171b99365a7SMin-Yih Hsu if (DI->getNumArgs() < 2) 172314155ebSSheng PrintFatalError(TheDef->getLoc(), 173314155ebSSheng "Expecting at least 2 arguments for `operand`"); 17431f9519dSMin-Yih Hsu HasDynamicSegment = true; 17531f9519dSMin-Yih Hsu const Init *OperandName = DI->getArg(0), *NumBits = DI->getArg(1); 17631f9519dSMin-Yih Hsu if (!isa<StringInit>(OperandName) || !isa<IntInit>(NumBits)) 177314155ebSSheng PrintFatalError(TheDef->getLoc(), "Invalid argument types for `operand`"); 17831f9519dSMin-Yih Hsu 17931f9519dSMin-Yih Hsu auto NumBitsVal = cast<IntInit>(NumBits)->getValue(); 18031f9519dSMin-Yih Hsu if (NumBitsVal <= 0) 181314155ebSSheng PrintFatalError(TheDef->getLoc(), "Invalid number of bits for `operand`"); 18231f9519dSMin-Yih Hsu 183b99365a7SMin-Yih Hsu StringRef CustomEncoder; 184b99365a7SMin-Yih Hsu if (DI->getNumArgs() >= 3) 185b99365a7SMin-Yih Hsu CustomEncoder = getCustomEncoderName(DI->getArg(2)); 186b99365a7SMin-Yih Hsu Segments.push_back( 187b99365a7SMin-Yih Hsu {static_cast<unsigned>(NumBitsVal), OperandName, CustomEncoder}); 18831f9519dSMin-Yih Hsu } else if (Op == "slice") { 189b99365a7SMin-Yih Hsu // (slice <operand name>, <high / low bit>, <low / high bit>, 190b99365a7SMin-Yih Hsu // [(encoder <custom encoder>)]) 191b99365a7SMin-Yih Hsu if (DI->getNumArgs() < 3) 192314155ebSSheng PrintFatalError(TheDef->getLoc(), 193314155ebSSheng "Expecting at least 3 arguments for `slice`"); 19431f9519dSMin-Yih Hsu HasDynamicSegment = true; 19531f9519dSMin-Yih Hsu Init *OperandName = DI->getArg(0), *HiBit = DI->getArg(1), 19631f9519dSMin-Yih Hsu *LoBit = DI->getArg(2); 19731f9519dSMin-Yih Hsu if (!isa<StringInit>(OperandName) || !isa<IntInit>(HiBit) || 19831f9519dSMin-Yih Hsu !isa<IntInit>(LoBit)) 199314155ebSSheng PrintFatalError(TheDef->getLoc(), "Invalid argument types for `slice`"); 20031f9519dSMin-Yih Hsu 20131f9519dSMin-Yih Hsu auto HiBitVal = cast<IntInit>(HiBit)->getValue(), 20231f9519dSMin-Yih Hsu LoBitVal = cast<IntInit>(LoBit)->getValue(); 20331f9519dSMin-Yih Hsu if (HiBitVal < 0 || LoBitVal < 0) 204314155ebSSheng PrintFatalError(TheDef->getLoc(), "Invalid bit range for `slice`"); 20531f9519dSMin-Yih Hsu bool NeedSwap = false; 20631f9519dSMin-Yih Hsu unsigned NumBits = 0U; 20731f9519dSMin-Yih Hsu if (HiBitVal < LoBitVal) { 20831f9519dSMin-Yih Hsu NeedSwap = true; 20931f9519dSMin-Yih Hsu NumBits = static_cast<unsigned>(LoBitVal - HiBitVal + 1); 21031f9519dSMin-Yih Hsu } else { 21131f9519dSMin-Yih Hsu NumBits = static_cast<unsigned>(HiBitVal - LoBitVal + 1); 21231f9519dSMin-Yih Hsu } 21331f9519dSMin-Yih Hsu 214b99365a7SMin-Yih Hsu StringRef CustomEncoder; 215b99365a7SMin-Yih Hsu if (DI->getNumArgs() >= 4) 216b99365a7SMin-Yih Hsu CustomEncoder = getCustomEncoderName(DI->getArg(3)); 217b99365a7SMin-Yih Hsu 21831f9519dSMin-Yih Hsu if (NeedSwap) { 21931f9519dSMin-Yih Hsu // Normalization: Hi bit should always be the second argument. 22031f9519dSMin-Yih Hsu Init *const NewArgs[] = {OperandName, LoBit, HiBit}; 221b99365a7SMin-Yih Hsu Segments.push_back({NumBits, 222b99365a7SMin-Yih Hsu DagInit::get(DI->getOperator(), nullptr, NewArgs, {}), 223b99365a7SMin-Yih Hsu CustomEncoder}); 22431f9519dSMin-Yih Hsu } else { 225b99365a7SMin-Yih Hsu Segments.push_back({NumBits, DI, CustomEncoder}); 22631f9519dSMin-Yih Hsu } 22731f9519dSMin-Yih Hsu } 22831f9519dSMin-Yih Hsu } 22931f9519dSMin-Yih Hsu 23031f9519dSMin-Yih Hsu void VarLenCodeEmitterGen::run(raw_ostream &OS) { 23131f9519dSMin-Yih Hsu CodeGenTarget Target(Records); 23231f9519dSMin-Yih Hsu auto Insts = Records.getAllDerivedDefinitions("Instruction"); 23331f9519dSMin-Yih Hsu 23431f9519dSMin-Yih Hsu auto NumberedInstructions = Target.getInstructionsByEnumValue(); 23531f9519dSMin-Yih Hsu const CodeGenHwModes &HWM = Target.getHwModes(); 23631f9519dSMin-Yih Hsu 23731f9519dSMin-Yih Hsu // The set of HwModes used by instruction encodings. 23831f9519dSMin-Yih Hsu std::set<unsigned> HwModes; 23931f9519dSMin-Yih Hsu for (const CodeGenInstruction *CGI : NumberedInstructions) { 24031f9519dSMin-Yih Hsu Record *R = CGI->TheDef; 24131f9519dSMin-Yih Hsu 24231f9519dSMin-Yih Hsu // Create the corresponding VarLenInst instance. 24331f9519dSMin-Yih Hsu if (R->getValueAsString("Namespace") == "TargetOpcode" || 24431f9519dSMin-Yih Hsu R->getValueAsBit("isPseudo")) 24531f9519dSMin-Yih Hsu continue; 24631f9519dSMin-Yih Hsu 24731f9519dSMin-Yih Hsu if (const RecordVal *RV = R->getValue("EncodingInfos")) { 24831f9519dSMin-Yih Hsu if (auto *DI = dyn_cast_or_null<DefInit>(RV->getValue())) { 24931f9519dSMin-Yih Hsu EncodingInfoByHwMode EBM(DI->getDef(), HWM); 25031f9519dSMin-Yih Hsu for (auto &KV : EBM) { 25131f9519dSMin-Yih Hsu HwModes.insert(KV.first); 25231f9519dSMin-Yih Hsu Record *EncodingDef = KV.second; 253314155ebSSheng RecordVal *RV = EncodingDef->getValue("Inst"); 254314155ebSSheng DagInit *DI = cast<DagInit>(RV->getValue()); 255314155ebSSheng VarLenInsts.insert({EncodingDef, VarLenInst(DI, RV)}); 25631f9519dSMin-Yih Hsu } 25731f9519dSMin-Yih Hsu continue; 25831f9519dSMin-Yih Hsu } 25931f9519dSMin-Yih Hsu } 260314155ebSSheng RecordVal *RV = R->getValue("Inst"); 261314155ebSSheng DagInit *DI = cast<DagInit>(RV->getValue()); 262314155ebSSheng VarLenInsts.insert({R, VarLenInst(DI, RV)}); 26331f9519dSMin-Yih Hsu } 26431f9519dSMin-Yih Hsu 26531f9519dSMin-Yih Hsu // Emit function declaration 26631f9519dSMin-Yih Hsu OS << "void " << Target.getName() 26731f9519dSMin-Yih Hsu << "MCCodeEmitter::getBinaryCodeForInstr(const MCInst &MI,\n" 26831f9519dSMin-Yih Hsu << " SmallVectorImpl<MCFixup> &Fixups,\n" 26931f9519dSMin-Yih Hsu << " APInt &Inst,\n" 27031f9519dSMin-Yih Hsu << " APInt &Scratch,\n" 27131f9519dSMin-Yih Hsu << " const MCSubtargetInfo &STI) const {\n"; 27231f9519dSMin-Yih Hsu 27331f9519dSMin-Yih Hsu // Emit instruction base values 27431f9519dSMin-Yih Hsu if (HwModes.empty()) { 27531f9519dSMin-Yih Hsu emitInstructionBaseValues(OS, NumberedInstructions, Target); 27631f9519dSMin-Yih Hsu } else { 27731f9519dSMin-Yih Hsu for (unsigned HwMode : HwModes) 27831f9519dSMin-Yih Hsu emitInstructionBaseValues(OS, NumberedInstructions, Target, (int)HwMode); 27931f9519dSMin-Yih Hsu } 28031f9519dSMin-Yih Hsu 28131f9519dSMin-Yih Hsu if (!HwModes.empty()) { 28231f9519dSMin-Yih Hsu OS << " const unsigned **Index;\n"; 28331f9519dSMin-Yih Hsu OS << " const uint64_t *InstBits;\n"; 28431f9519dSMin-Yih Hsu OS << " unsigned HwMode = STI.getHwMode();\n"; 28531f9519dSMin-Yih Hsu OS << " switch (HwMode) {\n"; 28631f9519dSMin-Yih Hsu OS << " default: llvm_unreachable(\"Unknown hardware mode!\"); break;\n"; 28731f9519dSMin-Yih Hsu for (unsigned I : HwModes) { 28831f9519dSMin-Yih Hsu OS << " case " << I << ": InstBits = InstBits_" << HWM.getMode(I).Name 28931f9519dSMin-Yih Hsu << "; Index = Index_" << HWM.getMode(I).Name << "; break;\n"; 29031f9519dSMin-Yih Hsu } 29131f9519dSMin-Yih Hsu OS << " };\n"; 29231f9519dSMin-Yih Hsu } 29331f9519dSMin-Yih Hsu 29431f9519dSMin-Yih Hsu // Emit helper function to retrieve base values. 29531f9519dSMin-Yih Hsu OS << " auto getInstBits = [&](unsigned Opcode) -> APInt {\n" 29631f9519dSMin-Yih Hsu << " unsigned NumBits = Index[Opcode][0];\n" 29731f9519dSMin-Yih Hsu << " if (!NumBits)\n" 29831f9519dSMin-Yih Hsu << " return APInt::getZeroWidth();\n" 29931f9519dSMin-Yih Hsu << " unsigned Idx = Index[Opcode][1];\n" 30031f9519dSMin-Yih Hsu << " ArrayRef<uint64_t> Data(&InstBits[Idx], " 30131f9519dSMin-Yih Hsu << "APInt::getNumWords(NumBits));\n" 30231f9519dSMin-Yih Hsu << " return APInt(NumBits, Data);\n" 30331f9519dSMin-Yih Hsu << " };\n"; 30431f9519dSMin-Yih Hsu 30531f9519dSMin-Yih Hsu // Map to accumulate all the cases. 30631f9519dSMin-Yih Hsu std::map<std::string, std::vector<std::string>> CaseMap; 30731f9519dSMin-Yih Hsu 30831f9519dSMin-Yih Hsu // Construct all cases statement for each opcode 30931f9519dSMin-Yih Hsu for (Record *R : Insts) { 31031f9519dSMin-Yih Hsu if (R->getValueAsString("Namespace") == "TargetOpcode" || 31131f9519dSMin-Yih Hsu R->getValueAsBit("isPseudo")) 31231f9519dSMin-Yih Hsu continue; 31331f9519dSMin-Yih Hsu std::string InstName = 31431f9519dSMin-Yih Hsu (R->getValueAsString("Namespace") + "::" + R->getName()).str(); 31531f9519dSMin-Yih Hsu std::string Case = getInstructionCase(R, Target); 31631f9519dSMin-Yih Hsu 31731f9519dSMin-Yih Hsu CaseMap[Case].push_back(std::move(InstName)); 31831f9519dSMin-Yih Hsu } 31931f9519dSMin-Yih Hsu 32031f9519dSMin-Yih Hsu // Emit initial function code 32131f9519dSMin-Yih Hsu OS << " const unsigned opcode = MI.getOpcode();\n" 32231f9519dSMin-Yih Hsu << " switch (opcode) {\n"; 32331f9519dSMin-Yih Hsu 32431f9519dSMin-Yih Hsu // Emit each case statement 32531f9519dSMin-Yih Hsu for (const auto &C : CaseMap) { 32631f9519dSMin-Yih Hsu const std::string &Case = C.first; 32731f9519dSMin-Yih Hsu const auto &InstList = C.second; 32831f9519dSMin-Yih Hsu 32931f9519dSMin-Yih Hsu ListSeparator LS("\n"); 33031f9519dSMin-Yih Hsu for (const auto &InstName : InstList) 33131f9519dSMin-Yih Hsu OS << LS << " case " << InstName << ":"; 33231f9519dSMin-Yih Hsu 33331f9519dSMin-Yih Hsu OS << " {\n"; 33431f9519dSMin-Yih Hsu OS << Case; 33531f9519dSMin-Yih Hsu OS << " break;\n" 33631f9519dSMin-Yih Hsu << " }\n"; 33731f9519dSMin-Yih Hsu } 33831f9519dSMin-Yih Hsu // Default case: unhandled opcode 33931f9519dSMin-Yih Hsu OS << " default:\n" 34031f9519dSMin-Yih Hsu << " std::string msg;\n" 34131f9519dSMin-Yih Hsu << " raw_string_ostream Msg(msg);\n" 34231f9519dSMin-Yih Hsu << " Msg << \"Not supported instr: \" << MI;\n" 34331f9519dSMin-Yih Hsu << " report_fatal_error(Msg.str().c_str());\n" 34431f9519dSMin-Yih Hsu << " }\n"; 34531f9519dSMin-Yih Hsu OS << "}\n\n"; 34631f9519dSMin-Yih Hsu } 34731f9519dSMin-Yih Hsu 34831f9519dSMin-Yih Hsu static void emitInstBits(raw_ostream &IS, raw_ostream &SS, const APInt &Bits, 34931f9519dSMin-Yih Hsu unsigned &Index) { 35031f9519dSMin-Yih Hsu if (!Bits.getNumWords()) { 35131f9519dSMin-Yih Hsu IS.indent(4) << "{/*NumBits*/0, /*Index*/0},"; 35231f9519dSMin-Yih Hsu return; 35331f9519dSMin-Yih Hsu } 35431f9519dSMin-Yih Hsu 35531f9519dSMin-Yih Hsu IS.indent(4) << "{/*NumBits*/" << Bits.getBitWidth() << ", " 35631f9519dSMin-Yih Hsu << "/*Index*/" << Index << "},"; 35731f9519dSMin-Yih Hsu 35831f9519dSMin-Yih Hsu SS.indent(4); 35931f9519dSMin-Yih Hsu for (unsigned I = 0; I < Bits.getNumWords(); ++I, ++Index) 36031f9519dSMin-Yih Hsu SS << "UINT64_C(" << utostr(Bits.getRawData()[I]) << "),"; 36131f9519dSMin-Yih Hsu } 36231f9519dSMin-Yih Hsu 36331f9519dSMin-Yih Hsu void VarLenCodeEmitterGen::emitInstructionBaseValues( 36431f9519dSMin-Yih Hsu raw_ostream &OS, ArrayRef<const CodeGenInstruction *> NumberedInstructions, 36531f9519dSMin-Yih Hsu CodeGenTarget &Target, int HwMode) { 36631f9519dSMin-Yih Hsu std::string IndexArray, StorageArray; 36731f9519dSMin-Yih Hsu raw_string_ostream IS(IndexArray), SS(StorageArray); 36831f9519dSMin-Yih Hsu 36931f9519dSMin-Yih Hsu const CodeGenHwModes &HWM = Target.getHwModes(); 37031f9519dSMin-Yih Hsu if (HwMode == -1) { 37131f9519dSMin-Yih Hsu IS << " static const unsigned Index[][2] = {\n"; 37231f9519dSMin-Yih Hsu SS << " static const uint64_t InstBits[] = {\n"; 37331f9519dSMin-Yih Hsu } else { 37431f9519dSMin-Yih Hsu StringRef Name = HWM.getMode(HwMode).Name; 37531f9519dSMin-Yih Hsu IS << " static const unsigned Index_" << Name << "[][2] = {\n"; 37631f9519dSMin-Yih Hsu SS << " static const uint64_t InstBits_" << Name << "[] = {\n"; 37731f9519dSMin-Yih Hsu } 37831f9519dSMin-Yih Hsu 37931f9519dSMin-Yih Hsu unsigned NumFixedValueWords = 0U; 38031f9519dSMin-Yih Hsu for (const CodeGenInstruction *CGI : NumberedInstructions) { 38131f9519dSMin-Yih Hsu Record *R = CGI->TheDef; 38231f9519dSMin-Yih Hsu 38331f9519dSMin-Yih Hsu if (R->getValueAsString("Namespace") == "TargetOpcode" || 38431f9519dSMin-Yih Hsu R->getValueAsBit("isPseudo")) { 38531f9519dSMin-Yih Hsu IS.indent(4) << "{/*NumBits*/0, /*Index*/0},\n"; 38631f9519dSMin-Yih Hsu continue; 38731f9519dSMin-Yih Hsu } 38831f9519dSMin-Yih Hsu 38931f9519dSMin-Yih Hsu Record *EncodingDef = R; 39031f9519dSMin-Yih Hsu if (const RecordVal *RV = R->getValue("EncodingInfos")) { 39131f9519dSMin-Yih Hsu if (auto *DI = dyn_cast_or_null<DefInit>(RV->getValue())) { 39231f9519dSMin-Yih Hsu EncodingInfoByHwMode EBM(DI->getDef(), HWM); 39331f9519dSMin-Yih Hsu if (EBM.hasMode(HwMode)) 39431f9519dSMin-Yih Hsu EncodingDef = EBM.get(HwMode); 39531f9519dSMin-Yih Hsu } 39631f9519dSMin-Yih Hsu } 39731f9519dSMin-Yih Hsu 39831f9519dSMin-Yih Hsu auto It = VarLenInsts.find(EncodingDef); 39931f9519dSMin-Yih Hsu if (It == VarLenInsts.end()) 40031f9519dSMin-Yih Hsu PrintFatalError(EncodingDef, "VarLenInst not found for this record"); 40131f9519dSMin-Yih Hsu const VarLenInst &VLI = It->second; 40231f9519dSMin-Yih Hsu 40331f9519dSMin-Yih Hsu unsigned i = 0U, BitWidth = VLI.size(); 40431f9519dSMin-Yih Hsu 40531f9519dSMin-Yih Hsu // Start by filling in fixed values. 40631f9519dSMin-Yih Hsu APInt Value(BitWidth, 0); 40731f9519dSMin-Yih Hsu auto SI = VLI.begin(), SE = VLI.end(); 40831f9519dSMin-Yih Hsu // Scan through all the segments that have fixed-bits values. 40931f9519dSMin-Yih Hsu while (i < BitWidth && SI != SE) { 410b99365a7SMin-Yih Hsu unsigned SegmentNumBits = SI->BitWidth; 411b99365a7SMin-Yih Hsu if (const auto *BI = dyn_cast<BitsInit>(SI->Value)) { 41231f9519dSMin-Yih Hsu for (unsigned Idx = 0U; Idx != SegmentNumBits; ++Idx) { 41331f9519dSMin-Yih Hsu auto *B = cast<BitInit>(BI->getBit(Idx)); 41431f9519dSMin-Yih Hsu Value.setBitVal(i + Idx, B->getValue()); 41531f9519dSMin-Yih Hsu } 41631f9519dSMin-Yih Hsu } 417b99365a7SMin-Yih Hsu if (const auto *BI = dyn_cast<BitInit>(SI->Value)) 41831f9519dSMin-Yih Hsu Value.setBitVal(i, BI->getValue()); 41931f9519dSMin-Yih Hsu 42031f9519dSMin-Yih Hsu i += SegmentNumBits; 42131f9519dSMin-Yih Hsu ++SI; 42231f9519dSMin-Yih Hsu } 42331f9519dSMin-Yih Hsu 42431f9519dSMin-Yih Hsu emitInstBits(IS, SS, Value, NumFixedValueWords); 42531f9519dSMin-Yih Hsu IS << '\t' << "// " << R->getName() << "\n"; 42631f9519dSMin-Yih Hsu if (Value.getNumWords()) 42731f9519dSMin-Yih Hsu SS << '\t' << "// " << R->getName() << "\n"; 42831f9519dSMin-Yih Hsu } 42931f9519dSMin-Yih Hsu IS.indent(4) << "{/*NumBits*/0, /*Index*/0}\n };\n"; 43031f9519dSMin-Yih Hsu SS.indent(4) << "UINT64_C(0)\n };\n"; 43131f9519dSMin-Yih Hsu 43231f9519dSMin-Yih Hsu OS << IS.str() << SS.str(); 43331f9519dSMin-Yih Hsu } 43431f9519dSMin-Yih Hsu 43531f9519dSMin-Yih Hsu std::string VarLenCodeEmitterGen::getInstructionCase(Record *R, 43631f9519dSMin-Yih Hsu CodeGenTarget &Target) { 43731f9519dSMin-Yih Hsu std::string Case; 43831f9519dSMin-Yih Hsu if (const RecordVal *RV = R->getValue("EncodingInfos")) { 43931f9519dSMin-Yih Hsu if (auto *DI = dyn_cast_or_null<DefInit>(RV->getValue())) { 44031f9519dSMin-Yih Hsu const CodeGenHwModes &HWM = Target.getHwModes(); 44131f9519dSMin-Yih Hsu EncodingInfoByHwMode EBM(DI->getDef(), HWM); 44231f9519dSMin-Yih Hsu Case += " switch (HwMode) {\n"; 44331f9519dSMin-Yih Hsu Case += " default: llvm_unreachable(\"Unhandled HwMode\");\n"; 44431f9519dSMin-Yih Hsu for (auto &KV : EBM) { 44531f9519dSMin-Yih Hsu Case += " case " + itostr(KV.first) + ": {\n"; 44631f9519dSMin-Yih Hsu Case += getInstructionCaseForEncoding(R, KV.second, Target); 44731f9519dSMin-Yih Hsu Case += " break;\n"; 44831f9519dSMin-Yih Hsu Case += " }\n"; 44931f9519dSMin-Yih Hsu } 45031f9519dSMin-Yih Hsu Case += " }\n"; 45131f9519dSMin-Yih Hsu return Case; 45231f9519dSMin-Yih Hsu } 45331f9519dSMin-Yih Hsu } 45431f9519dSMin-Yih Hsu return getInstructionCaseForEncoding(R, R, Target); 45531f9519dSMin-Yih Hsu } 45631f9519dSMin-Yih Hsu 45731f9519dSMin-Yih Hsu std::string VarLenCodeEmitterGen::getInstructionCaseForEncoding( 45831f9519dSMin-Yih Hsu Record *R, Record *EncodingDef, CodeGenTarget &Target) { 45931f9519dSMin-Yih Hsu auto It = VarLenInsts.find(EncodingDef); 46031f9519dSMin-Yih Hsu if (It == VarLenInsts.end()) 46131f9519dSMin-Yih Hsu PrintFatalError(EncodingDef, "Parsed encoding record not found"); 46231f9519dSMin-Yih Hsu const VarLenInst &VLI = It->second; 46331f9519dSMin-Yih Hsu size_t BitWidth = VLI.size(); 46431f9519dSMin-Yih Hsu 46531f9519dSMin-Yih Hsu CodeGenInstruction &CGI = Target.getInstruction(R); 46631f9519dSMin-Yih Hsu 46731f9519dSMin-Yih Hsu std::string Case; 46831f9519dSMin-Yih Hsu raw_string_ostream SS(Case); 46931f9519dSMin-Yih Hsu // Resize the scratch buffer. 47031f9519dSMin-Yih Hsu if (BitWidth && !VLI.isFixedValueOnly()) 47131f9519dSMin-Yih Hsu SS.indent(6) << "Scratch = Scratch.zextOrSelf(" << BitWidth << ");\n"; 47231f9519dSMin-Yih Hsu // Populate based value. 47331f9519dSMin-Yih Hsu SS.indent(6) << "Inst = getInstBits(opcode);\n"; 47431f9519dSMin-Yih Hsu 47531f9519dSMin-Yih Hsu // Process each segment in VLI. 47631f9519dSMin-Yih Hsu size_t Offset = 0U; 477b99365a7SMin-Yih Hsu for (const auto &ES : VLI) { 478b99365a7SMin-Yih Hsu unsigned NumBits = ES.BitWidth; 479b99365a7SMin-Yih Hsu const Init *Val = ES.Value; 48031f9519dSMin-Yih Hsu // If it's a StringInit or DagInit, it's a reference to an operand 48131f9519dSMin-Yih Hsu // or part of an operand. 48231f9519dSMin-Yih Hsu if (isa<StringInit>(Val) || isa<DagInit>(Val)) { 48331f9519dSMin-Yih Hsu StringRef OperandName; 48431f9519dSMin-Yih Hsu unsigned LoBit = 0U; 48531f9519dSMin-Yih Hsu if (const auto *SV = dyn_cast<StringInit>(Val)) { 48631f9519dSMin-Yih Hsu OperandName = SV->getValue(); 48731f9519dSMin-Yih Hsu } else { 48831f9519dSMin-Yih Hsu // Normalized: (slice <operand name>, <high bit>, <low bit>) 48931f9519dSMin-Yih Hsu const auto *DV = cast<DagInit>(Val); 49031f9519dSMin-Yih Hsu OperandName = cast<StringInit>(DV->getArg(0))->getValue(); 49131f9519dSMin-Yih Hsu LoBit = static_cast<unsigned>(cast<IntInit>(DV->getArg(2))->getValue()); 49231f9519dSMin-Yih Hsu } 49331f9519dSMin-Yih Hsu 49431f9519dSMin-Yih Hsu auto OpIdx = CGI.Operands.ParseOperandName(OperandName); 49531f9519dSMin-Yih Hsu unsigned FlatOpIdx = CGI.Operands.getFlattenedOperandNumber(OpIdx); 496b99365a7SMin-Yih Hsu StringRef CustomEncoder = CGI.Operands[OpIdx.first].EncoderMethodName; 497b99365a7SMin-Yih Hsu if (ES.CustomEncoder.size()) 498b99365a7SMin-Yih Hsu CustomEncoder = ES.CustomEncoder; 49931f9519dSMin-Yih Hsu 50031f9519dSMin-Yih Hsu SS.indent(6) << "Scratch.clearAllBits();\n"; 50131f9519dSMin-Yih Hsu SS.indent(6) << "// op: " << OperandName.drop_front(1) << "\n"; 502b99365a7SMin-Yih Hsu if (CustomEncoder.empty()) 503b99365a7SMin-Yih Hsu SS.indent(6) << "getMachineOpValue(MI, MI.getOperand(" 504b99365a7SMin-Yih Hsu << utostr(FlatOpIdx) << ")"; 505b99365a7SMin-Yih Hsu else 506b99365a7SMin-Yih Hsu SS.indent(6) << CustomEncoder << "(MI, /*OpIdx=*/" << utostr(FlatOpIdx); 507b99365a7SMin-Yih Hsu 508b99365a7SMin-Yih Hsu SS << ", /*Pos=*/" << utostr(Offset) << ", Scratch, Fixups, STI);\n"; 509b99365a7SMin-Yih Hsu 51031f9519dSMin-Yih Hsu SS.indent(6) << "Inst.insertBits(" 51131f9519dSMin-Yih Hsu << "Scratch.extractBits(" << utostr(NumBits) << ", " 51231f9519dSMin-Yih Hsu << utostr(LoBit) << ")" 51331f9519dSMin-Yih Hsu << ", " << Offset << ");\n"; 51431f9519dSMin-Yih Hsu } 51531f9519dSMin-Yih Hsu Offset += NumBits; 51631f9519dSMin-Yih Hsu } 51731f9519dSMin-Yih Hsu 51831f9519dSMin-Yih Hsu StringRef PostEmitter = R->getValueAsString("PostEncoderMethod"); 51931f9519dSMin-Yih Hsu if (!PostEmitter.empty()) 52031f9519dSMin-Yih Hsu SS.indent(6) << "Inst = " << PostEmitter << "(MI, Inst, STI);\n"; 52131f9519dSMin-Yih Hsu 52231f9519dSMin-Yih Hsu return Case; 52331f9519dSMin-Yih Hsu } 52431f9519dSMin-Yih Hsu 52531f9519dSMin-Yih Hsu namespace llvm { 52631f9519dSMin-Yih Hsu 52731f9519dSMin-Yih Hsu void emitVarLenCodeEmitter(RecordKeeper &R, raw_ostream &OS) { 52831f9519dSMin-Yih Hsu VarLenCodeEmitterGen(R).run(OS); 52931f9519dSMin-Yih Hsu } 53031f9519dSMin-Yih Hsu 53131f9519dSMin-Yih Hsu } // end namespace llvm 532