1009b1c42SEd Schouten //===- CodeEmitterGen.cpp - Code Emitter Generator ------------------------===//
2009b1c42SEd Schouten //
3e6d15924SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4e6d15924SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
5e6d15924SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6009b1c42SEd Schouten //
7009b1c42SEd Schouten //===----------------------------------------------------------------------===//
8009b1c42SEd Schouten //
9009b1c42SEd Schouten // CodeEmitterGen uses the descriptions of instructions and their fields to
107fa27ce4SDimitry Andric // construct an automated code emitter: a function called
117fa27ce4SDimitry Andric // getBinaryCodeForInstr() that, given a MCInst, returns the value of the
127fa27ce4SDimitry Andric // instruction - either as an uint64_t or as an APInt, depending on the
137fa27ce4SDimitry Andric // maximum bit width of all Inst definitions.
147fa27ce4SDimitry Andric //
157fa27ce4SDimitry Andric // In addition, it generates another function called getOperandBitOffset()
167fa27ce4SDimitry Andric // that, given a MCInst and an operand index, returns the minimum of indices of
177fa27ce4SDimitry Andric // all bits that carry some portion of the respective operand. When the target's
187fa27ce4SDimitry Andric // encodeInstruction() stores the instruction in a little-endian byte order, the
197fa27ce4SDimitry Andric // returned value is the offset of the start of the operand in the encoded
207fa27ce4SDimitry Andric // instruction. Other targets might need to adjust the returned value according
217fa27ce4SDimitry Andric // to their encodeInstruction() implementation.
22009b1c42SEd Schouten //
23009b1c42SEd Schouten //===----------------------------------------------------------------------===//
24009b1c42SEd Schouten
25ac9a064cSDimitry Andric #include "Common/CodeGenHwModes.h"
26ac9a064cSDimitry Andric #include "Common/CodeGenInstruction.h"
27ac9a064cSDimitry Andric #include "Common/CodeGenTarget.h"
28ac9a064cSDimitry Andric #include "Common/InfoByHwMode.h"
29ac9a064cSDimitry Andric #include "Common/VarLenCodeEmitterGen.h"
301d5ae102SDimitry Andric #include "llvm/ADT/APInt.h"
31b915e9e0SDimitry Andric #include "llvm/ADT/ArrayRef.h"
32009b1c42SEd Schouten #include "llvm/ADT/StringExtras.h"
33b915e9e0SDimitry Andric #include "llvm/Support/Casting.h"
34b915e9e0SDimitry Andric #include "llvm/Support/raw_ostream.h"
35145449b1SDimitry Andric #include "llvm/TableGen/Error.h"
364a16efa3SDimitry Andric #include "llvm/TableGen/Record.h"
3758b69754SDimitry Andric #include "llvm/TableGen/TableGenBackend.h"
38b915e9e0SDimitry Andric #include <cstdint>
39cf099d11SDimitry Andric #include <map>
40b915e9e0SDimitry Andric #include <set>
4158b69754SDimitry Andric #include <string>
42b915e9e0SDimitry Andric #include <utility>
4358b69754SDimitry Andric #include <vector>
44b915e9e0SDimitry Andric
45009b1c42SEd Schouten using namespace llvm;
46009b1c42SEd Schouten
4758b69754SDimitry Andric namespace {
4858b69754SDimitry Andric
4958b69754SDimitry Andric class CodeEmitterGen {
5058b69754SDimitry Andric RecordKeeper &Records;
51b915e9e0SDimitry Andric
5258b69754SDimitry Andric public:
CodeEmitterGen(RecordKeeper & R)5358b69754SDimitry Andric CodeEmitterGen(RecordKeeper &R) : Records(R) {}
5458b69754SDimitry Andric
5558b69754SDimitry Andric void run(raw_ostream &o);
56b915e9e0SDimitry Andric
5758b69754SDimitry Andric private:
5858b69754SDimitry Andric int getVariableBit(const std::string &VarName, BitsInit *BI, int bit);
597fa27ce4SDimitry Andric std::pair<std::string, std::string>
607fa27ce4SDimitry Andric getInstructionCases(Record *R, CodeGenTarget &Target);
617fa27ce4SDimitry Andric void addInstructionCasesForEncoding(Record *R, Record *EncodingDef,
627fa27ce4SDimitry Andric CodeGenTarget &Target, std::string &Case,
637fa27ce4SDimitry Andric std::string &BitOffsetCase);
64e3b55780SDimitry Andric bool addCodeToMergeInOperand(Record *R, BitsInit *BI,
657fa27ce4SDimitry Andric const std::string &VarName, std::string &Case,
667fa27ce4SDimitry Andric std::string &BitOffsetCase,
677fa27ce4SDimitry Andric CodeGenTarget &Target);
6858b69754SDimitry Andric
691d5ae102SDimitry Andric void emitInstructionBaseValues(
701d5ae102SDimitry Andric raw_ostream &o, ArrayRef<const CodeGenInstruction *> NumberedInstructions,
71ac9a064cSDimitry Andric CodeGenTarget &Target, unsigned HwMode = DefaultMode);
727fa27ce4SDimitry Andric void
737fa27ce4SDimitry Andric emitCaseMap(raw_ostream &o,
747fa27ce4SDimitry Andric const std::map<std::string, std::vector<std::string>> &CaseMap);
757fa27ce4SDimitry Andric unsigned BitWidth = 0u;
767fa27ce4SDimitry Andric bool UseAPInt = false;
7758b69754SDimitry Andric };
7858b69754SDimitry Andric
79009b1c42SEd Schouten // If the VarBitInit at position 'bit' matches the specified variable then
80009b1c42SEd Schouten // return the variable bit position. Otherwise return -1.
getVariableBit(const std::string & VarName,BitsInit * BI,int bit)81ac9a064cSDimitry Andric int CodeEmitterGen::getVariableBit(const std::string &VarName, BitsInit *BI,
82ac9a064cSDimitry Andric int bit) {
83522600a2SDimitry Andric if (VarBitInit *VBI = dyn_cast<VarBitInit>(BI->getBit(bit))) {
84522600a2SDimitry Andric if (VarInit *VI = dyn_cast<VarInit>(VBI->getBitVar()))
85cf099d11SDimitry Andric if (VI->getName() == VarName)
86cf099d11SDimitry Andric return VBI->getBitNum();
87522600a2SDimitry Andric } else if (VarInit *VI = dyn_cast<VarInit>(BI->getBit(bit))) {
886b943ff3SDimitry Andric if (VI->getName() == VarName)
896b943ff3SDimitry Andric return 0;
906b943ff3SDimitry Andric }
91009b1c42SEd Schouten
92009b1c42SEd Schouten return -1;
93009b1c42SEd Schouten }
94009b1c42SEd Schouten
95e3b55780SDimitry Andric // Returns true if it succeeds, false if an error.
addCodeToMergeInOperand(Record * R,BitsInit * BI,const std::string & VarName,std::string & Case,std::string & BitOffsetCase,CodeGenTarget & Target)96e3b55780SDimitry Andric bool CodeEmitterGen::addCodeToMergeInOperand(Record *R, BitsInit *BI,
97e3b55780SDimitry Andric const std::string &VarName,
98e3b55780SDimitry Andric std::string &Case,
997fa27ce4SDimitry Andric std::string &BitOffsetCase,
100e3b55780SDimitry Andric CodeGenTarget &Target) {
101cf099d11SDimitry Andric CodeGenInstruction &CGI = Target.getInstruction(R);
102cf099d11SDimitry Andric
103cf099d11SDimitry Andric // Determine if VarName actually contributes to the Inst encoding.
104cf099d11SDimitry Andric int bit = BI->getNumBits() - 1;
105cf099d11SDimitry Andric
106cf099d11SDimitry Andric // Scan for a bit that this contributed to.
107cf099d11SDimitry Andric for (; bit >= 0;) {
108cf099d11SDimitry Andric if (getVariableBit(VarName, BI, bit) != -1)
109cf099d11SDimitry Andric break;
110cf099d11SDimitry Andric
111cf099d11SDimitry Andric --bit;
112cf099d11SDimitry Andric }
113cf099d11SDimitry Andric
114cf099d11SDimitry Andric // If we found no bits, ignore this value, otherwise emit the call to get the
115cf099d11SDimitry Andric // operand encoding.
116e3b55780SDimitry Andric if (bit < 0)
117e3b55780SDimitry Andric return true;
118cf099d11SDimitry Andric
119cf099d11SDimitry Andric // If the operand matches by name, reference according to that
120cf099d11SDimitry Andric // operand number. Non-matching operands are assumed to be in
121cf099d11SDimitry Andric // order.
122cf099d11SDimitry Andric unsigned OpIdx;
123e3b55780SDimitry Andric std::pair<unsigned, unsigned> SubOp;
124e3b55780SDimitry Andric if (CGI.Operands.hasSubOperandAlias(VarName, SubOp)) {
125e3b55780SDimitry Andric OpIdx = CGI.Operands[SubOp.first].MIOperandNo + SubOp.second;
126e3b55780SDimitry Andric } else if (CGI.Operands.hasOperandNamed(VarName, OpIdx)) {
127cf099d11SDimitry Andric // Get the machine operand number for the indicated operand.
128cf099d11SDimitry Andric OpIdx = CGI.Operands[OpIdx].MIOperandNo;
129cf099d11SDimitry Andric } else {
130ac9a064cSDimitry Andric PrintError(R, Twine("No operand named ") + VarName + " in record " +
131ac9a064cSDimitry Andric R->getName());
132e3b55780SDimitry Andric return false;
1335ca98fd9SDimitry Andric }
1345ca98fd9SDimitry Andric
135e3b55780SDimitry Andric if (CGI.Operands.isFlatOperandNotEmitted(OpIdx)) {
136ac9a064cSDimitry Andric PrintError(R,
137ac9a064cSDimitry Andric "Operand " + VarName + " used but also marked as not emitted!");
138e3b55780SDimitry Andric return false;
139cf099d11SDimitry Andric }
140cf099d11SDimitry Andric
141cf099d11SDimitry Andric std::pair<unsigned, unsigned> SO = CGI.Operands.getSubOperandNumber(OpIdx);
142e3b55780SDimitry Andric std::string &EncoderMethodName =
143e3b55780SDimitry Andric CGI.Operands[SO.first].EncoderMethodNames[SO.second];
144cf099d11SDimitry Andric
1451d5ae102SDimitry Andric if (UseAPInt)
1461d5ae102SDimitry Andric Case += " op.clearAllBits();\n";
1471d5ae102SDimitry Andric
1481d5ae102SDimitry Andric Case += " // op: " + VarName + "\n";
149e3b55780SDimitry Andric
150e3b55780SDimitry Andric // If the source operand has a custom encoder, use it.
151e3b55780SDimitry Andric if (!EncoderMethodName.empty()) {
1521d5ae102SDimitry Andric if (UseAPInt) {
1531d5ae102SDimitry Andric Case += " " + EncoderMethodName + "(MI, " + utostr(OpIdx);
1541d5ae102SDimitry Andric Case += ", op";
1551d5ae102SDimitry Andric } else {
1561d5ae102SDimitry Andric Case += " op = " + EncoderMethodName + "(MI, " + utostr(OpIdx);
1571d5ae102SDimitry Andric }
1581d5ae102SDimitry Andric Case += ", Fixups, STI);\n";
159cf099d11SDimitry Andric } else {
1601d5ae102SDimitry Andric if (UseAPInt) {
161ac9a064cSDimitry Andric Case +=
162ac9a064cSDimitry Andric " getMachineOpValue(MI, MI.getOperand(" + utostr(OpIdx) + ")";
1631d5ae102SDimitry Andric Case += ", op, Fixups, STI";
1641d5ae102SDimitry Andric } else {
165ac9a064cSDimitry Andric Case += " op = getMachineOpValue(MI, MI.getOperand(" +
166ac9a064cSDimitry Andric utostr(OpIdx) + ")";
1675ca98fd9SDimitry Andric Case += ", Fixups, STI";
1681d5ae102SDimitry Andric }
169cf099d11SDimitry Andric Case += ");\n";
170cf099d11SDimitry Andric }
171cf099d11SDimitry Andric
1721d5ae102SDimitry Andric // Precalculate the number of lits this variable contributes to in the
1731d5ae102SDimitry Andric // operand. If there is a single lit (consecutive range of bits) we can use a
1741d5ae102SDimitry Andric // destructive sequence on APInt that reduces memory allocations.
1751d5ae102SDimitry Andric int numOperandLits = 0;
1761d5ae102SDimitry Andric for (int tmpBit = bit; tmpBit >= 0;) {
1771d5ae102SDimitry Andric int varBit = getVariableBit(VarName, BI, tmpBit);
1781d5ae102SDimitry Andric
1791d5ae102SDimitry Andric // If this bit isn't from a variable, skip it.
1801d5ae102SDimitry Andric if (varBit == -1) {
1811d5ae102SDimitry Andric --tmpBit;
1821d5ae102SDimitry Andric continue;
1831d5ae102SDimitry Andric }
1841d5ae102SDimitry Andric
1851d5ae102SDimitry Andric // Figure out the consecutive range of bits covered by this operand, in
1861d5ae102SDimitry Andric // order to generate better encoding code.
1871d5ae102SDimitry Andric int beginVarBit = varBit;
1881d5ae102SDimitry Andric int N = 1;
1891d5ae102SDimitry Andric for (--tmpBit; tmpBit >= 0;) {
1901d5ae102SDimitry Andric varBit = getVariableBit(VarName, BI, tmpBit);
1911d5ae102SDimitry Andric if (varBit == -1 || varBit != (beginVarBit - N))
1921d5ae102SDimitry Andric break;
1931d5ae102SDimitry Andric ++N;
1941d5ae102SDimitry Andric --tmpBit;
1951d5ae102SDimitry Andric }
1961d5ae102SDimitry Andric ++numOperandLits;
1971d5ae102SDimitry Andric }
1981d5ae102SDimitry Andric
1997fa27ce4SDimitry Andric unsigned BitOffset = -1;
200cf099d11SDimitry Andric for (; bit >= 0;) {
201cf099d11SDimitry Andric int varBit = getVariableBit(VarName, BI, bit);
202cf099d11SDimitry Andric
203cf099d11SDimitry Andric // If this bit isn't from a variable, skip it.
204cf099d11SDimitry Andric if (varBit == -1) {
205cf099d11SDimitry Andric --bit;
206cf099d11SDimitry Andric continue;
207cf099d11SDimitry Andric }
208cf099d11SDimitry Andric
209cf099d11SDimitry Andric // Figure out the consecutive range of bits covered by this operand, in
210cf099d11SDimitry Andric // order to generate better encoding code.
211cf099d11SDimitry Andric int beginInstBit = bit;
212cf099d11SDimitry Andric int beginVarBit = varBit;
213cf099d11SDimitry Andric int N = 1;
214cf099d11SDimitry Andric for (--bit; bit >= 0;) {
215cf099d11SDimitry Andric varBit = getVariableBit(VarName, BI, bit);
216ac9a064cSDimitry Andric if (varBit == -1 || varBit != (beginVarBit - N))
217ac9a064cSDimitry Andric break;
218cf099d11SDimitry Andric ++N;
219cf099d11SDimitry Andric --bit;
220cf099d11SDimitry Andric }
221cf099d11SDimitry Andric
2221d5ae102SDimitry Andric std::string maskStr;
2231d5ae102SDimitry Andric int opShift;
2241d5ae102SDimitry Andric
2251d5ae102SDimitry Andric unsigned loBit = beginVarBit - N + 1;
2261d5ae102SDimitry Andric unsigned hiBit = loBit + N;
2271d5ae102SDimitry Andric unsigned loInstBit = beginInstBit - N + 1;
2287fa27ce4SDimitry Andric BitOffset = loInstBit;
2291d5ae102SDimitry Andric if (UseAPInt) {
2301d5ae102SDimitry Andric std::string extractStr;
2311d5ae102SDimitry Andric if (N >= 64) {
2321d5ae102SDimitry Andric extractStr = "op.extractBits(" + itostr(hiBit - loBit) + ", " +
2331d5ae102SDimitry Andric itostr(loBit) + ")";
2341d5ae102SDimitry Andric Case += " Value.insertBits(" + extractStr + ", " +
2351d5ae102SDimitry Andric itostr(loInstBit) + ");\n";
2361d5ae102SDimitry Andric } else {
2371d5ae102SDimitry Andric extractStr = "op.extractBitsAsZExtValue(" + itostr(hiBit - loBit) +
2381d5ae102SDimitry Andric ", " + itostr(loBit) + ")";
2391d5ae102SDimitry Andric Case += " Value.insertBits(" + extractStr + ", " +
2401d5ae102SDimitry Andric itostr(loInstBit) + ", " + itostr(hiBit - loBit) + ");\n";
2411d5ae102SDimitry Andric }
2421d5ae102SDimitry Andric } else {
24363faed5bSDimitry Andric uint64_t opMask = ~(uint64_t)0 >> (64 - N);
2441d5ae102SDimitry Andric opShift = beginVarBit - N + 1;
245cf099d11SDimitry Andric opMask <<= opShift;
2461d5ae102SDimitry Andric maskStr = "UINT64_C(" + utostr(opMask) + ")";
247cf099d11SDimitry Andric opShift = beginInstBit - beginVarBit;
248cf099d11SDimitry Andric
2491d5ae102SDimitry Andric if (numOperandLits == 1) {
2501d5ae102SDimitry Andric Case += " op &= " + maskStr + ";\n";
251cf099d11SDimitry Andric if (opShift > 0) {
2521d5ae102SDimitry Andric Case += " op <<= " + itostr(opShift) + ";\n";
2531d5ae102SDimitry Andric } else if (opShift < 0) {
2541d5ae102SDimitry Andric Case += " op >>= " + itostr(-opShift) + ";\n";
2551d5ae102SDimitry Andric }
2561d5ae102SDimitry Andric Case += " Value |= op;\n";
2571d5ae102SDimitry Andric } else {
2581d5ae102SDimitry Andric if (opShift > 0) {
2591d5ae102SDimitry Andric Case += " Value |= (op & " + maskStr + ") << " +
260cf099d11SDimitry Andric itostr(opShift) + ";\n";
261cf099d11SDimitry Andric } else if (opShift < 0) {
2621d5ae102SDimitry Andric Case += " Value |= (op & " + maskStr + ") >> " +
263cf099d11SDimitry Andric itostr(-opShift) + ";\n";
264cf099d11SDimitry Andric } else {
2651d5ae102SDimitry Andric Case += " Value |= (op & " + maskStr + ");\n";
2661d5ae102SDimitry Andric }
2671d5ae102SDimitry Andric }
268cf099d11SDimitry Andric }
269cf099d11SDimitry Andric }
2707fa27ce4SDimitry Andric
2717fa27ce4SDimitry Andric if (BitOffset != (unsigned)-1) {
2727fa27ce4SDimitry Andric BitOffsetCase += " case " + utostr(OpIdx) + ":\n";
2737fa27ce4SDimitry Andric BitOffsetCase += " // op: " + VarName + "\n";
2747fa27ce4SDimitry Andric BitOffsetCase += " return " + utostr(BitOffset) + ";\n";
2757fa27ce4SDimitry Andric }
2767fa27ce4SDimitry Andric
277e3b55780SDimitry Andric return true;
278cf099d11SDimitry Andric }
279cf099d11SDimitry Andric
2807fa27ce4SDimitry Andric std::pair<std::string, std::string>
getInstructionCases(Record * R,CodeGenTarget & Target)2817fa27ce4SDimitry Andric CodeEmitterGen::getInstructionCases(Record *R, CodeGenTarget &Target) {
2827fa27ce4SDimitry Andric std::string Case, BitOffsetCase;
2837fa27ce4SDimitry Andric
284ac9a064cSDimitry Andric auto append = [&](const std::string &S) {
2857fa27ce4SDimitry Andric Case += S;
2867fa27ce4SDimitry Andric BitOffsetCase += S;
2877fa27ce4SDimitry Andric };
2887fa27ce4SDimitry Andric
2891d5ae102SDimitry Andric if (const RecordVal *RV = R->getValue("EncodingInfos")) {
2901d5ae102SDimitry Andric if (auto *DI = dyn_cast_or_null<DefInit>(RV->getValue())) {
2911d5ae102SDimitry Andric const CodeGenHwModes &HWM = Target.getHwModes();
2921d5ae102SDimitry Andric EncodingInfoByHwMode EBM(DI->getDef(), HWM);
293ac9a064cSDimitry Andric
294ac9a064cSDimitry Andric // Invoke the interface to obtain the HwMode ID controlling the
295ac9a064cSDimitry Andric // EncodingInfo for the current subtarget. This interface will
296ac9a064cSDimitry Andric // mask off irrelevant HwMode IDs.
297ac9a064cSDimitry Andric append(" unsigned HwMode = "
298ac9a064cSDimitry Andric "STI.getHwMode(MCSubtargetInfo::HwMode_EncodingInfo);\n");
299ac9a064cSDimitry Andric Case += " switch (HwMode) {\n";
300ac9a064cSDimitry Andric Case += " default: llvm_unreachable(\"Unknown hardware mode!\"); "
301ac9a064cSDimitry Andric "break;\n";
302ac9a064cSDimitry Andric for (auto &[ModeId, Encoding] : EBM) {
303ac9a064cSDimitry Andric if (ModeId == DefaultMode) {
304ac9a064cSDimitry Andric Case +=
305ac9a064cSDimitry Andric " case " + itostr(DefaultMode) + ": InstBitsByHw = InstBits";
306ac9a064cSDimitry Andric } else {
307ac9a064cSDimitry Andric Case += " case " + itostr(ModeId) +
308ac9a064cSDimitry Andric ": InstBitsByHw = InstBits_" +
309ac9a064cSDimitry Andric std::string(HWM.getMode(ModeId).Name);
310ac9a064cSDimitry Andric }
311ac9a064cSDimitry Andric Case += "; break;\n";
312ac9a064cSDimitry Andric }
313ac9a064cSDimitry Andric Case += " };\n";
314ac9a064cSDimitry Andric
315ac9a064cSDimitry Andric // We need to remodify the 'Inst' value from the table we found above.
316ac9a064cSDimitry Andric if (UseAPInt) {
317ac9a064cSDimitry Andric int NumWords = APInt::getNumWords(BitWidth);
318ac9a064cSDimitry Andric Case += " Inst = APInt(" + itostr(BitWidth);
319ac9a064cSDimitry Andric Case += ", ArrayRef(InstBitsByHw + opcode * " + itostr(NumWords) +
320ac9a064cSDimitry Andric ", " + itostr(NumWords);
321ac9a064cSDimitry Andric Case += "));\n";
322ac9a064cSDimitry Andric Case += " Value = Inst;\n";
323ac9a064cSDimitry Andric } else {
324ac9a064cSDimitry Andric Case += " Value = InstBitsByHw[opcode];\n";
325ac9a064cSDimitry Andric }
326ac9a064cSDimitry Andric
3277fa27ce4SDimitry Andric append(" switch (HwMode) {\n");
3287fa27ce4SDimitry Andric append(" default: llvm_unreachable(\"Unhandled HwMode\");\n");
329ac9a064cSDimitry Andric for (auto &[ModeId, Encoding] : EBM) {
330ac9a064cSDimitry Andric append(" case " + itostr(ModeId) + ": {\n");
331ac9a064cSDimitry Andric addInstructionCasesForEncoding(R, Encoding, Target, Case,
3327fa27ce4SDimitry Andric BitOffsetCase);
3337fa27ce4SDimitry Andric append(" break;\n");
3347fa27ce4SDimitry Andric append(" }\n");
3351d5ae102SDimitry Andric }
3367fa27ce4SDimitry Andric append(" }\n");
337ac9a064cSDimitry Andric return std::pair(std::move(Case), std::move(BitOffsetCase));
3381d5ae102SDimitry Andric }
3391d5ae102SDimitry Andric }
3407fa27ce4SDimitry Andric addInstructionCasesForEncoding(R, R, Target, Case, BitOffsetCase);
341ac9a064cSDimitry Andric return std::pair(std::move(Case), std::move(BitOffsetCase));
3421d5ae102SDimitry Andric }
3431d5ae102SDimitry Andric
addInstructionCasesForEncoding(Record * R,Record * EncodingDef,CodeGenTarget & Target,std::string & Case,std::string & BitOffsetCase)3447fa27ce4SDimitry Andric void CodeEmitterGen::addInstructionCasesForEncoding(
3457fa27ce4SDimitry Andric Record *R, Record *EncodingDef, CodeGenTarget &Target, std::string &Case,
3467fa27ce4SDimitry Andric std::string &BitOffsetCase) {
3471d5ae102SDimitry Andric BitsInit *BI = EncodingDef->getValueAsBitsInit("Inst");
3485ca98fd9SDimitry Andric
349cf099d11SDimitry Andric // Loop over all of the fields in the instruction, determining which are the
350cf099d11SDimitry Andric // operands to the instruction.
351e3b55780SDimitry Andric bool Success = true;
3527fa27ce4SDimitry Andric size_t OrigBitOffsetCaseSize = BitOffsetCase.size();
3537fa27ce4SDimitry Andric BitOffsetCase += " switch (OpNum) {\n";
3547fa27ce4SDimitry Andric size_t BitOffsetCaseSizeBeforeLoop = BitOffsetCase.size();
3551d5ae102SDimitry Andric for (const RecordVal &RV : EncodingDef->getValues()) {
356cf099d11SDimitry Andric // Ignore fixed fields in the record, we're looking for values like:
357cf099d11SDimitry Andric // bits<5> RST = { ?, ?, ?, ?, ? };
358b60736ecSDimitry Andric if (RV.isNonconcreteOK() || RV.getValue()->isComplete())
359cf099d11SDimitry Andric continue;
360cf099d11SDimitry Andric
3617fa27ce4SDimitry Andric Success &= addCodeToMergeInOperand(R, BI, std::string(RV.getName()), Case,
3627fa27ce4SDimitry Andric BitOffsetCase, Target);
363cf099d11SDimitry Andric }
3647fa27ce4SDimitry Andric // Avoid empty switches.
3657fa27ce4SDimitry Andric if (BitOffsetCase.size() == BitOffsetCaseSizeBeforeLoop)
3667fa27ce4SDimitry Andric BitOffsetCase.resize(OrigBitOffsetCaseSize);
3677fa27ce4SDimitry Andric else
3687fa27ce4SDimitry Andric BitOffsetCase += " }\n";
369cf099d11SDimitry Andric
370e3b55780SDimitry Andric if (!Success) {
371e3b55780SDimitry Andric // Dump the record, so we can see what's going on...
372e3b55780SDimitry Andric std::string E;
373e3b55780SDimitry Andric raw_string_ostream S(E);
374e3b55780SDimitry Andric S << "Dumping record for previous error:\n";
375e3b55780SDimitry Andric S << *R;
376e3b55780SDimitry Andric PrintNote(E);
377e3b55780SDimitry Andric }
378e3b55780SDimitry Andric
379f382538dSDimitry Andric StringRef PostEmitter = R->getValueAsString("PostEncoderMethod");
3805ca98fd9SDimitry Andric if (!PostEmitter.empty()) {
381f382538dSDimitry Andric Case += " Value = ";
382f382538dSDimitry Andric Case += PostEmitter;
383f382538dSDimitry Andric Case += "(MI, Value";
3845ca98fd9SDimitry Andric Case += ", STI";
3855ca98fd9SDimitry Andric Case += ");\n";
3865ca98fd9SDimitry Andric }
387cf099d11SDimitry Andric }
388009b1c42SEd Schouten
emitInstBits(raw_ostream & OS,const APInt & Bits)3891d5ae102SDimitry Andric static void emitInstBits(raw_ostream &OS, const APInt &Bits) {
3901d5ae102SDimitry Andric for (unsigned I = 0; I < Bits.getNumWords(); ++I)
3911d5ae102SDimitry Andric OS << ((I > 0) ? ", " : "") << "UINT64_C(" << utostr(Bits.getRawData()[I])
3921d5ae102SDimitry Andric << ")";
3931d5ae102SDimitry Andric }
3941d5ae102SDimitry Andric
emitInstructionBaseValues(raw_ostream & o,ArrayRef<const CodeGenInstruction * > NumberedInstructions,CodeGenTarget & Target,unsigned HwMode)3951d5ae102SDimitry Andric void CodeEmitterGen::emitInstructionBaseValues(
3961d5ae102SDimitry Andric raw_ostream &o, ArrayRef<const CodeGenInstruction *> NumberedInstructions,
397ac9a064cSDimitry Andric CodeGenTarget &Target, unsigned HwMode) {
3981d5ae102SDimitry Andric const CodeGenHwModes &HWM = Target.getHwModes();
399ac9a064cSDimitry Andric if (HwMode == DefaultMode)
4001d5ae102SDimitry Andric o << " static const uint64_t InstBits[] = {\n";
4011d5ae102SDimitry Andric else
402ac9a064cSDimitry Andric o << " static const uint64_t InstBits_"
403ac9a064cSDimitry Andric << HWM.getModeName(HwMode, /*IncludeDefault=*/true) << "[] = {\n";
4041d5ae102SDimitry Andric
4051d5ae102SDimitry Andric for (const CodeGenInstruction *CGI : NumberedInstructions) {
4061d5ae102SDimitry Andric Record *R = CGI->TheDef;
4071d5ae102SDimitry Andric
4081d5ae102SDimitry Andric if (R->getValueAsString("Namespace") == "TargetOpcode" ||
4091d5ae102SDimitry Andric R->getValueAsBit("isPseudo")) {
410ac9a064cSDimitry Andric o << " ";
411ac9a064cSDimitry Andric emitInstBits(o, APInt(BitWidth, 0));
412ac9a064cSDimitry Andric o << ",\n";
4131d5ae102SDimitry Andric continue;
4141d5ae102SDimitry Andric }
4151d5ae102SDimitry Andric
4161d5ae102SDimitry Andric Record *EncodingDef = R;
4171d5ae102SDimitry Andric if (const RecordVal *RV = R->getValue("EncodingInfos")) {
4181d5ae102SDimitry Andric if (auto *DI = dyn_cast_or_null<DefInit>(RV->getValue())) {
4191d5ae102SDimitry Andric EncodingInfoByHwMode EBM(DI->getDef(), HWM);
420ac9a064cSDimitry Andric if (EBM.hasMode(HwMode)) {
4211d5ae102SDimitry Andric EncodingDef = EBM.get(HwMode);
422ac9a064cSDimitry Andric } else {
423ac9a064cSDimitry Andric // If the HwMode does not match, then Encoding '0'
424ac9a064cSDimitry Andric // should be generated.
425ac9a064cSDimitry Andric APInt Value(BitWidth, 0);
426ac9a064cSDimitry Andric o << " ";
427ac9a064cSDimitry Andric emitInstBits(o, Value);
428ac9a064cSDimitry Andric o << "," << '\t' << "// " << R->getName() << "\n";
429ac9a064cSDimitry Andric continue;
430ac9a064cSDimitry Andric }
4311d5ae102SDimitry Andric }
4321d5ae102SDimitry Andric }
4331d5ae102SDimitry Andric BitsInit *BI = EncodingDef->getValueAsBitsInit("Inst");
4341d5ae102SDimitry Andric
4351d5ae102SDimitry Andric // Start by filling in fixed values.
4361d5ae102SDimitry Andric APInt Value(BitWidth, 0);
4371d5ae102SDimitry Andric for (unsigned i = 0, e = BI->getNumBits(); i != e; ++i) {
438e3b55780SDimitry Andric if (auto *B = dyn_cast<BitInit>(BI->getBit(i)); B && B->getValue())
439e3b55780SDimitry Andric Value.setBit(i);
4401d5ae102SDimitry Andric }
4411d5ae102SDimitry Andric o << " ";
4421d5ae102SDimitry Andric emitInstBits(o, Value);
4431d5ae102SDimitry Andric o << "," << '\t' << "// " << R->getName() << "\n";
4441d5ae102SDimitry Andric }
4451d5ae102SDimitry Andric o << " UINT64_C(0)\n };\n";
4461d5ae102SDimitry Andric }
4471d5ae102SDimitry Andric
emitCaseMap(raw_ostream & o,const std::map<std::string,std::vector<std::string>> & CaseMap)4487fa27ce4SDimitry Andric void CodeEmitterGen::emitCaseMap(
4497fa27ce4SDimitry Andric raw_ostream &o,
4507fa27ce4SDimitry Andric const std::map<std::string, std::vector<std::string>> &CaseMap) {
4517fa27ce4SDimitry Andric std::map<std::string, std::vector<std::string>>::const_iterator IE, EE;
4527fa27ce4SDimitry Andric for (IE = CaseMap.begin(), EE = CaseMap.end(); IE != EE; ++IE) {
4537fa27ce4SDimitry Andric const std::string &Case = IE->first;
4547fa27ce4SDimitry Andric const std::vector<std::string> &InstList = IE->second;
4557fa27ce4SDimitry Andric
4567fa27ce4SDimitry Andric for (int i = 0, N = InstList.size(); i < N; i++) {
4577fa27ce4SDimitry Andric if (i)
4587fa27ce4SDimitry Andric o << "\n";
4597fa27ce4SDimitry Andric o << " case " << InstList[i] << ":";
4607fa27ce4SDimitry Andric }
4617fa27ce4SDimitry Andric o << " {\n";
4627fa27ce4SDimitry Andric o << Case;
4637fa27ce4SDimitry Andric o << " break;\n"
4647fa27ce4SDimitry Andric << " }\n";
4657fa27ce4SDimitry Andric }
4667fa27ce4SDimitry Andric }
4677fa27ce4SDimitry Andric
run(raw_ostream & o)46818f153bdSEd Schouten void CodeEmitterGen::run(raw_ostream &o) {
4697fa27ce4SDimitry Andric emitSourceFileHeader("Machine Code Emitter", o);
4707fa27ce4SDimitry Andric
471cf099d11SDimitry Andric CodeGenTarget Target(Records);
472009b1c42SEd Schouten std::vector<Record *> Insts = Records.getAllDerivedDefinitions("Instruction");
473009b1c42SEd Schouten
474009b1c42SEd Schouten // For little-endian instruction bit encodings, reverse the bit order
4755ca98fd9SDimitry Andric Target.reverseBitsForLittleEndianEncoding();
476009b1c42SEd Schouten
47701095a5dSDimitry Andric ArrayRef<const CodeGenInstruction *> NumberedInstructions =
4782f12f10aSRoman Divacky Target.getInstructionsByEnumValue();
479009b1c42SEd Schouten
480ac9a064cSDimitry Andric if (Target.hasVariableLengthEncodings()) {
481145449b1SDimitry Andric emitVarLenCodeEmitter(Records, o);
482145449b1SDimitry Andric } else {
4831d5ae102SDimitry Andric const CodeGenHwModes &HWM = Target.getHwModes();
4841d5ae102SDimitry Andric // The set of HwModes used by instruction encodings.
4851d5ae102SDimitry Andric std::set<unsigned> HwModes;
4861d5ae102SDimitry Andric BitWidth = 0;
4871d5ae102SDimitry Andric for (const CodeGenInstruction *CGI : NumberedInstructions) {
4881d5ae102SDimitry Andric Record *R = CGI->TheDef;
4891d5ae102SDimitry Andric if (R->getValueAsString("Namespace") == "TargetOpcode" ||
4901d5ae102SDimitry Andric R->getValueAsBit("isPseudo"))
4911d5ae102SDimitry Andric continue;
4921d5ae102SDimitry Andric
4931d5ae102SDimitry Andric if (const RecordVal *RV = R->getValue("EncodingInfos")) {
4941d5ae102SDimitry Andric if (DefInit *DI = dyn_cast_or_null<DefInit>(RV->getValue())) {
4951d5ae102SDimitry Andric EncodingInfoByHwMode EBM(DI->getDef(), HWM);
496344a3780SDimitry Andric for (auto &KV : EBM) {
4971d5ae102SDimitry Andric BitsInit *BI = KV.second->getValueAsBitsInit("Inst");
4981d5ae102SDimitry Andric BitWidth = std::max(BitWidth, BI->getNumBits());
4991d5ae102SDimitry Andric HwModes.insert(KV.first);
5001d5ae102SDimitry Andric }
5011d5ae102SDimitry Andric continue;
5021d5ae102SDimitry Andric }
5031d5ae102SDimitry Andric }
5041d5ae102SDimitry Andric BitsInit *BI = R->getValueAsBitsInit("Inst");
5051d5ae102SDimitry Andric BitWidth = std::max(BitWidth, BI->getNumBits());
5061d5ae102SDimitry Andric }
5071d5ae102SDimitry Andric UseAPInt = BitWidth > 64;
5081d5ae102SDimitry Andric
509009b1c42SEd Schouten // Emit function declaration
5101d5ae102SDimitry Andric if (UseAPInt) {
5111d5ae102SDimitry Andric o << "void " << Target.getName()
5121d5ae102SDimitry Andric << "MCCodeEmitter::getBinaryCodeForInstr(const MCInst &MI,\n"
5131d5ae102SDimitry Andric << " SmallVectorImpl<MCFixup> &Fixups,\n"
5141d5ae102SDimitry Andric << " APInt &Inst,\n"
5151d5ae102SDimitry Andric << " APInt &Scratch,\n"
5161d5ae102SDimitry Andric << " const MCSubtargetInfo &STI) const {\n";
5171d5ae102SDimitry Andric } else {
51863faed5bSDimitry Andric o << "uint64_t " << Target.getName();
519cf099d11SDimitry Andric o << "MCCodeEmitter::getBinaryCodeForInstr(const MCInst &MI,\n"
5205ca98fd9SDimitry Andric << " SmallVectorImpl<MCFixup> &Fixups,\n"
5215ca98fd9SDimitry Andric << " const MCSubtargetInfo &STI) const {\n";
5221d5ae102SDimitry Andric }
523009b1c42SEd Schouten
524009b1c42SEd Schouten // Emit instruction base values
525ac9a064cSDimitry Andric emitInstructionBaseValues(o, NumberedInstructions, Target, DefaultMode);
526ac9a064cSDimitry Andric if (!HwModes.empty()) {
527ac9a064cSDimitry Andric // Emit table for instrs whose encodings are controlled by HwModes.
528ac9a064cSDimitry Andric for (unsigned HwMode : HwModes) {
529ac9a064cSDimitry Andric if (HwMode == DefaultMode)
530ac9a064cSDimitry Andric continue;
531ac9a064cSDimitry Andric emitInstructionBaseValues(o, NumberedInstructions, Target, HwMode);
532009b1c42SEd Schouten }
533009b1c42SEd Schouten
534ac9a064cSDimitry Andric // This pointer will be assigned to the HwMode table later.
535ac9a064cSDimitry Andric o << " const uint64_t *InstBitsByHw;\n";
536009b1c42SEd Schouten }
537009b1c42SEd Schouten
538009b1c42SEd Schouten // Map to accumulate all the cases.
539009b1c42SEd Schouten std::map<std::string, std::vector<std::string>> CaseMap;
5407fa27ce4SDimitry Andric std::map<std::string, std::vector<std::string>> BitOffsetCaseMap;
541009b1c42SEd Schouten
542009b1c42SEd Schouten // Construct all cases statement for each opcode
543344a3780SDimitry Andric for (Record *R : Insts) {
544411bd29eSDimitry Andric if (R->getValueAsString("Namespace") == "TargetOpcode" ||
545411bd29eSDimitry Andric R->getValueAsBit("isPseudo"))
54666e41e3cSRoman Divacky continue;
547f382538dSDimitry Andric std::string InstName =
548f382538dSDimitry Andric (R->getValueAsString("Namespace") + "::" + R->getName()).str();
5497fa27ce4SDimitry Andric std::string Case, BitOffsetCase;
5507fa27ce4SDimitry Andric std::tie(Case, BitOffsetCase) = getInstructionCases(R, Target);
551009b1c42SEd Schouten
5527fa27ce4SDimitry Andric CaseMap[Case].push_back(InstName);
5537fa27ce4SDimitry Andric BitOffsetCaseMap[BitOffsetCase].push_back(std::move(InstName));
554009b1c42SEd Schouten }
555009b1c42SEd Schouten
556009b1c42SEd Schouten // Emit initial function code
5571d5ae102SDimitry Andric if (UseAPInt) {
5581d5ae102SDimitry Andric int NumWords = APInt::getNumWords(BitWidth);
5591d5ae102SDimitry Andric o << " const unsigned opcode = MI.getOpcode();\n"
5601d5ae102SDimitry Andric << " if (Scratch.getBitWidth() != " << BitWidth << ")\n"
5611d5ae102SDimitry Andric << " Scratch = Scratch.zext(" << BitWidth << ");\n"
562e3b55780SDimitry Andric << " Inst = APInt(" << BitWidth << ", ArrayRef(InstBits + opcode * "
563e3b55780SDimitry Andric << NumWords << ", " << NumWords << "));\n"
5641d5ae102SDimitry Andric << " APInt &Value = Inst;\n"
5651d5ae102SDimitry Andric << " APInt &op = Scratch;\n"
5661d5ae102SDimitry Andric << " switch (opcode) {\n";
5671d5ae102SDimitry Andric } else {
568009b1c42SEd Schouten o << " const unsigned opcode = MI.getOpcode();\n"
56963faed5bSDimitry Andric << " uint64_t Value = InstBits[opcode];\n"
57063faed5bSDimitry Andric << " uint64_t op = 0;\n"
571cf099d11SDimitry Andric << " (void)op; // suppress warning\n"
572009b1c42SEd Schouten << " switch (opcode) {\n";
5731d5ae102SDimitry Andric }
574009b1c42SEd Schouten
575009b1c42SEd Schouten // Emit each case statement
5767fa27ce4SDimitry Andric emitCaseMap(o, CaseMap);
577009b1c42SEd Schouten
578009b1c42SEd Schouten // Default case: unhandled opcode
579009b1c42SEd Schouten o << " default:\n"
58059850d08SRoman Divacky << " std::string msg;\n"
58159850d08SRoman Divacky << " raw_string_ostream Msg(msg);\n"
58259850d08SRoman Divacky << " Msg << \"Not supported instr: \" << MI;\n"
583145449b1SDimitry Andric << " report_fatal_error(Msg.str().c_str());\n"
5841d5ae102SDimitry Andric << " }\n";
5851d5ae102SDimitry Andric if (UseAPInt)
5861d5ae102SDimitry Andric o << " Inst = Value;\n";
5871d5ae102SDimitry Andric else
5881d5ae102SDimitry Andric o << " return Value;\n";
5891d5ae102SDimitry Andric o << "}\n\n";
5907fa27ce4SDimitry Andric
5917fa27ce4SDimitry Andric o << "#ifdef GET_OPERAND_BIT_OFFSET\n"
5927fa27ce4SDimitry Andric << "#undef GET_OPERAND_BIT_OFFSET\n\n"
5937fa27ce4SDimitry Andric << "uint32_t " << Target.getName()
5947fa27ce4SDimitry Andric << "MCCodeEmitter::getOperandBitOffset(const MCInst &MI,\n"
5957fa27ce4SDimitry Andric << " unsigned OpNum,\n"
5967fa27ce4SDimitry Andric << " const MCSubtargetInfo &STI) const {\n"
5977fa27ce4SDimitry Andric << " switch (MI.getOpcode()) {\n";
5987fa27ce4SDimitry Andric emitCaseMap(o, BitOffsetCaseMap);
5997fa27ce4SDimitry Andric o << " }\n"
6007fa27ce4SDimitry Andric << " std::string msg;\n"
6017fa27ce4SDimitry Andric << " raw_string_ostream Msg(msg);\n"
6027fa27ce4SDimitry Andric << " Msg << \"Not supported instr[opcode]: \" << MI << \"[\" << OpNum "
6037fa27ce4SDimitry Andric "<< \"]\";\n"
6047fa27ce4SDimitry Andric << " report_fatal_error(Msg.str().c_str());\n"
6057fa27ce4SDimitry Andric << "}\n\n"
6067fa27ce4SDimitry Andric << "#endif // GET_OPERAND_BIT_OFFSET\n\n";
607145449b1SDimitry Andric }
608009b1c42SEd Schouten }
60958b69754SDimitry Andric
610b915e9e0SDimitry Andric } // end anonymous namespace
61158b69754SDimitry Andric
6127fa27ce4SDimitry Andric static TableGen::Emitter::OptClass<CodeEmitterGen>
6137fa27ce4SDimitry Andric X("gen-emitter", "Generate machine code emitter");
614