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