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
10*fe013be4SDimitry Andric // construct an automated code emitter: a function called
11*fe013be4SDimitry Andric // getBinaryCodeForInstr() that, given a MCInst, returns the value of the
12*fe013be4SDimitry Andric // instruction - either as an uint64_t or as an APInt, depending on the
13*fe013be4SDimitry Andric // maximum bit width of all Inst definitions.
14*fe013be4SDimitry Andric //
15*fe013be4SDimitry Andric // In addition, it generates another function called getOperandBitOffset()
16*fe013be4SDimitry Andric // that, given a MCInst and an operand index, returns the minimum of indices of
17*fe013be4SDimitry Andric // all bits that carry some portion of the respective operand. When the target's
18*fe013be4SDimitry Andric // encodeInstruction() stores the instruction in a little-endian byte order, the
19*fe013be4SDimitry Andric // returned value is the offset of the start of the operand in the encoded
20*fe013be4SDimitry Andric // instruction. Other targets might need to adjust the returned value according
21*fe013be4SDimitry Andric // to their encodeInstruction() implementation.
220b57cec5SDimitry Andric //
230b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
240b57cec5SDimitry Andric
25*fe013be4SDimitry Andric #include "CodeGenHwModes.h"
260b57cec5SDimitry Andric #include "CodeGenInstruction.h"
270b57cec5SDimitry Andric #include "CodeGenTarget.h"
28*fe013be4SDimitry Andric #include "InfoByHwMode.h"
2981ad6265SDimitry Andric #include "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:
CodeEmitterGen(RecordKeeper & R)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);
59*fe013be4SDimitry Andric std::pair<std::string, std::string>
60*fe013be4SDimitry Andric getInstructionCases(Record *R, CodeGenTarget &Target);
61*fe013be4SDimitry Andric void addInstructionCasesForEncoding(Record *R, Record *EncodingDef,
62*fe013be4SDimitry Andric CodeGenTarget &Target, std::string &Case,
63*fe013be4SDimitry Andric std::string &BitOffsetCase);
64bdd1243dSDimitry Andric bool addCodeToMergeInOperand(Record *R, BitsInit *BI,
65*fe013be4SDimitry Andric const std::string &VarName, std::string &Case,
66*fe013be4SDimitry Andric std::string &BitOffsetCase,
67*fe013be4SDimitry Andric CodeGenTarget &Target);
680b57cec5SDimitry Andric
698bcb0991SDimitry Andric void emitInstructionBaseValues(
708bcb0991SDimitry Andric raw_ostream &o, ArrayRef<const CodeGenInstruction *> NumberedInstructions,
718bcb0991SDimitry Andric CodeGenTarget &Target, int HwMode = -1);
72*fe013be4SDimitry Andric void
73*fe013be4SDimitry Andric emitCaseMap(raw_ostream &o,
74*fe013be4SDimitry Andric const std::map<std::string, std::vector<std::string>> &CaseMap);
75*fe013be4SDimitry Andric unsigned BitWidth = 0u;
76*fe013be4SDimitry 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.
getVariableBit(const std::string & VarName,BitsInit * BI,int bit)810b57cec5SDimitry Andric int CodeEmitterGen::getVariableBit(const std::string &VarName,
820b57cec5SDimitry Andric BitsInit *BI, 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.
addCodeToMergeInOperand(Record * R,BitsInit * BI,const std::string & VarName,std::string & Case,std::string & BitOffsetCase,CodeGenTarget & Target)96bdd1243dSDimitry Andric bool CodeEmitterGen::addCodeToMergeInOperand(Record *R, BitsInit *BI,
97bdd1243dSDimitry Andric const std::string &VarName,
98bdd1243dSDimitry Andric std::string &Case,
99*fe013be4SDimitry 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*fe013be4SDimitry Andric PrintError(R, Twine("No operand named ") + VarName + " in record " + R->getName());
131bdd1243dSDimitry Andric return false;
1320b57cec5SDimitry Andric }
1330b57cec5SDimitry Andric
134bdd1243dSDimitry Andric if (CGI.Operands.isFlatOperandNotEmitted(OpIdx)) {
135bdd1243dSDimitry Andric PrintError(R, "Operand " + VarName + " used but also marked as not emitted!");
136bdd1243dSDimitry Andric return false;
1370b57cec5SDimitry Andric }
1380b57cec5SDimitry Andric
1390b57cec5SDimitry Andric std::pair<unsigned, unsigned> SO = CGI.Operands.getSubOperandNumber(OpIdx);
140bdd1243dSDimitry Andric std::string &EncoderMethodName =
141bdd1243dSDimitry Andric CGI.Operands[SO.first].EncoderMethodNames[SO.second];
1420b57cec5SDimitry Andric
1438bcb0991SDimitry Andric if (UseAPInt)
1448bcb0991SDimitry Andric Case += " op.clearAllBits();\n";
1458bcb0991SDimitry Andric
1468bcb0991SDimitry Andric Case += " // op: " + VarName + "\n";
147bdd1243dSDimitry Andric
148bdd1243dSDimitry Andric // If the source operand has a custom encoder, use it.
149bdd1243dSDimitry Andric if (!EncoderMethodName.empty()) {
1508bcb0991SDimitry Andric if (UseAPInt) {
1518bcb0991SDimitry Andric Case += " " + EncoderMethodName + "(MI, " + utostr(OpIdx);
1528bcb0991SDimitry Andric Case += ", op";
1538bcb0991SDimitry Andric } else {
1548bcb0991SDimitry Andric Case += " op = " + EncoderMethodName + "(MI, " + utostr(OpIdx);
1558bcb0991SDimitry Andric }
1568bcb0991SDimitry Andric Case += ", Fixups, STI);\n";
1570b57cec5SDimitry Andric } else {
1588bcb0991SDimitry Andric if (UseAPInt) {
1598bcb0991SDimitry Andric Case += " getMachineOpValue(MI, MI.getOperand(" + utostr(OpIdx) + ")";
1608bcb0991SDimitry Andric Case += ", op, Fixups, STI";
1618bcb0991SDimitry Andric } else {
1628bcb0991SDimitry Andric Case += " op = getMachineOpValue(MI, MI.getOperand(" + utostr(OpIdx) + ")";
1630b57cec5SDimitry Andric Case += ", Fixups, STI";
1648bcb0991SDimitry Andric }
1650b57cec5SDimitry Andric Case += ");\n";
1660b57cec5SDimitry Andric }
1670b57cec5SDimitry Andric
1688bcb0991SDimitry Andric // Precalculate the number of lits this variable contributes to in the
1698bcb0991SDimitry Andric // operand. If there is a single lit (consecutive range of bits) we can use a
1708bcb0991SDimitry Andric // destructive sequence on APInt that reduces memory allocations.
1718bcb0991SDimitry Andric int numOperandLits = 0;
1728bcb0991SDimitry Andric for (int tmpBit = bit; tmpBit >= 0;) {
1738bcb0991SDimitry Andric int varBit = getVariableBit(VarName, BI, tmpBit);
1748bcb0991SDimitry Andric
1758bcb0991SDimitry Andric // If this bit isn't from a variable, skip it.
1768bcb0991SDimitry Andric if (varBit == -1) {
1778bcb0991SDimitry Andric --tmpBit;
1788bcb0991SDimitry Andric continue;
1798bcb0991SDimitry Andric }
1808bcb0991SDimitry Andric
1818bcb0991SDimitry Andric // Figure out the consecutive range of bits covered by this operand, in
1828bcb0991SDimitry Andric // order to generate better encoding code.
1838bcb0991SDimitry Andric int beginVarBit = varBit;
1848bcb0991SDimitry Andric int N = 1;
1858bcb0991SDimitry Andric for (--tmpBit; tmpBit >= 0;) {
1868bcb0991SDimitry Andric varBit = getVariableBit(VarName, BI, tmpBit);
1878bcb0991SDimitry Andric if (varBit == -1 || varBit != (beginVarBit - N))
1888bcb0991SDimitry Andric break;
1898bcb0991SDimitry Andric ++N;
1908bcb0991SDimitry Andric --tmpBit;
1918bcb0991SDimitry Andric }
1928bcb0991SDimitry Andric ++numOperandLits;
1938bcb0991SDimitry Andric }
1948bcb0991SDimitry Andric
195*fe013be4SDimitry Andric unsigned BitOffset = -1;
1960b57cec5SDimitry Andric for (; bit >= 0; ) {
1970b57cec5SDimitry Andric int varBit = getVariableBit(VarName, BI, bit);
1980b57cec5SDimitry Andric
1990b57cec5SDimitry Andric // If this bit isn't from a variable, skip it.
2000b57cec5SDimitry Andric if (varBit == -1) {
2010b57cec5SDimitry Andric --bit;
2020b57cec5SDimitry Andric continue;
2030b57cec5SDimitry Andric }
2040b57cec5SDimitry Andric
2050b57cec5SDimitry Andric // Figure out the consecutive range of bits covered by this operand, in
2060b57cec5SDimitry Andric // order to generate better encoding code.
2070b57cec5SDimitry Andric int beginInstBit = bit;
2080b57cec5SDimitry Andric int beginVarBit = varBit;
2090b57cec5SDimitry Andric int N = 1;
2100b57cec5SDimitry Andric for (--bit; bit >= 0;) {
2110b57cec5SDimitry Andric varBit = getVariableBit(VarName, BI, bit);
2120b57cec5SDimitry Andric if (varBit == -1 || varBit != (beginVarBit - N)) break;
2130b57cec5SDimitry Andric ++N;
2140b57cec5SDimitry Andric --bit;
2150b57cec5SDimitry Andric }
2160b57cec5SDimitry Andric
2178bcb0991SDimitry Andric std::string maskStr;
2188bcb0991SDimitry Andric int opShift;
2198bcb0991SDimitry Andric
2208bcb0991SDimitry Andric unsigned loBit = beginVarBit - N + 1;
2218bcb0991SDimitry Andric unsigned hiBit = loBit + N;
2228bcb0991SDimitry Andric unsigned loInstBit = beginInstBit - N + 1;
223*fe013be4SDimitry Andric BitOffset = loInstBit;
2248bcb0991SDimitry Andric if (UseAPInt) {
2258bcb0991SDimitry Andric std::string extractStr;
2268bcb0991SDimitry Andric if (N >= 64) {
2278bcb0991SDimitry Andric extractStr = "op.extractBits(" + itostr(hiBit - loBit) + ", " +
2288bcb0991SDimitry Andric itostr(loBit) + ")";
2298bcb0991SDimitry Andric Case += " Value.insertBits(" + extractStr + ", " +
2308bcb0991SDimitry Andric itostr(loInstBit) + ");\n";
2318bcb0991SDimitry Andric } else {
2328bcb0991SDimitry Andric extractStr = "op.extractBitsAsZExtValue(" + itostr(hiBit - loBit) +
2338bcb0991SDimitry Andric ", " + itostr(loBit) + ")";
2348bcb0991SDimitry Andric Case += " Value.insertBits(" + extractStr + ", " +
2358bcb0991SDimitry Andric itostr(loInstBit) + ", " + itostr(hiBit - loBit) + ");\n";
2368bcb0991SDimitry Andric }
2378bcb0991SDimitry Andric } else {
2380b57cec5SDimitry Andric uint64_t opMask = ~(uint64_t)0 >> (64 - N);
2398bcb0991SDimitry Andric opShift = beginVarBit - N + 1;
2400b57cec5SDimitry Andric opMask <<= opShift;
2418bcb0991SDimitry Andric maskStr = "UINT64_C(" + utostr(opMask) + ")";
2420b57cec5SDimitry Andric opShift = beginInstBit - beginVarBit;
2430b57cec5SDimitry Andric
2448bcb0991SDimitry Andric if (numOperandLits == 1) {
2458bcb0991SDimitry Andric Case += " op &= " + maskStr + ";\n";
2460b57cec5SDimitry Andric if (opShift > 0) {
2478bcb0991SDimitry Andric Case += " op <<= " + itostr(opShift) + ";\n";
2488bcb0991SDimitry Andric } else if (opShift < 0) {
2498bcb0991SDimitry Andric Case += " op >>= " + itostr(-opShift) + ";\n";
2508bcb0991SDimitry Andric }
2518bcb0991SDimitry Andric Case += " Value |= op;\n";
2528bcb0991SDimitry Andric } else {
2538bcb0991SDimitry Andric if (opShift > 0) {
2548bcb0991SDimitry Andric Case += " Value |= (op & " + maskStr + ") << " +
2550b57cec5SDimitry Andric itostr(opShift) + ";\n";
2560b57cec5SDimitry Andric } else if (opShift < 0) {
2578bcb0991SDimitry Andric Case += " Value |= (op & " + maskStr + ") >> " +
2580b57cec5SDimitry Andric itostr(-opShift) + ";\n";
2590b57cec5SDimitry Andric } else {
2608bcb0991SDimitry Andric Case += " Value |= (op & " + maskStr + ");\n";
2618bcb0991SDimitry Andric }
2628bcb0991SDimitry Andric }
2630b57cec5SDimitry Andric }
2640b57cec5SDimitry Andric }
265*fe013be4SDimitry Andric
266*fe013be4SDimitry Andric if (BitOffset != (unsigned)-1) {
267*fe013be4SDimitry Andric BitOffsetCase += " case " + utostr(OpIdx) + ":\n";
268*fe013be4SDimitry Andric BitOffsetCase += " // op: " + VarName + "\n";
269*fe013be4SDimitry Andric BitOffsetCase += " return " + utostr(BitOffset) + ";\n";
270*fe013be4SDimitry Andric }
271*fe013be4SDimitry Andric
272bdd1243dSDimitry Andric return true;
2730b57cec5SDimitry Andric }
2740b57cec5SDimitry Andric
275*fe013be4SDimitry Andric std::pair<std::string, std::string>
getInstructionCases(Record * R,CodeGenTarget & Target)276*fe013be4SDimitry Andric CodeEmitterGen::getInstructionCases(Record *R, CodeGenTarget &Target) {
277*fe013be4SDimitry Andric std::string Case, BitOffsetCase;
278*fe013be4SDimitry Andric
279*fe013be4SDimitry Andric auto append = [&](const char *S) {
280*fe013be4SDimitry Andric Case += S;
281*fe013be4SDimitry Andric BitOffsetCase += S;
282*fe013be4SDimitry Andric };
283*fe013be4SDimitry Andric
2848bcb0991SDimitry Andric if (const RecordVal *RV = R->getValue("EncodingInfos")) {
2858bcb0991SDimitry Andric if (auto *DI = dyn_cast_or_null<DefInit>(RV->getValue())) {
2868bcb0991SDimitry Andric const CodeGenHwModes &HWM = Target.getHwModes();
2878bcb0991SDimitry Andric EncodingInfoByHwMode EBM(DI->getDef(), HWM);
288*fe013be4SDimitry Andric append(" switch (HwMode) {\n");
289*fe013be4SDimitry Andric append(" default: llvm_unreachable(\"Unhandled HwMode\");\n");
290fe6060f1SDimitry Andric for (auto &KV : EBM) {
291*fe013be4SDimitry Andric append((" case " + itostr(KV.first) + ": {\n").c_str());
292*fe013be4SDimitry Andric addInstructionCasesForEncoding(R, KV.second, Target, Case,
293*fe013be4SDimitry Andric BitOffsetCase);
294*fe013be4SDimitry Andric append(" break;\n");
295*fe013be4SDimitry Andric append(" }\n");
2968bcb0991SDimitry Andric }
297*fe013be4SDimitry Andric append(" }\n");
298*fe013be4SDimitry Andric return std::make_pair(std::move(Case), std::move(BitOffsetCase));
2998bcb0991SDimitry Andric }
3008bcb0991SDimitry Andric }
301*fe013be4SDimitry Andric addInstructionCasesForEncoding(R, R, Target, Case, BitOffsetCase);
302*fe013be4SDimitry Andric return std::make_pair(std::move(Case), std::move(BitOffsetCase));
3038bcb0991SDimitry Andric }
3048bcb0991SDimitry Andric
addInstructionCasesForEncoding(Record * R,Record * EncodingDef,CodeGenTarget & Target,std::string & Case,std::string & BitOffsetCase)305*fe013be4SDimitry Andric void CodeEmitterGen::addInstructionCasesForEncoding(
306*fe013be4SDimitry Andric Record *R, Record *EncodingDef, CodeGenTarget &Target, std::string &Case,
307*fe013be4SDimitry Andric std::string &BitOffsetCase) {
3088bcb0991SDimitry Andric BitsInit *BI = EncodingDef->getValueAsBitsInit("Inst");
3090b57cec5SDimitry Andric
3100b57cec5SDimitry Andric // Loop over all of the fields in the instruction, determining which are the
3110b57cec5SDimitry Andric // operands to the instruction.
312bdd1243dSDimitry Andric bool Success = true;
313*fe013be4SDimitry Andric size_t OrigBitOffsetCaseSize = BitOffsetCase.size();
314*fe013be4SDimitry Andric BitOffsetCase += " switch (OpNum) {\n";
315*fe013be4SDimitry Andric size_t BitOffsetCaseSizeBeforeLoop = BitOffsetCase.size();
3168bcb0991SDimitry Andric for (const RecordVal &RV : EncodingDef->getValues()) {
3170b57cec5SDimitry Andric // Ignore fixed fields in the record, we're looking for values like:
3180b57cec5SDimitry Andric // bits<5> RST = { ?, ?, ?, ?, ? };
319e8d8bef9SDimitry Andric if (RV.isNonconcreteOK() || RV.getValue()->isComplete())
3200b57cec5SDimitry Andric continue;
3210b57cec5SDimitry Andric
322*fe013be4SDimitry Andric Success &= addCodeToMergeInOperand(R, BI, std::string(RV.getName()), Case,
323*fe013be4SDimitry Andric BitOffsetCase, Target);
3240b57cec5SDimitry Andric }
325*fe013be4SDimitry Andric // Avoid empty switches.
326*fe013be4SDimitry Andric if (BitOffsetCase.size() == BitOffsetCaseSizeBeforeLoop)
327*fe013be4SDimitry Andric BitOffsetCase.resize(OrigBitOffsetCaseSize);
328*fe013be4SDimitry Andric else
329*fe013be4SDimitry Andric BitOffsetCase += " }\n";
3300b57cec5SDimitry Andric
331bdd1243dSDimitry Andric if (!Success) {
332bdd1243dSDimitry Andric // Dump the record, so we can see what's going on...
333bdd1243dSDimitry Andric std::string E;
334bdd1243dSDimitry Andric raw_string_ostream S(E);
335bdd1243dSDimitry Andric S << "Dumping record for previous error:\n";
336bdd1243dSDimitry Andric S << *R;
337bdd1243dSDimitry Andric PrintNote(E);
338bdd1243dSDimitry Andric }
339bdd1243dSDimitry Andric
3400b57cec5SDimitry Andric StringRef PostEmitter = R->getValueAsString("PostEncoderMethod");
3410b57cec5SDimitry Andric if (!PostEmitter.empty()) {
3420b57cec5SDimitry Andric Case += " Value = ";
3430b57cec5SDimitry Andric Case += PostEmitter;
3440b57cec5SDimitry Andric Case += "(MI, Value";
3450b57cec5SDimitry Andric Case += ", STI";
3460b57cec5SDimitry Andric Case += ");\n";
3470b57cec5SDimitry Andric }
3480b57cec5SDimitry Andric }
3490b57cec5SDimitry Andric
emitInstBits(raw_ostream & OS,const APInt & Bits)3508bcb0991SDimitry Andric static void emitInstBits(raw_ostream &OS, const APInt &Bits) {
3518bcb0991SDimitry Andric for (unsigned I = 0; I < Bits.getNumWords(); ++I)
3528bcb0991SDimitry Andric OS << ((I > 0) ? ", " : "") << "UINT64_C(" << utostr(Bits.getRawData()[I])
3538bcb0991SDimitry Andric << ")";
3548bcb0991SDimitry Andric }
3558bcb0991SDimitry Andric
emitInstructionBaseValues(raw_ostream & o,ArrayRef<const CodeGenInstruction * > NumberedInstructions,CodeGenTarget & Target,int HwMode)3568bcb0991SDimitry Andric void CodeEmitterGen::emitInstructionBaseValues(
3578bcb0991SDimitry Andric raw_ostream &o, ArrayRef<const CodeGenInstruction *> NumberedInstructions,
3588bcb0991SDimitry Andric CodeGenTarget &Target, int HwMode) {
3598bcb0991SDimitry Andric const CodeGenHwModes &HWM = Target.getHwModes();
3608bcb0991SDimitry Andric if (HwMode == -1)
3618bcb0991SDimitry Andric o << " static const uint64_t InstBits[] = {\n";
3628bcb0991SDimitry Andric else
3638bcb0991SDimitry Andric o << " static const uint64_t InstBits_" << HWM.getMode(HwMode).Name
3648bcb0991SDimitry Andric << "[] = {\n";
3658bcb0991SDimitry Andric
3668bcb0991SDimitry Andric for (const CodeGenInstruction *CGI : NumberedInstructions) {
3678bcb0991SDimitry Andric Record *R = CGI->TheDef;
3688bcb0991SDimitry Andric
3698bcb0991SDimitry Andric if (R->getValueAsString("Namespace") == "TargetOpcode" ||
3708bcb0991SDimitry Andric R->getValueAsBit("isPseudo")) {
3718bcb0991SDimitry Andric o << " "; emitInstBits(o, APInt(BitWidth, 0)); o << ",\n";
3728bcb0991SDimitry Andric continue;
3738bcb0991SDimitry Andric }
3748bcb0991SDimitry Andric
3758bcb0991SDimitry Andric Record *EncodingDef = R;
3768bcb0991SDimitry Andric if (const RecordVal *RV = R->getValue("EncodingInfos")) {
3778bcb0991SDimitry Andric if (auto *DI = dyn_cast_or_null<DefInit>(RV->getValue())) {
3788bcb0991SDimitry Andric EncodingInfoByHwMode EBM(DI->getDef(), HWM);
3798bcb0991SDimitry Andric if (EBM.hasMode(HwMode))
3808bcb0991SDimitry Andric EncodingDef = EBM.get(HwMode);
3818bcb0991SDimitry Andric }
3828bcb0991SDimitry Andric }
3838bcb0991SDimitry Andric BitsInit *BI = EncodingDef->getValueAsBitsInit("Inst");
3848bcb0991SDimitry Andric
3858bcb0991SDimitry Andric // Start by filling in fixed values.
3868bcb0991SDimitry Andric APInt Value(BitWidth, 0);
3878bcb0991SDimitry Andric for (unsigned i = 0, e = BI->getNumBits(); i != e; ++i) {
388bdd1243dSDimitry Andric if (auto *B = dyn_cast<BitInit>(BI->getBit(i)); B && B->getValue())
389bdd1243dSDimitry Andric Value.setBit(i);
3908bcb0991SDimitry Andric }
3918bcb0991SDimitry Andric o << " ";
3928bcb0991SDimitry Andric emitInstBits(o, Value);
3938bcb0991SDimitry Andric o << "," << '\t' << "// " << R->getName() << "\n";
3948bcb0991SDimitry Andric }
3958bcb0991SDimitry Andric o << " UINT64_C(0)\n };\n";
3968bcb0991SDimitry Andric }
3978bcb0991SDimitry Andric
emitCaseMap(raw_ostream & o,const std::map<std::string,std::vector<std::string>> & CaseMap)398*fe013be4SDimitry Andric void CodeEmitterGen::emitCaseMap(
399*fe013be4SDimitry Andric raw_ostream &o,
400*fe013be4SDimitry Andric const std::map<std::string, std::vector<std::string>> &CaseMap) {
401*fe013be4SDimitry Andric std::map<std::string, std::vector<std::string>>::const_iterator IE, EE;
402*fe013be4SDimitry Andric for (IE = CaseMap.begin(), EE = CaseMap.end(); IE != EE; ++IE) {
403*fe013be4SDimitry Andric const std::string &Case = IE->first;
404*fe013be4SDimitry Andric const std::vector<std::string> &InstList = IE->second;
405*fe013be4SDimitry Andric
406*fe013be4SDimitry Andric for (int i = 0, N = InstList.size(); i < N; i++) {
407*fe013be4SDimitry Andric if (i)
408*fe013be4SDimitry Andric o << "\n";
409*fe013be4SDimitry Andric o << " case " << InstList[i] << ":";
410*fe013be4SDimitry Andric }
411*fe013be4SDimitry Andric o << " {\n";
412*fe013be4SDimitry Andric o << Case;
413*fe013be4SDimitry Andric o << " break;\n"
414*fe013be4SDimitry Andric << " }\n";
415*fe013be4SDimitry Andric }
416*fe013be4SDimitry Andric }
417*fe013be4SDimitry Andric
run(raw_ostream & o)4180b57cec5SDimitry Andric void CodeEmitterGen::run(raw_ostream &o) {
419*fe013be4SDimitry Andric emitSourceFileHeader("Machine Code Emitter", o);
420*fe013be4SDimitry Andric
4210b57cec5SDimitry Andric CodeGenTarget Target(Records);
4220b57cec5SDimitry Andric std::vector<Record*> Insts = Records.getAllDerivedDefinitions("Instruction");
4230b57cec5SDimitry Andric
4240b57cec5SDimitry Andric // For little-endian instruction bit encodings, reverse the bit order
4250b57cec5SDimitry Andric Target.reverseBitsForLittleEndianEncoding();
4260b57cec5SDimitry Andric
4270b57cec5SDimitry Andric ArrayRef<const CodeGenInstruction*> NumberedInstructions =
4280b57cec5SDimitry Andric Target.getInstructionsByEnumValue();
4290b57cec5SDimitry Andric
43081ad6265SDimitry Andric if (any_of(NumberedInstructions, [](const CodeGenInstruction *CGI) {
43181ad6265SDimitry Andric Record *R = CGI->TheDef;
43281ad6265SDimitry Andric return R->getValue("Inst") && isa<DagInit>(R->getValueInit("Inst"));
43381ad6265SDimitry Andric })) {
43481ad6265SDimitry Andric emitVarLenCodeEmitter(Records, o);
43581ad6265SDimitry Andric } else {
4368bcb0991SDimitry Andric const CodeGenHwModes &HWM = Target.getHwModes();
4378bcb0991SDimitry Andric // The set of HwModes used by instruction encodings.
4388bcb0991SDimitry Andric std::set<unsigned> HwModes;
4398bcb0991SDimitry Andric BitWidth = 0;
4408bcb0991SDimitry Andric for (const CodeGenInstruction *CGI : NumberedInstructions) {
4418bcb0991SDimitry Andric Record *R = CGI->TheDef;
4428bcb0991SDimitry Andric if (R->getValueAsString("Namespace") == "TargetOpcode" ||
4438bcb0991SDimitry Andric R->getValueAsBit("isPseudo"))
4448bcb0991SDimitry Andric continue;
4458bcb0991SDimitry Andric
4468bcb0991SDimitry Andric if (const RecordVal *RV = R->getValue("EncodingInfos")) {
4478bcb0991SDimitry Andric if (DefInit *DI = dyn_cast_or_null<DefInit>(RV->getValue())) {
4488bcb0991SDimitry Andric EncodingInfoByHwMode EBM(DI->getDef(), HWM);
449fe6060f1SDimitry Andric for (auto &KV : EBM) {
4508bcb0991SDimitry Andric BitsInit *BI = KV.second->getValueAsBitsInit("Inst");
4518bcb0991SDimitry Andric BitWidth = std::max(BitWidth, BI->getNumBits());
4528bcb0991SDimitry Andric HwModes.insert(KV.first);
4538bcb0991SDimitry Andric }
4548bcb0991SDimitry Andric continue;
4558bcb0991SDimitry Andric }
4568bcb0991SDimitry Andric }
4578bcb0991SDimitry Andric BitsInit *BI = R->getValueAsBitsInit("Inst");
4588bcb0991SDimitry Andric BitWidth = std::max(BitWidth, BI->getNumBits());
4598bcb0991SDimitry Andric }
4608bcb0991SDimitry Andric UseAPInt = BitWidth > 64;
4618bcb0991SDimitry Andric
4620b57cec5SDimitry Andric // Emit function declaration
4638bcb0991SDimitry Andric if (UseAPInt) {
4648bcb0991SDimitry Andric o << "void " << Target.getName()
4658bcb0991SDimitry Andric << "MCCodeEmitter::getBinaryCodeForInstr(const MCInst &MI,\n"
4668bcb0991SDimitry Andric << " SmallVectorImpl<MCFixup> &Fixups,\n"
4678bcb0991SDimitry Andric << " APInt &Inst,\n"
4688bcb0991SDimitry Andric << " APInt &Scratch,\n"
4698bcb0991SDimitry Andric << " const MCSubtargetInfo &STI) const {\n";
4708bcb0991SDimitry Andric } else {
4710b57cec5SDimitry Andric o << "uint64_t " << Target.getName();
4720b57cec5SDimitry Andric o << "MCCodeEmitter::getBinaryCodeForInstr(const MCInst &MI,\n"
4730b57cec5SDimitry Andric << " SmallVectorImpl<MCFixup> &Fixups,\n"
4740b57cec5SDimitry Andric << " const MCSubtargetInfo &STI) const {\n";
4758bcb0991SDimitry Andric }
4760b57cec5SDimitry Andric
4770b57cec5SDimitry Andric // Emit instruction base values
4788bcb0991SDimitry Andric if (HwModes.empty()) {
4798bcb0991SDimitry Andric emitInstructionBaseValues(o, NumberedInstructions, Target, -1);
4808bcb0991SDimitry Andric } else {
4818bcb0991SDimitry Andric for (unsigned HwMode : HwModes)
4828bcb0991SDimitry Andric emitInstructionBaseValues(o, NumberedInstructions, Target, (int)HwMode);
4830b57cec5SDimitry Andric }
4840b57cec5SDimitry Andric
4858bcb0991SDimitry Andric if (!HwModes.empty()) {
4868bcb0991SDimitry Andric o << " const uint64_t *InstBits;\n";
4878bcb0991SDimitry Andric o << " unsigned HwMode = STI.getHwMode();\n";
4888bcb0991SDimitry Andric o << " switch (HwMode) {\n";
4898bcb0991SDimitry Andric o << " default: llvm_unreachable(\"Unknown hardware mode!\"); break;\n";
4908bcb0991SDimitry Andric for (unsigned I : HwModes) {
4918bcb0991SDimitry Andric o << " case " << I << ": InstBits = InstBits_" << HWM.getMode(I).Name
4928bcb0991SDimitry Andric << "; break;\n";
4930b57cec5SDimitry Andric }
4948bcb0991SDimitry Andric o << " };\n";
4950b57cec5SDimitry Andric }
4960b57cec5SDimitry Andric
4970b57cec5SDimitry Andric // Map to accumulate all the cases.
4980b57cec5SDimitry Andric std::map<std::string, std::vector<std::string>> CaseMap;
499*fe013be4SDimitry Andric std::map<std::string, std::vector<std::string>> BitOffsetCaseMap;
5000b57cec5SDimitry Andric
5010b57cec5SDimitry Andric // Construct all cases statement for each opcode
502fe6060f1SDimitry Andric for (Record *R : Insts) {
5030b57cec5SDimitry Andric if (R->getValueAsString("Namespace") == "TargetOpcode" ||
5040b57cec5SDimitry Andric R->getValueAsBit("isPseudo"))
5050b57cec5SDimitry Andric continue;
5060b57cec5SDimitry Andric std::string InstName =
5070b57cec5SDimitry Andric (R->getValueAsString("Namespace") + "::" + R->getName()).str();
508*fe013be4SDimitry Andric std::string Case, BitOffsetCase;
509*fe013be4SDimitry Andric std::tie(Case, BitOffsetCase) = getInstructionCases(R, Target);
5100b57cec5SDimitry Andric
511*fe013be4SDimitry Andric CaseMap[Case].push_back(InstName);
512*fe013be4SDimitry Andric BitOffsetCaseMap[BitOffsetCase].push_back(std::move(InstName));
5130b57cec5SDimitry Andric }
5140b57cec5SDimitry Andric
5150b57cec5SDimitry Andric // Emit initial function code
5168bcb0991SDimitry Andric if (UseAPInt) {
5178bcb0991SDimitry Andric int NumWords = APInt::getNumWords(BitWidth);
5188bcb0991SDimitry Andric o << " const unsigned opcode = MI.getOpcode();\n"
5198bcb0991SDimitry Andric << " if (Scratch.getBitWidth() != " << BitWidth << ")\n"
5208bcb0991SDimitry Andric << " Scratch = Scratch.zext(" << BitWidth << ");\n"
521bdd1243dSDimitry Andric << " Inst = APInt(" << BitWidth << ", ArrayRef(InstBits + opcode * "
522bdd1243dSDimitry Andric << NumWords << ", " << NumWords << "));\n"
5238bcb0991SDimitry Andric << " APInt &Value = Inst;\n"
5248bcb0991SDimitry Andric << " APInt &op = Scratch;\n"
5258bcb0991SDimitry Andric << " switch (opcode) {\n";
5268bcb0991SDimitry Andric } else {
5270b57cec5SDimitry Andric o << " const unsigned opcode = MI.getOpcode();\n"
5280b57cec5SDimitry Andric << " uint64_t Value = InstBits[opcode];\n"
5290b57cec5SDimitry Andric << " uint64_t op = 0;\n"
5300b57cec5SDimitry Andric << " (void)op; // suppress warning\n"
5310b57cec5SDimitry Andric << " switch (opcode) {\n";
5328bcb0991SDimitry Andric }
5330b57cec5SDimitry Andric
5340b57cec5SDimitry Andric // Emit each case statement
535*fe013be4SDimitry Andric emitCaseMap(o, CaseMap);
5360b57cec5SDimitry Andric
5370b57cec5SDimitry Andric // Default case: unhandled opcode
5380b57cec5SDimitry Andric o << " default:\n"
5390b57cec5SDimitry Andric << " std::string msg;\n"
5400b57cec5SDimitry Andric << " raw_string_ostream Msg(msg);\n"
5410b57cec5SDimitry Andric << " Msg << \"Not supported instr: \" << MI;\n"
54281ad6265SDimitry Andric << " report_fatal_error(Msg.str().c_str());\n"
5438bcb0991SDimitry Andric << " }\n";
5448bcb0991SDimitry Andric if (UseAPInt)
5458bcb0991SDimitry Andric o << " Inst = Value;\n";
5468bcb0991SDimitry Andric else
5478bcb0991SDimitry Andric o << " return Value;\n";
5488bcb0991SDimitry Andric o << "}\n\n";
549*fe013be4SDimitry Andric
550*fe013be4SDimitry Andric o << "#ifdef GET_OPERAND_BIT_OFFSET\n"
551*fe013be4SDimitry Andric << "#undef GET_OPERAND_BIT_OFFSET\n\n"
552*fe013be4SDimitry Andric << "uint32_t " << Target.getName()
553*fe013be4SDimitry Andric << "MCCodeEmitter::getOperandBitOffset(const MCInst &MI,\n"
554*fe013be4SDimitry Andric << " unsigned OpNum,\n"
555*fe013be4SDimitry Andric << " const MCSubtargetInfo &STI) const {\n"
556*fe013be4SDimitry Andric << " switch (MI.getOpcode()) {\n";
557*fe013be4SDimitry Andric emitCaseMap(o, BitOffsetCaseMap);
558*fe013be4SDimitry Andric o << " }\n"
559*fe013be4SDimitry Andric << " std::string msg;\n"
560*fe013be4SDimitry Andric << " raw_string_ostream Msg(msg);\n"
561*fe013be4SDimitry Andric << " Msg << \"Not supported instr[opcode]: \" << MI << \"[\" << OpNum "
562*fe013be4SDimitry Andric "<< \"]\";\n"
563*fe013be4SDimitry Andric << " report_fatal_error(Msg.str().c_str());\n"
564*fe013be4SDimitry Andric << "}\n\n"
565*fe013be4SDimitry Andric << "#endif // GET_OPERAND_BIT_OFFSET\n\n";
56681ad6265SDimitry Andric }
5670b57cec5SDimitry Andric }
5680b57cec5SDimitry Andric
5690b57cec5SDimitry Andric } // end anonymous namespace
5700b57cec5SDimitry Andric
571*fe013be4SDimitry Andric static TableGen::Emitter::OptClass<CodeEmitterGen>
572*fe013be4SDimitry Andric X("gen-emitter", "Generate machine code emitter");
573