xref: /freebsd-src/contrib/llvm-project/llvm/utils/TableGen/CodeEmitterGen.cpp (revision 0fca6ea1d4eea4c934cfff25ac9ee8ad6fe95583)
10b57cec5SDimitry Andric //===- CodeEmitterGen.cpp - Code Emitter Generator ------------------------===//
20b57cec5SDimitry Andric //
30b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
40b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
50b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
60b57cec5SDimitry Andric //
70b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
80b57cec5SDimitry Andric //
90b57cec5SDimitry Andric // CodeEmitterGen uses the descriptions of instructions and their fields to
1006c3fb27SDimitry Andric // construct an automated code emitter: a function called
1106c3fb27SDimitry Andric // getBinaryCodeForInstr() that, given a MCInst, returns the value of the
1206c3fb27SDimitry Andric // instruction - either as an uint64_t or as an APInt, depending on the
1306c3fb27SDimitry Andric // maximum bit width of all Inst definitions.
1406c3fb27SDimitry Andric //
1506c3fb27SDimitry Andric // In addition, it generates another function called getOperandBitOffset()
1606c3fb27SDimitry Andric // that, given a MCInst and an operand index, returns the minimum of indices of
1706c3fb27SDimitry Andric // all bits that carry some portion of the respective operand. When the target's
1806c3fb27SDimitry Andric // encodeInstruction() stores the instruction in a little-endian byte order, the
1906c3fb27SDimitry Andric // returned value is the offset of the start of the operand in the encoded
2006c3fb27SDimitry Andric // instruction. Other targets might need to adjust the returned value according
2106c3fb27SDimitry Andric // to their encodeInstruction() implementation.
220b57cec5SDimitry Andric //
230b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
240b57cec5SDimitry Andric 
25*0fca6ea1SDimitry Andric #include "Common/CodeGenHwModes.h"
26*0fca6ea1SDimitry Andric #include "Common/CodeGenInstruction.h"
27*0fca6ea1SDimitry Andric #include "Common/CodeGenTarget.h"
28*0fca6ea1SDimitry Andric #include "Common/InfoByHwMode.h"
29*0fca6ea1SDimitry Andric #include "Common/VarLenCodeEmitterGen.h"
308bcb0991SDimitry Andric #include "llvm/ADT/APInt.h"
310b57cec5SDimitry Andric #include "llvm/ADT/ArrayRef.h"
320b57cec5SDimitry Andric #include "llvm/ADT/StringExtras.h"
330b57cec5SDimitry Andric #include "llvm/Support/Casting.h"
340b57cec5SDimitry Andric #include "llvm/Support/raw_ostream.h"
3581ad6265SDimitry Andric #include "llvm/TableGen/Error.h"
360b57cec5SDimitry Andric #include "llvm/TableGen/Record.h"
370b57cec5SDimitry Andric #include "llvm/TableGen/TableGenBackend.h"
380b57cec5SDimitry Andric #include <cstdint>
390b57cec5SDimitry Andric #include <map>
400b57cec5SDimitry Andric #include <set>
410b57cec5SDimitry Andric #include <string>
420b57cec5SDimitry Andric #include <utility>
430b57cec5SDimitry Andric #include <vector>
440b57cec5SDimitry Andric 
450b57cec5SDimitry Andric using namespace llvm;
460b57cec5SDimitry Andric 
470b57cec5SDimitry Andric namespace {
480b57cec5SDimitry Andric 
490b57cec5SDimitry Andric class CodeEmitterGen {
500b57cec5SDimitry Andric   RecordKeeper &Records;
510b57cec5SDimitry Andric 
520b57cec5SDimitry Andric public:
530b57cec5SDimitry Andric   CodeEmitterGen(RecordKeeper &R) : Records(R) {}
540b57cec5SDimitry Andric 
550b57cec5SDimitry Andric   void run(raw_ostream &o);
560b57cec5SDimitry Andric 
570b57cec5SDimitry Andric private:
580b57cec5SDimitry Andric   int getVariableBit(const std::string &VarName, BitsInit *BI, int bit);
5906c3fb27SDimitry Andric   std::pair<std::string, std::string>
6006c3fb27SDimitry Andric   getInstructionCases(Record *R, CodeGenTarget &Target);
6106c3fb27SDimitry Andric   void addInstructionCasesForEncoding(Record *R, Record *EncodingDef,
6206c3fb27SDimitry Andric                                       CodeGenTarget &Target, std::string &Case,
6306c3fb27SDimitry Andric                                       std::string &BitOffsetCase);
64bdd1243dSDimitry Andric   bool addCodeToMergeInOperand(Record *R, BitsInit *BI,
6506c3fb27SDimitry Andric                                const std::string &VarName, std::string &Case,
6606c3fb27SDimitry Andric                                std::string &BitOffsetCase,
6706c3fb27SDimitry Andric                                CodeGenTarget &Target);
680b57cec5SDimitry Andric 
698bcb0991SDimitry Andric   void emitInstructionBaseValues(
708bcb0991SDimitry Andric       raw_ostream &o, ArrayRef<const CodeGenInstruction *> NumberedInstructions,
71*0fca6ea1SDimitry Andric       CodeGenTarget &Target, unsigned HwMode = DefaultMode);
7206c3fb27SDimitry Andric   void
7306c3fb27SDimitry Andric   emitCaseMap(raw_ostream &o,
7406c3fb27SDimitry Andric               const std::map<std::string, std::vector<std::string>> &CaseMap);
7506c3fb27SDimitry Andric   unsigned BitWidth = 0u;
7606c3fb27SDimitry Andric   bool UseAPInt = false;
770b57cec5SDimitry Andric };
780b57cec5SDimitry Andric 
790b57cec5SDimitry Andric // If the VarBitInit at position 'bit' matches the specified variable then
800b57cec5SDimitry Andric // return the variable bit position.  Otherwise return -1.
81*0fca6ea1SDimitry Andric int CodeEmitterGen::getVariableBit(const std::string &VarName, BitsInit *BI,
82*0fca6ea1SDimitry Andric                                    int bit) {
830b57cec5SDimitry Andric   if (VarBitInit *VBI = dyn_cast<VarBitInit>(BI->getBit(bit))) {
840b57cec5SDimitry Andric     if (VarInit *VI = dyn_cast<VarInit>(VBI->getBitVar()))
850b57cec5SDimitry Andric       if (VI->getName() == VarName)
860b57cec5SDimitry Andric         return VBI->getBitNum();
870b57cec5SDimitry Andric   } else if (VarInit *VI = dyn_cast<VarInit>(BI->getBit(bit))) {
880b57cec5SDimitry Andric     if (VI->getName() == VarName)
890b57cec5SDimitry Andric       return 0;
900b57cec5SDimitry Andric   }
910b57cec5SDimitry Andric 
920b57cec5SDimitry Andric   return -1;
930b57cec5SDimitry Andric }
940b57cec5SDimitry Andric 
95bdd1243dSDimitry Andric // Returns true if it succeeds, false if an error.
96bdd1243dSDimitry Andric bool CodeEmitterGen::addCodeToMergeInOperand(Record *R, BitsInit *BI,
97bdd1243dSDimitry Andric                                              const std::string &VarName,
98bdd1243dSDimitry Andric                                              std::string &Case,
9906c3fb27SDimitry Andric                                              std::string &BitOffsetCase,
100bdd1243dSDimitry Andric                                              CodeGenTarget &Target) {
1010b57cec5SDimitry Andric   CodeGenInstruction &CGI = Target.getInstruction(R);
1020b57cec5SDimitry Andric 
1030b57cec5SDimitry Andric   // Determine if VarName actually contributes to the Inst encoding.
1040b57cec5SDimitry Andric   int bit = BI->getNumBits() - 1;
1050b57cec5SDimitry Andric 
1060b57cec5SDimitry Andric   // Scan for a bit that this contributed to.
1070b57cec5SDimitry Andric   for (; bit >= 0;) {
1080b57cec5SDimitry Andric     if (getVariableBit(VarName, BI, bit) != -1)
1090b57cec5SDimitry Andric       break;
1100b57cec5SDimitry Andric 
1110b57cec5SDimitry Andric     --bit;
1120b57cec5SDimitry Andric   }
1130b57cec5SDimitry Andric 
1140b57cec5SDimitry Andric   // If we found no bits, ignore this value, otherwise emit the call to get the
1150b57cec5SDimitry Andric   // operand encoding.
116bdd1243dSDimitry Andric   if (bit < 0)
117bdd1243dSDimitry Andric     return true;
1180b57cec5SDimitry Andric 
1190b57cec5SDimitry Andric   // If the operand matches by name, reference according to that
1200b57cec5SDimitry Andric   // operand number. Non-matching operands are assumed to be in
1210b57cec5SDimitry Andric   // order.
1220b57cec5SDimitry Andric   unsigned OpIdx;
123bdd1243dSDimitry Andric   std::pair<unsigned, unsigned> SubOp;
124bdd1243dSDimitry Andric   if (CGI.Operands.hasSubOperandAlias(VarName, SubOp)) {
125bdd1243dSDimitry Andric     OpIdx = CGI.Operands[SubOp.first].MIOperandNo + SubOp.second;
126bdd1243dSDimitry Andric   } else if (CGI.Operands.hasOperandNamed(VarName, OpIdx)) {
1270b57cec5SDimitry Andric     // Get the machine operand number for the indicated operand.
1280b57cec5SDimitry Andric     OpIdx = CGI.Operands[OpIdx].MIOperandNo;
1290b57cec5SDimitry Andric   } else {
130*0fca6ea1SDimitry Andric     PrintError(R, Twine("No operand named ") + VarName + " in record " +
131*0fca6ea1SDimitry Andric                       R->getName());
132bdd1243dSDimitry Andric     return false;
1330b57cec5SDimitry Andric   }
1340b57cec5SDimitry Andric 
135bdd1243dSDimitry Andric   if (CGI.Operands.isFlatOperandNotEmitted(OpIdx)) {
136*0fca6ea1SDimitry Andric     PrintError(R,
137*0fca6ea1SDimitry Andric                "Operand " + VarName + " used but also marked as not emitted!");
138bdd1243dSDimitry Andric     return false;
1390b57cec5SDimitry Andric   }
1400b57cec5SDimitry Andric 
1410b57cec5SDimitry Andric   std::pair<unsigned, unsigned> SO = CGI.Operands.getSubOperandNumber(OpIdx);
142bdd1243dSDimitry Andric   std::string &EncoderMethodName =
143bdd1243dSDimitry Andric       CGI.Operands[SO.first].EncoderMethodNames[SO.second];
1440b57cec5SDimitry Andric 
1458bcb0991SDimitry Andric   if (UseAPInt)
1468bcb0991SDimitry Andric     Case += "      op.clearAllBits();\n";
1478bcb0991SDimitry Andric 
1488bcb0991SDimitry Andric   Case += "      // op: " + VarName + "\n";
149bdd1243dSDimitry Andric 
150bdd1243dSDimitry Andric   // If the source operand has a custom encoder, use it.
151bdd1243dSDimitry Andric   if (!EncoderMethodName.empty()) {
1528bcb0991SDimitry Andric     if (UseAPInt) {
1538bcb0991SDimitry Andric       Case += "      " + EncoderMethodName + "(MI, " + utostr(OpIdx);
1548bcb0991SDimitry Andric       Case += ", op";
1558bcb0991SDimitry Andric     } else {
1568bcb0991SDimitry Andric       Case += "      op = " + EncoderMethodName + "(MI, " + utostr(OpIdx);
1578bcb0991SDimitry Andric     }
1588bcb0991SDimitry Andric     Case += ", Fixups, STI);\n";
1590b57cec5SDimitry Andric   } else {
1608bcb0991SDimitry Andric     if (UseAPInt) {
161*0fca6ea1SDimitry Andric       Case +=
162*0fca6ea1SDimitry Andric           "      getMachineOpValue(MI, MI.getOperand(" + utostr(OpIdx) + ")";
1638bcb0991SDimitry Andric       Case += ", op, Fixups, STI";
1648bcb0991SDimitry Andric     } else {
165*0fca6ea1SDimitry Andric       Case += "      op = getMachineOpValue(MI, MI.getOperand(" +
166*0fca6ea1SDimitry Andric               utostr(OpIdx) + ")";
1670b57cec5SDimitry Andric       Case += ", Fixups, STI";
1688bcb0991SDimitry Andric     }
1690b57cec5SDimitry Andric     Case += ");\n";
1700b57cec5SDimitry Andric   }
1710b57cec5SDimitry Andric 
1728bcb0991SDimitry Andric   // Precalculate the number of lits this variable contributes to in the
1738bcb0991SDimitry Andric   // operand. If there is a single lit (consecutive range of bits) we can use a
1748bcb0991SDimitry Andric   // destructive sequence on APInt that reduces memory allocations.
1758bcb0991SDimitry Andric   int numOperandLits = 0;
1768bcb0991SDimitry Andric   for (int tmpBit = bit; tmpBit >= 0;) {
1778bcb0991SDimitry Andric     int varBit = getVariableBit(VarName, BI, tmpBit);
1788bcb0991SDimitry Andric 
1798bcb0991SDimitry Andric     // If this bit isn't from a variable, skip it.
1808bcb0991SDimitry Andric     if (varBit == -1) {
1818bcb0991SDimitry Andric       --tmpBit;
1828bcb0991SDimitry Andric       continue;
1838bcb0991SDimitry Andric     }
1848bcb0991SDimitry Andric 
1858bcb0991SDimitry Andric     // Figure out the consecutive range of bits covered by this operand, in
1868bcb0991SDimitry Andric     // order to generate better encoding code.
1878bcb0991SDimitry Andric     int beginVarBit = varBit;
1888bcb0991SDimitry Andric     int N = 1;
1898bcb0991SDimitry Andric     for (--tmpBit; tmpBit >= 0;) {
1908bcb0991SDimitry Andric       varBit = getVariableBit(VarName, BI, tmpBit);
1918bcb0991SDimitry Andric       if (varBit == -1 || varBit != (beginVarBit - N))
1928bcb0991SDimitry Andric         break;
1938bcb0991SDimitry Andric       ++N;
1948bcb0991SDimitry Andric       --tmpBit;
1958bcb0991SDimitry Andric     }
1968bcb0991SDimitry Andric     ++numOperandLits;
1978bcb0991SDimitry Andric   }
1988bcb0991SDimitry Andric 
19906c3fb27SDimitry Andric   unsigned BitOffset = -1;
2000b57cec5SDimitry Andric   for (; bit >= 0;) {
2010b57cec5SDimitry Andric     int varBit = getVariableBit(VarName, BI, bit);
2020b57cec5SDimitry Andric 
2030b57cec5SDimitry Andric     // If this bit isn't from a variable, skip it.
2040b57cec5SDimitry Andric     if (varBit == -1) {
2050b57cec5SDimitry Andric       --bit;
2060b57cec5SDimitry Andric       continue;
2070b57cec5SDimitry Andric     }
2080b57cec5SDimitry Andric 
2090b57cec5SDimitry Andric     // Figure out the consecutive range of bits covered by this operand, in
2100b57cec5SDimitry Andric     // order to generate better encoding code.
2110b57cec5SDimitry Andric     int beginInstBit = bit;
2120b57cec5SDimitry Andric     int beginVarBit = varBit;
2130b57cec5SDimitry Andric     int N = 1;
2140b57cec5SDimitry Andric     for (--bit; bit >= 0;) {
2150b57cec5SDimitry Andric       varBit = getVariableBit(VarName, BI, bit);
216*0fca6ea1SDimitry Andric       if (varBit == -1 || varBit != (beginVarBit - N))
217*0fca6ea1SDimitry Andric         break;
2180b57cec5SDimitry Andric       ++N;
2190b57cec5SDimitry Andric       --bit;
2200b57cec5SDimitry Andric     }
2210b57cec5SDimitry Andric 
2228bcb0991SDimitry Andric     std::string maskStr;
2238bcb0991SDimitry Andric     int opShift;
2248bcb0991SDimitry Andric 
2258bcb0991SDimitry Andric     unsigned loBit = beginVarBit - N + 1;
2268bcb0991SDimitry Andric     unsigned hiBit = loBit + N;
2278bcb0991SDimitry Andric     unsigned loInstBit = beginInstBit - N + 1;
22806c3fb27SDimitry Andric     BitOffset = loInstBit;
2298bcb0991SDimitry Andric     if (UseAPInt) {
2308bcb0991SDimitry Andric       std::string extractStr;
2318bcb0991SDimitry Andric       if (N >= 64) {
2328bcb0991SDimitry Andric         extractStr = "op.extractBits(" + itostr(hiBit - loBit) + ", " +
2338bcb0991SDimitry Andric                      itostr(loBit) + ")";
2348bcb0991SDimitry Andric         Case += "      Value.insertBits(" + extractStr + ", " +
2358bcb0991SDimitry Andric                 itostr(loInstBit) + ");\n";
2368bcb0991SDimitry Andric       } else {
2378bcb0991SDimitry Andric         extractStr = "op.extractBitsAsZExtValue(" + itostr(hiBit - loBit) +
2388bcb0991SDimitry Andric                      ", " + itostr(loBit) + ")";
2398bcb0991SDimitry Andric         Case += "      Value.insertBits(" + extractStr + ", " +
2408bcb0991SDimitry Andric                 itostr(loInstBit) + ", " + itostr(hiBit - loBit) + ");\n";
2418bcb0991SDimitry Andric       }
2428bcb0991SDimitry Andric     } else {
2430b57cec5SDimitry Andric       uint64_t opMask = ~(uint64_t)0 >> (64 - N);
2448bcb0991SDimitry Andric       opShift = beginVarBit - N + 1;
2450b57cec5SDimitry Andric       opMask <<= opShift;
2468bcb0991SDimitry Andric       maskStr = "UINT64_C(" + utostr(opMask) + ")";
2470b57cec5SDimitry Andric       opShift = beginInstBit - beginVarBit;
2480b57cec5SDimitry Andric 
2498bcb0991SDimitry Andric       if (numOperandLits == 1) {
2508bcb0991SDimitry Andric         Case += "      op &= " + maskStr + ";\n";
2510b57cec5SDimitry Andric         if (opShift > 0) {
2528bcb0991SDimitry Andric           Case += "      op <<= " + itostr(opShift) + ";\n";
2538bcb0991SDimitry Andric         } else if (opShift < 0) {
2548bcb0991SDimitry Andric           Case += "      op >>= " + itostr(-opShift) + ";\n";
2558bcb0991SDimitry Andric         }
2568bcb0991SDimitry Andric         Case += "      Value |= op;\n";
2578bcb0991SDimitry Andric       } else {
2588bcb0991SDimitry Andric         if (opShift > 0) {
2598bcb0991SDimitry Andric           Case += "      Value |= (op & " + maskStr + ") << " +
2600b57cec5SDimitry Andric                   itostr(opShift) + ";\n";
2610b57cec5SDimitry Andric         } else if (opShift < 0) {
2628bcb0991SDimitry Andric           Case += "      Value |= (op & " + maskStr + ") >> " +
2630b57cec5SDimitry Andric                   itostr(-opShift) + ";\n";
2640b57cec5SDimitry Andric         } else {
2658bcb0991SDimitry Andric           Case += "      Value |= (op & " + maskStr + ");\n";
2668bcb0991SDimitry Andric         }
2678bcb0991SDimitry Andric       }
2680b57cec5SDimitry Andric     }
2690b57cec5SDimitry Andric   }
27006c3fb27SDimitry Andric 
27106c3fb27SDimitry Andric   if (BitOffset != (unsigned)-1) {
27206c3fb27SDimitry Andric     BitOffsetCase += "      case " + utostr(OpIdx) + ":\n";
27306c3fb27SDimitry Andric     BitOffsetCase += "        // op: " + VarName + "\n";
27406c3fb27SDimitry Andric     BitOffsetCase += "        return " + utostr(BitOffset) + ";\n";
27506c3fb27SDimitry Andric   }
27606c3fb27SDimitry Andric 
277bdd1243dSDimitry Andric   return true;
2780b57cec5SDimitry Andric }
2790b57cec5SDimitry Andric 
28006c3fb27SDimitry Andric std::pair<std::string, std::string>
28106c3fb27SDimitry Andric CodeEmitterGen::getInstructionCases(Record *R, CodeGenTarget &Target) {
28206c3fb27SDimitry Andric   std::string Case, BitOffsetCase;
28306c3fb27SDimitry Andric 
284*0fca6ea1SDimitry Andric   auto append = [&](const std::string &S) {
28506c3fb27SDimitry Andric     Case += S;
28606c3fb27SDimitry Andric     BitOffsetCase += S;
28706c3fb27SDimitry Andric   };
28806c3fb27SDimitry Andric 
2898bcb0991SDimitry Andric   if (const RecordVal *RV = R->getValue("EncodingInfos")) {
2908bcb0991SDimitry Andric     if (auto *DI = dyn_cast_or_null<DefInit>(RV->getValue())) {
2918bcb0991SDimitry Andric       const CodeGenHwModes &HWM = Target.getHwModes();
2928bcb0991SDimitry Andric       EncodingInfoByHwMode EBM(DI->getDef(), HWM);
293*0fca6ea1SDimitry Andric 
294*0fca6ea1SDimitry Andric       // Invoke the interface to obtain the HwMode ID controlling the
295*0fca6ea1SDimitry Andric       // EncodingInfo for the current subtarget. This interface will
296*0fca6ea1SDimitry Andric       // mask off irrelevant HwMode IDs.
297*0fca6ea1SDimitry Andric       append("      unsigned HwMode = "
298*0fca6ea1SDimitry Andric              "STI.getHwMode(MCSubtargetInfo::HwMode_EncodingInfo);\n");
299*0fca6ea1SDimitry Andric       Case += "      switch (HwMode) {\n";
300*0fca6ea1SDimitry Andric       Case += "      default: llvm_unreachable(\"Unknown hardware mode!\"); "
301*0fca6ea1SDimitry Andric               "break;\n";
302*0fca6ea1SDimitry Andric       for (auto &[ModeId, Encoding] : EBM) {
303*0fca6ea1SDimitry Andric         if (ModeId == DefaultMode) {
304*0fca6ea1SDimitry Andric           Case +=
305*0fca6ea1SDimitry Andric               "      case " + itostr(DefaultMode) + ": InstBitsByHw = InstBits";
306*0fca6ea1SDimitry Andric         } else {
307*0fca6ea1SDimitry Andric           Case += "      case " + itostr(ModeId) +
308*0fca6ea1SDimitry Andric                   ": InstBitsByHw = InstBits_" +
309*0fca6ea1SDimitry Andric                   std::string(HWM.getMode(ModeId).Name);
310*0fca6ea1SDimitry Andric         }
311*0fca6ea1SDimitry Andric         Case += "; break;\n";
312*0fca6ea1SDimitry Andric       }
313*0fca6ea1SDimitry Andric       Case += "      };\n";
314*0fca6ea1SDimitry Andric 
315*0fca6ea1SDimitry Andric       // We need to remodify the 'Inst' value from the table we found above.
316*0fca6ea1SDimitry Andric       if (UseAPInt) {
317*0fca6ea1SDimitry Andric         int NumWords = APInt::getNumWords(BitWidth);
318*0fca6ea1SDimitry Andric         Case += "      Inst = APInt(" + itostr(BitWidth);
319*0fca6ea1SDimitry Andric         Case += ", ArrayRef(InstBitsByHw + opcode * " + itostr(NumWords) +
320*0fca6ea1SDimitry Andric                 ", " + itostr(NumWords);
321*0fca6ea1SDimitry Andric         Case += "));\n";
322*0fca6ea1SDimitry Andric         Case += "      Value = Inst;\n";
323*0fca6ea1SDimitry Andric       } else {
324*0fca6ea1SDimitry Andric         Case += "      Value = InstBitsByHw[opcode];\n";
325*0fca6ea1SDimitry Andric       }
326*0fca6ea1SDimitry Andric 
32706c3fb27SDimitry Andric       append("      switch (HwMode) {\n");
32806c3fb27SDimitry Andric       append("      default: llvm_unreachable(\"Unhandled HwMode\");\n");
329*0fca6ea1SDimitry Andric       for (auto &[ModeId, Encoding] : EBM) {
330*0fca6ea1SDimitry Andric         append("      case " + itostr(ModeId) + ": {\n");
331*0fca6ea1SDimitry Andric         addInstructionCasesForEncoding(R, Encoding, Target, Case,
33206c3fb27SDimitry Andric                                        BitOffsetCase);
33306c3fb27SDimitry Andric         append("      break;\n");
33406c3fb27SDimitry Andric         append("      }\n");
3358bcb0991SDimitry Andric       }
33606c3fb27SDimitry Andric       append("      }\n");
337*0fca6ea1SDimitry Andric       return std::pair(std::move(Case), std::move(BitOffsetCase));
3388bcb0991SDimitry Andric     }
3398bcb0991SDimitry Andric   }
34006c3fb27SDimitry Andric   addInstructionCasesForEncoding(R, R, Target, Case, BitOffsetCase);
341*0fca6ea1SDimitry Andric   return std::pair(std::move(Case), std::move(BitOffsetCase));
3428bcb0991SDimitry Andric }
3438bcb0991SDimitry Andric 
34406c3fb27SDimitry Andric void CodeEmitterGen::addInstructionCasesForEncoding(
34506c3fb27SDimitry Andric     Record *R, Record *EncodingDef, CodeGenTarget &Target, std::string &Case,
34606c3fb27SDimitry Andric     std::string &BitOffsetCase) {
3478bcb0991SDimitry Andric   BitsInit *BI = EncodingDef->getValueAsBitsInit("Inst");
3480b57cec5SDimitry Andric 
3490b57cec5SDimitry Andric   // Loop over all of the fields in the instruction, determining which are the
3500b57cec5SDimitry Andric   // operands to the instruction.
351bdd1243dSDimitry Andric   bool Success = true;
35206c3fb27SDimitry Andric   size_t OrigBitOffsetCaseSize = BitOffsetCase.size();
35306c3fb27SDimitry Andric   BitOffsetCase += "      switch (OpNum) {\n";
35406c3fb27SDimitry Andric   size_t BitOffsetCaseSizeBeforeLoop = BitOffsetCase.size();
3558bcb0991SDimitry Andric   for (const RecordVal &RV : EncodingDef->getValues()) {
3560b57cec5SDimitry Andric     // Ignore fixed fields in the record, we're looking for values like:
3570b57cec5SDimitry Andric     //    bits<5> RST = { ?, ?, ?, ?, ? };
358e8d8bef9SDimitry Andric     if (RV.isNonconcreteOK() || RV.getValue()->isComplete())
3590b57cec5SDimitry Andric       continue;
3600b57cec5SDimitry Andric 
36106c3fb27SDimitry Andric     Success &= addCodeToMergeInOperand(R, BI, std::string(RV.getName()), Case,
36206c3fb27SDimitry Andric                                        BitOffsetCase, Target);
3630b57cec5SDimitry Andric   }
36406c3fb27SDimitry Andric   // Avoid empty switches.
36506c3fb27SDimitry Andric   if (BitOffsetCase.size() == BitOffsetCaseSizeBeforeLoop)
36606c3fb27SDimitry Andric     BitOffsetCase.resize(OrigBitOffsetCaseSize);
36706c3fb27SDimitry Andric   else
36806c3fb27SDimitry Andric     BitOffsetCase += "      }\n";
3690b57cec5SDimitry Andric 
370bdd1243dSDimitry Andric   if (!Success) {
371bdd1243dSDimitry Andric     // Dump the record, so we can see what's going on...
372bdd1243dSDimitry Andric     std::string E;
373bdd1243dSDimitry Andric     raw_string_ostream S(E);
374bdd1243dSDimitry Andric     S << "Dumping record for previous error:\n";
375bdd1243dSDimitry Andric     S << *R;
376bdd1243dSDimitry Andric     PrintNote(E);
377bdd1243dSDimitry Andric   }
378bdd1243dSDimitry Andric 
3790b57cec5SDimitry Andric   StringRef PostEmitter = R->getValueAsString("PostEncoderMethod");
3800b57cec5SDimitry Andric   if (!PostEmitter.empty()) {
3810b57cec5SDimitry Andric     Case += "      Value = ";
3820b57cec5SDimitry Andric     Case += PostEmitter;
3830b57cec5SDimitry Andric     Case += "(MI, Value";
3840b57cec5SDimitry Andric     Case += ", STI";
3850b57cec5SDimitry Andric     Case += ");\n";
3860b57cec5SDimitry Andric   }
3870b57cec5SDimitry Andric }
3880b57cec5SDimitry Andric 
3898bcb0991SDimitry Andric static void emitInstBits(raw_ostream &OS, const APInt &Bits) {
3908bcb0991SDimitry Andric   for (unsigned I = 0; I < Bits.getNumWords(); ++I)
3918bcb0991SDimitry Andric     OS << ((I > 0) ? ", " : "") << "UINT64_C(" << utostr(Bits.getRawData()[I])
3928bcb0991SDimitry Andric        << ")";
3938bcb0991SDimitry Andric }
3948bcb0991SDimitry Andric 
3958bcb0991SDimitry Andric void CodeEmitterGen::emitInstructionBaseValues(
3968bcb0991SDimitry Andric     raw_ostream &o, ArrayRef<const CodeGenInstruction *> NumberedInstructions,
397*0fca6ea1SDimitry Andric     CodeGenTarget &Target, unsigned HwMode) {
3988bcb0991SDimitry Andric   const CodeGenHwModes &HWM = Target.getHwModes();
399*0fca6ea1SDimitry Andric   if (HwMode == DefaultMode)
4008bcb0991SDimitry Andric     o << "  static const uint64_t InstBits[] = {\n";
4018bcb0991SDimitry Andric   else
402*0fca6ea1SDimitry Andric     o << "  static const uint64_t InstBits_"
403*0fca6ea1SDimitry Andric       << HWM.getModeName(HwMode, /*IncludeDefault=*/true) << "[] = {\n";
4048bcb0991SDimitry Andric 
4058bcb0991SDimitry Andric   for (const CodeGenInstruction *CGI : NumberedInstructions) {
4068bcb0991SDimitry Andric     Record *R = CGI->TheDef;
4078bcb0991SDimitry Andric 
4088bcb0991SDimitry Andric     if (R->getValueAsString("Namespace") == "TargetOpcode" ||
4098bcb0991SDimitry Andric         R->getValueAsBit("isPseudo")) {
410*0fca6ea1SDimitry Andric       o << "    ";
411*0fca6ea1SDimitry Andric       emitInstBits(o, APInt(BitWidth, 0));
412*0fca6ea1SDimitry Andric       o << ",\n";
4138bcb0991SDimitry Andric       continue;
4148bcb0991SDimitry Andric     }
4158bcb0991SDimitry Andric 
4168bcb0991SDimitry Andric     Record *EncodingDef = R;
4178bcb0991SDimitry Andric     if (const RecordVal *RV = R->getValue("EncodingInfos")) {
4188bcb0991SDimitry Andric       if (auto *DI = dyn_cast_or_null<DefInit>(RV->getValue())) {
4198bcb0991SDimitry Andric         EncodingInfoByHwMode EBM(DI->getDef(), HWM);
420*0fca6ea1SDimitry Andric         if (EBM.hasMode(HwMode)) {
4218bcb0991SDimitry Andric           EncodingDef = EBM.get(HwMode);
422*0fca6ea1SDimitry Andric         } else {
423*0fca6ea1SDimitry Andric           // If the HwMode does not match, then Encoding '0'
424*0fca6ea1SDimitry Andric           // should be generated.
425*0fca6ea1SDimitry Andric           APInt Value(BitWidth, 0);
426*0fca6ea1SDimitry Andric           o << "    ";
427*0fca6ea1SDimitry Andric           emitInstBits(o, Value);
428*0fca6ea1SDimitry Andric           o << "," << '\t' << "// " << R->getName() << "\n";
429*0fca6ea1SDimitry Andric           continue;
430*0fca6ea1SDimitry Andric         }
4318bcb0991SDimitry Andric       }
4328bcb0991SDimitry Andric     }
4338bcb0991SDimitry Andric     BitsInit *BI = EncodingDef->getValueAsBitsInit("Inst");
4348bcb0991SDimitry Andric 
4358bcb0991SDimitry Andric     // Start by filling in fixed values.
4368bcb0991SDimitry Andric     APInt Value(BitWidth, 0);
4378bcb0991SDimitry Andric     for (unsigned i = 0, e = BI->getNumBits(); i != e; ++i) {
438bdd1243dSDimitry Andric       if (auto *B = dyn_cast<BitInit>(BI->getBit(i)); B && B->getValue())
439bdd1243dSDimitry Andric         Value.setBit(i);
4408bcb0991SDimitry Andric     }
4418bcb0991SDimitry Andric     o << "    ";
4428bcb0991SDimitry Andric     emitInstBits(o, Value);
4438bcb0991SDimitry Andric     o << "," << '\t' << "// " << R->getName() << "\n";
4448bcb0991SDimitry Andric   }
4458bcb0991SDimitry Andric   o << "    UINT64_C(0)\n  };\n";
4468bcb0991SDimitry Andric }
4478bcb0991SDimitry Andric 
44806c3fb27SDimitry Andric void CodeEmitterGen::emitCaseMap(
44906c3fb27SDimitry Andric     raw_ostream &o,
45006c3fb27SDimitry Andric     const std::map<std::string, std::vector<std::string>> &CaseMap) {
45106c3fb27SDimitry Andric   std::map<std::string, std::vector<std::string>>::const_iterator IE, EE;
45206c3fb27SDimitry Andric   for (IE = CaseMap.begin(), EE = CaseMap.end(); IE != EE; ++IE) {
45306c3fb27SDimitry Andric     const std::string &Case = IE->first;
45406c3fb27SDimitry Andric     const std::vector<std::string> &InstList = IE->second;
45506c3fb27SDimitry Andric 
45606c3fb27SDimitry Andric     for (int i = 0, N = InstList.size(); i < N; i++) {
45706c3fb27SDimitry Andric       if (i)
45806c3fb27SDimitry Andric         o << "\n";
45906c3fb27SDimitry Andric       o << "    case " << InstList[i] << ":";
46006c3fb27SDimitry Andric     }
46106c3fb27SDimitry Andric     o << " {\n";
46206c3fb27SDimitry Andric     o << Case;
46306c3fb27SDimitry Andric     o << "      break;\n"
46406c3fb27SDimitry Andric       << "    }\n";
46506c3fb27SDimitry Andric   }
46606c3fb27SDimitry Andric }
46706c3fb27SDimitry Andric 
4680b57cec5SDimitry Andric void CodeEmitterGen::run(raw_ostream &o) {
46906c3fb27SDimitry Andric   emitSourceFileHeader("Machine Code Emitter", o);
47006c3fb27SDimitry Andric 
4710b57cec5SDimitry Andric   CodeGenTarget Target(Records);
4720b57cec5SDimitry Andric   std::vector<Record *> Insts = Records.getAllDerivedDefinitions("Instruction");
4730b57cec5SDimitry Andric 
4740b57cec5SDimitry Andric   // For little-endian instruction bit encodings, reverse the bit order
4750b57cec5SDimitry Andric   Target.reverseBitsForLittleEndianEncoding();
4760b57cec5SDimitry Andric 
4770b57cec5SDimitry Andric   ArrayRef<const CodeGenInstruction *> NumberedInstructions =
4780b57cec5SDimitry Andric       Target.getInstructionsByEnumValue();
4790b57cec5SDimitry Andric 
480*0fca6ea1SDimitry Andric   if (Target.hasVariableLengthEncodings()) {
48181ad6265SDimitry Andric     emitVarLenCodeEmitter(Records, o);
48281ad6265SDimitry Andric   } else {
4838bcb0991SDimitry Andric     const CodeGenHwModes &HWM = Target.getHwModes();
4848bcb0991SDimitry Andric     // The set of HwModes used by instruction encodings.
4858bcb0991SDimitry Andric     std::set<unsigned> HwModes;
4868bcb0991SDimitry Andric     BitWidth = 0;
4878bcb0991SDimitry Andric     for (const CodeGenInstruction *CGI : NumberedInstructions) {
4888bcb0991SDimitry Andric       Record *R = CGI->TheDef;
4898bcb0991SDimitry Andric       if (R->getValueAsString("Namespace") == "TargetOpcode" ||
4908bcb0991SDimitry Andric           R->getValueAsBit("isPseudo"))
4918bcb0991SDimitry Andric         continue;
4928bcb0991SDimitry Andric 
4938bcb0991SDimitry Andric       if (const RecordVal *RV = R->getValue("EncodingInfos")) {
4948bcb0991SDimitry Andric         if (DefInit *DI = dyn_cast_or_null<DefInit>(RV->getValue())) {
4958bcb0991SDimitry Andric           EncodingInfoByHwMode EBM(DI->getDef(), HWM);
496fe6060f1SDimitry Andric           for (auto &KV : EBM) {
4978bcb0991SDimitry Andric             BitsInit *BI = KV.second->getValueAsBitsInit("Inst");
4988bcb0991SDimitry Andric             BitWidth = std::max(BitWidth, BI->getNumBits());
4998bcb0991SDimitry Andric             HwModes.insert(KV.first);
5008bcb0991SDimitry Andric           }
5018bcb0991SDimitry Andric           continue;
5028bcb0991SDimitry Andric         }
5038bcb0991SDimitry Andric       }
5048bcb0991SDimitry Andric       BitsInit *BI = R->getValueAsBitsInit("Inst");
5058bcb0991SDimitry Andric       BitWidth = std::max(BitWidth, BI->getNumBits());
5068bcb0991SDimitry Andric     }
5078bcb0991SDimitry Andric     UseAPInt = BitWidth > 64;
5088bcb0991SDimitry Andric 
5090b57cec5SDimitry Andric     // Emit function declaration
5108bcb0991SDimitry Andric     if (UseAPInt) {
5118bcb0991SDimitry Andric       o << "void " << Target.getName()
5128bcb0991SDimitry Andric         << "MCCodeEmitter::getBinaryCodeForInstr(const MCInst &MI,\n"
5138bcb0991SDimitry Andric         << "    SmallVectorImpl<MCFixup> &Fixups,\n"
5148bcb0991SDimitry Andric         << "    APInt &Inst,\n"
5158bcb0991SDimitry Andric         << "    APInt &Scratch,\n"
5168bcb0991SDimitry Andric         << "    const MCSubtargetInfo &STI) const {\n";
5178bcb0991SDimitry Andric     } else {
5180b57cec5SDimitry Andric       o << "uint64_t " << Target.getName();
5190b57cec5SDimitry Andric       o << "MCCodeEmitter::getBinaryCodeForInstr(const MCInst &MI,\n"
5200b57cec5SDimitry Andric         << "    SmallVectorImpl<MCFixup> &Fixups,\n"
5210b57cec5SDimitry Andric         << "    const MCSubtargetInfo &STI) const {\n";
5228bcb0991SDimitry Andric     }
5230b57cec5SDimitry Andric 
5240b57cec5SDimitry Andric     // Emit instruction base values
525*0fca6ea1SDimitry Andric     emitInstructionBaseValues(o, NumberedInstructions, Target, DefaultMode);
526*0fca6ea1SDimitry Andric     if (!HwModes.empty()) {
527*0fca6ea1SDimitry Andric       // Emit table for instrs whose encodings are controlled by HwModes.
528*0fca6ea1SDimitry Andric       for (unsigned HwMode : HwModes) {
529*0fca6ea1SDimitry Andric         if (HwMode == DefaultMode)
530*0fca6ea1SDimitry Andric           continue;
531*0fca6ea1SDimitry Andric         emitInstructionBaseValues(o, NumberedInstructions, Target, HwMode);
5320b57cec5SDimitry Andric       }
5330b57cec5SDimitry Andric 
534*0fca6ea1SDimitry Andric       // This pointer will be assigned to the HwMode table later.
535*0fca6ea1SDimitry Andric       o << "  const uint64_t *InstBitsByHw;\n";
5360b57cec5SDimitry Andric     }
5370b57cec5SDimitry Andric 
5380b57cec5SDimitry Andric     // Map to accumulate all the cases.
5390b57cec5SDimitry Andric     std::map<std::string, std::vector<std::string>> CaseMap;
54006c3fb27SDimitry Andric     std::map<std::string, std::vector<std::string>> BitOffsetCaseMap;
5410b57cec5SDimitry Andric 
5420b57cec5SDimitry Andric     // Construct all cases statement for each opcode
543fe6060f1SDimitry Andric     for (Record *R : Insts) {
5440b57cec5SDimitry Andric       if (R->getValueAsString("Namespace") == "TargetOpcode" ||
5450b57cec5SDimitry Andric           R->getValueAsBit("isPseudo"))
5460b57cec5SDimitry Andric         continue;
5470b57cec5SDimitry Andric       std::string InstName =
5480b57cec5SDimitry Andric           (R->getValueAsString("Namespace") + "::" + R->getName()).str();
54906c3fb27SDimitry Andric       std::string Case, BitOffsetCase;
55006c3fb27SDimitry Andric       std::tie(Case, BitOffsetCase) = getInstructionCases(R, Target);
5510b57cec5SDimitry Andric 
55206c3fb27SDimitry Andric       CaseMap[Case].push_back(InstName);
55306c3fb27SDimitry Andric       BitOffsetCaseMap[BitOffsetCase].push_back(std::move(InstName));
5540b57cec5SDimitry Andric     }
5550b57cec5SDimitry Andric 
5560b57cec5SDimitry Andric     // Emit initial function code
5578bcb0991SDimitry Andric     if (UseAPInt) {
5588bcb0991SDimitry Andric       int NumWords = APInt::getNumWords(BitWidth);
5598bcb0991SDimitry Andric       o << "  const unsigned opcode = MI.getOpcode();\n"
5608bcb0991SDimitry Andric         << "  if (Scratch.getBitWidth() != " << BitWidth << ")\n"
5618bcb0991SDimitry Andric         << "    Scratch = Scratch.zext(" << BitWidth << ");\n"
562bdd1243dSDimitry Andric         << "  Inst = APInt(" << BitWidth << ", ArrayRef(InstBits + opcode * "
563bdd1243dSDimitry Andric         << NumWords << ", " << NumWords << "));\n"
5648bcb0991SDimitry Andric         << "  APInt &Value = Inst;\n"
5658bcb0991SDimitry Andric         << "  APInt &op = Scratch;\n"
5668bcb0991SDimitry Andric         << "  switch (opcode) {\n";
5678bcb0991SDimitry Andric     } else {
5680b57cec5SDimitry Andric       o << "  const unsigned opcode = MI.getOpcode();\n"
5690b57cec5SDimitry Andric         << "  uint64_t Value = InstBits[opcode];\n"
5700b57cec5SDimitry Andric         << "  uint64_t op = 0;\n"
5710b57cec5SDimitry Andric         << "  (void)op;  // suppress warning\n"
5720b57cec5SDimitry Andric         << "  switch (opcode) {\n";
5738bcb0991SDimitry Andric     }
5740b57cec5SDimitry Andric 
5750b57cec5SDimitry Andric     // Emit each case statement
57606c3fb27SDimitry Andric     emitCaseMap(o, CaseMap);
5770b57cec5SDimitry Andric 
5780b57cec5SDimitry Andric     // Default case: unhandled opcode
5790b57cec5SDimitry Andric     o << "  default:\n"
5800b57cec5SDimitry Andric       << "    std::string msg;\n"
5810b57cec5SDimitry Andric       << "    raw_string_ostream Msg(msg);\n"
5820b57cec5SDimitry Andric       << "    Msg << \"Not supported instr: \" << MI;\n"
58381ad6265SDimitry Andric       << "    report_fatal_error(Msg.str().c_str());\n"
5848bcb0991SDimitry Andric       << "  }\n";
5858bcb0991SDimitry Andric     if (UseAPInt)
5868bcb0991SDimitry Andric       o << "  Inst = Value;\n";
5878bcb0991SDimitry Andric     else
5888bcb0991SDimitry Andric       o << "  return Value;\n";
5898bcb0991SDimitry Andric     o << "}\n\n";
59006c3fb27SDimitry Andric 
59106c3fb27SDimitry Andric     o << "#ifdef GET_OPERAND_BIT_OFFSET\n"
59206c3fb27SDimitry Andric       << "#undef GET_OPERAND_BIT_OFFSET\n\n"
59306c3fb27SDimitry Andric       << "uint32_t " << Target.getName()
59406c3fb27SDimitry Andric       << "MCCodeEmitter::getOperandBitOffset(const MCInst &MI,\n"
59506c3fb27SDimitry Andric       << "    unsigned OpNum,\n"
59606c3fb27SDimitry Andric       << "    const MCSubtargetInfo &STI) const {\n"
59706c3fb27SDimitry Andric       << "  switch (MI.getOpcode()) {\n";
59806c3fb27SDimitry Andric     emitCaseMap(o, BitOffsetCaseMap);
59906c3fb27SDimitry Andric     o << "  }\n"
60006c3fb27SDimitry Andric       << "  std::string msg;\n"
60106c3fb27SDimitry Andric       << "  raw_string_ostream Msg(msg);\n"
60206c3fb27SDimitry Andric       << "  Msg << \"Not supported instr[opcode]: \" << MI << \"[\" << OpNum "
60306c3fb27SDimitry Andric          "<< \"]\";\n"
60406c3fb27SDimitry Andric       << "  report_fatal_error(Msg.str().c_str());\n"
60506c3fb27SDimitry Andric       << "}\n\n"
60606c3fb27SDimitry Andric       << "#endif // GET_OPERAND_BIT_OFFSET\n\n";
60781ad6265SDimitry Andric   }
6080b57cec5SDimitry Andric }
6090b57cec5SDimitry Andric 
6100b57cec5SDimitry Andric } // end anonymous namespace
6110b57cec5SDimitry Andric 
61206c3fb27SDimitry Andric static TableGen::Emitter::OptClass<CodeEmitterGen>
61306c3fb27SDimitry Andric     X("gen-emitter", "Generate machine code emitter");
614