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"
53fbbc41f8Sserge-sans-paille #include "CodeGenHwModes.h"
5431f9519dSMin-Yih Hsu #include "CodeGenInstruction.h"
5531f9519dSMin-Yih Hsu #include "CodeGenTarget.h"
56fbbc41f8Sserge-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 
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 
6931f9519dSMin-Yih Hsu   DenseMap<Record *, VarLenInst> VarLenInsts;
7031f9519dSMin-Yih Hsu 
7131f9519dSMin-Yih Hsu   // Emit based values (i.e. fixed bits in the encoded instructions)
7231f9519dSMin-Yih Hsu   void emitInstructionBaseValues(
7331f9519dSMin-Yih Hsu       raw_ostream &OS,
7431f9519dSMin-Yih Hsu       ArrayRef<const CodeGenInstruction *> NumberedInstructions,
7531f9519dSMin-Yih Hsu       CodeGenTarget &Target, int HwMode = -1);
7631f9519dSMin-Yih Hsu 
7731f9519dSMin-Yih Hsu   std::string getInstructionCase(Record *R, CodeGenTarget &Target);
7831f9519dSMin-Yih Hsu   std::string getInstructionCaseForEncoding(Record *R, Record *EncodingDef,
7931f9519dSMin-Yih Hsu                                             CodeGenTarget &Target);
8031f9519dSMin-Yih Hsu 
8131f9519dSMin-Yih Hsu public:
VarLenCodeEmitterGen(RecordKeeper & R)8231f9519dSMin-Yih Hsu   explicit VarLenCodeEmitterGen(RecordKeeper &R) : Records(R) {}
8331f9519dSMin-Yih Hsu 
8431f9519dSMin-Yih Hsu   void run(raw_ostream &OS);
8531f9519dSMin-Yih Hsu };
8631f9519dSMin-Yih Hsu 
8731f9519dSMin-Yih Hsu } // end anonymous namespace
8831f9519dSMin-Yih Hsu 
VarLenInst(const DagInit * DI,const RecordVal * TheDef)8928e850a8SSheng VarLenInst::VarLenInst(const DagInit *DI, const RecordVal *TheDef)
90314155ebSSheng     : TheDef(TheDef), NumBits(0U) {
9131f9519dSMin-Yih Hsu   buildRec(DI);
9231f9519dSMin-Yih Hsu   for (const auto &S : Segments)
93b99365a7SMin-Yih Hsu     NumBits += S.BitWidth;
9431f9519dSMin-Yih Hsu }
9531f9519dSMin-Yih Hsu 
buildRec(const DagInit * DI)9628e850a8SSheng void VarLenInst::buildRec(const DagInit *DI) {
97314155ebSSheng   assert(TheDef && "The def record is nullptr ?");
98314155ebSSheng 
9931f9519dSMin-Yih Hsu   std::string Op = DI->getOperator()->getAsString();
10031f9519dSMin-Yih Hsu 
10131f9519dSMin-Yih Hsu   if (Op == "ascend" || Op == "descend") {
10231f9519dSMin-Yih Hsu     bool Reverse = Op == "descend";
10331f9519dSMin-Yih Hsu     int i = Reverse ? DI->getNumArgs() - 1 : 0;
10431f9519dSMin-Yih Hsu     int e = Reverse ? -1 : DI->getNumArgs();
10531f9519dSMin-Yih Hsu     int s = Reverse ? -1 : 1;
10631f9519dSMin-Yih Hsu     for (; i != e; i += s) {
10731f9519dSMin-Yih Hsu       const Init *Arg = DI->getArg(i);
10831f9519dSMin-Yih Hsu       if (const auto *BI = dyn_cast<BitsInit>(Arg)) {
10931f9519dSMin-Yih Hsu         if (!BI->isComplete())
110314155ebSSheng           PrintFatalError(TheDef->getLoc(),
111314155ebSSheng                           "Expecting complete bits init in `" + Op + "`");
11231f9519dSMin-Yih Hsu         Segments.push_back({BI->getNumBits(), BI});
11331f9519dSMin-Yih Hsu       } else if (const auto *BI = dyn_cast<BitInit>(Arg)) {
11431f9519dSMin-Yih Hsu         if (!BI->isConcrete())
115314155ebSSheng           PrintFatalError(TheDef->getLoc(),
116314155ebSSheng                           "Expecting concrete bit init in `" + Op + "`");
11731f9519dSMin-Yih Hsu         Segments.push_back({1, BI});
11831f9519dSMin-Yih Hsu       } else if (const auto *SubDI = dyn_cast<DagInit>(Arg)) {
11931f9519dSMin-Yih Hsu         buildRec(SubDI);
12031f9519dSMin-Yih Hsu       } else {
121314155ebSSheng         PrintFatalError(TheDef->getLoc(), "Unrecognized type of argument in `" +
122314155ebSSheng                                               Op + "`: " + Arg->getAsString());
12331f9519dSMin-Yih Hsu       }
12431f9519dSMin-Yih Hsu     }
12531f9519dSMin-Yih Hsu   } else if (Op == "operand") {
126b99365a7SMin-Yih Hsu     // (operand <operand name>, <# of bits>, [(encoder <custom encoder>)])
127b99365a7SMin-Yih Hsu     if (DI->getNumArgs() < 2)
128314155ebSSheng       PrintFatalError(TheDef->getLoc(),
129314155ebSSheng                       "Expecting at least 2 arguments for `operand`");
13031f9519dSMin-Yih Hsu     HasDynamicSegment = true;
13131f9519dSMin-Yih Hsu     const Init *OperandName = DI->getArg(0), *NumBits = DI->getArg(1);
13231f9519dSMin-Yih Hsu     if (!isa<StringInit>(OperandName) || !isa<IntInit>(NumBits))
133314155ebSSheng       PrintFatalError(TheDef->getLoc(), "Invalid argument types for `operand`");
13431f9519dSMin-Yih Hsu 
13531f9519dSMin-Yih Hsu     auto NumBitsVal = cast<IntInit>(NumBits)->getValue();
13631f9519dSMin-Yih Hsu     if (NumBitsVal <= 0)
137314155ebSSheng       PrintFatalError(TheDef->getLoc(), "Invalid number of bits for `operand`");
13831f9519dSMin-Yih Hsu 
139b99365a7SMin-Yih Hsu     StringRef CustomEncoder;
140b99365a7SMin-Yih Hsu     if (DI->getNumArgs() >= 3)
141b99365a7SMin-Yih Hsu       CustomEncoder = getCustomEncoderName(DI->getArg(2));
142b99365a7SMin-Yih Hsu     Segments.push_back(
143b99365a7SMin-Yih Hsu         {static_cast<unsigned>(NumBitsVal), OperandName, CustomEncoder});
14431f9519dSMin-Yih Hsu   } else if (Op == "slice") {
145b99365a7SMin-Yih Hsu     // (slice <operand name>, <high / low bit>, <low / high bit>,
146b99365a7SMin-Yih Hsu     //        [(encoder <custom encoder>)])
147b99365a7SMin-Yih Hsu     if (DI->getNumArgs() < 3)
148314155ebSSheng       PrintFatalError(TheDef->getLoc(),
149314155ebSSheng                       "Expecting at least 3 arguments for `slice`");
15031f9519dSMin-Yih Hsu     HasDynamicSegment = true;
15131f9519dSMin-Yih Hsu     Init *OperandName = DI->getArg(0), *HiBit = DI->getArg(1),
15231f9519dSMin-Yih Hsu          *LoBit = DI->getArg(2);
15331f9519dSMin-Yih Hsu     if (!isa<StringInit>(OperandName) || !isa<IntInit>(HiBit) ||
15431f9519dSMin-Yih Hsu         !isa<IntInit>(LoBit))
155314155ebSSheng       PrintFatalError(TheDef->getLoc(), "Invalid argument types for `slice`");
15631f9519dSMin-Yih Hsu 
15731f9519dSMin-Yih Hsu     auto HiBitVal = cast<IntInit>(HiBit)->getValue(),
15831f9519dSMin-Yih Hsu          LoBitVal = cast<IntInit>(LoBit)->getValue();
15931f9519dSMin-Yih Hsu     if (HiBitVal < 0 || LoBitVal < 0)
160314155ebSSheng       PrintFatalError(TheDef->getLoc(), "Invalid bit range for `slice`");
16131f9519dSMin-Yih Hsu     bool NeedSwap = false;
16231f9519dSMin-Yih Hsu     unsigned NumBits = 0U;
16331f9519dSMin-Yih Hsu     if (HiBitVal < LoBitVal) {
16431f9519dSMin-Yih Hsu       NeedSwap = true;
16531f9519dSMin-Yih Hsu       NumBits = static_cast<unsigned>(LoBitVal - HiBitVal + 1);
16631f9519dSMin-Yih Hsu     } else {
16731f9519dSMin-Yih Hsu       NumBits = static_cast<unsigned>(HiBitVal - LoBitVal + 1);
16831f9519dSMin-Yih Hsu     }
16931f9519dSMin-Yih Hsu 
170b99365a7SMin-Yih Hsu     StringRef CustomEncoder;
171b99365a7SMin-Yih Hsu     if (DI->getNumArgs() >= 4)
172b99365a7SMin-Yih Hsu       CustomEncoder = getCustomEncoderName(DI->getArg(3));
173b99365a7SMin-Yih Hsu 
17431f9519dSMin-Yih Hsu     if (NeedSwap) {
17531f9519dSMin-Yih Hsu       // Normalization: Hi bit should always be the second argument.
17631f9519dSMin-Yih Hsu       Init *const NewArgs[] = {OperandName, LoBit, HiBit};
177b99365a7SMin-Yih Hsu       Segments.push_back({NumBits,
178b99365a7SMin-Yih Hsu                           DagInit::get(DI->getOperator(), nullptr, NewArgs, {}),
179b99365a7SMin-Yih Hsu                           CustomEncoder});
18031f9519dSMin-Yih Hsu     } else {
181b99365a7SMin-Yih Hsu       Segments.push_back({NumBits, DI, CustomEncoder});
18231f9519dSMin-Yih Hsu     }
18331f9519dSMin-Yih Hsu   }
18431f9519dSMin-Yih Hsu }
18531f9519dSMin-Yih Hsu 
run(raw_ostream & OS)18631f9519dSMin-Yih Hsu void VarLenCodeEmitterGen::run(raw_ostream &OS) {
18731f9519dSMin-Yih Hsu   CodeGenTarget Target(Records);
18831f9519dSMin-Yih Hsu   auto Insts = Records.getAllDerivedDefinitions("Instruction");
18931f9519dSMin-Yih Hsu 
19031f9519dSMin-Yih Hsu   auto NumberedInstructions = Target.getInstructionsByEnumValue();
19131f9519dSMin-Yih Hsu   const CodeGenHwModes &HWM = Target.getHwModes();
19231f9519dSMin-Yih Hsu 
19331f9519dSMin-Yih Hsu   // The set of HwModes used by instruction encodings.
19431f9519dSMin-Yih Hsu   std::set<unsigned> HwModes;
19531f9519dSMin-Yih Hsu   for (const CodeGenInstruction *CGI : NumberedInstructions) {
19631f9519dSMin-Yih Hsu     Record *R = CGI->TheDef;
19731f9519dSMin-Yih Hsu 
19831f9519dSMin-Yih Hsu     // Create the corresponding VarLenInst instance.
19931f9519dSMin-Yih Hsu     if (R->getValueAsString("Namespace") == "TargetOpcode" ||
20031f9519dSMin-Yih Hsu         R->getValueAsBit("isPseudo"))
20131f9519dSMin-Yih Hsu       continue;
20231f9519dSMin-Yih Hsu 
20331f9519dSMin-Yih Hsu     if (const RecordVal *RV = R->getValue("EncodingInfos")) {
20431f9519dSMin-Yih Hsu       if (auto *DI = dyn_cast_or_null<DefInit>(RV->getValue())) {
20531f9519dSMin-Yih Hsu         EncodingInfoByHwMode EBM(DI->getDef(), HWM);
20631f9519dSMin-Yih Hsu         for (auto &KV : EBM) {
20731f9519dSMin-Yih Hsu           HwModes.insert(KV.first);
20831f9519dSMin-Yih Hsu           Record *EncodingDef = KV.second;
209314155ebSSheng           RecordVal *RV = EncodingDef->getValue("Inst");
210314155ebSSheng           DagInit *DI = cast<DagInit>(RV->getValue());
211314155ebSSheng           VarLenInsts.insert({EncodingDef, VarLenInst(DI, RV)});
21231f9519dSMin-Yih Hsu         }
21331f9519dSMin-Yih Hsu         continue;
21431f9519dSMin-Yih Hsu       }
21531f9519dSMin-Yih Hsu     }
216314155ebSSheng     RecordVal *RV = R->getValue("Inst");
217314155ebSSheng     DagInit *DI = cast<DagInit>(RV->getValue());
218314155ebSSheng     VarLenInsts.insert({R, VarLenInst(DI, RV)});
21931f9519dSMin-Yih Hsu   }
22031f9519dSMin-Yih Hsu 
22131f9519dSMin-Yih Hsu   // Emit function declaration
22231f9519dSMin-Yih Hsu   OS << "void " << Target.getName()
22331f9519dSMin-Yih Hsu      << "MCCodeEmitter::getBinaryCodeForInstr(const MCInst &MI,\n"
22431f9519dSMin-Yih Hsu      << "    SmallVectorImpl<MCFixup> &Fixups,\n"
22531f9519dSMin-Yih Hsu      << "    APInt &Inst,\n"
22631f9519dSMin-Yih Hsu      << "    APInt &Scratch,\n"
22731f9519dSMin-Yih Hsu      << "    const MCSubtargetInfo &STI) const {\n";
22831f9519dSMin-Yih Hsu 
22931f9519dSMin-Yih Hsu   // Emit instruction base values
23031f9519dSMin-Yih Hsu   if (HwModes.empty()) {
23131f9519dSMin-Yih Hsu     emitInstructionBaseValues(OS, NumberedInstructions, Target);
23231f9519dSMin-Yih Hsu   } else {
23331f9519dSMin-Yih Hsu     for (unsigned HwMode : HwModes)
23431f9519dSMin-Yih Hsu       emitInstructionBaseValues(OS, NumberedInstructions, Target, (int)HwMode);
23531f9519dSMin-Yih Hsu   }
23631f9519dSMin-Yih Hsu 
23731f9519dSMin-Yih Hsu   if (!HwModes.empty()) {
23831f9519dSMin-Yih Hsu     OS << "  const unsigned **Index;\n";
23931f9519dSMin-Yih Hsu     OS << "  const uint64_t *InstBits;\n";
24031f9519dSMin-Yih Hsu     OS << "  unsigned HwMode = STI.getHwMode();\n";
24131f9519dSMin-Yih Hsu     OS << "  switch (HwMode) {\n";
24231f9519dSMin-Yih Hsu     OS << "  default: llvm_unreachable(\"Unknown hardware mode!\"); break;\n";
24331f9519dSMin-Yih Hsu     for (unsigned I : HwModes) {
24431f9519dSMin-Yih Hsu       OS << "  case " << I << ": InstBits = InstBits_" << HWM.getMode(I).Name
24531f9519dSMin-Yih Hsu          << "; Index = Index_" << HWM.getMode(I).Name << "; break;\n";
24631f9519dSMin-Yih Hsu     }
24731f9519dSMin-Yih Hsu     OS << "  };\n";
24831f9519dSMin-Yih Hsu   }
24931f9519dSMin-Yih Hsu 
25031f9519dSMin-Yih Hsu   // Emit helper function to retrieve base values.
25131f9519dSMin-Yih Hsu   OS << "  auto getInstBits = [&](unsigned Opcode) -> APInt {\n"
25231f9519dSMin-Yih Hsu      << "    unsigned NumBits = Index[Opcode][0];\n"
25331f9519dSMin-Yih Hsu      << "    if (!NumBits)\n"
25431f9519dSMin-Yih Hsu      << "      return APInt::getZeroWidth();\n"
25531f9519dSMin-Yih Hsu      << "    unsigned Idx = Index[Opcode][1];\n"
25631f9519dSMin-Yih Hsu      << "    ArrayRef<uint64_t> Data(&InstBits[Idx], "
25731f9519dSMin-Yih Hsu      << "APInt::getNumWords(NumBits));\n"
25831f9519dSMin-Yih Hsu      << "    return APInt(NumBits, Data);\n"
25931f9519dSMin-Yih Hsu      << "  };\n";
26031f9519dSMin-Yih Hsu 
26131f9519dSMin-Yih Hsu   // Map to accumulate all the cases.
26231f9519dSMin-Yih Hsu   std::map<std::string, std::vector<std::string>> CaseMap;
26331f9519dSMin-Yih Hsu 
26431f9519dSMin-Yih Hsu   // Construct all cases statement for each opcode
26531f9519dSMin-Yih Hsu   for (Record *R : Insts) {
26631f9519dSMin-Yih Hsu     if (R->getValueAsString("Namespace") == "TargetOpcode" ||
26731f9519dSMin-Yih Hsu         R->getValueAsBit("isPseudo"))
26831f9519dSMin-Yih Hsu       continue;
26931f9519dSMin-Yih Hsu     std::string InstName =
27031f9519dSMin-Yih Hsu         (R->getValueAsString("Namespace") + "::" + R->getName()).str();
27131f9519dSMin-Yih Hsu     std::string Case = getInstructionCase(R, Target);
27231f9519dSMin-Yih Hsu 
27331f9519dSMin-Yih Hsu     CaseMap[Case].push_back(std::move(InstName));
27431f9519dSMin-Yih Hsu   }
27531f9519dSMin-Yih Hsu 
27631f9519dSMin-Yih Hsu   // Emit initial function code
27731f9519dSMin-Yih Hsu   OS << "  const unsigned opcode = MI.getOpcode();\n"
27831f9519dSMin-Yih Hsu      << "  switch (opcode) {\n";
27931f9519dSMin-Yih Hsu 
28031f9519dSMin-Yih Hsu   // Emit each case statement
28131f9519dSMin-Yih Hsu   for (const auto &C : CaseMap) {
28231f9519dSMin-Yih Hsu     const std::string &Case = C.first;
28331f9519dSMin-Yih Hsu     const auto &InstList = C.second;
28431f9519dSMin-Yih Hsu 
28531f9519dSMin-Yih Hsu     ListSeparator LS("\n");
28631f9519dSMin-Yih Hsu     for (const auto &InstName : InstList)
28731f9519dSMin-Yih Hsu       OS << LS << "    case " << InstName << ":";
28831f9519dSMin-Yih Hsu 
28931f9519dSMin-Yih Hsu     OS << " {\n";
29031f9519dSMin-Yih Hsu     OS << Case;
29131f9519dSMin-Yih Hsu     OS << "      break;\n"
29231f9519dSMin-Yih Hsu        << "    }\n";
29331f9519dSMin-Yih Hsu   }
29431f9519dSMin-Yih Hsu   // Default case: unhandled opcode
29531f9519dSMin-Yih Hsu   OS << "  default:\n"
29631f9519dSMin-Yih Hsu      << "    std::string msg;\n"
29731f9519dSMin-Yih Hsu      << "    raw_string_ostream Msg(msg);\n"
29831f9519dSMin-Yih Hsu      << "    Msg << \"Not supported instr: \" << MI;\n"
29931f9519dSMin-Yih Hsu      << "    report_fatal_error(Msg.str().c_str());\n"
30031f9519dSMin-Yih Hsu      << "  }\n";
30131f9519dSMin-Yih Hsu   OS << "}\n\n";
30231f9519dSMin-Yih Hsu }
30331f9519dSMin-Yih Hsu 
emitInstBits(raw_ostream & IS,raw_ostream & SS,const APInt & Bits,unsigned & Index)30431f9519dSMin-Yih Hsu static void emitInstBits(raw_ostream &IS, raw_ostream &SS, const APInt &Bits,
30531f9519dSMin-Yih Hsu                          unsigned &Index) {
30631f9519dSMin-Yih Hsu   if (!Bits.getNumWords()) {
30731f9519dSMin-Yih Hsu     IS.indent(4) << "{/*NumBits*/0, /*Index*/0},";
30831f9519dSMin-Yih Hsu     return;
30931f9519dSMin-Yih Hsu   }
31031f9519dSMin-Yih Hsu 
31131f9519dSMin-Yih Hsu   IS.indent(4) << "{/*NumBits*/" << Bits.getBitWidth() << ", "
31231f9519dSMin-Yih Hsu                << "/*Index*/" << Index << "},";
31331f9519dSMin-Yih Hsu 
31431f9519dSMin-Yih Hsu   SS.indent(4);
31531f9519dSMin-Yih Hsu   for (unsigned I = 0; I < Bits.getNumWords(); ++I, ++Index)
31631f9519dSMin-Yih Hsu     SS << "UINT64_C(" << utostr(Bits.getRawData()[I]) << "),";
31731f9519dSMin-Yih Hsu }
31831f9519dSMin-Yih Hsu 
emitInstructionBaseValues(raw_ostream & OS,ArrayRef<const CodeGenInstruction * > NumberedInstructions,CodeGenTarget & Target,int HwMode)31931f9519dSMin-Yih Hsu void VarLenCodeEmitterGen::emitInstructionBaseValues(
32031f9519dSMin-Yih Hsu     raw_ostream &OS, ArrayRef<const CodeGenInstruction *> NumberedInstructions,
32131f9519dSMin-Yih Hsu     CodeGenTarget &Target, int HwMode) {
32231f9519dSMin-Yih Hsu   std::string IndexArray, StorageArray;
32331f9519dSMin-Yih Hsu   raw_string_ostream IS(IndexArray), SS(StorageArray);
32431f9519dSMin-Yih Hsu 
32531f9519dSMin-Yih Hsu   const CodeGenHwModes &HWM = Target.getHwModes();
32631f9519dSMin-Yih Hsu   if (HwMode == -1) {
32731f9519dSMin-Yih Hsu     IS << "  static const unsigned Index[][2] = {\n";
32831f9519dSMin-Yih Hsu     SS << "  static const uint64_t InstBits[] = {\n";
32931f9519dSMin-Yih Hsu   } else {
33031f9519dSMin-Yih Hsu     StringRef Name = HWM.getMode(HwMode).Name;
33131f9519dSMin-Yih Hsu     IS << "  static const unsigned Index_" << Name << "[][2] = {\n";
33231f9519dSMin-Yih Hsu     SS << "  static const uint64_t InstBits_" << Name << "[] = {\n";
33331f9519dSMin-Yih Hsu   }
33431f9519dSMin-Yih Hsu 
33531f9519dSMin-Yih Hsu   unsigned NumFixedValueWords = 0U;
33631f9519dSMin-Yih Hsu   for (const CodeGenInstruction *CGI : NumberedInstructions) {
33731f9519dSMin-Yih Hsu     Record *R = CGI->TheDef;
33831f9519dSMin-Yih Hsu 
33931f9519dSMin-Yih Hsu     if (R->getValueAsString("Namespace") == "TargetOpcode" ||
34031f9519dSMin-Yih Hsu         R->getValueAsBit("isPseudo")) {
34131f9519dSMin-Yih Hsu       IS.indent(4) << "{/*NumBits*/0, /*Index*/0},\n";
34231f9519dSMin-Yih Hsu       continue;
34331f9519dSMin-Yih Hsu     }
34431f9519dSMin-Yih Hsu 
34531f9519dSMin-Yih Hsu     Record *EncodingDef = R;
34631f9519dSMin-Yih Hsu     if (const RecordVal *RV = R->getValue("EncodingInfos")) {
34731f9519dSMin-Yih Hsu       if (auto *DI = dyn_cast_or_null<DefInit>(RV->getValue())) {
34831f9519dSMin-Yih Hsu         EncodingInfoByHwMode EBM(DI->getDef(), HWM);
34931f9519dSMin-Yih Hsu         if (EBM.hasMode(HwMode))
35031f9519dSMin-Yih Hsu           EncodingDef = EBM.get(HwMode);
35131f9519dSMin-Yih Hsu       }
35231f9519dSMin-Yih Hsu     }
35331f9519dSMin-Yih Hsu 
35431f9519dSMin-Yih Hsu     auto It = VarLenInsts.find(EncodingDef);
35531f9519dSMin-Yih Hsu     if (It == VarLenInsts.end())
35631f9519dSMin-Yih Hsu       PrintFatalError(EncodingDef, "VarLenInst not found for this record");
35731f9519dSMin-Yih Hsu     const VarLenInst &VLI = It->second;
35831f9519dSMin-Yih Hsu 
35931f9519dSMin-Yih Hsu     unsigned i = 0U, BitWidth = VLI.size();
36031f9519dSMin-Yih Hsu 
36131f9519dSMin-Yih Hsu     // Start by filling in fixed values.
36231f9519dSMin-Yih Hsu     APInt Value(BitWidth, 0);
36331f9519dSMin-Yih Hsu     auto SI = VLI.begin(), SE = VLI.end();
36431f9519dSMin-Yih Hsu     // Scan through all the segments that have fixed-bits values.
36531f9519dSMin-Yih Hsu     while (i < BitWidth && SI != SE) {
366b99365a7SMin-Yih Hsu       unsigned SegmentNumBits = SI->BitWidth;
367b99365a7SMin-Yih Hsu       if (const auto *BI = dyn_cast<BitsInit>(SI->Value)) {
36831f9519dSMin-Yih Hsu         for (unsigned Idx = 0U; Idx != SegmentNumBits; ++Idx) {
36931f9519dSMin-Yih Hsu           auto *B = cast<BitInit>(BI->getBit(Idx));
37031f9519dSMin-Yih Hsu           Value.setBitVal(i + Idx, B->getValue());
37131f9519dSMin-Yih Hsu         }
37231f9519dSMin-Yih Hsu       }
373b99365a7SMin-Yih Hsu       if (const auto *BI = dyn_cast<BitInit>(SI->Value))
37431f9519dSMin-Yih Hsu         Value.setBitVal(i, BI->getValue());
37531f9519dSMin-Yih Hsu 
37631f9519dSMin-Yih Hsu       i += SegmentNumBits;
37731f9519dSMin-Yih Hsu       ++SI;
37831f9519dSMin-Yih Hsu     }
37931f9519dSMin-Yih Hsu 
38031f9519dSMin-Yih Hsu     emitInstBits(IS, SS, Value, NumFixedValueWords);
38131f9519dSMin-Yih Hsu     IS << '\t' << "// " << R->getName() << "\n";
38231f9519dSMin-Yih Hsu     if (Value.getNumWords())
38331f9519dSMin-Yih Hsu       SS << '\t' << "// " << R->getName() << "\n";
38431f9519dSMin-Yih Hsu   }
38531f9519dSMin-Yih Hsu   IS.indent(4) << "{/*NumBits*/0, /*Index*/0}\n  };\n";
38631f9519dSMin-Yih Hsu   SS.indent(4) << "UINT64_C(0)\n  };\n";
38731f9519dSMin-Yih Hsu 
38831f9519dSMin-Yih Hsu   OS << IS.str() << SS.str();
38931f9519dSMin-Yih Hsu }
39031f9519dSMin-Yih Hsu 
getInstructionCase(Record * R,CodeGenTarget & Target)39131f9519dSMin-Yih Hsu std::string VarLenCodeEmitterGen::getInstructionCase(Record *R,
39231f9519dSMin-Yih Hsu                                                      CodeGenTarget &Target) {
39331f9519dSMin-Yih Hsu   std::string Case;
39431f9519dSMin-Yih Hsu   if (const RecordVal *RV = R->getValue("EncodingInfos")) {
39531f9519dSMin-Yih Hsu     if (auto *DI = dyn_cast_or_null<DefInit>(RV->getValue())) {
39631f9519dSMin-Yih Hsu       const CodeGenHwModes &HWM = Target.getHwModes();
39731f9519dSMin-Yih Hsu       EncodingInfoByHwMode EBM(DI->getDef(), HWM);
39831f9519dSMin-Yih Hsu       Case += "      switch (HwMode) {\n";
39931f9519dSMin-Yih Hsu       Case += "      default: llvm_unreachable(\"Unhandled HwMode\");\n";
40031f9519dSMin-Yih Hsu       for (auto &KV : EBM) {
40131f9519dSMin-Yih Hsu         Case += "      case " + itostr(KV.first) + ": {\n";
40231f9519dSMin-Yih Hsu         Case += getInstructionCaseForEncoding(R, KV.second, Target);
40331f9519dSMin-Yih Hsu         Case += "      break;\n";
40431f9519dSMin-Yih Hsu         Case += "      }\n";
40531f9519dSMin-Yih Hsu       }
40631f9519dSMin-Yih Hsu       Case += "      }\n";
40731f9519dSMin-Yih Hsu       return Case;
40831f9519dSMin-Yih Hsu     }
40931f9519dSMin-Yih Hsu   }
41031f9519dSMin-Yih Hsu   return getInstructionCaseForEncoding(R, R, Target);
41131f9519dSMin-Yih Hsu }
41231f9519dSMin-Yih Hsu 
getInstructionCaseForEncoding(Record * R,Record * EncodingDef,CodeGenTarget & Target)41331f9519dSMin-Yih Hsu std::string VarLenCodeEmitterGen::getInstructionCaseForEncoding(
41431f9519dSMin-Yih Hsu     Record *R, Record *EncodingDef, CodeGenTarget &Target) {
41531f9519dSMin-Yih Hsu   auto It = VarLenInsts.find(EncodingDef);
41631f9519dSMin-Yih Hsu   if (It == VarLenInsts.end())
41731f9519dSMin-Yih Hsu     PrintFatalError(EncodingDef, "Parsed encoding record not found");
41831f9519dSMin-Yih Hsu   const VarLenInst &VLI = It->second;
41931f9519dSMin-Yih Hsu   size_t BitWidth = VLI.size();
42031f9519dSMin-Yih Hsu 
42131f9519dSMin-Yih Hsu   CodeGenInstruction &CGI = Target.getInstruction(R);
42231f9519dSMin-Yih Hsu 
42331f9519dSMin-Yih Hsu   std::string Case;
42431f9519dSMin-Yih Hsu   raw_string_ostream SS(Case);
42531f9519dSMin-Yih Hsu   // Resize the scratch buffer.
42631f9519dSMin-Yih Hsu   if (BitWidth && !VLI.isFixedValueOnly())
427*6bec3e93SJay Foad     SS.indent(6) << "Scratch = Scratch.zext(" << BitWidth << ");\n";
42831f9519dSMin-Yih Hsu   // Populate based value.
42931f9519dSMin-Yih Hsu   SS.indent(6) << "Inst = getInstBits(opcode);\n";
43031f9519dSMin-Yih Hsu 
43131f9519dSMin-Yih Hsu   // Process each segment in VLI.
43231f9519dSMin-Yih Hsu   size_t Offset = 0U;
433b99365a7SMin-Yih Hsu   for (const auto &ES : VLI) {
434b99365a7SMin-Yih Hsu     unsigned NumBits = ES.BitWidth;
435b99365a7SMin-Yih Hsu     const Init *Val = ES.Value;
43631f9519dSMin-Yih Hsu     // If it's a StringInit or DagInit, it's a reference to an operand
43731f9519dSMin-Yih Hsu     // or part of an operand.
43831f9519dSMin-Yih Hsu     if (isa<StringInit>(Val) || isa<DagInit>(Val)) {
43931f9519dSMin-Yih Hsu       StringRef OperandName;
44031f9519dSMin-Yih Hsu       unsigned LoBit = 0U;
44131f9519dSMin-Yih Hsu       if (const auto *SV = dyn_cast<StringInit>(Val)) {
44231f9519dSMin-Yih Hsu         OperandName = SV->getValue();
44331f9519dSMin-Yih Hsu       } else {
44431f9519dSMin-Yih Hsu         // Normalized: (slice <operand name>, <high bit>, <low bit>)
44531f9519dSMin-Yih Hsu         const auto *DV = cast<DagInit>(Val);
44631f9519dSMin-Yih Hsu         OperandName = cast<StringInit>(DV->getArg(0))->getValue();
44731f9519dSMin-Yih Hsu         LoBit = static_cast<unsigned>(cast<IntInit>(DV->getArg(2))->getValue());
44831f9519dSMin-Yih Hsu       }
44931f9519dSMin-Yih Hsu 
45031f9519dSMin-Yih Hsu       auto OpIdx = CGI.Operands.ParseOperandName(OperandName);
45131f9519dSMin-Yih Hsu       unsigned FlatOpIdx = CGI.Operands.getFlattenedOperandNumber(OpIdx);
452b99365a7SMin-Yih Hsu       StringRef CustomEncoder = CGI.Operands[OpIdx.first].EncoderMethodName;
453b99365a7SMin-Yih Hsu       if (ES.CustomEncoder.size())
454b99365a7SMin-Yih Hsu         CustomEncoder = ES.CustomEncoder;
45531f9519dSMin-Yih Hsu 
45631f9519dSMin-Yih Hsu       SS.indent(6) << "Scratch.clearAllBits();\n";
45731f9519dSMin-Yih Hsu       SS.indent(6) << "// op: " << OperandName.drop_front(1) << "\n";
458b99365a7SMin-Yih Hsu       if (CustomEncoder.empty())
459b99365a7SMin-Yih Hsu         SS.indent(6) << "getMachineOpValue(MI, MI.getOperand("
460b99365a7SMin-Yih Hsu                      << utostr(FlatOpIdx) << ")";
461b99365a7SMin-Yih Hsu       else
462b99365a7SMin-Yih Hsu         SS.indent(6) << CustomEncoder << "(MI, /*OpIdx=*/" << utostr(FlatOpIdx);
463b99365a7SMin-Yih Hsu 
464b99365a7SMin-Yih Hsu       SS << ", /*Pos=*/" << utostr(Offset) << ", Scratch, Fixups, STI);\n";
465b99365a7SMin-Yih Hsu 
46631f9519dSMin-Yih Hsu       SS.indent(6) << "Inst.insertBits("
46731f9519dSMin-Yih Hsu                    << "Scratch.extractBits(" << utostr(NumBits) << ", "
46831f9519dSMin-Yih Hsu                    << utostr(LoBit) << ")"
46931f9519dSMin-Yih Hsu                    << ", " << Offset << ");\n";
47031f9519dSMin-Yih Hsu     }
47131f9519dSMin-Yih Hsu     Offset += NumBits;
47231f9519dSMin-Yih Hsu   }
47331f9519dSMin-Yih Hsu 
47431f9519dSMin-Yih Hsu   StringRef PostEmitter = R->getValueAsString("PostEncoderMethod");
47531f9519dSMin-Yih Hsu   if (!PostEmitter.empty())
47631f9519dSMin-Yih Hsu     SS.indent(6) << "Inst = " << PostEmitter << "(MI, Inst, STI);\n";
47731f9519dSMin-Yih Hsu 
47831f9519dSMin-Yih Hsu   return Case;
47931f9519dSMin-Yih Hsu }
48031f9519dSMin-Yih Hsu 
48131f9519dSMin-Yih Hsu namespace llvm {
48231f9519dSMin-Yih Hsu 
emitVarLenCodeEmitter(RecordKeeper & R,raw_ostream & OS)48331f9519dSMin-Yih Hsu void emitVarLenCodeEmitter(RecordKeeper &R, raw_ostream &OS) {
48431f9519dSMin-Yih Hsu   VarLenCodeEmitterGen(R).run(OS);
48531f9519dSMin-Yih Hsu }
48631f9519dSMin-Yih Hsu 
48731f9519dSMin-Yih Hsu } // end namespace llvm
488