1f22ef01cSRoman Divacky //===- CodeEmitterGen.cpp - Code Emitter Generator ------------------------===//
2f22ef01cSRoman Divacky //
3f22ef01cSRoman Divacky // The LLVM Compiler Infrastructure
4f22ef01cSRoman Divacky //
5f22ef01cSRoman Divacky // This file is distributed under the University of Illinois Open Source
6f22ef01cSRoman Divacky // License. See LICENSE.TXT for details.
7f22ef01cSRoman Divacky //
8f22ef01cSRoman Divacky //===----------------------------------------------------------------------===//
9f22ef01cSRoman Divacky //
10f22ef01cSRoman Divacky // CodeEmitterGen uses the descriptions of instructions and their fields to
11f22ef01cSRoman Divacky // construct an automated code emitter: a function that, given a MachineInstr,
12f22ef01cSRoman Divacky // returns the (currently, 32-bit unsigned) value of the instruction.
13f22ef01cSRoman Divacky //
14f22ef01cSRoman Divacky //===----------------------------------------------------------------------===//
15f22ef01cSRoman Divacky
16d88c1a5aSDimitry Andric #include "CodeGenInstruction.h"
17f22ef01cSRoman Divacky #include "CodeGenTarget.h"
18d88c1a5aSDimitry Andric #include "SubtargetFeatureInfo.h"
19d88c1a5aSDimitry Andric #include "llvm/ADT/ArrayRef.h"
20f22ef01cSRoman Divacky #include "llvm/ADT/StringExtras.h"
21d88c1a5aSDimitry Andric #include "llvm/Support/Casting.h"
22d88c1a5aSDimitry Andric #include "llvm/Support/raw_ostream.h"
23139f7f9bSDimitry Andric #include "llvm/TableGen/Record.h"
247ae0e2c9SDimitry Andric #include "llvm/TableGen/TableGenBackend.h"
25d88c1a5aSDimitry Andric #include <cassert>
26d88c1a5aSDimitry Andric #include <cstdint>
272754fe60SDimitry Andric #include <map>
28d88c1a5aSDimitry Andric #include <set>
297ae0e2c9SDimitry Andric #include <string>
30d88c1a5aSDimitry Andric #include <utility>
317ae0e2c9SDimitry Andric #include <vector>
32d88c1a5aSDimitry Andric
33f22ef01cSRoman Divacky using namespace llvm;
34f22ef01cSRoman Divacky
357ae0e2c9SDimitry Andric namespace {
367ae0e2c9SDimitry Andric
377ae0e2c9SDimitry Andric class CodeEmitterGen {
387ae0e2c9SDimitry Andric RecordKeeper &Records;
39d88c1a5aSDimitry Andric
407ae0e2c9SDimitry Andric public:
CodeEmitterGen(RecordKeeper & R)417ae0e2c9SDimitry Andric CodeEmitterGen(RecordKeeper &R) : Records(R) {}
427ae0e2c9SDimitry Andric
437ae0e2c9SDimitry Andric void run(raw_ostream &o);
44d88c1a5aSDimitry Andric
457ae0e2c9SDimitry Andric private:
467ae0e2c9SDimitry Andric int getVariableBit(const std::string &VarName, BitsInit *BI, int bit);
477ae0e2c9SDimitry Andric std::string getInstructionCase(Record *R, CodeGenTarget &Target);
487ae0e2c9SDimitry Andric void AddCodeToMergeInOperand(Record *R, BitsInit *BI,
497ae0e2c9SDimitry Andric const std::string &VarName,
507ae0e2c9SDimitry Andric unsigned &NumberedOp,
5191bc56edSDimitry Andric std::set<unsigned> &NamedOpIndices,
527ae0e2c9SDimitry Andric std::string &Case, CodeGenTarget &Target);
537ae0e2c9SDimitry Andric
547ae0e2c9SDimitry Andric };
557ae0e2c9SDimitry Andric
56f22ef01cSRoman Divacky // If the VarBitInit at position 'bit' matches the specified variable then
57f22ef01cSRoman Divacky // return the variable bit position. Otherwise return -1.
getVariableBit(const std::string & VarName,BitsInit * BI,int bit)58f22ef01cSRoman Divacky int CodeEmitterGen::getVariableBit(const std::string &VarName,
59f22ef01cSRoman Divacky BitsInit *BI, int bit) {
603861d79fSDimitry Andric if (VarBitInit *VBI = dyn_cast<VarBitInit>(BI->getBit(bit))) {
613861d79fSDimitry Andric if (VarInit *VI = dyn_cast<VarInit>(VBI->getBitVar()))
622754fe60SDimitry Andric if (VI->getName() == VarName)
632754fe60SDimitry Andric return VBI->getBitNum();
643861d79fSDimitry Andric } else if (VarInit *VI = dyn_cast<VarInit>(BI->getBit(bit))) {
653b0f4066SDimitry Andric if (VI->getName() == VarName)
663b0f4066SDimitry Andric return 0;
673b0f4066SDimitry Andric }
68f22ef01cSRoman Divacky
69f22ef01cSRoman Divacky return -1;
70f22ef01cSRoman Divacky }
71f22ef01cSRoman Divacky
722754fe60SDimitry Andric void CodeEmitterGen::
AddCodeToMergeInOperand(Record * R,BitsInit * BI,const std::string & VarName,unsigned & NumberedOp,std::set<unsigned> & NamedOpIndices,std::string & Case,CodeGenTarget & Target)732754fe60SDimitry Andric AddCodeToMergeInOperand(Record *R, BitsInit *BI, const std::string &VarName,
742754fe60SDimitry Andric unsigned &NumberedOp,
7591bc56edSDimitry Andric std::set<unsigned> &NamedOpIndices,
762754fe60SDimitry Andric std::string &Case, CodeGenTarget &Target) {
772754fe60SDimitry Andric CodeGenInstruction &CGI = Target.getInstruction(R);
782754fe60SDimitry Andric
792754fe60SDimitry Andric // Determine if VarName actually contributes to the Inst encoding.
802754fe60SDimitry Andric int bit = BI->getNumBits()-1;
812754fe60SDimitry Andric
822754fe60SDimitry Andric // Scan for a bit that this contributed to.
832754fe60SDimitry Andric for (; bit >= 0; ) {
842754fe60SDimitry Andric if (getVariableBit(VarName, BI, bit) != -1)
852754fe60SDimitry Andric break;
862754fe60SDimitry Andric
872754fe60SDimitry Andric --bit;
882754fe60SDimitry Andric }
892754fe60SDimitry Andric
902754fe60SDimitry Andric // If we found no bits, ignore this value, otherwise emit the call to get the
912754fe60SDimitry Andric // operand encoding.
922754fe60SDimitry Andric if (bit < 0) return;
932754fe60SDimitry Andric
942754fe60SDimitry Andric // If the operand matches by name, reference according to that
952754fe60SDimitry Andric // operand number. Non-matching operands are assumed to be in
962754fe60SDimitry Andric // order.
972754fe60SDimitry Andric unsigned OpIdx;
982754fe60SDimitry Andric if (CGI.Operands.hasOperandNamed(VarName, OpIdx)) {
992754fe60SDimitry Andric // Get the machine operand number for the indicated operand.
1002754fe60SDimitry Andric OpIdx = CGI.Operands[OpIdx].MIOperandNo;
1012754fe60SDimitry Andric assert(!CGI.Operands.isFlatOperandNotEmitted(OpIdx) &&
1022754fe60SDimitry Andric "Explicitly used operand also marked as not emitted!");
1032754fe60SDimitry Andric } else {
1043861d79fSDimitry Andric unsigned NumberOps = CGI.Operands.size();
1052754fe60SDimitry Andric /// If this operand is not supposed to be emitted by the
1062754fe60SDimitry Andric /// generated emitter, skip it.
1073861d79fSDimitry Andric while (NumberedOp < NumberOps &&
10891bc56edSDimitry Andric (CGI.Operands.isFlatOperandNotEmitted(NumberedOp) ||
109ff0cc061SDimitry Andric (!NamedOpIndices.empty() && NamedOpIndices.count(
11091bc56edSDimitry Andric CGI.Operands.getSubOperandNumber(NumberedOp).first)))) {
1112754fe60SDimitry Andric ++NumberedOp;
1123861d79fSDimitry Andric
11391bc56edSDimitry Andric if (NumberedOp >= CGI.Operands.back().MIOperandNo +
11491bc56edSDimitry Andric CGI.Operands.back().MINumOperands) {
11591bc56edSDimitry Andric errs() << "Too few operands in record " << R->getName() <<
11691bc56edSDimitry Andric " (no match for variable " << VarName << "):\n";
11791bc56edSDimitry Andric errs() << *R;
11891bc56edSDimitry Andric errs() << '\n';
11991bc56edSDimitry Andric
12091bc56edSDimitry Andric return;
12191bc56edSDimitry Andric }
12291bc56edSDimitry Andric }
12391bc56edSDimitry Andric
1242754fe60SDimitry Andric OpIdx = NumberedOp++;
1252754fe60SDimitry Andric }
1262754fe60SDimitry Andric
1272754fe60SDimitry Andric std::pair<unsigned, unsigned> SO = CGI.Operands.getSubOperandNumber(OpIdx);
1282754fe60SDimitry Andric std::string &EncoderMethodName = CGI.Operands[SO.first].EncoderMethodName;
1292754fe60SDimitry Andric
1302754fe60SDimitry Andric // If the source operand has a custom encoder, use it. This will
1312754fe60SDimitry Andric // get the encoding for all of the suboperands.
1322754fe60SDimitry Andric if (!EncoderMethodName.empty()) {
1332754fe60SDimitry Andric // A custom encoder has all of the information for the
1342754fe60SDimitry Andric // sub-operands, if there are more than one, so only
1352754fe60SDimitry Andric // query the encoder once per source operand.
1362754fe60SDimitry Andric if (SO.second == 0) {
1372754fe60SDimitry Andric Case += " // op: " + VarName + "\n" +
1382754fe60SDimitry Andric " op = " + EncoderMethodName + "(MI, " + utostr(OpIdx);
13991bc56edSDimitry Andric Case += ", Fixups, STI";
1402754fe60SDimitry Andric Case += ");\n";
1412754fe60SDimitry Andric }
1422754fe60SDimitry Andric } else {
1432754fe60SDimitry Andric Case += " // op: " + VarName + "\n" +
1442754fe60SDimitry Andric " op = getMachineOpValue(MI, MI.getOperand(" + utostr(OpIdx) + ")";
14591bc56edSDimitry Andric Case += ", Fixups, STI";
1462754fe60SDimitry Andric Case += ");\n";
1472754fe60SDimitry Andric }
1482754fe60SDimitry Andric
1492754fe60SDimitry Andric for (; bit >= 0; ) {
1502754fe60SDimitry Andric int varBit = getVariableBit(VarName, BI, bit);
1512754fe60SDimitry Andric
1522754fe60SDimitry Andric // If this bit isn't from a variable, skip it.
1532754fe60SDimitry Andric if (varBit == -1) {
1542754fe60SDimitry Andric --bit;
1552754fe60SDimitry Andric continue;
1562754fe60SDimitry Andric }
1572754fe60SDimitry Andric
1582754fe60SDimitry Andric // Figure out the consecutive range of bits covered by this operand, in
1592754fe60SDimitry Andric // order to generate better encoding code.
1602754fe60SDimitry Andric int beginInstBit = bit;
1612754fe60SDimitry Andric int beginVarBit = varBit;
1622754fe60SDimitry Andric int N = 1;
1632754fe60SDimitry Andric for (--bit; bit >= 0;) {
1642754fe60SDimitry Andric varBit = getVariableBit(VarName, BI, bit);
1652754fe60SDimitry Andric if (varBit == -1 || varBit != (beginVarBit - N)) break;
1662754fe60SDimitry Andric ++N;
1672754fe60SDimitry Andric --bit;
1682754fe60SDimitry Andric }
1692754fe60SDimitry Andric
170dff0c46cSDimitry Andric uint64_t opMask = ~(uint64_t)0 >> (64-N);
1712754fe60SDimitry Andric int opShift = beginVarBit - N + 1;
1722754fe60SDimitry Andric opMask <<= opShift;
1732754fe60SDimitry Andric opShift = beginInstBit - beginVarBit;
1742754fe60SDimitry Andric
1752754fe60SDimitry Andric if (opShift > 0) {
176dff0c46cSDimitry Andric Case += " Value |= (op & UINT64_C(" + utostr(opMask) + ")) << " +
1772754fe60SDimitry Andric itostr(opShift) + ";\n";
1782754fe60SDimitry Andric } else if (opShift < 0) {
179dff0c46cSDimitry Andric Case += " Value |= (op & UINT64_C(" + utostr(opMask) + ")) >> " +
1802754fe60SDimitry Andric itostr(-opShift) + ";\n";
1812754fe60SDimitry Andric } else {
182dff0c46cSDimitry Andric Case += " Value |= op & UINT64_C(" + utostr(opMask) + ");\n";
1832754fe60SDimitry Andric }
1842754fe60SDimitry Andric }
1852754fe60SDimitry Andric }
1862754fe60SDimitry Andric
getInstructionCase(Record * R,CodeGenTarget & Target)1872754fe60SDimitry Andric std::string CodeEmitterGen::getInstructionCase(Record *R,
1882754fe60SDimitry Andric CodeGenTarget &Target) {
1892754fe60SDimitry Andric std::string Case;
1902754fe60SDimitry Andric BitsInit *BI = R->getValueAsBitsInit("Inst");
1912754fe60SDimitry Andric unsigned NumberedOp = 0;
19291bc56edSDimitry Andric std::set<unsigned> NamedOpIndices;
193*c4394386SDimitry Andric
19491bc56edSDimitry Andric // Collect the set of operand indices that might correspond to named
19591bc56edSDimitry Andric // operand, and skip these when assigning operands based on position.
19691bc56edSDimitry Andric if (Target.getInstructionSet()->
19791bc56edSDimitry Andric getValueAsBit("noNamedPositionallyEncodedOperands")) {
19891bc56edSDimitry Andric CodeGenInstruction &CGI = Target.getInstruction(R);
199*c4394386SDimitry Andric for (const RecordVal &RV : R->getValues()) {
20091bc56edSDimitry Andric unsigned OpIdx;
201*c4394386SDimitry Andric if (!CGI.Operands.hasOperandNamed(RV.getName(), OpIdx))
20291bc56edSDimitry Andric continue;
20391bc56edSDimitry Andric
20491bc56edSDimitry Andric NamedOpIndices.insert(OpIdx);
20591bc56edSDimitry Andric }
20691bc56edSDimitry Andric }
20791bc56edSDimitry Andric
2082754fe60SDimitry Andric // Loop over all of the fields in the instruction, determining which are the
2092754fe60SDimitry Andric // operands to the instruction.
210*c4394386SDimitry Andric for (const RecordVal &RV : R->getValues()) {
2112754fe60SDimitry Andric // Ignore fixed fields in the record, we're looking for values like:
2122754fe60SDimitry Andric // bits<5> RST = { ?, ?, ?, ?, ? };
213*c4394386SDimitry Andric if (RV.getPrefix() || RV.getValue()->isComplete())
2142754fe60SDimitry Andric continue;
2152754fe60SDimitry Andric
216*c4394386SDimitry Andric AddCodeToMergeInOperand(R, BI, RV.getName(), NumberedOp,
21791bc56edSDimitry Andric NamedOpIndices, Case, Target);
2182754fe60SDimitry Andric }
2192754fe60SDimitry Andric
220f9448bf3SDimitry Andric StringRef PostEmitter = R->getValueAsString("PostEncoderMethod");
22191bc56edSDimitry Andric if (!PostEmitter.empty()) {
222f9448bf3SDimitry Andric Case += " Value = ";
223f9448bf3SDimitry Andric Case += PostEmitter;
224f9448bf3SDimitry Andric Case += "(MI, Value";
22591bc56edSDimitry Andric Case += ", STI";
22691bc56edSDimitry Andric Case += ");\n";
22791bc56edSDimitry Andric }
2282754fe60SDimitry Andric
2292754fe60SDimitry Andric return Case;
2302754fe60SDimitry Andric }
231f22ef01cSRoman Divacky
run(raw_ostream & o)232f22ef01cSRoman Divacky void CodeEmitterGen::run(raw_ostream &o) {
2332754fe60SDimitry Andric CodeGenTarget Target(Records);
234f22ef01cSRoman Divacky std::vector<Record*> Insts = Records.getAllDerivedDefinitions("Instruction");
235f22ef01cSRoman Divacky
236f22ef01cSRoman Divacky // For little-endian instruction bit encodings, reverse the bit order
23791bc56edSDimitry Andric Target.reverseBitsForLittleEndianEncoding();
238f22ef01cSRoman Divacky
2393ca95b02SDimitry Andric ArrayRef<const CodeGenInstruction*> NumberedInstructions =
240f22ef01cSRoman Divacky Target.getInstructionsByEnumValue();
241f22ef01cSRoman Divacky
242f22ef01cSRoman Divacky // Emit function declaration
243dff0c46cSDimitry Andric o << "uint64_t " << Target.getName();
2442754fe60SDimitry Andric o << "MCCodeEmitter::getBinaryCodeForInstr(const MCInst &MI,\n"
24591bc56edSDimitry Andric << " SmallVectorImpl<MCFixup> &Fixups,\n"
24691bc56edSDimitry Andric << " const MCSubtargetInfo &STI) const {\n";
247f22ef01cSRoman Divacky
248f22ef01cSRoman Divacky // Emit instruction base values
249dff0c46cSDimitry Andric o << " static const uint64_t InstBits[] = {\n";
2503ca95b02SDimitry Andric for (const CodeGenInstruction *CGI : NumberedInstructions) {
251f22ef01cSRoman Divacky Record *R = CGI->TheDef;
252f22ef01cSRoman Divacky
25317a519f9SDimitry Andric if (R->getValueAsString("Namespace") == "TargetOpcode" ||
25417a519f9SDimitry Andric R->getValueAsBit("isPseudo")) {
255dff0c46cSDimitry Andric o << " UINT64_C(0),\n";
256f22ef01cSRoman Divacky continue;
257f22ef01cSRoman Divacky }
258f22ef01cSRoman Divacky
259f22ef01cSRoman Divacky BitsInit *BI = R->getValueAsBitsInit("Inst");
260f22ef01cSRoman Divacky
2612754fe60SDimitry Andric // Start by filling in fixed values.
262dff0c46cSDimitry Andric uint64_t Value = 0;
263f22ef01cSRoman Divacky for (unsigned i = 0, e = BI->getNumBits(); i != e; ++i) {
2643861d79fSDimitry Andric if (BitInit *B = dyn_cast<BitInit>(BI->getBit(e-i-1)))
265dff0c46cSDimitry Andric Value |= (uint64_t)B->getValue() << (e-i-1);
266f22ef01cSRoman Divacky }
267dff0c46cSDimitry Andric o << " UINT64_C(" << Value << ")," << '\t' << "// " << R->getName() << "\n";
268f22ef01cSRoman Divacky }
269dff0c46cSDimitry Andric o << " UINT64_C(0)\n };\n";
270f22ef01cSRoman Divacky
271f22ef01cSRoman Divacky // Map to accumulate all the cases.
272f22ef01cSRoman Divacky std::map<std::string, std::vector<std::string>> CaseMap;
273f22ef01cSRoman Divacky
274f22ef01cSRoman Divacky // Construct all cases statement for each opcode
275f22ef01cSRoman Divacky for (std::vector<Record*>::iterator IC = Insts.begin(), EC = Insts.end();
276f22ef01cSRoman Divacky IC != EC; ++IC) {
277f22ef01cSRoman Divacky Record *R = *IC;
27817a519f9SDimitry Andric if (R->getValueAsString("Namespace") == "TargetOpcode" ||
27917a519f9SDimitry Andric R->getValueAsBit("isPseudo"))
280ffd1746dSEd Schouten continue;
281f9448bf3SDimitry Andric std::string InstName =
282f9448bf3SDimitry Andric (R->getValueAsString("Namespace") + "::" + R->getName()).str();
2832754fe60SDimitry Andric std::string Case = getInstructionCase(R, Target);
284f22ef01cSRoman Divacky
285f9448bf3SDimitry Andric CaseMap[Case].push_back(std::move(InstName));
286f22ef01cSRoman Divacky }
287f22ef01cSRoman Divacky
288f22ef01cSRoman Divacky // Emit initial function code
289f22ef01cSRoman Divacky o << " const unsigned opcode = MI.getOpcode();\n"
290dff0c46cSDimitry Andric << " uint64_t Value = InstBits[opcode];\n"
291dff0c46cSDimitry Andric << " uint64_t op = 0;\n"
2922754fe60SDimitry Andric << " (void)op; // suppress warning\n"
293f22ef01cSRoman Divacky << " switch (opcode) {\n";
294f22ef01cSRoman Divacky
295f22ef01cSRoman Divacky // Emit each case statement
296f22ef01cSRoman Divacky std::map<std::string, std::vector<std::string>>::iterator IE, EE;
297f22ef01cSRoman Divacky for (IE = CaseMap.begin(), EE = CaseMap.end(); IE != EE; ++IE) {
298f22ef01cSRoman Divacky const std::string &Case = IE->first;
299f22ef01cSRoman Divacky std::vector<std::string> &InstList = IE->second;
300f22ef01cSRoman Divacky
301f22ef01cSRoman Divacky for (int i = 0, N = InstList.size(); i < N; i++) {
302f22ef01cSRoman Divacky if (i) o << "\n";
3032754fe60SDimitry Andric o << " case " << InstList[i] << ":";
304f22ef01cSRoman Divacky }
305f22ef01cSRoman Divacky o << " {\n";
306f22ef01cSRoman Divacky o << Case;
307f22ef01cSRoman Divacky o << " break;\n"
308f22ef01cSRoman Divacky << " }\n";
309f22ef01cSRoman Divacky }
310f22ef01cSRoman Divacky
311f22ef01cSRoman Divacky // Default case: unhandled opcode
312f22ef01cSRoman Divacky o << " default:\n"
313f22ef01cSRoman Divacky << " std::string msg;\n"
314f22ef01cSRoman Divacky << " raw_string_ostream Msg(msg);\n"
315f22ef01cSRoman Divacky << " Msg << \"Not supported instr: \" << MI;\n"
316f22ef01cSRoman Divacky << " report_fatal_error(Msg.str());\n"
317f22ef01cSRoman Divacky << " }\n"
318f22ef01cSRoman Divacky << " return Value;\n"
319f22ef01cSRoman Divacky << "}\n\n";
320d88c1a5aSDimitry Andric
321d88c1a5aSDimitry Andric const auto &All = SubtargetFeatureInfo::getAll(Records);
322d88c1a5aSDimitry Andric std::map<Record *, SubtargetFeatureInfo, LessRecordByID> SubtargetFeatures;
323d88c1a5aSDimitry Andric SubtargetFeatures.insert(All.begin(), All.end());
324d88c1a5aSDimitry Andric
325d88c1a5aSDimitry Andric o << "#ifdef ENABLE_INSTR_PREDICATE_VERIFIER\n"
326d88c1a5aSDimitry Andric << "#undef ENABLE_INSTR_PREDICATE_VERIFIER\n"
327d88c1a5aSDimitry Andric << "#include <sstream>\n\n";
328d88c1a5aSDimitry Andric
329d88c1a5aSDimitry Andric // Emit the subtarget feature enumeration.
330d88c1a5aSDimitry Andric SubtargetFeatureInfo::emitSubtargetFeatureFlagEnumeration(SubtargetFeatures,
331d88c1a5aSDimitry Andric o);
332d88c1a5aSDimitry Andric
333d88c1a5aSDimitry Andric // Emit the name table for error messages.
334d88c1a5aSDimitry Andric o << "#ifndef NDEBUG\n";
335d88c1a5aSDimitry Andric SubtargetFeatureInfo::emitNameTable(SubtargetFeatures, o);
336d88c1a5aSDimitry Andric o << "#endif // NDEBUG\n";
337d88c1a5aSDimitry Andric
338d88c1a5aSDimitry Andric // Emit the available features compute function.
33951690af2SDimitry Andric SubtargetFeatureInfo::emitComputeAssemblerAvailableFeatures(
340d88c1a5aSDimitry Andric Target.getName(), "MCCodeEmitter", "computeAvailableFeatures",
341d88c1a5aSDimitry Andric SubtargetFeatures, o);
342d88c1a5aSDimitry Andric
343d88c1a5aSDimitry Andric // Emit the predicate verifier.
344d88c1a5aSDimitry Andric o << "void " << Target.getName()
345d88c1a5aSDimitry Andric << "MCCodeEmitter::verifyInstructionPredicates(\n"
346d88c1a5aSDimitry Andric << " const MCInst &Inst, uint64_t AvailableFeatures) const {\n"
347d88c1a5aSDimitry Andric << "#ifndef NDEBUG\n"
348d88c1a5aSDimitry Andric << " static uint64_t RequiredFeatures[] = {\n";
349d88c1a5aSDimitry Andric unsigned InstIdx = 0;
350d88c1a5aSDimitry Andric for (const CodeGenInstruction *Inst : Target.getInstructionsByEnumValue()) {
351d88c1a5aSDimitry Andric o << " ";
352d88c1a5aSDimitry Andric for (Record *Predicate : Inst->TheDef->getValueAsListOfDefs("Predicates")) {
353d88c1a5aSDimitry Andric const auto &I = SubtargetFeatures.find(Predicate);
354d88c1a5aSDimitry Andric if (I != SubtargetFeatures.end())
355d88c1a5aSDimitry Andric o << I->second.getEnumName() << " | ";
356d88c1a5aSDimitry Andric }
357d88c1a5aSDimitry Andric o << "0, // " << Inst->TheDef->getName() << " = " << InstIdx << "\n";
358d88c1a5aSDimitry Andric InstIdx++;
359d88c1a5aSDimitry Andric }
360d88c1a5aSDimitry Andric o << " };\n\n";
361d88c1a5aSDimitry Andric o << " assert(Inst.getOpcode() < " << InstIdx << ");\n";
362d88c1a5aSDimitry Andric o << " uint64_t MissingFeatures =\n"
363d88c1a5aSDimitry Andric << " (AvailableFeatures & RequiredFeatures[Inst.getOpcode()]) ^\n"
364d88c1a5aSDimitry Andric << " RequiredFeatures[Inst.getOpcode()];\n"
365d88c1a5aSDimitry Andric << " if (MissingFeatures) {\n"
366d88c1a5aSDimitry Andric << " std::ostringstream Msg;\n"
367d88c1a5aSDimitry Andric << " Msg << \"Attempting to emit \" << "
368d88c1a5aSDimitry Andric "MCII.getName(Inst.getOpcode()).str()\n"
369d88c1a5aSDimitry Andric << " << \" instruction but the \";\n"
370d88c1a5aSDimitry Andric << " for (unsigned i = 0; i < 8 * sizeof(MissingFeatures); ++i)\n"
371d88c1a5aSDimitry Andric << " if (MissingFeatures & (1ULL << i))\n"
372d88c1a5aSDimitry Andric << " Msg << SubtargetFeatureNames[i] << \" \";\n"
373d88c1a5aSDimitry Andric << " Msg << \"predicate(s) are not met\";\n"
374d88c1a5aSDimitry Andric << " report_fatal_error(Msg.str());\n"
375d88c1a5aSDimitry Andric << " }\n"
376d88c1a5aSDimitry Andric << "#else\n"
377d88c1a5aSDimitry Andric << "// Silence unused variable warning on targets that don't use MCII for "
378d88c1a5aSDimitry Andric "other purposes (e.g. BPF).\n"
379d88c1a5aSDimitry Andric << "(void)MCII;\n"
380d88c1a5aSDimitry Andric << "#endif // NDEBUG\n";
381d88c1a5aSDimitry Andric o << "}\n";
382d88c1a5aSDimitry Andric o << "#endif\n";
383f22ef01cSRoman Divacky }
3847ae0e2c9SDimitry Andric
385d88c1a5aSDimitry Andric } // end anonymous namespace
3867ae0e2c9SDimitry Andric
3877ae0e2c9SDimitry Andric namespace llvm {
3887ae0e2c9SDimitry Andric
EmitCodeEmitter(RecordKeeper & RK,raw_ostream & OS)3897ae0e2c9SDimitry Andric void EmitCodeEmitter(RecordKeeper &RK, raw_ostream &OS) {
3907ae0e2c9SDimitry Andric emitSourceFileHeader("Machine Code Emitter", OS);
3917ae0e2c9SDimitry Andric CodeEmitterGen(RK).run(OS);
3927ae0e2c9SDimitry Andric }
3937ae0e2c9SDimitry Andric
394d88c1a5aSDimitry Andric } // end namespace llvm
395