1145449b1SDimitry Andric //===- VarLenCodeEmitterGen.cpp - CEG for variable-length insts -----------===//
2145449b1SDimitry Andric //
3145449b1SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4145449b1SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
5145449b1SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6145449b1SDimitry Andric //
7145449b1SDimitry Andric //===----------------------------------------------------------------------===//
8145449b1SDimitry Andric //
9145449b1SDimitry Andric // The CodeEmitterGen component for variable-length instructions.
10145449b1SDimitry Andric //
11145449b1SDimitry Andric // The basic CodeEmitterGen is almost exclusively designed for fixed-
12145449b1SDimitry Andric // length instructions. A good analogy for its encoding scheme is how printf
13145449b1SDimitry Andric // works: The (immutable) formatting string represent the fixed values in the
14145449b1SDimitry Andric // encoded instruction. Placeholders (i.e. %something), on the other hand,
15145449b1SDimitry Andric // represent encoding for instruction operands.
16145449b1SDimitry Andric // ```
17145449b1SDimitry Andric // printf("1101 %src 1001 %dst", <encoded value for operand `src`>,
18145449b1SDimitry Andric // <encoded value for operand `dst`>);
19145449b1SDimitry Andric // ```
20145449b1SDimitry Andric // VarLenCodeEmitterGen in this file provides an alternative encoding scheme
21145449b1SDimitry Andric // that works more like a C++ stream operator:
22145449b1SDimitry Andric // ```
23145449b1SDimitry Andric // OS << 0b1101;
24145449b1SDimitry Andric // if (Cond)
25145449b1SDimitry Andric // OS << OperandEncoding0;
26145449b1SDimitry Andric // OS << 0b1001 << OperandEncoding1;
27145449b1SDimitry Andric // ```
28145449b1SDimitry Andric // You are free to concatenate arbitrary types (and sizes) of encoding
29145449b1SDimitry Andric // fragments on any bit position, bringing more flexibilities on defining
30145449b1SDimitry Andric // encoding for variable-length instructions.
31145449b1SDimitry Andric //
32145449b1SDimitry Andric // In a more specific way, instruction encoding is represented by a DAG type
33145449b1SDimitry Andric // `Inst` field. Here is an example:
34145449b1SDimitry Andric // ```
35145449b1SDimitry Andric // dag Inst = (descend 0b1101, (operand "$src", 4), 0b1001,
36145449b1SDimitry Andric // (operand "$dst", 4));
37145449b1SDimitry Andric // ```
38145449b1SDimitry Andric // It represents the following instruction encoding:
39145449b1SDimitry Andric // ```
40145449b1SDimitry Andric // MSB LSB
41145449b1SDimitry Andric // 1101<encoding for operand src>1001<encoding for operand dst>
42145449b1SDimitry Andric // ```
43145449b1SDimitry Andric // For more details about DAG operators in the above snippet, please
44145449b1SDimitry Andric // refer to \file include/llvm/Target/Target.td.
45145449b1SDimitry Andric //
46145449b1SDimitry Andric // VarLenCodeEmitter will convert the above DAG into the same helper function
47145449b1SDimitry Andric // generated by CodeEmitter, `MCCodeEmitter::getBinaryCodeForInstr` (except
48145449b1SDimitry Andric // for few details).
49145449b1SDimitry Andric //
50145449b1SDimitry Andric //===----------------------------------------------------------------------===//
51145449b1SDimitry Andric
52145449b1SDimitry Andric #include "VarLenCodeEmitterGen.h"
53145449b1SDimitry Andric #include "CodeGenHwModes.h"
54145449b1SDimitry Andric #include "CodeGenInstruction.h"
55145449b1SDimitry Andric #include "CodeGenTarget.h"
56145449b1SDimitry Andric #include "InfoByHwMode.h"
57145449b1SDimitry Andric #include "llvm/ADT/ArrayRef.h"
58145449b1SDimitry Andric #include "llvm/ADT/DenseMap.h"
59145449b1SDimitry Andric #include "llvm/Support/raw_ostream.h"
60145449b1SDimitry Andric #include "llvm/TableGen/Error.h"
617fa27ce4SDimitry Andric #include "llvm/TableGen/Record.h"
62145449b1SDimitry Andric
63b1c73532SDimitry Andric #include <algorithm>
64b1c73532SDimitry Andric
65145449b1SDimitry Andric using namespace llvm;
66145449b1SDimitry Andric
67145449b1SDimitry Andric namespace {
68145449b1SDimitry Andric
69145449b1SDimitry Andric class VarLenCodeEmitterGen {
70145449b1SDimitry Andric RecordKeeper &Records;
71145449b1SDimitry Andric
72b1c73532SDimitry Andric // Representaton of alternative encodings used for HwModes.
73b1c73532SDimitry Andric using AltEncodingTy = int;
74b1c73532SDimitry Andric // Mode identifier when only one encoding is defined.
75b1c73532SDimitry Andric const AltEncodingTy Universal = -1;
76b1c73532SDimitry Andric // The set of alternative instruction encodings with a descriptive
77b1c73532SDimitry Andric // name suffix to improve readability of the generated code.
78b1c73532SDimitry Andric std::map<AltEncodingTy, std::string> Modes;
79b1c73532SDimitry Andric
80b1c73532SDimitry Andric DenseMap<Record *, DenseMap<AltEncodingTy, VarLenInst>> VarLenInsts;
81145449b1SDimitry Andric
82145449b1SDimitry Andric // Emit based values (i.e. fixed bits in the encoded instructions)
83145449b1SDimitry Andric void emitInstructionBaseValues(
84145449b1SDimitry Andric raw_ostream &OS,
85145449b1SDimitry Andric ArrayRef<const CodeGenInstruction *> NumberedInstructions,
86b1c73532SDimitry Andric CodeGenTarget &Target, AltEncodingTy Mode);
87145449b1SDimitry Andric
88b1c73532SDimitry Andric std::string getInstructionCases(Record *R, CodeGenTarget &Target);
89b1c73532SDimitry Andric std::string getInstructionCaseForEncoding(Record *R, AltEncodingTy Mode,
90b1c73532SDimitry Andric const VarLenInst &VLI,
91b1c73532SDimitry Andric CodeGenTarget &Target, int I);
92145449b1SDimitry Andric
93145449b1SDimitry Andric public:
VarLenCodeEmitterGen(RecordKeeper & R)94145449b1SDimitry Andric explicit VarLenCodeEmitterGen(RecordKeeper &R) : Records(R) {}
95145449b1SDimitry Andric
96145449b1SDimitry Andric void run(raw_ostream &OS);
97145449b1SDimitry Andric };
98145449b1SDimitry Andric } // end anonymous namespace
99145449b1SDimitry Andric
100e3b55780SDimitry Andric // Get the name of custom encoder or decoder, if there is any.
101e3b55780SDimitry Andric // Returns `{encoder name, decoder name}`.
getCustomCoders(ArrayRef<Init * > Args)102e3b55780SDimitry Andric static std::pair<StringRef, StringRef> getCustomCoders(ArrayRef<Init *> Args) {
103e3b55780SDimitry Andric std::pair<StringRef, StringRef> Result;
104e3b55780SDimitry Andric for (const auto *Arg : Args) {
105e3b55780SDimitry Andric const auto *DI = dyn_cast<DagInit>(Arg);
106e3b55780SDimitry Andric if (!DI)
107e3b55780SDimitry Andric continue;
108e3b55780SDimitry Andric const Init *Op = DI->getOperator();
109e3b55780SDimitry Andric if (!isa<DefInit>(Op))
110e3b55780SDimitry Andric continue;
111e3b55780SDimitry Andric // syntax: `(<encoder | decoder> "function name")`
112e3b55780SDimitry Andric StringRef OpName = cast<DefInit>(Op)->getDef()->getName();
113e3b55780SDimitry Andric if (OpName != "encoder" && OpName != "decoder")
114e3b55780SDimitry Andric continue;
115e3b55780SDimitry Andric if (!DI->getNumArgs() || !isa<StringInit>(DI->getArg(0)))
116e3b55780SDimitry Andric PrintFatalError("expected '" + OpName +
117e3b55780SDimitry Andric "' directive to be followed by a custom function name.");
118e3b55780SDimitry Andric StringRef FuncName = cast<StringInit>(DI->getArg(0))->getValue();
119e3b55780SDimitry Andric if (OpName == "encoder")
120e3b55780SDimitry Andric Result.first = FuncName;
121e3b55780SDimitry Andric else
122e3b55780SDimitry Andric Result.second = FuncName;
123e3b55780SDimitry Andric }
124e3b55780SDimitry Andric return Result;
125e3b55780SDimitry Andric }
126e3b55780SDimitry Andric
VarLenInst(const DagInit * DI,const RecordVal * TheDef)127145449b1SDimitry Andric VarLenInst::VarLenInst(const DagInit *DI, const RecordVal *TheDef)
128b1c73532SDimitry Andric : TheDef(TheDef), NumBits(0U), HasDynamicSegment(false) {
129145449b1SDimitry Andric buildRec(DI);
130145449b1SDimitry Andric for (const auto &S : Segments)
131145449b1SDimitry Andric NumBits += S.BitWidth;
132145449b1SDimitry Andric }
133145449b1SDimitry Andric
buildRec(const DagInit * DI)134145449b1SDimitry Andric void VarLenInst::buildRec(const DagInit *DI) {
135145449b1SDimitry Andric assert(TheDef && "The def record is nullptr ?");
136145449b1SDimitry Andric
137145449b1SDimitry Andric std::string Op = DI->getOperator()->getAsString();
138145449b1SDimitry Andric
139145449b1SDimitry Andric if (Op == "ascend" || Op == "descend") {
140145449b1SDimitry Andric bool Reverse = Op == "descend";
141145449b1SDimitry Andric int i = Reverse ? DI->getNumArgs() - 1 : 0;
142145449b1SDimitry Andric int e = Reverse ? -1 : DI->getNumArgs();
143145449b1SDimitry Andric int s = Reverse ? -1 : 1;
144145449b1SDimitry Andric for (; i != e; i += s) {
145145449b1SDimitry Andric const Init *Arg = DI->getArg(i);
146145449b1SDimitry Andric if (const auto *BI = dyn_cast<BitsInit>(Arg)) {
147145449b1SDimitry Andric if (!BI->isComplete())
148145449b1SDimitry Andric PrintFatalError(TheDef->getLoc(),
149145449b1SDimitry Andric "Expecting complete bits init in `" + Op + "`");
150145449b1SDimitry Andric Segments.push_back({BI->getNumBits(), BI});
151145449b1SDimitry Andric } else if (const auto *BI = dyn_cast<BitInit>(Arg)) {
152145449b1SDimitry Andric if (!BI->isConcrete())
153145449b1SDimitry Andric PrintFatalError(TheDef->getLoc(),
154145449b1SDimitry Andric "Expecting concrete bit init in `" + Op + "`");
155145449b1SDimitry Andric Segments.push_back({1, BI});
156145449b1SDimitry Andric } else if (const auto *SubDI = dyn_cast<DagInit>(Arg)) {
157145449b1SDimitry Andric buildRec(SubDI);
158145449b1SDimitry Andric } else {
159145449b1SDimitry Andric PrintFatalError(TheDef->getLoc(), "Unrecognized type of argument in `" +
160145449b1SDimitry Andric Op + "`: " + Arg->getAsString());
161145449b1SDimitry Andric }
162145449b1SDimitry Andric }
163145449b1SDimitry Andric } else if (Op == "operand") {
164e3b55780SDimitry Andric // (operand <operand name>, <# of bits>,
165e3b55780SDimitry Andric // [(encoder <custom encoder>)][, (decoder <custom decoder>)])
166145449b1SDimitry Andric if (DI->getNumArgs() < 2)
167145449b1SDimitry Andric PrintFatalError(TheDef->getLoc(),
168145449b1SDimitry Andric "Expecting at least 2 arguments for `operand`");
169145449b1SDimitry Andric HasDynamicSegment = true;
170145449b1SDimitry Andric const Init *OperandName = DI->getArg(0), *NumBits = DI->getArg(1);
171145449b1SDimitry Andric if (!isa<StringInit>(OperandName) || !isa<IntInit>(NumBits))
172145449b1SDimitry Andric PrintFatalError(TheDef->getLoc(), "Invalid argument types for `operand`");
173145449b1SDimitry Andric
174145449b1SDimitry Andric auto NumBitsVal = cast<IntInit>(NumBits)->getValue();
175145449b1SDimitry Andric if (NumBitsVal <= 0)
176145449b1SDimitry Andric PrintFatalError(TheDef->getLoc(), "Invalid number of bits for `operand`");
177145449b1SDimitry Andric
178e3b55780SDimitry Andric auto [CustomEncoder, CustomDecoder] =
179e3b55780SDimitry Andric getCustomCoders(DI->getArgs().slice(2));
180e3b55780SDimitry Andric Segments.push_back({static_cast<unsigned>(NumBitsVal), OperandName,
181e3b55780SDimitry Andric CustomEncoder, CustomDecoder});
182145449b1SDimitry Andric } else if (Op == "slice") {
183145449b1SDimitry Andric // (slice <operand name>, <high / low bit>, <low / high bit>,
184e3b55780SDimitry Andric // [(encoder <custom encoder>)][, (decoder <custom decoder>)])
185145449b1SDimitry Andric if (DI->getNumArgs() < 3)
186145449b1SDimitry Andric PrintFatalError(TheDef->getLoc(),
187145449b1SDimitry Andric "Expecting at least 3 arguments for `slice`");
188145449b1SDimitry Andric HasDynamicSegment = true;
189145449b1SDimitry Andric Init *OperandName = DI->getArg(0), *HiBit = DI->getArg(1),
190145449b1SDimitry Andric *LoBit = DI->getArg(2);
191145449b1SDimitry Andric if (!isa<StringInit>(OperandName) || !isa<IntInit>(HiBit) ||
192145449b1SDimitry Andric !isa<IntInit>(LoBit))
193145449b1SDimitry Andric PrintFatalError(TheDef->getLoc(), "Invalid argument types for `slice`");
194145449b1SDimitry Andric
195145449b1SDimitry Andric auto HiBitVal = cast<IntInit>(HiBit)->getValue(),
196145449b1SDimitry Andric LoBitVal = cast<IntInit>(LoBit)->getValue();
197145449b1SDimitry Andric if (HiBitVal < 0 || LoBitVal < 0)
198145449b1SDimitry Andric PrintFatalError(TheDef->getLoc(), "Invalid bit range for `slice`");
199145449b1SDimitry Andric bool NeedSwap = false;
200145449b1SDimitry Andric unsigned NumBits = 0U;
201145449b1SDimitry Andric if (HiBitVal < LoBitVal) {
202145449b1SDimitry Andric NeedSwap = true;
203145449b1SDimitry Andric NumBits = static_cast<unsigned>(LoBitVal - HiBitVal + 1);
204145449b1SDimitry Andric } else {
205145449b1SDimitry Andric NumBits = static_cast<unsigned>(HiBitVal - LoBitVal + 1);
206145449b1SDimitry Andric }
207145449b1SDimitry Andric
208e3b55780SDimitry Andric auto [CustomEncoder, CustomDecoder] =
209e3b55780SDimitry Andric getCustomCoders(DI->getArgs().slice(3));
210145449b1SDimitry Andric
211145449b1SDimitry Andric if (NeedSwap) {
212145449b1SDimitry Andric // Normalization: Hi bit should always be the second argument.
213145449b1SDimitry Andric Init *const NewArgs[] = {OperandName, LoBit, HiBit};
214145449b1SDimitry Andric Segments.push_back({NumBits,
215145449b1SDimitry Andric DagInit::get(DI->getOperator(), nullptr, NewArgs, {}),
216e3b55780SDimitry Andric CustomEncoder, CustomDecoder});
217145449b1SDimitry Andric } else {
218e3b55780SDimitry Andric Segments.push_back({NumBits, DI, CustomEncoder, CustomDecoder});
219145449b1SDimitry Andric }
220145449b1SDimitry Andric }
221145449b1SDimitry Andric }
222145449b1SDimitry Andric
run(raw_ostream & OS)223145449b1SDimitry Andric void VarLenCodeEmitterGen::run(raw_ostream &OS) {
224145449b1SDimitry Andric CodeGenTarget Target(Records);
225145449b1SDimitry Andric auto Insts = Records.getAllDerivedDefinitions("Instruction");
226145449b1SDimitry Andric
227145449b1SDimitry Andric auto NumberedInstructions = Target.getInstructionsByEnumValue();
228145449b1SDimitry Andric
229145449b1SDimitry Andric for (const CodeGenInstruction *CGI : NumberedInstructions) {
230145449b1SDimitry Andric Record *R = CGI->TheDef;
231145449b1SDimitry Andric // Create the corresponding VarLenInst instance.
232145449b1SDimitry Andric if (R->getValueAsString("Namespace") == "TargetOpcode" ||
233145449b1SDimitry Andric R->getValueAsBit("isPseudo"))
234145449b1SDimitry Andric continue;
235145449b1SDimitry Andric
236b1c73532SDimitry Andric // Setup alternative encodings according to HwModes
237145449b1SDimitry Andric if (const RecordVal *RV = R->getValue("EncodingInfos")) {
238145449b1SDimitry Andric if (auto *DI = dyn_cast_or_null<DefInit>(RV->getValue())) {
239b1c73532SDimitry Andric const CodeGenHwModes &HWM = Target.getHwModes();
240145449b1SDimitry Andric EncodingInfoByHwMode EBM(DI->getDef(), HWM);
241145449b1SDimitry Andric for (auto &KV : EBM) {
242b1c73532SDimitry Andric AltEncodingTy Mode = KV.first;
243b1c73532SDimitry Andric Modes.insert({Mode, "_" + HWM.getMode(Mode).Name.str()});
244145449b1SDimitry Andric Record *EncodingDef = KV.second;
245145449b1SDimitry Andric RecordVal *RV = EncodingDef->getValue("Inst");
246145449b1SDimitry Andric DagInit *DI = cast<DagInit>(RV->getValue());
247b1c73532SDimitry Andric VarLenInsts[R].insert({Mode, VarLenInst(DI, RV)});
248145449b1SDimitry Andric }
249145449b1SDimitry Andric continue;
250145449b1SDimitry Andric }
251145449b1SDimitry Andric }
252145449b1SDimitry Andric RecordVal *RV = R->getValue("Inst");
253145449b1SDimitry Andric DagInit *DI = cast<DagInit>(RV->getValue());
254b1c73532SDimitry Andric VarLenInsts[R].insert({Universal, VarLenInst(DI, RV)});
255145449b1SDimitry Andric }
256145449b1SDimitry Andric
257b1c73532SDimitry Andric if (Modes.empty())
258b1c73532SDimitry Andric Modes.insert({Universal, ""}); // Base case, skip suffix.
259b1c73532SDimitry Andric
260145449b1SDimitry Andric // Emit function declaration
261145449b1SDimitry Andric OS << "void " << Target.getName()
262145449b1SDimitry Andric << "MCCodeEmitter::getBinaryCodeForInstr(const MCInst &MI,\n"
263145449b1SDimitry Andric << " SmallVectorImpl<MCFixup> &Fixups,\n"
264145449b1SDimitry Andric << " APInt &Inst,\n"
265145449b1SDimitry Andric << " APInt &Scratch,\n"
266145449b1SDimitry Andric << " const MCSubtargetInfo &STI) const {\n";
267145449b1SDimitry Andric
268145449b1SDimitry Andric // Emit instruction base values
269b1c73532SDimitry Andric for (const auto &Mode : Modes)
270b1c73532SDimitry Andric emitInstructionBaseValues(OS, NumberedInstructions, Target, Mode.first);
271b1c73532SDimitry Andric
272b1c73532SDimitry Andric if (Modes.size() > 1) {
273b1c73532SDimitry Andric OS << " unsigned Mode = STI.getHwMode();\n";
274145449b1SDimitry Andric }
275145449b1SDimitry Andric
276b1c73532SDimitry Andric for (const auto &Mode : Modes) {
277145449b1SDimitry Andric // Emit helper function to retrieve base values.
278b1c73532SDimitry Andric OS << " auto getInstBits" << Mode.second
279b1c73532SDimitry Andric << " = [&](unsigned Opcode) -> APInt {\n"
280b1c73532SDimitry Andric << " unsigned NumBits = Index" << Mode.second << "[Opcode][0];\n"
281145449b1SDimitry Andric << " if (!NumBits)\n"
282145449b1SDimitry Andric << " return APInt::getZeroWidth();\n"
283b1c73532SDimitry Andric << " unsigned Idx = Index" << Mode.second << "[Opcode][1];\n"
284b1c73532SDimitry Andric << " ArrayRef<uint64_t> Data(&InstBits" << Mode.second << "[Idx], "
285145449b1SDimitry Andric << "APInt::getNumWords(NumBits));\n"
286145449b1SDimitry Andric << " return APInt(NumBits, Data);\n"
287145449b1SDimitry Andric << " };\n";
288b1c73532SDimitry Andric }
289145449b1SDimitry Andric
290145449b1SDimitry Andric // Map to accumulate all the cases.
291145449b1SDimitry Andric std::map<std::string, std::vector<std::string>> CaseMap;
292145449b1SDimitry Andric
293145449b1SDimitry Andric // Construct all cases statement for each opcode
294145449b1SDimitry Andric for (Record *R : Insts) {
295145449b1SDimitry Andric if (R->getValueAsString("Namespace") == "TargetOpcode" ||
296145449b1SDimitry Andric R->getValueAsBit("isPseudo"))
297145449b1SDimitry Andric continue;
298145449b1SDimitry Andric std::string InstName =
299145449b1SDimitry Andric (R->getValueAsString("Namespace") + "::" + R->getName()).str();
300b1c73532SDimitry Andric std::string Case = getInstructionCases(R, Target);
301145449b1SDimitry Andric
302145449b1SDimitry Andric CaseMap[Case].push_back(std::move(InstName));
303145449b1SDimitry Andric }
304145449b1SDimitry Andric
305145449b1SDimitry Andric // Emit initial function code
306145449b1SDimitry Andric OS << " const unsigned opcode = MI.getOpcode();\n"
307145449b1SDimitry Andric << " switch (opcode) {\n";
308145449b1SDimitry Andric
309145449b1SDimitry Andric // Emit each case statement
310145449b1SDimitry Andric for (const auto &C : CaseMap) {
311145449b1SDimitry Andric const std::string &Case = C.first;
312145449b1SDimitry Andric const auto &InstList = C.second;
313145449b1SDimitry Andric
314145449b1SDimitry Andric ListSeparator LS("\n");
315145449b1SDimitry Andric for (const auto &InstName : InstList)
316145449b1SDimitry Andric OS << LS << " case " << InstName << ":";
317145449b1SDimitry Andric
318145449b1SDimitry Andric OS << " {\n";
319145449b1SDimitry Andric OS << Case;
320145449b1SDimitry Andric OS << " break;\n"
321145449b1SDimitry Andric << " }\n";
322145449b1SDimitry Andric }
323145449b1SDimitry Andric // Default case: unhandled opcode
324145449b1SDimitry Andric OS << " default:\n"
325145449b1SDimitry Andric << " std::string msg;\n"
326145449b1SDimitry Andric << " raw_string_ostream Msg(msg);\n"
327145449b1SDimitry Andric << " Msg << \"Not supported instr: \" << MI;\n"
328145449b1SDimitry Andric << " report_fatal_error(Msg.str().c_str());\n"
329145449b1SDimitry Andric << " }\n";
330145449b1SDimitry Andric OS << "}\n\n";
331145449b1SDimitry Andric }
332145449b1SDimitry Andric
emitInstBits(raw_ostream & IS,raw_ostream & SS,const APInt & Bits,unsigned & Index)333145449b1SDimitry Andric static void emitInstBits(raw_ostream &IS, raw_ostream &SS, const APInt &Bits,
334145449b1SDimitry Andric unsigned &Index) {
335145449b1SDimitry Andric if (!Bits.getNumWords()) {
336145449b1SDimitry Andric IS.indent(4) << "{/*NumBits*/0, /*Index*/0},";
337145449b1SDimitry Andric return;
338145449b1SDimitry Andric }
339145449b1SDimitry Andric
340ac9a064cSDimitry Andric IS.indent(4) << "{/*NumBits*/" << Bits.getBitWidth() << ", " << "/*Index*/"
341ac9a064cSDimitry Andric << Index << "},";
342145449b1SDimitry Andric
343145449b1SDimitry Andric SS.indent(4);
344145449b1SDimitry Andric for (unsigned I = 0; I < Bits.getNumWords(); ++I, ++Index)
345145449b1SDimitry Andric SS << "UINT64_C(" << utostr(Bits.getRawData()[I]) << "),";
346145449b1SDimitry Andric }
347145449b1SDimitry Andric
emitInstructionBaseValues(raw_ostream & OS,ArrayRef<const CodeGenInstruction * > NumberedInstructions,CodeGenTarget & Target,AltEncodingTy Mode)348145449b1SDimitry Andric void VarLenCodeEmitterGen::emitInstructionBaseValues(
349145449b1SDimitry Andric raw_ostream &OS, ArrayRef<const CodeGenInstruction *> NumberedInstructions,
350b1c73532SDimitry Andric CodeGenTarget &Target, AltEncodingTy Mode) {
351145449b1SDimitry Andric std::string IndexArray, StorageArray;
352145449b1SDimitry Andric raw_string_ostream IS(IndexArray), SS(StorageArray);
353145449b1SDimitry Andric
354b1c73532SDimitry Andric IS << " static const unsigned Index" << Modes[Mode] << "[][2] = {\n";
355b1c73532SDimitry Andric SS << " static const uint64_t InstBits" << Modes[Mode] << "[] = {\n";
356145449b1SDimitry Andric
357145449b1SDimitry Andric unsigned NumFixedValueWords = 0U;
358145449b1SDimitry Andric for (const CodeGenInstruction *CGI : NumberedInstructions) {
359145449b1SDimitry Andric Record *R = CGI->TheDef;
360145449b1SDimitry Andric
361145449b1SDimitry Andric if (R->getValueAsString("Namespace") == "TargetOpcode" ||
362145449b1SDimitry Andric R->getValueAsBit("isPseudo")) {
363145449b1SDimitry Andric IS.indent(4) << "{/*NumBits*/0, /*Index*/0},\n";
364145449b1SDimitry Andric continue;
365145449b1SDimitry Andric }
366145449b1SDimitry Andric
367b1c73532SDimitry Andric const auto InstIt = VarLenInsts.find(R);
368b1c73532SDimitry Andric if (InstIt == VarLenInsts.end())
369b1c73532SDimitry Andric PrintFatalError(R, "VarLenInst not found for this record");
370b1c73532SDimitry Andric auto ModeIt = InstIt->second.find(Mode);
371b1c73532SDimitry Andric if (ModeIt == InstIt->second.end())
372b1c73532SDimitry Andric ModeIt = InstIt->second.find(Universal);
373b1c73532SDimitry Andric if (ModeIt == InstIt->second.end()) {
374ac9a064cSDimitry Andric IS.indent(4) << "{/*NumBits*/0, /*Index*/0},\t" << "// " << R->getName()
375ac9a064cSDimitry Andric << " no encoding\n";
376b1c73532SDimitry Andric continue;
377145449b1SDimitry Andric }
378b1c73532SDimitry Andric const VarLenInst &VLI = ModeIt->second;
379145449b1SDimitry Andric unsigned i = 0U, BitWidth = VLI.size();
380145449b1SDimitry Andric
381145449b1SDimitry Andric // Start by filling in fixed values.
382145449b1SDimitry Andric APInt Value(BitWidth, 0);
383145449b1SDimitry Andric auto SI = VLI.begin(), SE = VLI.end();
384145449b1SDimitry Andric // Scan through all the segments that have fixed-bits values.
385145449b1SDimitry Andric while (i < BitWidth && SI != SE) {
386145449b1SDimitry Andric unsigned SegmentNumBits = SI->BitWidth;
387145449b1SDimitry Andric if (const auto *BI = dyn_cast<BitsInit>(SI->Value)) {
388145449b1SDimitry Andric for (unsigned Idx = 0U; Idx != SegmentNumBits; ++Idx) {
389145449b1SDimitry Andric auto *B = cast<BitInit>(BI->getBit(Idx));
390145449b1SDimitry Andric Value.setBitVal(i + Idx, B->getValue());
391145449b1SDimitry Andric }
392145449b1SDimitry Andric }
393145449b1SDimitry Andric if (const auto *BI = dyn_cast<BitInit>(SI->Value))
394145449b1SDimitry Andric Value.setBitVal(i, BI->getValue());
395145449b1SDimitry Andric
396145449b1SDimitry Andric i += SegmentNumBits;
397145449b1SDimitry Andric ++SI;
398145449b1SDimitry Andric }
399145449b1SDimitry Andric
400145449b1SDimitry Andric emitInstBits(IS, SS, Value, NumFixedValueWords);
401145449b1SDimitry Andric IS << '\t' << "// " << R->getName() << "\n";
402145449b1SDimitry Andric if (Value.getNumWords())
403145449b1SDimitry Andric SS << '\t' << "// " << R->getName() << "\n";
404145449b1SDimitry Andric }
405145449b1SDimitry Andric IS.indent(4) << "{/*NumBits*/0, /*Index*/0}\n };\n";
406145449b1SDimitry Andric SS.indent(4) << "UINT64_C(0)\n };\n";
407145449b1SDimitry Andric
408ac9a064cSDimitry Andric OS << IndexArray << StorageArray;
409145449b1SDimitry Andric }
410145449b1SDimitry Andric
getInstructionCases(Record * R,CodeGenTarget & Target)411b1c73532SDimitry Andric std::string VarLenCodeEmitterGen::getInstructionCases(Record *R,
412145449b1SDimitry Andric CodeGenTarget &Target) {
413b1c73532SDimitry Andric auto It = VarLenInsts.find(R);
414b1c73532SDimitry Andric if (It == VarLenInsts.end())
415b1c73532SDimitry Andric PrintFatalError(R, "Parsed encoding record not found");
416b1c73532SDimitry Andric const auto &Map = It->second;
417b1c73532SDimitry Andric
418b1c73532SDimitry Andric // Is this instructions encoding universal (same for all modes)?
419b1c73532SDimitry Andric // Allways true if there is only one mode.
420b1c73532SDimitry Andric if (Map.size() == 1 && Map.begin()->first == Universal) {
421b1c73532SDimitry Andric // Universal, just pick the first mode.
422b1c73532SDimitry Andric AltEncodingTy Mode = Modes.begin()->first;
423b1c73532SDimitry Andric const auto &Encoding = Map.begin()->second;
424b1c73532SDimitry Andric return getInstructionCaseForEncoding(R, Mode, Encoding, Target, 6);
425b1c73532SDimitry Andric }
426b1c73532SDimitry Andric
427145449b1SDimitry Andric std::string Case;
428b1c73532SDimitry Andric Case += " switch (Mode) {\n";
429b1c73532SDimitry Andric Case += " default: llvm_unreachable(\"Unhandled Mode\");\n";
430b1c73532SDimitry Andric for (const auto &Mode : Modes) {
431b1c73532SDimitry Andric Case += " case " + itostr(Mode.first) + ": {\n";
432b1c73532SDimitry Andric const auto &It = Map.find(Mode.first);
433b1c73532SDimitry Andric if (It == Map.end()) {
434b1c73532SDimitry Andric Case +=
435b1c73532SDimitry Andric " llvm_unreachable(\"Undefined encoding in this mode\");\n";
436b1c73532SDimitry Andric } else {
437b1c73532SDimitry Andric Case +=
438b1c73532SDimitry Andric getInstructionCaseForEncoding(R, It->first, It->second, Target, 8);
439b1c73532SDimitry Andric }
440145449b1SDimitry Andric Case += " break;\n";
441145449b1SDimitry Andric Case += " }\n";
442145449b1SDimitry Andric }
443145449b1SDimitry Andric Case += " }\n";
444145449b1SDimitry Andric return Case;
445145449b1SDimitry Andric }
446145449b1SDimitry Andric
getInstructionCaseForEncoding(Record * R,AltEncodingTy Mode,const VarLenInst & VLI,CodeGenTarget & Target,int I)447145449b1SDimitry Andric std::string VarLenCodeEmitterGen::getInstructionCaseForEncoding(
448b1c73532SDimitry Andric Record *R, AltEncodingTy Mode, const VarLenInst &VLI, CodeGenTarget &Target,
449b1c73532SDimitry Andric int I) {
450145449b1SDimitry Andric
451145449b1SDimitry Andric CodeGenInstruction &CGI = Target.getInstruction(R);
452145449b1SDimitry Andric
453145449b1SDimitry Andric std::string Case;
454145449b1SDimitry Andric raw_string_ostream SS(Case);
455145449b1SDimitry Andric // Populate based value.
456b1c73532SDimitry Andric SS.indent(I) << "Inst = getInstBits" << Modes[Mode] << "(opcode);\n";
457145449b1SDimitry Andric
458145449b1SDimitry Andric // Process each segment in VLI.
459145449b1SDimitry Andric size_t Offset = 0U;
460b1c73532SDimitry Andric unsigned HighScratchAccess = 0U;
461145449b1SDimitry Andric for (const auto &ES : VLI) {
462145449b1SDimitry Andric unsigned NumBits = ES.BitWidth;
463145449b1SDimitry Andric const Init *Val = ES.Value;
464145449b1SDimitry Andric // If it's a StringInit or DagInit, it's a reference to an operand
465145449b1SDimitry Andric // or part of an operand.
466145449b1SDimitry Andric if (isa<StringInit>(Val) || isa<DagInit>(Val)) {
467145449b1SDimitry Andric StringRef OperandName;
468145449b1SDimitry Andric unsigned LoBit = 0U;
469145449b1SDimitry Andric if (const auto *SV = dyn_cast<StringInit>(Val)) {
470145449b1SDimitry Andric OperandName = SV->getValue();
471145449b1SDimitry Andric } else {
472145449b1SDimitry Andric // Normalized: (slice <operand name>, <high bit>, <low bit>)
473145449b1SDimitry Andric const auto *DV = cast<DagInit>(Val);
474145449b1SDimitry Andric OperandName = cast<StringInit>(DV->getArg(0))->getValue();
475145449b1SDimitry Andric LoBit = static_cast<unsigned>(cast<IntInit>(DV->getArg(2))->getValue());
476145449b1SDimitry Andric }
477145449b1SDimitry Andric
478145449b1SDimitry Andric auto OpIdx = CGI.Operands.ParseOperandName(OperandName);
479145449b1SDimitry Andric unsigned FlatOpIdx = CGI.Operands.getFlattenedOperandNumber(OpIdx);
480e3b55780SDimitry Andric StringRef CustomEncoder =
481e3b55780SDimitry Andric CGI.Operands[OpIdx.first].EncoderMethodNames[OpIdx.second];
482145449b1SDimitry Andric if (ES.CustomEncoder.size())
483145449b1SDimitry Andric CustomEncoder = ES.CustomEncoder;
484145449b1SDimitry Andric
485b1c73532SDimitry Andric SS.indent(I) << "Scratch.clearAllBits();\n";
486b1c73532SDimitry Andric SS.indent(I) << "// op: " << OperandName.drop_front(1) << "\n";
487145449b1SDimitry Andric if (CustomEncoder.empty())
488b1c73532SDimitry Andric SS.indent(I) << "getMachineOpValue(MI, MI.getOperand("
489145449b1SDimitry Andric << utostr(FlatOpIdx) << ")";
490145449b1SDimitry Andric else
491b1c73532SDimitry Andric SS.indent(I) << CustomEncoder << "(MI, /*OpIdx=*/" << utostr(FlatOpIdx);
492145449b1SDimitry Andric
493145449b1SDimitry Andric SS << ", /*Pos=*/" << utostr(Offset) << ", Scratch, Fixups, STI);\n";
494145449b1SDimitry Andric
495ac9a064cSDimitry Andric SS.indent(I) << "Inst.insertBits(" << "Scratch.extractBits("
496ac9a064cSDimitry Andric << utostr(NumBits) << ", " << utostr(LoBit) << ")" << ", "
497ac9a064cSDimitry Andric << Offset << ");\n";
498b1c73532SDimitry Andric
499b1c73532SDimitry Andric HighScratchAccess = std::max(HighScratchAccess, NumBits + LoBit);
500145449b1SDimitry Andric }
501145449b1SDimitry Andric Offset += NumBits;
502145449b1SDimitry Andric }
503145449b1SDimitry Andric
504145449b1SDimitry Andric StringRef PostEmitter = R->getValueAsString("PostEncoderMethod");
505145449b1SDimitry Andric if (!PostEmitter.empty())
506b1c73532SDimitry Andric SS.indent(I) << "Inst = " << PostEmitter << "(MI, Inst, STI);\n";
507145449b1SDimitry Andric
508b1c73532SDimitry Andric // Resize the scratch buffer if it's to small.
509b1c73532SDimitry Andric std::string ScratchResizeStr;
510b1c73532SDimitry Andric if (VLI.size() && !VLI.isFixedValueOnly()) {
511b1c73532SDimitry Andric raw_string_ostream RS(ScratchResizeStr);
512b1c73532SDimitry Andric RS.indent(I) << "if (Scratch.getBitWidth() < " << HighScratchAccess
513b1c73532SDimitry Andric << ") { Scratch = Scratch.zext(" << HighScratchAccess
514b1c73532SDimitry Andric << "); }\n";
515b1c73532SDimitry Andric }
516b1c73532SDimitry Andric
517b1c73532SDimitry Andric return ScratchResizeStr + Case;
518145449b1SDimitry Andric }
519145449b1SDimitry Andric
520145449b1SDimitry Andric namespace llvm {
521145449b1SDimitry Andric
emitVarLenCodeEmitter(RecordKeeper & R,raw_ostream & OS)522145449b1SDimitry Andric void emitVarLenCodeEmitter(RecordKeeper &R, raw_ostream &OS) {
523145449b1SDimitry Andric VarLenCodeEmitterGen(R).run(OS);
524145449b1SDimitry Andric }
525145449b1SDimitry Andric
526145449b1SDimitry Andric } // end namespace llvm
527