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" 5331f9519dSMin-Yih Hsu #include "CodeGenInstruction.h" 5431f9519dSMin-Yih Hsu #include "CodeGenTarget.h" 5531f9519dSMin-Yih Hsu #include "SubtargetFeatureInfo.h" 5631f9519dSMin-Yih Hsu #include "llvm/ADT/ArrayRef.h" 5731f9519dSMin-Yih Hsu #include "llvm/ADT/DenseMap.h" 5831f9519dSMin-Yih Hsu #include "llvm/Support/raw_ostream.h" 5931f9519dSMin-Yih Hsu #include "llvm/TableGen/Error.h" 6031f9519dSMin-Yih Hsu #include "llvm/TableGen/Record.h" 6131f9519dSMin-Yih Hsu 6231f9519dSMin-Yih Hsu using namespace llvm; 6331f9519dSMin-Yih Hsu 6431f9519dSMin-Yih Hsu namespace { 6531f9519dSMin-Yih Hsu 6631f9519dSMin-Yih Hsu class VarLenCodeEmitterGen { 6731f9519dSMin-Yih Hsu RecordKeeper &Records; 6831f9519dSMin-Yih Hsu 69b99365a7SMin-Yih Hsu struct EncodingSegment { 70b99365a7SMin-Yih Hsu unsigned BitWidth; 71b99365a7SMin-Yih Hsu const Init *Value; 72b99365a7SMin-Yih Hsu StringRef CustomEncoder = ""; 73b99365a7SMin-Yih Hsu }; 74b99365a7SMin-Yih Hsu 7531f9519dSMin-Yih Hsu class VarLenInst { 76*314155ebSSheng RecordVal *TheDef; 7731f9519dSMin-Yih Hsu size_t NumBits; 7831f9519dSMin-Yih Hsu 7931f9519dSMin-Yih Hsu // Set if any of the segment is not fixed value. 8031f9519dSMin-Yih Hsu bool HasDynamicSegment; 8131f9519dSMin-Yih Hsu 82b99365a7SMin-Yih Hsu SmallVector<EncodingSegment, 4> Segments; 8331f9519dSMin-Yih Hsu 8431f9519dSMin-Yih Hsu void buildRec(const DagInit *DI); 8531f9519dSMin-Yih Hsu 86b99365a7SMin-Yih Hsu StringRef getCustomEncoderName(const Init *EI) const { 87b99365a7SMin-Yih Hsu if (const auto *DI = dyn_cast<DagInit>(EI)) { 88b99365a7SMin-Yih Hsu if (DI->getNumArgs() && isa<StringInit>(DI->getArg(0))) 89b99365a7SMin-Yih Hsu return cast<StringInit>(DI->getArg(0))->getValue(); 90b99365a7SMin-Yih Hsu } 91b99365a7SMin-Yih Hsu return ""; 92b99365a7SMin-Yih Hsu } 93b99365a7SMin-Yih Hsu 9431f9519dSMin-Yih Hsu public: 95*314155ebSSheng VarLenInst() : TheDef(nullptr), NumBits(0U), HasDynamicSegment(false) {} 9631f9519dSMin-Yih Hsu 97*314155ebSSheng explicit VarLenInst(const DagInit *DI, RecordVal *TheDef); 9831f9519dSMin-Yih Hsu 9931f9519dSMin-Yih Hsu /// Number of bits 10031f9519dSMin-Yih Hsu size_t size() const { return NumBits; } 10131f9519dSMin-Yih Hsu 10231f9519dSMin-Yih Hsu using const_iterator = decltype(Segments)::const_iterator; 10331f9519dSMin-Yih Hsu 10431f9519dSMin-Yih Hsu const_iterator begin() const { return Segments.begin(); } 10531f9519dSMin-Yih Hsu const_iterator end() const { return Segments.end(); } 10631f9519dSMin-Yih Hsu size_t getNumSegments() const { return Segments.size(); } 10731f9519dSMin-Yih Hsu 10831f9519dSMin-Yih Hsu bool isFixedValueOnly() const { return !HasDynamicSegment; } 10931f9519dSMin-Yih Hsu }; 11031f9519dSMin-Yih Hsu 11131f9519dSMin-Yih Hsu DenseMap<Record *, VarLenInst> VarLenInsts; 11231f9519dSMin-Yih Hsu 11331f9519dSMin-Yih Hsu // Emit based values (i.e. fixed bits in the encoded instructions) 11431f9519dSMin-Yih Hsu void emitInstructionBaseValues( 11531f9519dSMin-Yih Hsu raw_ostream &OS, 11631f9519dSMin-Yih Hsu ArrayRef<const CodeGenInstruction *> NumberedInstructions, 11731f9519dSMin-Yih Hsu CodeGenTarget &Target, int HwMode = -1); 11831f9519dSMin-Yih Hsu 11931f9519dSMin-Yih Hsu std::string getInstructionCase(Record *R, CodeGenTarget &Target); 12031f9519dSMin-Yih Hsu std::string getInstructionCaseForEncoding(Record *R, Record *EncodingDef, 12131f9519dSMin-Yih Hsu CodeGenTarget &Target); 12231f9519dSMin-Yih Hsu 12331f9519dSMin-Yih Hsu public: 12431f9519dSMin-Yih Hsu explicit VarLenCodeEmitterGen(RecordKeeper &R) : Records(R) {} 12531f9519dSMin-Yih Hsu 12631f9519dSMin-Yih Hsu void run(raw_ostream &OS); 12731f9519dSMin-Yih Hsu }; 12831f9519dSMin-Yih Hsu 12931f9519dSMin-Yih Hsu } // end anonymous namespace 13031f9519dSMin-Yih Hsu 131*314155ebSSheng VarLenCodeEmitterGen::VarLenInst::VarLenInst(const DagInit *DI, 132*314155ebSSheng RecordVal *TheDef) 133*314155ebSSheng : TheDef(TheDef), NumBits(0U) { 13431f9519dSMin-Yih Hsu buildRec(DI); 13531f9519dSMin-Yih Hsu for (const auto &S : Segments) 136b99365a7SMin-Yih Hsu NumBits += S.BitWidth; 13731f9519dSMin-Yih Hsu } 13831f9519dSMin-Yih Hsu 13931f9519dSMin-Yih Hsu void VarLenCodeEmitterGen::VarLenInst::buildRec(const DagInit *DI) { 140*314155ebSSheng assert(TheDef && "The def record is nullptr ?"); 141*314155ebSSheng 14231f9519dSMin-Yih Hsu std::string Op = DI->getOperator()->getAsString(); 14331f9519dSMin-Yih Hsu 14431f9519dSMin-Yih Hsu if (Op == "ascend" || Op == "descend") { 14531f9519dSMin-Yih Hsu bool Reverse = Op == "descend"; 14631f9519dSMin-Yih Hsu int i = Reverse ? DI->getNumArgs() - 1 : 0; 14731f9519dSMin-Yih Hsu int e = Reverse ? -1 : DI->getNumArgs(); 14831f9519dSMin-Yih Hsu int s = Reverse ? -1 : 1; 14931f9519dSMin-Yih Hsu for (; i != e; i += s) { 15031f9519dSMin-Yih Hsu const Init *Arg = DI->getArg(i); 15131f9519dSMin-Yih Hsu if (const auto *BI = dyn_cast<BitsInit>(Arg)) { 15231f9519dSMin-Yih Hsu if (!BI->isComplete()) 153*314155ebSSheng PrintFatalError(TheDef->getLoc(), 154*314155ebSSheng "Expecting complete bits init in `" + Op + "`"); 15531f9519dSMin-Yih Hsu Segments.push_back({BI->getNumBits(), BI}); 15631f9519dSMin-Yih Hsu } else if (const auto *BI = dyn_cast<BitInit>(Arg)) { 15731f9519dSMin-Yih Hsu if (!BI->isConcrete()) 158*314155ebSSheng PrintFatalError(TheDef->getLoc(), 159*314155ebSSheng "Expecting concrete bit init in `" + Op + "`"); 16031f9519dSMin-Yih Hsu Segments.push_back({1, BI}); 16131f9519dSMin-Yih Hsu } else if (const auto *SubDI = dyn_cast<DagInit>(Arg)) { 16231f9519dSMin-Yih Hsu buildRec(SubDI); 16331f9519dSMin-Yih Hsu } else { 164*314155ebSSheng PrintFatalError(TheDef->getLoc(), "Unrecognized type of argument in `" + 165*314155ebSSheng Op + "`: " + Arg->getAsString()); 16631f9519dSMin-Yih Hsu } 16731f9519dSMin-Yih Hsu } 16831f9519dSMin-Yih Hsu } else if (Op == "operand") { 169b99365a7SMin-Yih Hsu // (operand <operand name>, <# of bits>, [(encoder <custom encoder>)]) 170b99365a7SMin-Yih Hsu if (DI->getNumArgs() < 2) 171*314155ebSSheng PrintFatalError(TheDef->getLoc(), 172*314155ebSSheng "Expecting at least 2 arguments for `operand`"); 17331f9519dSMin-Yih Hsu HasDynamicSegment = true; 17431f9519dSMin-Yih Hsu const Init *OperandName = DI->getArg(0), *NumBits = DI->getArg(1); 17531f9519dSMin-Yih Hsu if (!isa<StringInit>(OperandName) || !isa<IntInit>(NumBits)) 176*314155ebSSheng PrintFatalError(TheDef->getLoc(), "Invalid argument types for `operand`"); 17731f9519dSMin-Yih Hsu 17831f9519dSMin-Yih Hsu auto NumBitsVal = cast<IntInit>(NumBits)->getValue(); 17931f9519dSMin-Yih Hsu if (NumBitsVal <= 0) 180*314155ebSSheng PrintFatalError(TheDef->getLoc(), "Invalid number of bits for `operand`"); 18131f9519dSMin-Yih Hsu 182b99365a7SMin-Yih Hsu StringRef CustomEncoder; 183b99365a7SMin-Yih Hsu if (DI->getNumArgs() >= 3) 184b99365a7SMin-Yih Hsu CustomEncoder = getCustomEncoderName(DI->getArg(2)); 185b99365a7SMin-Yih Hsu Segments.push_back( 186b99365a7SMin-Yih Hsu {static_cast<unsigned>(NumBitsVal), OperandName, CustomEncoder}); 18731f9519dSMin-Yih Hsu } else if (Op == "slice") { 188b99365a7SMin-Yih Hsu // (slice <operand name>, <high / low bit>, <low / high bit>, 189b99365a7SMin-Yih Hsu // [(encoder <custom encoder>)]) 190b99365a7SMin-Yih Hsu if (DI->getNumArgs() < 3) 191*314155ebSSheng PrintFatalError(TheDef->getLoc(), 192*314155ebSSheng "Expecting at least 3 arguments for `slice`"); 19331f9519dSMin-Yih Hsu HasDynamicSegment = true; 19431f9519dSMin-Yih Hsu Init *OperandName = DI->getArg(0), *HiBit = DI->getArg(1), 19531f9519dSMin-Yih Hsu *LoBit = DI->getArg(2); 19631f9519dSMin-Yih Hsu if (!isa<StringInit>(OperandName) || !isa<IntInit>(HiBit) || 19731f9519dSMin-Yih Hsu !isa<IntInit>(LoBit)) 198*314155ebSSheng PrintFatalError(TheDef->getLoc(), "Invalid argument types for `slice`"); 19931f9519dSMin-Yih Hsu 20031f9519dSMin-Yih Hsu auto HiBitVal = cast<IntInit>(HiBit)->getValue(), 20131f9519dSMin-Yih Hsu LoBitVal = cast<IntInit>(LoBit)->getValue(); 20231f9519dSMin-Yih Hsu if (HiBitVal < 0 || LoBitVal < 0) 203*314155ebSSheng PrintFatalError(TheDef->getLoc(), "Invalid bit range for `slice`"); 20431f9519dSMin-Yih Hsu bool NeedSwap = false; 20531f9519dSMin-Yih Hsu unsigned NumBits = 0U; 20631f9519dSMin-Yih Hsu if (HiBitVal < LoBitVal) { 20731f9519dSMin-Yih Hsu NeedSwap = true; 20831f9519dSMin-Yih Hsu NumBits = static_cast<unsigned>(LoBitVal - HiBitVal + 1); 20931f9519dSMin-Yih Hsu } else { 21031f9519dSMin-Yih Hsu NumBits = static_cast<unsigned>(HiBitVal - LoBitVal + 1); 21131f9519dSMin-Yih Hsu } 21231f9519dSMin-Yih Hsu 213b99365a7SMin-Yih Hsu StringRef CustomEncoder; 214b99365a7SMin-Yih Hsu if (DI->getNumArgs() >= 4) 215b99365a7SMin-Yih Hsu CustomEncoder = getCustomEncoderName(DI->getArg(3)); 216b99365a7SMin-Yih Hsu 21731f9519dSMin-Yih Hsu if (NeedSwap) { 21831f9519dSMin-Yih Hsu // Normalization: Hi bit should always be the second argument. 21931f9519dSMin-Yih Hsu Init *const NewArgs[] = {OperandName, LoBit, HiBit}; 220b99365a7SMin-Yih Hsu Segments.push_back({NumBits, 221b99365a7SMin-Yih Hsu DagInit::get(DI->getOperator(), nullptr, NewArgs, {}), 222b99365a7SMin-Yih Hsu CustomEncoder}); 22331f9519dSMin-Yih Hsu } else { 224b99365a7SMin-Yih Hsu Segments.push_back({NumBits, DI, CustomEncoder}); 22531f9519dSMin-Yih Hsu } 22631f9519dSMin-Yih Hsu } 22731f9519dSMin-Yih Hsu } 22831f9519dSMin-Yih Hsu 22931f9519dSMin-Yih Hsu void VarLenCodeEmitterGen::run(raw_ostream &OS) { 23031f9519dSMin-Yih Hsu CodeGenTarget Target(Records); 23131f9519dSMin-Yih Hsu auto Insts = Records.getAllDerivedDefinitions("Instruction"); 23231f9519dSMin-Yih Hsu 23331f9519dSMin-Yih Hsu auto NumberedInstructions = Target.getInstructionsByEnumValue(); 23431f9519dSMin-Yih Hsu const CodeGenHwModes &HWM = Target.getHwModes(); 23531f9519dSMin-Yih Hsu 23631f9519dSMin-Yih Hsu // The set of HwModes used by instruction encodings. 23731f9519dSMin-Yih Hsu std::set<unsigned> HwModes; 23831f9519dSMin-Yih Hsu for (const CodeGenInstruction *CGI : NumberedInstructions) { 23931f9519dSMin-Yih Hsu Record *R = CGI->TheDef; 24031f9519dSMin-Yih Hsu 24131f9519dSMin-Yih Hsu // Create the corresponding VarLenInst instance. 24231f9519dSMin-Yih Hsu if (R->getValueAsString("Namespace") == "TargetOpcode" || 24331f9519dSMin-Yih Hsu R->getValueAsBit("isPseudo")) 24431f9519dSMin-Yih Hsu continue; 24531f9519dSMin-Yih Hsu 24631f9519dSMin-Yih Hsu if (const RecordVal *RV = R->getValue("EncodingInfos")) { 24731f9519dSMin-Yih Hsu if (auto *DI = dyn_cast_or_null<DefInit>(RV->getValue())) { 24831f9519dSMin-Yih Hsu EncodingInfoByHwMode EBM(DI->getDef(), HWM); 24931f9519dSMin-Yih Hsu for (auto &KV : EBM) { 25031f9519dSMin-Yih Hsu HwModes.insert(KV.first); 25131f9519dSMin-Yih Hsu Record *EncodingDef = KV.second; 252*314155ebSSheng RecordVal *RV = EncodingDef->getValue("Inst"); 253*314155ebSSheng DagInit *DI = cast<DagInit>(RV->getValue()); 254*314155ebSSheng VarLenInsts.insert({EncodingDef, VarLenInst(DI, RV)}); 25531f9519dSMin-Yih Hsu } 25631f9519dSMin-Yih Hsu continue; 25731f9519dSMin-Yih Hsu } 25831f9519dSMin-Yih Hsu } 259*314155ebSSheng RecordVal *RV = R->getValue("Inst"); 260*314155ebSSheng DagInit *DI = cast<DagInit>(RV->getValue()); 261*314155ebSSheng VarLenInsts.insert({R, VarLenInst(DI, RV)}); 26231f9519dSMin-Yih Hsu } 26331f9519dSMin-Yih Hsu 26431f9519dSMin-Yih Hsu // Emit function declaration 26531f9519dSMin-Yih Hsu OS << "void " << Target.getName() 26631f9519dSMin-Yih Hsu << "MCCodeEmitter::getBinaryCodeForInstr(const MCInst &MI,\n" 26731f9519dSMin-Yih Hsu << " SmallVectorImpl<MCFixup> &Fixups,\n" 26831f9519dSMin-Yih Hsu << " APInt &Inst,\n" 26931f9519dSMin-Yih Hsu << " APInt &Scratch,\n" 27031f9519dSMin-Yih Hsu << " const MCSubtargetInfo &STI) const {\n"; 27131f9519dSMin-Yih Hsu 27231f9519dSMin-Yih Hsu // Emit instruction base values 27331f9519dSMin-Yih Hsu if (HwModes.empty()) { 27431f9519dSMin-Yih Hsu emitInstructionBaseValues(OS, NumberedInstructions, Target); 27531f9519dSMin-Yih Hsu } else { 27631f9519dSMin-Yih Hsu for (unsigned HwMode : HwModes) 27731f9519dSMin-Yih Hsu emitInstructionBaseValues(OS, NumberedInstructions, Target, (int)HwMode); 27831f9519dSMin-Yih Hsu } 27931f9519dSMin-Yih Hsu 28031f9519dSMin-Yih Hsu if (!HwModes.empty()) { 28131f9519dSMin-Yih Hsu OS << " const unsigned **Index;\n"; 28231f9519dSMin-Yih Hsu OS << " const uint64_t *InstBits;\n"; 28331f9519dSMin-Yih Hsu OS << " unsigned HwMode = STI.getHwMode();\n"; 28431f9519dSMin-Yih Hsu OS << " switch (HwMode) {\n"; 28531f9519dSMin-Yih Hsu OS << " default: llvm_unreachable(\"Unknown hardware mode!\"); break;\n"; 28631f9519dSMin-Yih Hsu for (unsigned I : HwModes) { 28731f9519dSMin-Yih Hsu OS << " case " << I << ": InstBits = InstBits_" << HWM.getMode(I).Name 28831f9519dSMin-Yih Hsu << "; Index = Index_" << HWM.getMode(I).Name << "; break;\n"; 28931f9519dSMin-Yih Hsu } 29031f9519dSMin-Yih Hsu OS << " };\n"; 29131f9519dSMin-Yih Hsu } 29231f9519dSMin-Yih Hsu 29331f9519dSMin-Yih Hsu // Emit helper function to retrieve base values. 29431f9519dSMin-Yih Hsu OS << " auto getInstBits = [&](unsigned Opcode) -> APInt {\n" 29531f9519dSMin-Yih Hsu << " unsigned NumBits = Index[Opcode][0];\n" 29631f9519dSMin-Yih Hsu << " if (!NumBits)\n" 29731f9519dSMin-Yih Hsu << " return APInt::getZeroWidth();\n" 29831f9519dSMin-Yih Hsu << " unsigned Idx = Index[Opcode][1];\n" 29931f9519dSMin-Yih Hsu << " ArrayRef<uint64_t> Data(&InstBits[Idx], " 30031f9519dSMin-Yih Hsu << "APInt::getNumWords(NumBits));\n" 30131f9519dSMin-Yih Hsu << " return APInt(NumBits, Data);\n" 30231f9519dSMin-Yih Hsu << " };\n"; 30331f9519dSMin-Yih Hsu 30431f9519dSMin-Yih Hsu // Map to accumulate all the cases. 30531f9519dSMin-Yih Hsu std::map<std::string, std::vector<std::string>> CaseMap; 30631f9519dSMin-Yih Hsu 30731f9519dSMin-Yih Hsu // Construct all cases statement for each opcode 30831f9519dSMin-Yih Hsu for (Record *R : Insts) { 30931f9519dSMin-Yih Hsu if (R->getValueAsString("Namespace") == "TargetOpcode" || 31031f9519dSMin-Yih Hsu R->getValueAsBit("isPseudo")) 31131f9519dSMin-Yih Hsu continue; 31231f9519dSMin-Yih Hsu std::string InstName = 31331f9519dSMin-Yih Hsu (R->getValueAsString("Namespace") + "::" + R->getName()).str(); 31431f9519dSMin-Yih Hsu std::string Case = getInstructionCase(R, Target); 31531f9519dSMin-Yih Hsu 31631f9519dSMin-Yih Hsu CaseMap[Case].push_back(std::move(InstName)); 31731f9519dSMin-Yih Hsu } 31831f9519dSMin-Yih Hsu 31931f9519dSMin-Yih Hsu // Emit initial function code 32031f9519dSMin-Yih Hsu OS << " const unsigned opcode = MI.getOpcode();\n" 32131f9519dSMin-Yih Hsu << " switch (opcode) {\n"; 32231f9519dSMin-Yih Hsu 32331f9519dSMin-Yih Hsu // Emit each case statement 32431f9519dSMin-Yih Hsu for (const auto &C : CaseMap) { 32531f9519dSMin-Yih Hsu const std::string &Case = C.first; 32631f9519dSMin-Yih Hsu const auto &InstList = C.second; 32731f9519dSMin-Yih Hsu 32831f9519dSMin-Yih Hsu ListSeparator LS("\n"); 32931f9519dSMin-Yih Hsu for (const auto &InstName : InstList) 33031f9519dSMin-Yih Hsu OS << LS << " case " << InstName << ":"; 33131f9519dSMin-Yih Hsu 33231f9519dSMin-Yih Hsu OS << " {\n"; 33331f9519dSMin-Yih Hsu OS << Case; 33431f9519dSMin-Yih Hsu OS << " break;\n" 33531f9519dSMin-Yih Hsu << " }\n"; 33631f9519dSMin-Yih Hsu } 33731f9519dSMin-Yih Hsu // Default case: unhandled opcode 33831f9519dSMin-Yih Hsu OS << " default:\n" 33931f9519dSMin-Yih Hsu << " std::string msg;\n" 34031f9519dSMin-Yih Hsu << " raw_string_ostream Msg(msg);\n" 34131f9519dSMin-Yih Hsu << " Msg << \"Not supported instr: \" << MI;\n" 34231f9519dSMin-Yih Hsu << " report_fatal_error(Msg.str().c_str());\n" 34331f9519dSMin-Yih Hsu << " }\n"; 34431f9519dSMin-Yih Hsu OS << "}\n\n"; 34531f9519dSMin-Yih Hsu } 34631f9519dSMin-Yih Hsu 34731f9519dSMin-Yih Hsu static void emitInstBits(raw_ostream &IS, raw_ostream &SS, const APInt &Bits, 34831f9519dSMin-Yih Hsu unsigned &Index) { 34931f9519dSMin-Yih Hsu if (!Bits.getNumWords()) { 35031f9519dSMin-Yih Hsu IS.indent(4) << "{/*NumBits*/0, /*Index*/0},"; 35131f9519dSMin-Yih Hsu return; 35231f9519dSMin-Yih Hsu } 35331f9519dSMin-Yih Hsu 35431f9519dSMin-Yih Hsu IS.indent(4) << "{/*NumBits*/" << Bits.getBitWidth() << ", " 35531f9519dSMin-Yih Hsu << "/*Index*/" << Index << "},"; 35631f9519dSMin-Yih Hsu 35731f9519dSMin-Yih Hsu SS.indent(4); 35831f9519dSMin-Yih Hsu for (unsigned I = 0; I < Bits.getNumWords(); ++I, ++Index) 35931f9519dSMin-Yih Hsu SS << "UINT64_C(" << utostr(Bits.getRawData()[I]) << "),"; 36031f9519dSMin-Yih Hsu } 36131f9519dSMin-Yih Hsu 36231f9519dSMin-Yih Hsu void VarLenCodeEmitterGen::emitInstructionBaseValues( 36331f9519dSMin-Yih Hsu raw_ostream &OS, ArrayRef<const CodeGenInstruction *> NumberedInstructions, 36431f9519dSMin-Yih Hsu CodeGenTarget &Target, int HwMode) { 36531f9519dSMin-Yih Hsu std::string IndexArray, StorageArray; 36631f9519dSMin-Yih Hsu raw_string_ostream IS(IndexArray), SS(StorageArray); 36731f9519dSMin-Yih Hsu 36831f9519dSMin-Yih Hsu const CodeGenHwModes &HWM = Target.getHwModes(); 36931f9519dSMin-Yih Hsu if (HwMode == -1) { 37031f9519dSMin-Yih Hsu IS << " static const unsigned Index[][2] = {\n"; 37131f9519dSMin-Yih Hsu SS << " static const uint64_t InstBits[] = {\n"; 37231f9519dSMin-Yih Hsu } else { 37331f9519dSMin-Yih Hsu StringRef Name = HWM.getMode(HwMode).Name; 37431f9519dSMin-Yih Hsu IS << " static const unsigned Index_" << Name << "[][2] = {\n"; 37531f9519dSMin-Yih Hsu SS << " static const uint64_t InstBits_" << Name << "[] = {\n"; 37631f9519dSMin-Yih Hsu } 37731f9519dSMin-Yih Hsu 37831f9519dSMin-Yih Hsu unsigned NumFixedValueWords = 0U; 37931f9519dSMin-Yih Hsu for (const CodeGenInstruction *CGI : NumberedInstructions) { 38031f9519dSMin-Yih Hsu Record *R = CGI->TheDef; 38131f9519dSMin-Yih Hsu 38231f9519dSMin-Yih Hsu if (R->getValueAsString("Namespace") == "TargetOpcode" || 38331f9519dSMin-Yih Hsu R->getValueAsBit("isPseudo")) { 38431f9519dSMin-Yih Hsu IS.indent(4) << "{/*NumBits*/0, /*Index*/0},\n"; 38531f9519dSMin-Yih Hsu continue; 38631f9519dSMin-Yih Hsu } 38731f9519dSMin-Yih Hsu 38831f9519dSMin-Yih Hsu Record *EncodingDef = R; 38931f9519dSMin-Yih Hsu if (const RecordVal *RV = R->getValue("EncodingInfos")) { 39031f9519dSMin-Yih Hsu if (auto *DI = dyn_cast_or_null<DefInit>(RV->getValue())) { 39131f9519dSMin-Yih Hsu EncodingInfoByHwMode EBM(DI->getDef(), HWM); 39231f9519dSMin-Yih Hsu if (EBM.hasMode(HwMode)) 39331f9519dSMin-Yih Hsu EncodingDef = EBM.get(HwMode); 39431f9519dSMin-Yih Hsu } 39531f9519dSMin-Yih Hsu } 39631f9519dSMin-Yih Hsu 39731f9519dSMin-Yih Hsu auto It = VarLenInsts.find(EncodingDef); 39831f9519dSMin-Yih Hsu if (It == VarLenInsts.end()) 39931f9519dSMin-Yih Hsu PrintFatalError(EncodingDef, "VarLenInst not found for this record"); 40031f9519dSMin-Yih Hsu const VarLenInst &VLI = It->second; 40131f9519dSMin-Yih Hsu 40231f9519dSMin-Yih Hsu unsigned i = 0U, BitWidth = VLI.size(); 40331f9519dSMin-Yih Hsu 40431f9519dSMin-Yih Hsu // Start by filling in fixed values. 40531f9519dSMin-Yih Hsu APInt Value(BitWidth, 0); 40631f9519dSMin-Yih Hsu auto SI = VLI.begin(), SE = VLI.end(); 40731f9519dSMin-Yih Hsu // Scan through all the segments that have fixed-bits values. 40831f9519dSMin-Yih Hsu while (i < BitWidth && SI != SE) { 409b99365a7SMin-Yih Hsu unsigned SegmentNumBits = SI->BitWidth; 410b99365a7SMin-Yih Hsu if (const auto *BI = dyn_cast<BitsInit>(SI->Value)) { 41131f9519dSMin-Yih Hsu for (unsigned Idx = 0U; Idx != SegmentNumBits; ++Idx) { 41231f9519dSMin-Yih Hsu auto *B = cast<BitInit>(BI->getBit(Idx)); 41331f9519dSMin-Yih Hsu Value.setBitVal(i + Idx, B->getValue()); 41431f9519dSMin-Yih Hsu } 41531f9519dSMin-Yih Hsu } 416b99365a7SMin-Yih Hsu if (const auto *BI = dyn_cast<BitInit>(SI->Value)) 41731f9519dSMin-Yih Hsu Value.setBitVal(i, BI->getValue()); 41831f9519dSMin-Yih Hsu 41931f9519dSMin-Yih Hsu i += SegmentNumBits; 42031f9519dSMin-Yih Hsu ++SI; 42131f9519dSMin-Yih Hsu } 42231f9519dSMin-Yih Hsu 42331f9519dSMin-Yih Hsu emitInstBits(IS, SS, Value, NumFixedValueWords); 42431f9519dSMin-Yih Hsu IS << '\t' << "// " << R->getName() << "\n"; 42531f9519dSMin-Yih Hsu if (Value.getNumWords()) 42631f9519dSMin-Yih Hsu SS << '\t' << "// " << R->getName() << "\n"; 42731f9519dSMin-Yih Hsu } 42831f9519dSMin-Yih Hsu IS.indent(4) << "{/*NumBits*/0, /*Index*/0}\n };\n"; 42931f9519dSMin-Yih Hsu SS.indent(4) << "UINT64_C(0)\n };\n"; 43031f9519dSMin-Yih Hsu 43131f9519dSMin-Yih Hsu OS << IS.str() << SS.str(); 43231f9519dSMin-Yih Hsu } 43331f9519dSMin-Yih Hsu 43431f9519dSMin-Yih Hsu std::string VarLenCodeEmitterGen::getInstructionCase(Record *R, 43531f9519dSMin-Yih Hsu CodeGenTarget &Target) { 43631f9519dSMin-Yih Hsu std::string Case; 43731f9519dSMin-Yih Hsu if (const RecordVal *RV = R->getValue("EncodingInfos")) { 43831f9519dSMin-Yih Hsu if (auto *DI = dyn_cast_or_null<DefInit>(RV->getValue())) { 43931f9519dSMin-Yih Hsu const CodeGenHwModes &HWM = Target.getHwModes(); 44031f9519dSMin-Yih Hsu EncodingInfoByHwMode EBM(DI->getDef(), HWM); 44131f9519dSMin-Yih Hsu Case += " switch (HwMode) {\n"; 44231f9519dSMin-Yih Hsu Case += " default: llvm_unreachable(\"Unhandled HwMode\");\n"; 44331f9519dSMin-Yih Hsu for (auto &KV : EBM) { 44431f9519dSMin-Yih Hsu Case += " case " + itostr(KV.first) + ": {\n"; 44531f9519dSMin-Yih Hsu Case += getInstructionCaseForEncoding(R, KV.second, Target); 44631f9519dSMin-Yih Hsu Case += " break;\n"; 44731f9519dSMin-Yih Hsu Case += " }\n"; 44831f9519dSMin-Yih Hsu } 44931f9519dSMin-Yih Hsu Case += " }\n"; 45031f9519dSMin-Yih Hsu return Case; 45131f9519dSMin-Yih Hsu } 45231f9519dSMin-Yih Hsu } 45331f9519dSMin-Yih Hsu return getInstructionCaseForEncoding(R, R, Target); 45431f9519dSMin-Yih Hsu } 45531f9519dSMin-Yih Hsu 45631f9519dSMin-Yih Hsu std::string VarLenCodeEmitterGen::getInstructionCaseForEncoding( 45731f9519dSMin-Yih Hsu Record *R, Record *EncodingDef, CodeGenTarget &Target) { 45831f9519dSMin-Yih Hsu auto It = VarLenInsts.find(EncodingDef); 45931f9519dSMin-Yih Hsu if (It == VarLenInsts.end()) 46031f9519dSMin-Yih Hsu PrintFatalError(EncodingDef, "Parsed encoding record not found"); 46131f9519dSMin-Yih Hsu const VarLenInst &VLI = It->second; 46231f9519dSMin-Yih Hsu size_t BitWidth = VLI.size(); 46331f9519dSMin-Yih Hsu 46431f9519dSMin-Yih Hsu CodeGenInstruction &CGI = Target.getInstruction(R); 46531f9519dSMin-Yih Hsu 46631f9519dSMin-Yih Hsu std::string Case; 46731f9519dSMin-Yih Hsu raw_string_ostream SS(Case); 46831f9519dSMin-Yih Hsu // Resize the scratch buffer. 46931f9519dSMin-Yih Hsu if (BitWidth && !VLI.isFixedValueOnly()) 47031f9519dSMin-Yih Hsu SS.indent(6) << "Scratch = Scratch.zextOrSelf(" << BitWidth << ");\n"; 47131f9519dSMin-Yih Hsu // Populate based value. 47231f9519dSMin-Yih Hsu SS.indent(6) << "Inst = getInstBits(opcode);\n"; 47331f9519dSMin-Yih Hsu 47431f9519dSMin-Yih Hsu // Process each segment in VLI. 47531f9519dSMin-Yih Hsu size_t Offset = 0U; 476b99365a7SMin-Yih Hsu for (const auto &ES : VLI) { 477b99365a7SMin-Yih Hsu unsigned NumBits = ES.BitWidth; 478b99365a7SMin-Yih Hsu const Init *Val = ES.Value; 47931f9519dSMin-Yih Hsu // If it's a StringInit or DagInit, it's a reference to an operand 48031f9519dSMin-Yih Hsu // or part of an operand. 48131f9519dSMin-Yih Hsu if (isa<StringInit>(Val) || isa<DagInit>(Val)) { 48231f9519dSMin-Yih Hsu StringRef OperandName; 48331f9519dSMin-Yih Hsu unsigned LoBit = 0U; 48431f9519dSMin-Yih Hsu if (const auto *SV = dyn_cast<StringInit>(Val)) { 48531f9519dSMin-Yih Hsu OperandName = SV->getValue(); 48631f9519dSMin-Yih Hsu } else { 48731f9519dSMin-Yih Hsu // Normalized: (slice <operand name>, <high bit>, <low bit>) 48831f9519dSMin-Yih Hsu const auto *DV = cast<DagInit>(Val); 48931f9519dSMin-Yih Hsu OperandName = cast<StringInit>(DV->getArg(0))->getValue(); 49031f9519dSMin-Yih Hsu LoBit = static_cast<unsigned>(cast<IntInit>(DV->getArg(2))->getValue()); 49131f9519dSMin-Yih Hsu } 49231f9519dSMin-Yih Hsu 49331f9519dSMin-Yih Hsu auto OpIdx = CGI.Operands.ParseOperandName(OperandName); 49431f9519dSMin-Yih Hsu unsigned FlatOpIdx = CGI.Operands.getFlattenedOperandNumber(OpIdx); 495b99365a7SMin-Yih Hsu StringRef CustomEncoder = CGI.Operands[OpIdx.first].EncoderMethodName; 496b99365a7SMin-Yih Hsu if (ES.CustomEncoder.size()) 497b99365a7SMin-Yih Hsu CustomEncoder = ES.CustomEncoder; 49831f9519dSMin-Yih Hsu 49931f9519dSMin-Yih Hsu SS.indent(6) << "Scratch.clearAllBits();\n"; 50031f9519dSMin-Yih Hsu SS.indent(6) << "// op: " << OperandName.drop_front(1) << "\n"; 501b99365a7SMin-Yih Hsu if (CustomEncoder.empty()) 502b99365a7SMin-Yih Hsu SS.indent(6) << "getMachineOpValue(MI, MI.getOperand(" 503b99365a7SMin-Yih Hsu << utostr(FlatOpIdx) << ")"; 504b99365a7SMin-Yih Hsu else 505b99365a7SMin-Yih Hsu SS.indent(6) << CustomEncoder << "(MI, /*OpIdx=*/" << utostr(FlatOpIdx); 506b99365a7SMin-Yih Hsu 507b99365a7SMin-Yih Hsu SS << ", /*Pos=*/" << utostr(Offset) << ", Scratch, Fixups, STI);\n"; 508b99365a7SMin-Yih Hsu 50931f9519dSMin-Yih Hsu SS.indent(6) << "Inst.insertBits(" 51031f9519dSMin-Yih Hsu << "Scratch.extractBits(" << utostr(NumBits) << ", " 51131f9519dSMin-Yih Hsu << utostr(LoBit) << ")" 51231f9519dSMin-Yih Hsu << ", " << Offset << ");\n"; 51331f9519dSMin-Yih Hsu } 51431f9519dSMin-Yih Hsu Offset += NumBits; 51531f9519dSMin-Yih Hsu } 51631f9519dSMin-Yih Hsu 51731f9519dSMin-Yih Hsu StringRef PostEmitter = R->getValueAsString("PostEncoderMethod"); 51831f9519dSMin-Yih Hsu if (!PostEmitter.empty()) 51931f9519dSMin-Yih Hsu SS.indent(6) << "Inst = " << PostEmitter << "(MI, Inst, STI);\n"; 52031f9519dSMin-Yih Hsu 52131f9519dSMin-Yih Hsu return Case; 52231f9519dSMin-Yih Hsu } 52331f9519dSMin-Yih Hsu 52431f9519dSMin-Yih Hsu namespace llvm { 52531f9519dSMin-Yih Hsu 52631f9519dSMin-Yih Hsu void emitVarLenCodeEmitter(RecordKeeper &R, raw_ostream &OS) { 52731f9519dSMin-Yih Hsu VarLenCodeEmitterGen(R).run(OS); 52831f9519dSMin-Yih Hsu } 52931f9519dSMin-Yih Hsu 53031f9519dSMin-Yih Hsu } // end namespace llvm 531