181ad6265SDimitry Andric //===- VarLenCodeEmitterGen.cpp - CEG for variable-length insts -----------===//
281ad6265SDimitry Andric //
381ad6265SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
481ad6265SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
581ad6265SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
681ad6265SDimitry Andric //
781ad6265SDimitry Andric //===----------------------------------------------------------------------===//
881ad6265SDimitry Andric //
981ad6265SDimitry Andric // The CodeEmitterGen component for variable-length instructions.
1081ad6265SDimitry Andric //
1181ad6265SDimitry Andric // The basic CodeEmitterGen is almost exclusively designed for fixed-
1281ad6265SDimitry Andric // length instructions. A good analogy for its encoding scheme is how printf
1381ad6265SDimitry Andric // works: The (immutable) formatting string represent the fixed values in the
1481ad6265SDimitry Andric // encoded instruction. Placeholders (i.e. %something), on the other hand,
1581ad6265SDimitry Andric // represent encoding for instruction operands.
1681ad6265SDimitry Andric // ```
1781ad6265SDimitry Andric // printf("1101 %src 1001 %dst", <encoded value for operand `src`>,
1881ad6265SDimitry Andric //                               <encoded value for operand `dst`>);
1981ad6265SDimitry Andric // ```
2081ad6265SDimitry Andric // VarLenCodeEmitterGen in this file provides an alternative encoding scheme
2181ad6265SDimitry Andric // that works more like a C++ stream operator:
2281ad6265SDimitry Andric // ```
2381ad6265SDimitry Andric // OS << 0b1101;
2481ad6265SDimitry Andric // if (Cond)
2581ad6265SDimitry Andric //   OS << OperandEncoding0;
2681ad6265SDimitry Andric // OS << 0b1001 << OperandEncoding1;
2781ad6265SDimitry Andric // ```
2881ad6265SDimitry Andric // You are free to concatenate arbitrary types (and sizes) of encoding
2981ad6265SDimitry Andric // fragments on any bit position, bringing more flexibilities on defining
3081ad6265SDimitry Andric // encoding for variable-length instructions.
3181ad6265SDimitry Andric //
3281ad6265SDimitry Andric // In a more specific way, instruction encoding is represented by a DAG type
3381ad6265SDimitry Andric // `Inst` field. Here is an example:
3481ad6265SDimitry Andric // ```
3581ad6265SDimitry Andric // dag Inst = (descend 0b1101, (operand "$src", 4), 0b1001,
3681ad6265SDimitry Andric //                     (operand "$dst", 4));
3781ad6265SDimitry Andric // ```
3881ad6265SDimitry Andric // It represents the following instruction encoding:
3981ad6265SDimitry Andric // ```
4081ad6265SDimitry Andric // MSB                                                     LSB
4181ad6265SDimitry Andric // 1101<encoding for operand src>1001<encoding for operand dst>
4281ad6265SDimitry Andric // ```
4381ad6265SDimitry Andric // For more details about DAG operators in the above snippet, please
4481ad6265SDimitry Andric // refer to \file include/llvm/Target/Target.td.
4581ad6265SDimitry Andric //
4681ad6265SDimitry Andric // VarLenCodeEmitter will convert the above DAG into the same helper function
4781ad6265SDimitry Andric // generated by CodeEmitter, `MCCodeEmitter::getBinaryCodeForInstr` (except
4881ad6265SDimitry Andric // for few details).
4981ad6265SDimitry Andric //
5081ad6265SDimitry Andric //===----------------------------------------------------------------------===//
5181ad6265SDimitry Andric 
5281ad6265SDimitry Andric #include "VarLenCodeEmitterGen.h"
5381ad6265SDimitry Andric #include "CodeGenHwModes.h"
5481ad6265SDimitry Andric #include "CodeGenInstruction.h"
5581ad6265SDimitry Andric #include "CodeGenTarget.h"
5681ad6265SDimitry Andric #include "InfoByHwMode.h"
5781ad6265SDimitry Andric #include "llvm/ADT/ArrayRef.h"
5881ad6265SDimitry Andric #include "llvm/ADT/DenseMap.h"
5981ad6265SDimitry Andric #include "llvm/Support/raw_ostream.h"
6081ad6265SDimitry Andric #include "llvm/TableGen/Error.h"
6106c3fb27SDimitry Andric #include "llvm/TableGen/Record.h"
6281ad6265SDimitry Andric 
63*5f757f3fSDimitry Andric #include <algorithm>
64*5f757f3fSDimitry Andric 
6581ad6265SDimitry Andric using namespace llvm;
6681ad6265SDimitry Andric 
6781ad6265SDimitry Andric namespace {
6881ad6265SDimitry Andric 
6981ad6265SDimitry Andric class VarLenCodeEmitterGen {
7081ad6265SDimitry Andric   RecordKeeper &Records;
7181ad6265SDimitry Andric 
72*5f757f3fSDimitry Andric   // Representaton of alternative encodings used for HwModes.
73*5f757f3fSDimitry Andric   using AltEncodingTy = int;
74*5f757f3fSDimitry Andric   // Mode identifier when only one encoding is defined.
75*5f757f3fSDimitry Andric   const AltEncodingTy Universal = -1;
76*5f757f3fSDimitry Andric   // The set of alternative instruction encodings with a descriptive
77*5f757f3fSDimitry Andric   // name suffix to improve readability of the generated code.
78*5f757f3fSDimitry Andric   std::map<AltEncodingTy, std::string> Modes;
79*5f757f3fSDimitry Andric 
80*5f757f3fSDimitry Andric   DenseMap<Record *, DenseMap<AltEncodingTy, VarLenInst>> VarLenInsts;
8181ad6265SDimitry Andric 
8281ad6265SDimitry Andric   // Emit based values (i.e. fixed bits in the encoded instructions)
8381ad6265SDimitry Andric   void emitInstructionBaseValues(
8481ad6265SDimitry Andric       raw_ostream &OS,
8581ad6265SDimitry Andric       ArrayRef<const CodeGenInstruction *> NumberedInstructions,
86*5f757f3fSDimitry Andric       CodeGenTarget &Target, AltEncodingTy Mode);
8781ad6265SDimitry Andric 
88*5f757f3fSDimitry Andric   std::string getInstructionCases(Record *R, CodeGenTarget &Target);
89*5f757f3fSDimitry Andric   std::string getInstructionCaseForEncoding(Record *R, AltEncodingTy Mode,
90*5f757f3fSDimitry Andric                                             const VarLenInst &VLI,
91*5f757f3fSDimitry Andric                                             CodeGenTarget &Target, int I);
9281ad6265SDimitry Andric 
9381ad6265SDimitry Andric public:
VarLenCodeEmitterGen(RecordKeeper & R)9481ad6265SDimitry Andric   explicit VarLenCodeEmitterGen(RecordKeeper &R) : Records(R) {}
9581ad6265SDimitry Andric 
9681ad6265SDimitry Andric   void run(raw_ostream &OS);
9781ad6265SDimitry Andric };
9881ad6265SDimitry Andric } // end anonymous namespace
9981ad6265SDimitry Andric 
100bdd1243dSDimitry Andric // Get the name of custom encoder or decoder, if there is any.
101bdd1243dSDimitry Andric // Returns `{encoder name, decoder name}`.
getCustomCoders(ArrayRef<Init * > Args)102bdd1243dSDimitry Andric static std::pair<StringRef, StringRef> getCustomCoders(ArrayRef<Init *> Args) {
103bdd1243dSDimitry Andric   std::pair<StringRef, StringRef> Result;
104bdd1243dSDimitry Andric   for (const auto *Arg : Args) {
105bdd1243dSDimitry Andric     const auto *DI = dyn_cast<DagInit>(Arg);
106bdd1243dSDimitry Andric     if (!DI)
107bdd1243dSDimitry Andric       continue;
108bdd1243dSDimitry Andric     const Init *Op = DI->getOperator();
109bdd1243dSDimitry Andric     if (!isa<DefInit>(Op))
110bdd1243dSDimitry Andric       continue;
111bdd1243dSDimitry Andric     // syntax: `(<encoder | decoder> "function name")`
112bdd1243dSDimitry Andric     StringRef OpName = cast<DefInit>(Op)->getDef()->getName();
113bdd1243dSDimitry Andric     if (OpName != "encoder" && OpName != "decoder")
114bdd1243dSDimitry Andric       continue;
115bdd1243dSDimitry Andric     if (!DI->getNumArgs() || !isa<StringInit>(DI->getArg(0)))
116bdd1243dSDimitry Andric       PrintFatalError("expected '" + OpName +
117bdd1243dSDimitry Andric                       "' directive to be followed by a custom function name.");
118bdd1243dSDimitry Andric     StringRef FuncName = cast<StringInit>(DI->getArg(0))->getValue();
119bdd1243dSDimitry Andric     if (OpName == "encoder")
120bdd1243dSDimitry Andric       Result.first = FuncName;
121bdd1243dSDimitry Andric     else
122bdd1243dSDimitry Andric       Result.second = FuncName;
123bdd1243dSDimitry Andric   }
124bdd1243dSDimitry Andric   return Result;
125bdd1243dSDimitry Andric }
126bdd1243dSDimitry Andric 
VarLenInst(const DagInit * DI,const RecordVal * TheDef)12781ad6265SDimitry Andric VarLenInst::VarLenInst(const DagInit *DI, const RecordVal *TheDef)
128*5f757f3fSDimitry Andric     : TheDef(TheDef), NumBits(0U), HasDynamicSegment(false) {
12981ad6265SDimitry Andric   buildRec(DI);
13081ad6265SDimitry Andric   for (const auto &S : Segments)
13181ad6265SDimitry Andric     NumBits += S.BitWidth;
13281ad6265SDimitry Andric }
13381ad6265SDimitry Andric 
buildRec(const DagInit * DI)13481ad6265SDimitry Andric void VarLenInst::buildRec(const DagInit *DI) {
13581ad6265SDimitry Andric   assert(TheDef && "The def record is nullptr ?");
13681ad6265SDimitry Andric 
13781ad6265SDimitry Andric   std::string Op = DI->getOperator()->getAsString();
13881ad6265SDimitry Andric 
13981ad6265SDimitry Andric   if (Op == "ascend" || Op == "descend") {
14081ad6265SDimitry Andric     bool Reverse = Op == "descend";
14181ad6265SDimitry Andric     int i = Reverse ? DI->getNumArgs() - 1 : 0;
14281ad6265SDimitry Andric     int e = Reverse ? -1 : DI->getNumArgs();
14381ad6265SDimitry Andric     int s = Reverse ? -1 : 1;
14481ad6265SDimitry Andric     for (; i != e; i += s) {
14581ad6265SDimitry Andric       const Init *Arg = DI->getArg(i);
14681ad6265SDimitry Andric       if (const auto *BI = dyn_cast<BitsInit>(Arg)) {
14781ad6265SDimitry Andric         if (!BI->isComplete())
14881ad6265SDimitry Andric           PrintFatalError(TheDef->getLoc(),
14981ad6265SDimitry Andric                           "Expecting complete bits init in `" + Op + "`");
15081ad6265SDimitry Andric         Segments.push_back({BI->getNumBits(), BI});
15181ad6265SDimitry Andric       } else if (const auto *BI = dyn_cast<BitInit>(Arg)) {
15281ad6265SDimitry Andric         if (!BI->isConcrete())
15381ad6265SDimitry Andric           PrintFatalError(TheDef->getLoc(),
15481ad6265SDimitry Andric                           "Expecting concrete bit init in `" + Op + "`");
15581ad6265SDimitry Andric         Segments.push_back({1, BI});
15681ad6265SDimitry Andric       } else if (const auto *SubDI = dyn_cast<DagInit>(Arg)) {
15781ad6265SDimitry Andric         buildRec(SubDI);
15881ad6265SDimitry Andric       } else {
15981ad6265SDimitry Andric         PrintFatalError(TheDef->getLoc(), "Unrecognized type of argument in `" +
16081ad6265SDimitry Andric                                               Op + "`: " + Arg->getAsString());
16181ad6265SDimitry Andric       }
16281ad6265SDimitry Andric     }
16381ad6265SDimitry Andric   } else if (Op == "operand") {
164bdd1243dSDimitry Andric     // (operand <operand name>, <# of bits>,
165bdd1243dSDimitry Andric     //          [(encoder <custom encoder>)][, (decoder <custom decoder>)])
16681ad6265SDimitry Andric     if (DI->getNumArgs() < 2)
16781ad6265SDimitry Andric       PrintFatalError(TheDef->getLoc(),
16881ad6265SDimitry Andric                       "Expecting at least 2 arguments for `operand`");
16981ad6265SDimitry Andric     HasDynamicSegment = true;
17081ad6265SDimitry Andric     const Init *OperandName = DI->getArg(0), *NumBits = DI->getArg(1);
17181ad6265SDimitry Andric     if (!isa<StringInit>(OperandName) || !isa<IntInit>(NumBits))
17281ad6265SDimitry Andric       PrintFatalError(TheDef->getLoc(), "Invalid argument types for `operand`");
17381ad6265SDimitry Andric 
17481ad6265SDimitry Andric     auto NumBitsVal = cast<IntInit>(NumBits)->getValue();
17581ad6265SDimitry Andric     if (NumBitsVal <= 0)
17681ad6265SDimitry Andric       PrintFatalError(TheDef->getLoc(), "Invalid number of bits for `operand`");
17781ad6265SDimitry Andric 
178bdd1243dSDimitry Andric     auto [CustomEncoder, CustomDecoder] =
179bdd1243dSDimitry Andric         getCustomCoders(DI->getArgs().slice(2));
180bdd1243dSDimitry Andric     Segments.push_back({static_cast<unsigned>(NumBitsVal), OperandName,
181bdd1243dSDimitry Andric                         CustomEncoder, CustomDecoder});
18281ad6265SDimitry Andric   } else if (Op == "slice") {
18381ad6265SDimitry Andric     // (slice <operand name>, <high / low bit>, <low / high bit>,
184bdd1243dSDimitry Andric     //        [(encoder <custom encoder>)][, (decoder <custom decoder>)])
18581ad6265SDimitry Andric     if (DI->getNumArgs() < 3)
18681ad6265SDimitry Andric       PrintFatalError(TheDef->getLoc(),
18781ad6265SDimitry Andric                       "Expecting at least 3 arguments for `slice`");
18881ad6265SDimitry Andric     HasDynamicSegment = true;
18981ad6265SDimitry Andric     Init *OperandName = DI->getArg(0), *HiBit = DI->getArg(1),
19081ad6265SDimitry Andric          *LoBit = DI->getArg(2);
19181ad6265SDimitry Andric     if (!isa<StringInit>(OperandName) || !isa<IntInit>(HiBit) ||
19281ad6265SDimitry Andric         !isa<IntInit>(LoBit))
19381ad6265SDimitry Andric       PrintFatalError(TheDef->getLoc(), "Invalid argument types for `slice`");
19481ad6265SDimitry Andric 
19581ad6265SDimitry Andric     auto HiBitVal = cast<IntInit>(HiBit)->getValue(),
19681ad6265SDimitry Andric          LoBitVal = cast<IntInit>(LoBit)->getValue();
19781ad6265SDimitry Andric     if (HiBitVal < 0 || LoBitVal < 0)
19881ad6265SDimitry Andric       PrintFatalError(TheDef->getLoc(), "Invalid bit range for `slice`");
19981ad6265SDimitry Andric     bool NeedSwap = false;
20081ad6265SDimitry Andric     unsigned NumBits = 0U;
20181ad6265SDimitry Andric     if (HiBitVal < LoBitVal) {
20281ad6265SDimitry Andric       NeedSwap = true;
20381ad6265SDimitry Andric       NumBits = static_cast<unsigned>(LoBitVal - HiBitVal + 1);
20481ad6265SDimitry Andric     } else {
20581ad6265SDimitry Andric       NumBits = static_cast<unsigned>(HiBitVal - LoBitVal + 1);
20681ad6265SDimitry Andric     }
20781ad6265SDimitry Andric 
208bdd1243dSDimitry Andric     auto [CustomEncoder, CustomDecoder] =
209bdd1243dSDimitry Andric         getCustomCoders(DI->getArgs().slice(3));
21081ad6265SDimitry Andric 
21181ad6265SDimitry Andric     if (NeedSwap) {
21281ad6265SDimitry Andric       // Normalization: Hi bit should always be the second argument.
21381ad6265SDimitry Andric       Init *const NewArgs[] = {OperandName, LoBit, HiBit};
21481ad6265SDimitry Andric       Segments.push_back({NumBits,
21581ad6265SDimitry Andric                           DagInit::get(DI->getOperator(), nullptr, NewArgs, {}),
216bdd1243dSDimitry Andric                           CustomEncoder, CustomDecoder});
21781ad6265SDimitry Andric     } else {
218bdd1243dSDimitry Andric       Segments.push_back({NumBits, DI, CustomEncoder, CustomDecoder});
21981ad6265SDimitry Andric     }
22081ad6265SDimitry Andric   }
22181ad6265SDimitry Andric }
22281ad6265SDimitry Andric 
run(raw_ostream & OS)22381ad6265SDimitry Andric void VarLenCodeEmitterGen::run(raw_ostream &OS) {
22481ad6265SDimitry Andric   CodeGenTarget Target(Records);
22581ad6265SDimitry Andric   auto Insts = Records.getAllDerivedDefinitions("Instruction");
22681ad6265SDimitry Andric 
22781ad6265SDimitry Andric   auto NumberedInstructions = Target.getInstructionsByEnumValue();
22881ad6265SDimitry Andric 
22981ad6265SDimitry Andric   for (const CodeGenInstruction *CGI : NumberedInstructions) {
23081ad6265SDimitry Andric     Record *R = CGI->TheDef;
23181ad6265SDimitry Andric     // Create the corresponding VarLenInst instance.
23281ad6265SDimitry Andric     if (R->getValueAsString("Namespace") == "TargetOpcode" ||
23381ad6265SDimitry Andric         R->getValueAsBit("isPseudo"))
23481ad6265SDimitry Andric       continue;
23581ad6265SDimitry Andric 
236*5f757f3fSDimitry Andric     // Setup alternative encodings according to HwModes
23781ad6265SDimitry Andric     if (const RecordVal *RV = R->getValue("EncodingInfos")) {
23881ad6265SDimitry Andric       if (auto *DI = dyn_cast_or_null<DefInit>(RV->getValue())) {
239*5f757f3fSDimitry Andric         const CodeGenHwModes &HWM = Target.getHwModes();
24081ad6265SDimitry Andric         EncodingInfoByHwMode EBM(DI->getDef(), HWM);
24181ad6265SDimitry Andric         for (auto &KV : EBM) {
242*5f757f3fSDimitry Andric           AltEncodingTy Mode = KV.first;
243*5f757f3fSDimitry Andric           Modes.insert({Mode, "_" + HWM.getMode(Mode).Name.str()});
24481ad6265SDimitry Andric           Record *EncodingDef = KV.second;
24581ad6265SDimitry Andric           RecordVal *RV = EncodingDef->getValue("Inst");
24681ad6265SDimitry Andric           DagInit *DI = cast<DagInit>(RV->getValue());
247*5f757f3fSDimitry Andric           VarLenInsts[R].insert({Mode, VarLenInst(DI, RV)});
24881ad6265SDimitry Andric         }
24981ad6265SDimitry Andric         continue;
25081ad6265SDimitry Andric       }
25181ad6265SDimitry Andric     }
25281ad6265SDimitry Andric     RecordVal *RV = R->getValue("Inst");
25381ad6265SDimitry Andric     DagInit *DI = cast<DagInit>(RV->getValue());
254*5f757f3fSDimitry Andric     VarLenInsts[R].insert({Universal, VarLenInst(DI, RV)});
25581ad6265SDimitry Andric   }
25681ad6265SDimitry Andric 
257*5f757f3fSDimitry Andric   if (Modes.empty())
258*5f757f3fSDimitry Andric     Modes.insert({Universal, ""}); // Base case, skip suffix.
259*5f757f3fSDimitry Andric 
26081ad6265SDimitry Andric   // Emit function declaration
26181ad6265SDimitry Andric   OS << "void " << Target.getName()
26281ad6265SDimitry Andric      << "MCCodeEmitter::getBinaryCodeForInstr(const MCInst &MI,\n"
26381ad6265SDimitry Andric      << "    SmallVectorImpl<MCFixup> &Fixups,\n"
26481ad6265SDimitry Andric      << "    APInt &Inst,\n"
26581ad6265SDimitry Andric      << "    APInt &Scratch,\n"
26681ad6265SDimitry Andric      << "    const MCSubtargetInfo &STI) const {\n";
26781ad6265SDimitry Andric 
26881ad6265SDimitry Andric   // Emit instruction base values
269*5f757f3fSDimitry Andric   for (const auto &Mode : Modes)
270*5f757f3fSDimitry Andric     emitInstructionBaseValues(OS, NumberedInstructions, Target, Mode.first);
271*5f757f3fSDimitry Andric 
272*5f757f3fSDimitry Andric   if (Modes.size() > 1) {
273*5f757f3fSDimitry Andric     OS << "  unsigned Mode = STI.getHwMode();\n";
27481ad6265SDimitry Andric   }
27581ad6265SDimitry Andric 
276*5f757f3fSDimitry Andric   for (const auto &Mode : Modes) {
27781ad6265SDimitry Andric     // Emit helper function to retrieve base values.
278*5f757f3fSDimitry Andric     OS << "  auto getInstBits" << Mode.second
279*5f757f3fSDimitry Andric        << " = [&](unsigned Opcode) -> APInt {\n"
280*5f757f3fSDimitry Andric        << "    unsigned NumBits = Index" << Mode.second << "[Opcode][0];\n"
28181ad6265SDimitry Andric        << "    if (!NumBits)\n"
28281ad6265SDimitry Andric        << "      return APInt::getZeroWidth();\n"
283*5f757f3fSDimitry Andric        << "    unsigned Idx = Index" << Mode.second << "[Opcode][1];\n"
284*5f757f3fSDimitry Andric        << "    ArrayRef<uint64_t> Data(&InstBits" << Mode.second << "[Idx], "
28581ad6265SDimitry Andric        << "APInt::getNumWords(NumBits));\n"
28681ad6265SDimitry Andric        << "    return APInt(NumBits, Data);\n"
28781ad6265SDimitry Andric        << "  };\n";
288*5f757f3fSDimitry Andric   }
28981ad6265SDimitry Andric 
29081ad6265SDimitry Andric   // Map to accumulate all the cases.
29181ad6265SDimitry Andric   std::map<std::string, std::vector<std::string>> CaseMap;
29281ad6265SDimitry Andric 
29381ad6265SDimitry Andric   // Construct all cases statement for each opcode
29481ad6265SDimitry Andric   for (Record *R : Insts) {
29581ad6265SDimitry Andric     if (R->getValueAsString("Namespace") == "TargetOpcode" ||
29681ad6265SDimitry Andric         R->getValueAsBit("isPseudo"))
29781ad6265SDimitry Andric       continue;
29881ad6265SDimitry Andric     std::string InstName =
29981ad6265SDimitry Andric         (R->getValueAsString("Namespace") + "::" + R->getName()).str();
300*5f757f3fSDimitry Andric     std::string Case = getInstructionCases(R, Target);
30181ad6265SDimitry Andric 
30281ad6265SDimitry Andric     CaseMap[Case].push_back(std::move(InstName));
30381ad6265SDimitry Andric   }
30481ad6265SDimitry Andric 
30581ad6265SDimitry Andric   // Emit initial function code
30681ad6265SDimitry Andric   OS << "  const unsigned opcode = MI.getOpcode();\n"
30781ad6265SDimitry Andric      << "  switch (opcode) {\n";
30881ad6265SDimitry Andric 
30981ad6265SDimitry Andric   // Emit each case statement
31081ad6265SDimitry Andric   for (const auto &C : CaseMap) {
31181ad6265SDimitry Andric     const std::string &Case = C.first;
31281ad6265SDimitry Andric     const auto &InstList = C.second;
31381ad6265SDimitry Andric 
31481ad6265SDimitry Andric     ListSeparator LS("\n");
31581ad6265SDimitry Andric     for (const auto &InstName : InstList)
31681ad6265SDimitry Andric       OS << LS << "    case " << InstName << ":";
31781ad6265SDimitry Andric 
31881ad6265SDimitry Andric     OS << " {\n";
31981ad6265SDimitry Andric     OS << Case;
32081ad6265SDimitry Andric     OS << "      break;\n"
32181ad6265SDimitry Andric        << "    }\n";
32281ad6265SDimitry Andric   }
32381ad6265SDimitry Andric   // Default case: unhandled opcode
32481ad6265SDimitry Andric   OS << "  default:\n"
32581ad6265SDimitry Andric      << "    std::string msg;\n"
32681ad6265SDimitry Andric      << "    raw_string_ostream Msg(msg);\n"
32781ad6265SDimitry Andric      << "    Msg << \"Not supported instr: \" << MI;\n"
32881ad6265SDimitry Andric      << "    report_fatal_error(Msg.str().c_str());\n"
32981ad6265SDimitry Andric      << "  }\n";
33081ad6265SDimitry Andric   OS << "}\n\n";
33181ad6265SDimitry Andric }
33281ad6265SDimitry Andric 
emitInstBits(raw_ostream & IS,raw_ostream & SS,const APInt & Bits,unsigned & Index)33381ad6265SDimitry Andric static void emitInstBits(raw_ostream &IS, raw_ostream &SS, const APInt &Bits,
33481ad6265SDimitry Andric                          unsigned &Index) {
33581ad6265SDimitry Andric   if (!Bits.getNumWords()) {
33681ad6265SDimitry Andric     IS.indent(4) << "{/*NumBits*/0, /*Index*/0},";
33781ad6265SDimitry Andric     return;
33881ad6265SDimitry Andric   }
33981ad6265SDimitry Andric 
34081ad6265SDimitry Andric   IS.indent(4) << "{/*NumBits*/" << Bits.getBitWidth() << ", "
34181ad6265SDimitry Andric                << "/*Index*/" << Index << "},";
34281ad6265SDimitry Andric 
34381ad6265SDimitry Andric   SS.indent(4);
34481ad6265SDimitry Andric   for (unsigned I = 0; I < Bits.getNumWords(); ++I, ++Index)
34581ad6265SDimitry Andric     SS << "UINT64_C(" << utostr(Bits.getRawData()[I]) << "),";
34681ad6265SDimitry Andric }
34781ad6265SDimitry Andric 
emitInstructionBaseValues(raw_ostream & OS,ArrayRef<const CodeGenInstruction * > NumberedInstructions,CodeGenTarget & Target,AltEncodingTy Mode)34881ad6265SDimitry Andric void VarLenCodeEmitterGen::emitInstructionBaseValues(
34981ad6265SDimitry Andric     raw_ostream &OS, ArrayRef<const CodeGenInstruction *> NumberedInstructions,
350*5f757f3fSDimitry Andric     CodeGenTarget &Target, AltEncodingTy Mode) {
35181ad6265SDimitry Andric   std::string IndexArray, StorageArray;
35281ad6265SDimitry Andric   raw_string_ostream IS(IndexArray), SS(StorageArray);
35381ad6265SDimitry Andric 
354*5f757f3fSDimitry Andric   IS << "  static const unsigned Index" << Modes[Mode] << "[][2] = {\n";
355*5f757f3fSDimitry Andric   SS << "  static const uint64_t InstBits" << Modes[Mode] << "[] = {\n";
35681ad6265SDimitry Andric 
35781ad6265SDimitry Andric   unsigned NumFixedValueWords = 0U;
35881ad6265SDimitry Andric   for (const CodeGenInstruction *CGI : NumberedInstructions) {
35981ad6265SDimitry Andric     Record *R = CGI->TheDef;
36081ad6265SDimitry Andric 
36181ad6265SDimitry Andric     if (R->getValueAsString("Namespace") == "TargetOpcode" ||
36281ad6265SDimitry Andric         R->getValueAsBit("isPseudo")) {
36381ad6265SDimitry Andric       IS.indent(4) << "{/*NumBits*/0, /*Index*/0},\n";
36481ad6265SDimitry Andric       continue;
36581ad6265SDimitry Andric     }
36681ad6265SDimitry Andric 
367*5f757f3fSDimitry Andric     const auto InstIt = VarLenInsts.find(R);
368*5f757f3fSDimitry Andric     if (InstIt == VarLenInsts.end())
369*5f757f3fSDimitry Andric       PrintFatalError(R, "VarLenInst not found for this record");
370*5f757f3fSDimitry Andric     auto ModeIt = InstIt->second.find(Mode);
371*5f757f3fSDimitry Andric     if (ModeIt == InstIt->second.end())
372*5f757f3fSDimitry Andric       ModeIt = InstIt->second.find(Universal);
373*5f757f3fSDimitry Andric     if (ModeIt == InstIt->second.end()) {
374*5f757f3fSDimitry Andric       IS.indent(4) << "{/*NumBits*/0, /*Index*/0},\t"
375*5f757f3fSDimitry Andric                    << "// " << R->getName() << " no encoding\n";
376*5f757f3fSDimitry Andric       continue;
37781ad6265SDimitry Andric     }
378*5f757f3fSDimitry Andric     const VarLenInst &VLI = ModeIt->second;
37981ad6265SDimitry Andric     unsigned i = 0U, BitWidth = VLI.size();
38081ad6265SDimitry Andric 
38181ad6265SDimitry Andric     // Start by filling in fixed values.
38281ad6265SDimitry Andric     APInt Value(BitWidth, 0);
38381ad6265SDimitry Andric     auto SI = VLI.begin(), SE = VLI.end();
38481ad6265SDimitry Andric     // Scan through all the segments that have fixed-bits values.
38581ad6265SDimitry Andric     while (i < BitWidth && SI != SE) {
38681ad6265SDimitry Andric       unsigned SegmentNumBits = SI->BitWidth;
38781ad6265SDimitry Andric       if (const auto *BI = dyn_cast<BitsInit>(SI->Value)) {
38881ad6265SDimitry Andric         for (unsigned Idx = 0U; Idx != SegmentNumBits; ++Idx) {
38981ad6265SDimitry Andric           auto *B = cast<BitInit>(BI->getBit(Idx));
39081ad6265SDimitry Andric           Value.setBitVal(i + Idx, B->getValue());
39181ad6265SDimitry Andric         }
39281ad6265SDimitry Andric       }
39381ad6265SDimitry Andric       if (const auto *BI = dyn_cast<BitInit>(SI->Value))
39481ad6265SDimitry Andric         Value.setBitVal(i, BI->getValue());
39581ad6265SDimitry Andric 
39681ad6265SDimitry Andric       i += SegmentNumBits;
39781ad6265SDimitry Andric       ++SI;
39881ad6265SDimitry Andric     }
39981ad6265SDimitry Andric 
40081ad6265SDimitry Andric     emitInstBits(IS, SS, Value, NumFixedValueWords);
40181ad6265SDimitry Andric     IS << '\t' << "// " << R->getName() << "\n";
40281ad6265SDimitry Andric     if (Value.getNumWords())
40381ad6265SDimitry Andric       SS << '\t' << "// " << R->getName() << "\n";
40481ad6265SDimitry Andric   }
40581ad6265SDimitry Andric   IS.indent(4) << "{/*NumBits*/0, /*Index*/0}\n  };\n";
40681ad6265SDimitry Andric   SS.indent(4) << "UINT64_C(0)\n  };\n";
40781ad6265SDimitry Andric 
40881ad6265SDimitry Andric   OS << IS.str() << SS.str();
40981ad6265SDimitry Andric }
41081ad6265SDimitry Andric 
getInstructionCases(Record * R,CodeGenTarget & Target)411*5f757f3fSDimitry Andric std::string VarLenCodeEmitterGen::getInstructionCases(Record *R,
41281ad6265SDimitry Andric                                                       CodeGenTarget &Target) {
413*5f757f3fSDimitry Andric   auto It = VarLenInsts.find(R);
414*5f757f3fSDimitry Andric   if (It == VarLenInsts.end())
415*5f757f3fSDimitry Andric     PrintFatalError(R, "Parsed encoding record not found");
416*5f757f3fSDimitry Andric   const auto &Map = It->second;
417*5f757f3fSDimitry Andric 
418*5f757f3fSDimitry Andric   // Is this instructions encoding universal (same for all modes)?
419*5f757f3fSDimitry Andric   // Allways true if there is only one mode.
420*5f757f3fSDimitry Andric   if (Map.size() == 1 && Map.begin()->first == Universal) {
421*5f757f3fSDimitry Andric     // Universal, just pick the first mode.
422*5f757f3fSDimitry Andric     AltEncodingTy Mode = Modes.begin()->first;
423*5f757f3fSDimitry Andric     const auto &Encoding = Map.begin()->second;
424*5f757f3fSDimitry Andric     return getInstructionCaseForEncoding(R, Mode, Encoding, Target, 6);
425*5f757f3fSDimitry Andric   }
426*5f757f3fSDimitry Andric 
42781ad6265SDimitry Andric   std::string Case;
428*5f757f3fSDimitry Andric   Case += "      switch (Mode) {\n";
429*5f757f3fSDimitry Andric   Case += "      default: llvm_unreachable(\"Unhandled Mode\");\n";
430*5f757f3fSDimitry Andric   for (const auto &Mode : Modes) {
431*5f757f3fSDimitry Andric     Case += "      case " + itostr(Mode.first) + ": {\n";
432*5f757f3fSDimitry Andric     const auto &It = Map.find(Mode.first);
433*5f757f3fSDimitry Andric     if (It == Map.end()) {
434*5f757f3fSDimitry Andric       Case +=
435*5f757f3fSDimitry Andric           "        llvm_unreachable(\"Undefined encoding in this mode\");\n";
436*5f757f3fSDimitry Andric     } else {
437*5f757f3fSDimitry Andric       Case +=
438*5f757f3fSDimitry Andric           getInstructionCaseForEncoding(R, It->first, It->second, Target, 8);
439*5f757f3fSDimitry Andric     }
44081ad6265SDimitry Andric     Case += "        break;\n";
44181ad6265SDimitry Andric     Case += "      }\n";
44281ad6265SDimitry Andric   }
44381ad6265SDimitry Andric   Case += "      }\n";
44481ad6265SDimitry Andric   return Case;
44581ad6265SDimitry Andric }
44681ad6265SDimitry Andric 
getInstructionCaseForEncoding(Record * R,AltEncodingTy Mode,const VarLenInst & VLI,CodeGenTarget & Target,int I)44781ad6265SDimitry Andric std::string VarLenCodeEmitterGen::getInstructionCaseForEncoding(
448*5f757f3fSDimitry Andric     Record *R, AltEncodingTy Mode, const VarLenInst &VLI, CodeGenTarget &Target,
449*5f757f3fSDimitry Andric     int I) {
45081ad6265SDimitry Andric 
45181ad6265SDimitry Andric   CodeGenInstruction &CGI = Target.getInstruction(R);
45281ad6265SDimitry Andric 
45381ad6265SDimitry Andric   std::string Case;
45481ad6265SDimitry Andric   raw_string_ostream SS(Case);
45581ad6265SDimitry Andric   // Populate based value.
456*5f757f3fSDimitry Andric   SS.indent(I) << "Inst = getInstBits" << Modes[Mode] << "(opcode);\n";
45781ad6265SDimitry Andric 
45881ad6265SDimitry Andric   // Process each segment in VLI.
45981ad6265SDimitry Andric   size_t Offset = 0U;
460*5f757f3fSDimitry Andric   unsigned HighScratchAccess = 0U;
46181ad6265SDimitry Andric   for (const auto &ES : VLI) {
46281ad6265SDimitry Andric     unsigned NumBits = ES.BitWidth;
46381ad6265SDimitry Andric     const Init *Val = ES.Value;
46481ad6265SDimitry Andric     // If it's a StringInit or DagInit, it's a reference to an operand
46581ad6265SDimitry Andric     // or part of an operand.
46681ad6265SDimitry Andric     if (isa<StringInit>(Val) || isa<DagInit>(Val)) {
46781ad6265SDimitry Andric       StringRef OperandName;
46881ad6265SDimitry Andric       unsigned LoBit = 0U;
46981ad6265SDimitry Andric       if (const auto *SV = dyn_cast<StringInit>(Val)) {
47081ad6265SDimitry Andric         OperandName = SV->getValue();
47181ad6265SDimitry Andric       } else {
47281ad6265SDimitry Andric         // Normalized: (slice <operand name>, <high bit>, <low bit>)
47381ad6265SDimitry Andric         const auto *DV = cast<DagInit>(Val);
47481ad6265SDimitry Andric         OperandName = cast<StringInit>(DV->getArg(0))->getValue();
47581ad6265SDimitry Andric         LoBit = static_cast<unsigned>(cast<IntInit>(DV->getArg(2))->getValue());
47681ad6265SDimitry Andric       }
47781ad6265SDimitry Andric 
47881ad6265SDimitry Andric       auto OpIdx = CGI.Operands.ParseOperandName(OperandName);
47981ad6265SDimitry Andric       unsigned FlatOpIdx = CGI.Operands.getFlattenedOperandNumber(OpIdx);
480bdd1243dSDimitry Andric       StringRef CustomEncoder =
481bdd1243dSDimitry Andric           CGI.Operands[OpIdx.first].EncoderMethodNames[OpIdx.second];
48281ad6265SDimitry Andric       if (ES.CustomEncoder.size())
48381ad6265SDimitry Andric         CustomEncoder = ES.CustomEncoder;
48481ad6265SDimitry Andric 
485*5f757f3fSDimitry Andric       SS.indent(I) << "Scratch.clearAllBits();\n";
486*5f757f3fSDimitry Andric       SS.indent(I) << "// op: " << OperandName.drop_front(1) << "\n";
48781ad6265SDimitry Andric       if (CustomEncoder.empty())
488*5f757f3fSDimitry Andric         SS.indent(I) << "getMachineOpValue(MI, MI.getOperand("
48981ad6265SDimitry Andric                      << utostr(FlatOpIdx) << ")";
49081ad6265SDimitry Andric       else
491*5f757f3fSDimitry Andric         SS.indent(I) << CustomEncoder << "(MI, /*OpIdx=*/" << utostr(FlatOpIdx);
49281ad6265SDimitry Andric 
49381ad6265SDimitry Andric       SS << ", /*Pos=*/" << utostr(Offset) << ", Scratch, Fixups, STI);\n";
49481ad6265SDimitry Andric 
495*5f757f3fSDimitry Andric       SS.indent(I) << "Inst.insertBits("
49681ad6265SDimitry Andric                    << "Scratch.extractBits(" << utostr(NumBits) << ", "
49781ad6265SDimitry Andric                    << utostr(LoBit) << ")"
49881ad6265SDimitry Andric                    << ", " << Offset << ");\n";
499*5f757f3fSDimitry Andric 
500*5f757f3fSDimitry Andric       HighScratchAccess = std::max(HighScratchAccess, NumBits + LoBit);
50181ad6265SDimitry Andric     }
50281ad6265SDimitry Andric     Offset += NumBits;
50381ad6265SDimitry Andric   }
50481ad6265SDimitry Andric 
50581ad6265SDimitry Andric   StringRef PostEmitter = R->getValueAsString("PostEncoderMethod");
50681ad6265SDimitry Andric   if (!PostEmitter.empty())
507*5f757f3fSDimitry Andric     SS.indent(I) << "Inst = " << PostEmitter << "(MI, Inst, STI);\n";
50881ad6265SDimitry Andric 
509*5f757f3fSDimitry Andric   // Resize the scratch buffer if it's to small.
510*5f757f3fSDimitry Andric   std::string ScratchResizeStr;
511*5f757f3fSDimitry Andric   if (VLI.size() && !VLI.isFixedValueOnly()) {
512*5f757f3fSDimitry Andric     raw_string_ostream RS(ScratchResizeStr);
513*5f757f3fSDimitry Andric     RS.indent(I) << "if (Scratch.getBitWidth() < " << HighScratchAccess
514*5f757f3fSDimitry Andric                  << ") { Scratch = Scratch.zext(" << HighScratchAccess
515*5f757f3fSDimitry Andric                  << "); }\n";
516*5f757f3fSDimitry Andric   }
517*5f757f3fSDimitry Andric 
518*5f757f3fSDimitry Andric   return ScratchResizeStr + Case;
51981ad6265SDimitry Andric }
52081ad6265SDimitry Andric 
52181ad6265SDimitry Andric namespace llvm {
52281ad6265SDimitry Andric 
emitVarLenCodeEmitter(RecordKeeper & R,raw_ostream & OS)52381ad6265SDimitry Andric void emitVarLenCodeEmitter(RecordKeeper &R, raw_ostream &OS) {
52481ad6265SDimitry Andric   VarLenCodeEmitterGen(R).run(OS);
52581ad6265SDimitry Andric }
52681ad6265SDimitry Andric 
52781ad6265SDimitry Andric } // end namespace llvm
528