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