xref: /freebsd-src/contrib/llvm-project/llvm/utils/TableGen/Common/VarLenCodeEmitterGen.cpp (revision 0fca6ea1d4eea4c934cfff25ac9ee8ad6fe95583)
1*0fca6ea1SDimitry Andric //===- VarLenCodeEmitterGen.cpp - CEG for variable-length insts -----------===//
2*0fca6ea1SDimitry Andric //
3*0fca6ea1SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4*0fca6ea1SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
5*0fca6ea1SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6*0fca6ea1SDimitry Andric //
7*0fca6ea1SDimitry Andric //===----------------------------------------------------------------------===//
8*0fca6ea1SDimitry Andric //
9*0fca6ea1SDimitry Andric // The CodeEmitterGen component for variable-length instructions.
10*0fca6ea1SDimitry Andric //
11*0fca6ea1SDimitry Andric // The basic CodeEmitterGen is almost exclusively designed for fixed-
12*0fca6ea1SDimitry Andric // length instructions. A good analogy for its encoding scheme is how printf
13*0fca6ea1SDimitry Andric // works: The (immutable) formatting string represent the fixed values in the
14*0fca6ea1SDimitry Andric // encoded instruction. Placeholders (i.e. %something), on the other hand,
15*0fca6ea1SDimitry Andric // represent encoding for instruction operands.
16*0fca6ea1SDimitry Andric // ```
17*0fca6ea1SDimitry Andric // printf("1101 %src 1001 %dst", <encoded value for operand `src`>,
18*0fca6ea1SDimitry Andric //                               <encoded value for operand `dst`>);
19*0fca6ea1SDimitry Andric // ```
20*0fca6ea1SDimitry Andric // VarLenCodeEmitterGen in this file provides an alternative encoding scheme
21*0fca6ea1SDimitry Andric // that works more like a C++ stream operator:
22*0fca6ea1SDimitry Andric // ```
23*0fca6ea1SDimitry Andric // OS << 0b1101;
24*0fca6ea1SDimitry Andric // if (Cond)
25*0fca6ea1SDimitry Andric //   OS << OperandEncoding0;
26*0fca6ea1SDimitry Andric // OS << 0b1001 << OperandEncoding1;
27*0fca6ea1SDimitry Andric // ```
28*0fca6ea1SDimitry Andric // You are free to concatenate arbitrary types (and sizes) of encoding
29*0fca6ea1SDimitry Andric // fragments on any bit position, bringing more flexibilities on defining
30*0fca6ea1SDimitry Andric // encoding for variable-length instructions.
31*0fca6ea1SDimitry Andric //
32*0fca6ea1SDimitry Andric // In a more specific way, instruction encoding is represented by a DAG type
33*0fca6ea1SDimitry Andric // `Inst` field. Here is an example:
34*0fca6ea1SDimitry Andric // ```
35*0fca6ea1SDimitry Andric // dag Inst = (descend 0b1101, (operand "$src", 4), 0b1001,
36*0fca6ea1SDimitry Andric //                     (operand "$dst", 4));
37*0fca6ea1SDimitry Andric // ```
38*0fca6ea1SDimitry Andric // It represents the following instruction encoding:
39*0fca6ea1SDimitry Andric // ```
40*0fca6ea1SDimitry Andric // MSB                                                     LSB
41*0fca6ea1SDimitry Andric // 1101<encoding for operand src>1001<encoding for operand dst>
42*0fca6ea1SDimitry Andric // ```
43*0fca6ea1SDimitry Andric // For more details about DAG operators in the above snippet, please
44*0fca6ea1SDimitry Andric // refer to \file include/llvm/Target/Target.td.
45*0fca6ea1SDimitry Andric //
46*0fca6ea1SDimitry Andric // VarLenCodeEmitter will convert the above DAG into the same helper function
47*0fca6ea1SDimitry Andric // generated by CodeEmitter, `MCCodeEmitter::getBinaryCodeForInstr` (except
48*0fca6ea1SDimitry Andric // for few details).
49*0fca6ea1SDimitry Andric //
50*0fca6ea1SDimitry Andric //===----------------------------------------------------------------------===//
51*0fca6ea1SDimitry Andric 
52*0fca6ea1SDimitry Andric #include "VarLenCodeEmitterGen.h"
53*0fca6ea1SDimitry Andric #include "CodeGenHwModes.h"
54*0fca6ea1SDimitry Andric #include "CodeGenInstruction.h"
55*0fca6ea1SDimitry Andric #include "CodeGenTarget.h"
56*0fca6ea1SDimitry Andric #include "InfoByHwMode.h"
57*0fca6ea1SDimitry Andric #include "llvm/ADT/ArrayRef.h"
58*0fca6ea1SDimitry Andric #include "llvm/ADT/DenseMap.h"
59*0fca6ea1SDimitry Andric #include "llvm/Support/raw_ostream.h"
60*0fca6ea1SDimitry Andric #include "llvm/TableGen/Error.h"
61*0fca6ea1SDimitry Andric #include "llvm/TableGen/Record.h"
62*0fca6ea1SDimitry Andric 
63*0fca6ea1SDimitry Andric #include <algorithm>
64*0fca6ea1SDimitry Andric 
65*0fca6ea1SDimitry Andric using namespace llvm;
66*0fca6ea1SDimitry Andric 
67*0fca6ea1SDimitry Andric namespace {
68*0fca6ea1SDimitry Andric 
69*0fca6ea1SDimitry Andric class VarLenCodeEmitterGen {
70*0fca6ea1SDimitry Andric   RecordKeeper &Records;
71*0fca6ea1SDimitry Andric 
72*0fca6ea1SDimitry Andric   // Representaton of alternative encodings used for HwModes.
73*0fca6ea1SDimitry Andric   using AltEncodingTy = int;
74*0fca6ea1SDimitry Andric   // Mode identifier when only one encoding is defined.
75*0fca6ea1SDimitry Andric   const AltEncodingTy Universal = -1;
76*0fca6ea1SDimitry Andric   // The set of alternative instruction encodings with a descriptive
77*0fca6ea1SDimitry Andric   // name suffix to improve readability of the generated code.
78*0fca6ea1SDimitry Andric   std::map<AltEncodingTy, std::string> Modes;
79*0fca6ea1SDimitry Andric 
80*0fca6ea1SDimitry Andric   DenseMap<Record *, DenseMap<AltEncodingTy, VarLenInst>> VarLenInsts;
81*0fca6ea1SDimitry Andric 
82*0fca6ea1SDimitry Andric   // Emit based values (i.e. fixed bits in the encoded instructions)
83*0fca6ea1SDimitry Andric   void emitInstructionBaseValues(
84*0fca6ea1SDimitry Andric       raw_ostream &OS,
85*0fca6ea1SDimitry Andric       ArrayRef<const CodeGenInstruction *> NumberedInstructions,
86*0fca6ea1SDimitry Andric       CodeGenTarget &Target, AltEncodingTy Mode);
87*0fca6ea1SDimitry Andric 
88*0fca6ea1SDimitry Andric   std::string getInstructionCases(Record *R, CodeGenTarget &Target);
89*0fca6ea1SDimitry Andric   std::string getInstructionCaseForEncoding(Record *R, AltEncodingTy Mode,
90*0fca6ea1SDimitry Andric                                             const VarLenInst &VLI,
91*0fca6ea1SDimitry Andric                                             CodeGenTarget &Target, int I);
92*0fca6ea1SDimitry Andric 
93*0fca6ea1SDimitry Andric public:
94*0fca6ea1SDimitry Andric   explicit VarLenCodeEmitterGen(RecordKeeper &R) : Records(R) {}
95*0fca6ea1SDimitry Andric 
96*0fca6ea1SDimitry Andric   void run(raw_ostream &OS);
97*0fca6ea1SDimitry Andric };
98*0fca6ea1SDimitry Andric } // end anonymous namespace
99*0fca6ea1SDimitry Andric 
100*0fca6ea1SDimitry Andric // Get the name of custom encoder or decoder, if there is any.
101*0fca6ea1SDimitry Andric // Returns `{encoder name, decoder name}`.
102*0fca6ea1SDimitry Andric static std::pair<StringRef, StringRef> getCustomCoders(ArrayRef<Init *> Args) {
103*0fca6ea1SDimitry Andric   std::pair<StringRef, StringRef> Result;
104*0fca6ea1SDimitry Andric   for (const auto *Arg : Args) {
105*0fca6ea1SDimitry Andric     const auto *DI = dyn_cast<DagInit>(Arg);
106*0fca6ea1SDimitry Andric     if (!DI)
107*0fca6ea1SDimitry Andric       continue;
108*0fca6ea1SDimitry Andric     const Init *Op = DI->getOperator();
109*0fca6ea1SDimitry Andric     if (!isa<DefInit>(Op))
110*0fca6ea1SDimitry Andric       continue;
111*0fca6ea1SDimitry Andric     // syntax: `(<encoder | decoder> "function name")`
112*0fca6ea1SDimitry Andric     StringRef OpName = cast<DefInit>(Op)->getDef()->getName();
113*0fca6ea1SDimitry Andric     if (OpName != "encoder" && OpName != "decoder")
114*0fca6ea1SDimitry Andric       continue;
115*0fca6ea1SDimitry Andric     if (!DI->getNumArgs() || !isa<StringInit>(DI->getArg(0)))
116*0fca6ea1SDimitry Andric       PrintFatalError("expected '" + OpName +
117*0fca6ea1SDimitry Andric                       "' directive to be followed by a custom function name.");
118*0fca6ea1SDimitry Andric     StringRef FuncName = cast<StringInit>(DI->getArg(0))->getValue();
119*0fca6ea1SDimitry Andric     if (OpName == "encoder")
120*0fca6ea1SDimitry Andric       Result.first = FuncName;
121*0fca6ea1SDimitry Andric     else
122*0fca6ea1SDimitry Andric       Result.second = FuncName;
123*0fca6ea1SDimitry Andric   }
124*0fca6ea1SDimitry Andric   return Result;
125*0fca6ea1SDimitry Andric }
126*0fca6ea1SDimitry Andric 
127*0fca6ea1SDimitry Andric VarLenInst::VarLenInst(const DagInit *DI, const RecordVal *TheDef)
128*0fca6ea1SDimitry Andric     : TheDef(TheDef), NumBits(0U), HasDynamicSegment(false) {
129*0fca6ea1SDimitry Andric   buildRec(DI);
130*0fca6ea1SDimitry Andric   for (const auto &S : Segments)
131*0fca6ea1SDimitry Andric     NumBits += S.BitWidth;
132*0fca6ea1SDimitry Andric }
133*0fca6ea1SDimitry Andric 
134*0fca6ea1SDimitry Andric void VarLenInst::buildRec(const DagInit *DI) {
135*0fca6ea1SDimitry Andric   assert(TheDef && "The def record is nullptr ?");
136*0fca6ea1SDimitry Andric 
137*0fca6ea1SDimitry Andric   std::string Op = DI->getOperator()->getAsString();
138*0fca6ea1SDimitry Andric 
139*0fca6ea1SDimitry Andric   if (Op == "ascend" || Op == "descend") {
140*0fca6ea1SDimitry Andric     bool Reverse = Op == "descend";
141*0fca6ea1SDimitry Andric     int i = Reverse ? DI->getNumArgs() - 1 : 0;
142*0fca6ea1SDimitry Andric     int e = Reverse ? -1 : DI->getNumArgs();
143*0fca6ea1SDimitry Andric     int s = Reverse ? -1 : 1;
144*0fca6ea1SDimitry Andric     for (; i != e; i += s) {
145*0fca6ea1SDimitry Andric       const Init *Arg = DI->getArg(i);
146*0fca6ea1SDimitry Andric       if (const auto *BI = dyn_cast<BitsInit>(Arg)) {
147*0fca6ea1SDimitry Andric         if (!BI->isComplete())
148*0fca6ea1SDimitry Andric           PrintFatalError(TheDef->getLoc(),
149*0fca6ea1SDimitry Andric                           "Expecting complete bits init in `" + Op + "`");
150*0fca6ea1SDimitry Andric         Segments.push_back({BI->getNumBits(), BI});
151*0fca6ea1SDimitry Andric       } else if (const auto *BI = dyn_cast<BitInit>(Arg)) {
152*0fca6ea1SDimitry Andric         if (!BI->isConcrete())
153*0fca6ea1SDimitry Andric           PrintFatalError(TheDef->getLoc(),
154*0fca6ea1SDimitry Andric                           "Expecting concrete bit init in `" + Op + "`");
155*0fca6ea1SDimitry Andric         Segments.push_back({1, BI});
156*0fca6ea1SDimitry Andric       } else if (const auto *SubDI = dyn_cast<DagInit>(Arg)) {
157*0fca6ea1SDimitry Andric         buildRec(SubDI);
158*0fca6ea1SDimitry Andric       } else {
159*0fca6ea1SDimitry Andric         PrintFatalError(TheDef->getLoc(), "Unrecognized type of argument in `" +
160*0fca6ea1SDimitry Andric                                               Op + "`: " + Arg->getAsString());
161*0fca6ea1SDimitry Andric       }
162*0fca6ea1SDimitry Andric     }
163*0fca6ea1SDimitry Andric   } else if (Op == "operand") {
164*0fca6ea1SDimitry Andric     // (operand <operand name>, <# of bits>,
165*0fca6ea1SDimitry Andric     //          [(encoder <custom encoder>)][, (decoder <custom decoder>)])
166*0fca6ea1SDimitry Andric     if (DI->getNumArgs() < 2)
167*0fca6ea1SDimitry Andric       PrintFatalError(TheDef->getLoc(),
168*0fca6ea1SDimitry Andric                       "Expecting at least 2 arguments for `operand`");
169*0fca6ea1SDimitry Andric     HasDynamicSegment = true;
170*0fca6ea1SDimitry Andric     const Init *OperandName = DI->getArg(0), *NumBits = DI->getArg(1);
171*0fca6ea1SDimitry Andric     if (!isa<StringInit>(OperandName) || !isa<IntInit>(NumBits))
172*0fca6ea1SDimitry Andric       PrintFatalError(TheDef->getLoc(), "Invalid argument types for `operand`");
173*0fca6ea1SDimitry Andric 
174*0fca6ea1SDimitry Andric     auto NumBitsVal = cast<IntInit>(NumBits)->getValue();
175*0fca6ea1SDimitry Andric     if (NumBitsVal <= 0)
176*0fca6ea1SDimitry Andric       PrintFatalError(TheDef->getLoc(), "Invalid number of bits for `operand`");
177*0fca6ea1SDimitry Andric 
178*0fca6ea1SDimitry Andric     auto [CustomEncoder, CustomDecoder] =
179*0fca6ea1SDimitry Andric         getCustomCoders(DI->getArgs().slice(2));
180*0fca6ea1SDimitry Andric     Segments.push_back({static_cast<unsigned>(NumBitsVal), OperandName,
181*0fca6ea1SDimitry Andric                         CustomEncoder, CustomDecoder});
182*0fca6ea1SDimitry Andric   } else if (Op == "slice") {
183*0fca6ea1SDimitry Andric     // (slice <operand name>, <high / low bit>, <low / high bit>,
184*0fca6ea1SDimitry Andric     //        [(encoder <custom encoder>)][, (decoder <custom decoder>)])
185*0fca6ea1SDimitry Andric     if (DI->getNumArgs() < 3)
186*0fca6ea1SDimitry Andric       PrintFatalError(TheDef->getLoc(),
187*0fca6ea1SDimitry Andric                       "Expecting at least 3 arguments for `slice`");
188*0fca6ea1SDimitry Andric     HasDynamicSegment = true;
189*0fca6ea1SDimitry Andric     Init *OperandName = DI->getArg(0), *HiBit = DI->getArg(1),
190*0fca6ea1SDimitry Andric          *LoBit = DI->getArg(2);
191*0fca6ea1SDimitry Andric     if (!isa<StringInit>(OperandName) || !isa<IntInit>(HiBit) ||
192*0fca6ea1SDimitry Andric         !isa<IntInit>(LoBit))
193*0fca6ea1SDimitry Andric       PrintFatalError(TheDef->getLoc(), "Invalid argument types for `slice`");
194*0fca6ea1SDimitry Andric 
195*0fca6ea1SDimitry Andric     auto HiBitVal = cast<IntInit>(HiBit)->getValue(),
196*0fca6ea1SDimitry Andric          LoBitVal = cast<IntInit>(LoBit)->getValue();
197*0fca6ea1SDimitry Andric     if (HiBitVal < 0 || LoBitVal < 0)
198*0fca6ea1SDimitry Andric       PrintFatalError(TheDef->getLoc(), "Invalid bit range for `slice`");
199*0fca6ea1SDimitry Andric     bool NeedSwap = false;
200*0fca6ea1SDimitry Andric     unsigned NumBits = 0U;
201*0fca6ea1SDimitry Andric     if (HiBitVal < LoBitVal) {
202*0fca6ea1SDimitry Andric       NeedSwap = true;
203*0fca6ea1SDimitry Andric       NumBits = static_cast<unsigned>(LoBitVal - HiBitVal + 1);
204*0fca6ea1SDimitry Andric     } else {
205*0fca6ea1SDimitry Andric       NumBits = static_cast<unsigned>(HiBitVal - LoBitVal + 1);
206*0fca6ea1SDimitry Andric     }
207*0fca6ea1SDimitry Andric 
208*0fca6ea1SDimitry Andric     auto [CustomEncoder, CustomDecoder] =
209*0fca6ea1SDimitry Andric         getCustomCoders(DI->getArgs().slice(3));
210*0fca6ea1SDimitry Andric 
211*0fca6ea1SDimitry Andric     if (NeedSwap) {
212*0fca6ea1SDimitry Andric       // Normalization: Hi bit should always be the second argument.
213*0fca6ea1SDimitry Andric       Init *const NewArgs[] = {OperandName, LoBit, HiBit};
214*0fca6ea1SDimitry Andric       Segments.push_back({NumBits,
215*0fca6ea1SDimitry Andric                           DagInit::get(DI->getOperator(), nullptr, NewArgs, {}),
216*0fca6ea1SDimitry Andric                           CustomEncoder, CustomDecoder});
217*0fca6ea1SDimitry Andric     } else {
218*0fca6ea1SDimitry Andric       Segments.push_back({NumBits, DI, CustomEncoder, CustomDecoder});
219*0fca6ea1SDimitry Andric     }
220*0fca6ea1SDimitry Andric   }
221*0fca6ea1SDimitry Andric }
222*0fca6ea1SDimitry Andric 
223*0fca6ea1SDimitry Andric void VarLenCodeEmitterGen::run(raw_ostream &OS) {
224*0fca6ea1SDimitry Andric   CodeGenTarget Target(Records);
225*0fca6ea1SDimitry Andric   auto Insts = Records.getAllDerivedDefinitions("Instruction");
226*0fca6ea1SDimitry Andric 
227*0fca6ea1SDimitry Andric   auto NumberedInstructions = Target.getInstructionsByEnumValue();
228*0fca6ea1SDimitry Andric 
229*0fca6ea1SDimitry Andric   for (const CodeGenInstruction *CGI : NumberedInstructions) {
230*0fca6ea1SDimitry Andric     Record *R = CGI->TheDef;
231*0fca6ea1SDimitry Andric     // Create the corresponding VarLenInst instance.
232*0fca6ea1SDimitry Andric     if (R->getValueAsString("Namespace") == "TargetOpcode" ||
233*0fca6ea1SDimitry Andric         R->getValueAsBit("isPseudo"))
234*0fca6ea1SDimitry Andric       continue;
235*0fca6ea1SDimitry Andric 
236*0fca6ea1SDimitry Andric     // Setup alternative encodings according to HwModes
237*0fca6ea1SDimitry Andric     if (const RecordVal *RV = R->getValue("EncodingInfos")) {
238*0fca6ea1SDimitry Andric       if (auto *DI = dyn_cast_or_null<DefInit>(RV->getValue())) {
239*0fca6ea1SDimitry Andric         const CodeGenHwModes &HWM = Target.getHwModes();
240*0fca6ea1SDimitry Andric         EncodingInfoByHwMode EBM(DI->getDef(), HWM);
241*0fca6ea1SDimitry Andric         for (auto &KV : EBM) {
242*0fca6ea1SDimitry Andric           AltEncodingTy Mode = KV.first;
243*0fca6ea1SDimitry Andric           Modes.insert({Mode, "_" + HWM.getMode(Mode).Name.str()});
244*0fca6ea1SDimitry Andric           Record *EncodingDef = KV.second;
245*0fca6ea1SDimitry Andric           RecordVal *RV = EncodingDef->getValue("Inst");
246*0fca6ea1SDimitry Andric           DagInit *DI = cast<DagInit>(RV->getValue());
247*0fca6ea1SDimitry Andric           VarLenInsts[R].insert({Mode, VarLenInst(DI, RV)});
248*0fca6ea1SDimitry Andric         }
249*0fca6ea1SDimitry Andric         continue;
250*0fca6ea1SDimitry Andric       }
251*0fca6ea1SDimitry Andric     }
252*0fca6ea1SDimitry Andric     RecordVal *RV = R->getValue("Inst");
253*0fca6ea1SDimitry Andric     DagInit *DI = cast<DagInit>(RV->getValue());
254*0fca6ea1SDimitry Andric     VarLenInsts[R].insert({Universal, VarLenInst(DI, RV)});
255*0fca6ea1SDimitry Andric   }
256*0fca6ea1SDimitry Andric 
257*0fca6ea1SDimitry Andric   if (Modes.empty())
258*0fca6ea1SDimitry Andric     Modes.insert({Universal, ""}); // Base case, skip suffix.
259*0fca6ea1SDimitry Andric 
260*0fca6ea1SDimitry Andric   // Emit function declaration
261*0fca6ea1SDimitry Andric   OS << "void " << Target.getName()
262*0fca6ea1SDimitry Andric      << "MCCodeEmitter::getBinaryCodeForInstr(const MCInst &MI,\n"
263*0fca6ea1SDimitry Andric      << "    SmallVectorImpl<MCFixup> &Fixups,\n"
264*0fca6ea1SDimitry Andric      << "    APInt &Inst,\n"
265*0fca6ea1SDimitry Andric      << "    APInt &Scratch,\n"
266*0fca6ea1SDimitry Andric      << "    const MCSubtargetInfo &STI) const {\n";
267*0fca6ea1SDimitry Andric 
268*0fca6ea1SDimitry Andric   // Emit instruction base values
269*0fca6ea1SDimitry Andric   for (const auto &Mode : Modes)
270*0fca6ea1SDimitry Andric     emitInstructionBaseValues(OS, NumberedInstructions, Target, Mode.first);
271*0fca6ea1SDimitry Andric 
272*0fca6ea1SDimitry Andric   if (Modes.size() > 1) {
273*0fca6ea1SDimitry Andric     OS << "  unsigned Mode = STI.getHwMode();\n";
274*0fca6ea1SDimitry Andric   }
275*0fca6ea1SDimitry Andric 
276*0fca6ea1SDimitry Andric   for (const auto &Mode : Modes) {
277*0fca6ea1SDimitry Andric     // Emit helper function to retrieve base values.
278*0fca6ea1SDimitry Andric     OS << "  auto getInstBits" << Mode.second
279*0fca6ea1SDimitry Andric        << " = [&](unsigned Opcode) -> APInt {\n"
280*0fca6ea1SDimitry Andric        << "    unsigned NumBits = Index" << Mode.second << "[Opcode][0];\n"
281*0fca6ea1SDimitry Andric        << "    if (!NumBits)\n"
282*0fca6ea1SDimitry Andric        << "      return APInt::getZeroWidth();\n"
283*0fca6ea1SDimitry Andric        << "    unsigned Idx = Index" << Mode.second << "[Opcode][1];\n"
284*0fca6ea1SDimitry Andric        << "    ArrayRef<uint64_t> Data(&InstBits" << Mode.second << "[Idx], "
285*0fca6ea1SDimitry Andric        << "APInt::getNumWords(NumBits));\n"
286*0fca6ea1SDimitry Andric        << "    return APInt(NumBits, Data);\n"
287*0fca6ea1SDimitry Andric        << "  };\n";
288*0fca6ea1SDimitry Andric   }
289*0fca6ea1SDimitry Andric 
290*0fca6ea1SDimitry Andric   // Map to accumulate all the cases.
291*0fca6ea1SDimitry Andric   std::map<std::string, std::vector<std::string>> CaseMap;
292*0fca6ea1SDimitry Andric 
293*0fca6ea1SDimitry Andric   // Construct all cases statement for each opcode
294*0fca6ea1SDimitry Andric   for (Record *R : Insts) {
295*0fca6ea1SDimitry Andric     if (R->getValueAsString("Namespace") == "TargetOpcode" ||
296*0fca6ea1SDimitry Andric         R->getValueAsBit("isPseudo"))
297*0fca6ea1SDimitry Andric       continue;
298*0fca6ea1SDimitry Andric     std::string InstName =
299*0fca6ea1SDimitry Andric         (R->getValueAsString("Namespace") + "::" + R->getName()).str();
300*0fca6ea1SDimitry Andric     std::string Case = getInstructionCases(R, Target);
301*0fca6ea1SDimitry Andric 
302*0fca6ea1SDimitry Andric     CaseMap[Case].push_back(std::move(InstName));
303*0fca6ea1SDimitry Andric   }
304*0fca6ea1SDimitry Andric 
305*0fca6ea1SDimitry Andric   // Emit initial function code
306*0fca6ea1SDimitry Andric   OS << "  const unsigned opcode = MI.getOpcode();\n"
307*0fca6ea1SDimitry Andric      << "  switch (opcode) {\n";
308*0fca6ea1SDimitry Andric 
309*0fca6ea1SDimitry Andric   // Emit each case statement
310*0fca6ea1SDimitry Andric   for (const auto &C : CaseMap) {
311*0fca6ea1SDimitry Andric     const std::string &Case = C.first;
312*0fca6ea1SDimitry Andric     const auto &InstList = C.second;
313*0fca6ea1SDimitry Andric 
314*0fca6ea1SDimitry Andric     ListSeparator LS("\n");
315*0fca6ea1SDimitry Andric     for (const auto &InstName : InstList)
316*0fca6ea1SDimitry Andric       OS << LS << "    case " << InstName << ":";
317*0fca6ea1SDimitry Andric 
318*0fca6ea1SDimitry Andric     OS << " {\n";
319*0fca6ea1SDimitry Andric     OS << Case;
320*0fca6ea1SDimitry Andric     OS << "      break;\n"
321*0fca6ea1SDimitry Andric        << "    }\n";
322*0fca6ea1SDimitry Andric   }
323*0fca6ea1SDimitry Andric   // Default case: unhandled opcode
324*0fca6ea1SDimitry Andric   OS << "  default:\n"
325*0fca6ea1SDimitry Andric      << "    std::string msg;\n"
326*0fca6ea1SDimitry Andric      << "    raw_string_ostream Msg(msg);\n"
327*0fca6ea1SDimitry Andric      << "    Msg << \"Not supported instr: \" << MI;\n"
328*0fca6ea1SDimitry Andric      << "    report_fatal_error(Msg.str().c_str());\n"
329*0fca6ea1SDimitry Andric      << "  }\n";
330*0fca6ea1SDimitry Andric   OS << "}\n\n";
331*0fca6ea1SDimitry Andric }
332*0fca6ea1SDimitry Andric 
333*0fca6ea1SDimitry Andric static void emitInstBits(raw_ostream &IS, raw_ostream &SS, const APInt &Bits,
334*0fca6ea1SDimitry Andric                          unsigned &Index) {
335*0fca6ea1SDimitry Andric   if (!Bits.getNumWords()) {
336*0fca6ea1SDimitry Andric     IS.indent(4) << "{/*NumBits*/0, /*Index*/0},";
337*0fca6ea1SDimitry Andric     return;
338*0fca6ea1SDimitry Andric   }
339*0fca6ea1SDimitry Andric 
340*0fca6ea1SDimitry Andric   IS.indent(4) << "{/*NumBits*/" << Bits.getBitWidth() << ", " << "/*Index*/"
341*0fca6ea1SDimitry Andric                << Index << "},";
342*0fca6ea1SDimitry Andric 
343*0fca6ea1SDimitry Andric   SS.indent(4);
344*0fca6ea1SDimitry Andric   for (unsigned I = 0; I < Bits.getNumWords(); ++I, ++Index)
345*0fca6ea1SDimitry Andric     SS << "UINT64_C(" << utostr(Bits.getRawData()[I]) << "),";
346*0fca6ea1SDimitry Andric }
347*0fca6ea1SDimitry Andric 
348*0fca6ea1SDimitry Andric void VarLenCodeEmitterGen::emitInstructionBaseValues(
349*0fca6ea1SDimitry Andric     raw_ostream &OS, ArrayRef<const CodeGenInstruction *> NumberedInstructions,
350*0fca6ea1SDimitry Andric     CodeGenTarget &Target, AltEncodingTy Mode) {
351*0fca6ea1SDimitry Andric   std::string IndexArray, StorageArray;
352*0fca6ea1SDimitry Andric   raw_string_ostream IS(IndexArray), SS(StorageArray);
353*0fca6ea1SDimitry Andric 
354*0fca6ea1SDimitry Andric   IS << "  static const unsigned Index" << Modes[Mode] << "[][2] = {\n";
355*0fca6ea1SDimitry Andric   SS << "  static const uint64_t InstBits" << Modes[Mode] << "[] = {\n";
356*0fca6ea1SDimitry Andric 
357*0fca6ea1SDimitry Andric   unsigned NumFixedValueWords = 0U;
358*0fca6ea1SDimitry Andric   for (const CodeGenInstruction *CGI : NumberedInstructions) {
359*0fca6ea1SDimitry Andric     Record *R = CGI->TheDef;
360*0fca6ea1SDimitry Andric 
361*0fca6ea1SDimitry Andric     if (R->getValueAsString("Namespace") == "TargetOpcode" ||
362*0fca6ea1SDimitry Andric         R->getValueAsBit("isPseudo")) {
363*0fca6ea1SDimitry Andric       IS.indent(4) << "{/*NumBits*/0, /*Index*/0},\n";
364*0fca6ea1SDimitry Andric       continue;
365*0fca6ea1SDimitry Andric     }
366*0fca6ea1SDimitry Andric 
367*0fca6ea1SDimitry Andric     const auto InstIt = VarLenInsts.find(R);
368*0fca6ea1SDimitry Andric     if (InstIt == VarLenInsts.end())
369*0fca6ea1SDimitry Andric       PrintFatalError(R, "VarLenInst not found for this record");
370*0fca6ea1SDimitry Andric     auto ModeIt = InstIt->second.find(Mode);
371*0fca6ea1SDimitry Andric     if (ModeIt == InstIt->second.end())
372*0fca6ea1SDimitry Andric       ModeIt = InstIt->second.find(Universal);
373*0fca6ea1SDimitry Andric     if (ModeIt == InstIt->second.end()) {
374*0fca6ea1SDimitry Andric       IS.indent(4) << "{/*NumBits*/0, /*Index*/0},\t" << "// " << R->getName()
375*0fca6ea1SDimitry Andric                    << " no encoding\n";
376*0fca6ea1SDimitry Andric       continue;
377*0fca6ea1SDimitry Andric     }
378*0fca6ea1SDimitry Andric     const VarLenInst &VLI = ModeIt->second;
379*0fca6ea1SDimitry Andric     unsigned i = 0U, BitWidth = VLI.size();
380*0fca6ea1SDimitry Andric 
381*0fca6ea1SDimitry Andric     // Start by filling in fixed values.
382*0fca6ea1SDimitry Andric     APInt Value(BitWidth, 0);
383*0fca6ea1SDimitry Andric     auto SI = VLI.begin(), SE = VLI.end();
384*0fca6ea1SDimitry Andric     // Scan through all the segments that have fixed-bits values.
385*0fca6ea1SDimitry Andric     while (i < BitWidth && SI != SE) {
386*0fca6ea1SDimitry Andric       unsigned SegmentNumBits = SI->BitWidth;
387*0fca6ea1SDimitry Andric       if (const auto *BI = dyn_cast<BitsInit>(SI->Value)) {
388*0fca6ea1SDimitry Andric         for (unsigned Idx = 0U; Idx != SegmentNumBits; ++Idx) {
389*0fca6ea1SDimitry Andric           auto *B = cast<BitInit>(BI->getBit(Idx));
390*0fca6ea1SDimitry Andric           Value.setBitVal(i + Idx, B->getValue());
391*0fca6ea1SDimitry Andric         }
392*0fca6ea1SDimitry Andric       }
393*0fca6ea1SDimitry Andric       if (const auto *BI = dyn_cast<BitInit>(SI->Value))
394*0fca6ea1SDimitry Andric         Value.setBitVal(i, BI->getValue());
395*0fca6ea1SDimitry Andric 
396*0fca6ea1SDimitry Andric       i += SegmentNumBits;
397*0fca6ea1SDimitry Andric       ++SI;
398*0fca6ea1SDimitry Andric     }
399*0fca6ea1SDimitry Andric 
400*0fca6ea1SDimitry Andric     emitInstBits(IS, SS, Value, NumFixedValueWords);
401*0fca6ea1SDimitry Andric     IS << '\t' << "// " << R->getName() << "\n";
402*0fca6ea1SDimitry Andric     if (Value.getNumWords())
403*0fca6ea1SDimitry Andric       SS << '\t' << "// " << R->getName() << "\n";
404*0fca6ea1SDimitry Andric   }
405*0fca6ea1SDimitry Andric   IS.indent(4) << "{/*NumBits*/0, /*Index*/0}\n  };\n";
406*0fca6ea1SDimitry Andric   SS.indent(4) << "UINT64_C(0)\n  };\n";
407*0fca6ea1SDimitry Andric 
408*0fca6ea1SDimitry Andric   OS << IndexArray << StorageArray;
409*0fca6ea1SDimitry Andric }
410*0fca6ea1SDimitry Andric 
411*0fca6ea1SDimitry Andric std::string VarLenCodeEmitterGen::getInstructionCases(Record *R,
412*0fca6ea1SDimitry Andric                                                       CodeGenTarget &Target) {
413*0fca6ea1SDimitry Andric   auto It = VarLenInsts.find(R);
414*0fca6ea1SDimitry Andric   if (It == VarLenInsts.end())
415*0fca6ea1SDimitry Andric     PrintFatalError(R, "Parsed encoding record not found");
416*0fca6ea1SDimitry Andric   const auto &Map = It->second;
417*0fca6ea1SDimitry Andric 
418*0fca6ea1SDimitry Andric   // Is this instructions encoding universal (same for all modes)?
419*0fca6ea1SDimitry Andric   // Allways true if there is only one mode.
420*0fca6ea1SDimitry Andric   if (Map.size() == 1 && Map.begin()->first == Universal) {
421*0fca6ea1SDimitry Andric     // Universal, just pick the first mode.
422*0fca6ea1SDimitry Andric     AltEncodingTy Mode = Modes.begin()->first;
423*0fca6ea1SDimitry Andric     const auto &Encoding = Map.begin()->second;
424*0fca6ea1SDimitry Andric     return getInstructionCaseForEncoding(R, Mode, Encoding, Target, 6);
425*0fca6ea1SDimitry Andric   }
426*0fca6ea1SDimitry Andric 
427*0fca6ea1SDimitry Andric   std::string Case;
428*0fca6ea1SDimitry Andric   Case += "      switch (Mode) {\n";
429*0fca6ea1SDimitry Andric   Case += "      default: llvm_unreachable(\"Unhandled Mode\");\n";
430*0fca6ea1SDimitry Andric   for (const auto &Mode : Modes) {
431*0fca6ea1SDimitry Andric     Case += "      case " + itostr(Mode.first) + ": {\n";
432*0fca6ea1SDimitry Andric     const auto &It = Map.find(Mode.first);
433*0fca6ea1SDimitry Andric     if (It == Map.end()) {
434*0fca6ea1SDimitry Andric       Case +=
435*0fca6ea1SDimitry Andric           "        llvm_unreachable(\"Undefined encoding in this mode\");\n";
436*0fca6ea1SDimitry Andric     } else {
437*0fca6ea1SDimitry Andric       Case +=
438*0fca6ea1SDimitry Andric           getInstructionCaseForEncoding(R, It->first, It->second, Target, 8);
439*0fca6ea1SDimitry Andric     }
440*0fca6ea1SDimitry Andric     Case += "        break;\n";
441*0fca6ea1SDimitry Andric     Case += "      }\n";
442*0fca6ea1SDimitry Andric   }
443*0fca6ea1SDimitry Andric   Case += "      }\n";
444*0fca6ea1SDimitry Andric   return Case;
445*0fca6ea1SDimitry Andric }
446*0fca6ea1SDimitry Andric 
447*0fca6ea1SDimitry Andric std::string VarLenCodeEmitterGen::getInstructionCaseForEncoding(
448*0fca6ea1SDimitry Andric     Record *R, AltEncodingTy Mode, const VarLenInst &VLI, CodeGenTarget &Target,
449*0fca6ea1SDimitry Andric     int I) {
450*0fca6ea1SDimitry Andric 
451*0fca6ea1SDimitry Andric   CodeGenInstruction &CGI = Target.getInstruction(R);
452*0fca6ea1SDimitry Andric 
453*0fca6ea1SDimitry Andric   std::string Case;
454*0fca6ea1SDimitry Andric   raw_string_ostream SS(Case);
455*0fca6ea1SDimitry Andric   // Populate based value.
456*0fca6ea1SDimitry Andric   SS.indent(I) << "Inst = getInstBits" << Modes[Mode] << "(opcode);\n";
457*0fca6ea1SDimitry Andric 
458*0fca6ea1SDimitry Andric   // Process each segment in VLI.
459*0fca6ea1SDimitry Andric   size_t Offset = 0U;
460*0fca6ea1SDimitry Andric   unsigned HighScratchAccess = 0U;
461*0fca6ea1SDimitry Andric   for (const auto &ES : VLI) {
462*0fca6ea1SDimitry Andric     unsigned NumBits = ES.BitWidth;
463*0fca6ea1SDimitry Andric     const Init *Val = ES.Value;
464*0fca6ea1SDimitry Andric     // If it's a StringInit or DagInit, it's a reference to an operand
465*0fca6ea1SDimitry Andric     // or part of an operand.
466*0fca6ea1SDimitry Andric     if (isa<StringInit>(Val) || isa<DagInit>(Val)) {
467*0fca6ea1SDimitry Andric       StringRef OperandName;
468*0fca6ea1SDimitry Andric       unsigned LoBit = 0U;
469*0fca6ea1SDimitry Andric       if (const auto *SV = dyn_cast<StringInit>(Val)) {
470*0fca6ea1SDimitry Andric         OperandName = SV->getValue();
471*0fca6ea1SDimitry Andric       } else {
472*0fca6ea1SDimitry Andric         // Normalized: (slice <operand name>, <high bit>, <low bit>)
473*0fca6ea1SDimitry Andric         const auto *DV = cast<DagInit>(Val);
474*0fca6ea1SDimitry Andric         OperandName = cast<StringInit>(DV->getArg(0))->getValue();
475*0fca6ea1SDimitry Andric         LoBit = static_cast<unsigned>(cast<IntInit>(DV->getArg(2))->getValue());
476*0fca6ea1SDimitry Andric       }
477*0fca6ea1SDimitry Andric 
478*0fca6ea1SDimitry Andric       auto OpIdx = CGI.Operands.ParseOperandName(OperandName);
479*0fca6ea1SDimitry Andric       unsigned FlatOpIdx = CGI.Operands.getFlattenedOperandNumber(OpIdx);
480*0fca6ea1SDimitry Andric       StringRef CustomEncoder =
481*0fca6ea1SDimitry Andric           CGI.Operands[OpIdx.first].EncoderMethodNames[OpIdx.second];
482*0fca6ea1SDimitry Andric       if (ES.CustomEncoder.size())
483*0fca6ea1SDimitry Andric         CustomEncoder = ES.CustomEncoder;
484*0fca6ea1SDimitry Andric 
485*0fca6ea1SDimitry Andric       SS.indent(I) << "Scratch.clearAllBits();\n";
486*0fca6ea1SDimitry Andric       SS.indent(I) << "// op: " << OperandName.drop_front(1) << "\n";
487*0fca6ea1SDimitry Andric       if (CustomEncoder.empty())
488*0fca6ea1SDimitry Andric         SS.indent(I) << "getMachineOpValue(MI, MI.getOperand("
489*0fca6ea1SDimitry Andric                      << utostr(FlatOpIdx) << ")";
490*0fca6ea1SDimitry Andric       else
491*0fca6ea1SDimitry Andric         SS.indent(I) << CustomEncoder << "(MI, /*OpIdx=*/" << utostr(FlatOpIdx);
492*0fca6ea1SDimitry Andric 
493*0fca6ea1SDimitry Andric       SS << ", /*Pos=*/" << utostr(Offset) << ", Scratch, Fixups, STI);\n";
494*0fca6ea1SDimitry Andric 
495*0fca6ea1SDimitry Andric       SS.indent(I) << "Inst.insertBits(" << "Scratch.extractBits("
496*0fca6ea1SDimitry Andric                    << utostr(NumBits) << ", " << utostr(LoBit) << ")" << ", "
497*0fca6ea1SDimitry Andric                    << Offset << ");\n";
498*0fca6ea1SDimitry Andric 
499*0fca6ea1SDimitry Andric       HighScratchAccess = std::max(HighScratchAccess, NumBits + LoBit);
500*0fca6ea1SDimitry Andric     }
501*0fca6ea1SDimitry Andric     Offset += NumBits;
502*0fca6ea1SDimitry Andric   }
503*0fca6ea1SDimitry Andric 
504*0fca6ea1SDimitry Andric   StringRef PostEmitter = R->getValueAsString("PostEncoderMethod");
505*0fca6ea1SDimitry Andric   if (!PostEmitter.empty())
506*0fca6ea1SDimitry Andric     SS.indent(I) << "Inst = " << PostEmitter << "(MI, Inst, STI);\n";
507*0fca6ea1SDimitry Andric 
508*0fca6ea1SDimitry Andric   // Resize the scratch buffer if it's to small.
509*0fca6ea1SDimitry Andric   std::string ScratchResizeStr;
510*0fca6ea1SDimitry Andric   if (VLI.size() && !VLI.isFixedValueOnly()) {
511*0fca6ea1SDimitry Andric     raw_string_ostream RS(ScratchResizeStr);
512*0fca6ea1SDimitry Andric     RS.indent(I) << "if (Scratch.getBitWidth() < " << HighScratchAccess
513*0fca6ea1SDimitry Andric                  << ") { Scratch = Scratch.zext(" << HighScratchAccess
514*0fca6ea1SDimitry Andric                  << "); }\n";
515*0fca6ea1SDimitry Andric   }
516*0fca6ea1SDimitry Andric 
517*0fca6ea1SDimitry Andric   return ScratchResizeStr + Case;
518*0fca6ea1SDimitry Andric }
519*0fca6ea1SDimitry Andric 
520*0fca6ea1SDimitry Andric namespace llvm {
521*0fca6ea1SDimitry Andric 
522*0fca6ea1SDimitry Andric void emitVarLenCodeEmitter(RecordKeeper &R, raw_ostream &OS) {
523*0fca6ea1SDimitry Andric   VarLenCodeEmitterGen(R).run(OS);
524*0fca6ea1SDimitry Andric }
525*0fca6ea1SDimitry Andric 
526*0fca6ea1SDimitry Andric } // end namespace llvm
527