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