Index: utils/TableGen/FixedLenDecoderEmitter.cpp =================================================================== --- utils/TableGen/FixedLenDecoderEmitter.cpp +++ utils/TableGen/FixedLenDecoderEmitter.cpp @@ -2067,21 +2067,59 @@ // using the VS compiler. It has a bug which causes the function // to be optimized out in some circustances. See llvm.org/pr38292 static void emitFieldFromInstruction(formatted_raw_ostream &OS) { - OS << "// Helper function for extracting fields from encoded instructions.\n" - << "template\n" + OS << "// Helper functions for extracting fields from encoded instructions.\n" + << "// InsnType must either be integral or an APInt-like object that " + "must:\n" + << "// * Have a static const max_size_in_bits equal to the number of bits " + "in the\n" + << "// encoding.\n" + << "// * be default-constructible and copy-constructible\n" + << "// * be constructible from a uint64_t\n" + << "// * be constructible from an APInt (this can be private)\n" + << "// * Support getBitsSet(loBit, hiBit)\n" + << "// * be convertible to uint64_t\n" + << "// * Support the ~, &, ==, !=, and |= operators with other objects of " + "the same type\n" + << "// * Support shift (<<, >>) with signed and unsigned integers on the " + "RHS\n" + << "// * Support put (<<) to raw_ostream&\n" << "#if defined(_MSC_VER) && !defined(__clang__)\n" << "__declspec(noinline)\n" << "#endif\n" - << "static InsnType fieldFromInstruction(InsnType insn, unsigned startBit,\n" + << "template\n" + << "static InsnType fieldFromInstruction(InsnType insn, unsigned " + "startBit,\n" + << " unsigned numBits, " + "std::true_type) {\n" + << " assert(startBit + numBits <= (sizeof(InsnType) * 8) &&\n" + << " \"Instruction field out of bounds!\");\n" + << " InsnType fieldMask;\n" + << " if (numBits == sizeof(InsnType) * 8)\n" + << " fieldMask = (InsnType)(-1LL);\n" + << " else\n" + << " fieldMask = (((InsnType)1 << numBits) - 1) << startBit;\n" + << " return (insn & fieldMask) >> startBit;\n" + << "}\n" + << "\n" + << "template\n" + << "static InsnType fieldFromInstruction(InsnType insn, unsigned " + "startBit,\n" + << " unsigned numBits, " + "std::false_type) {\n" + << " assert(startBit + numBits <= InsnType::max_size_in_bits && " + "\"Instruction field out of bounds!\");\n" + << " InsnType fieldMask = InsnType::getBitsSet(0, numBits);\n" + << " return (insn >> startBit) & fieldMask;\n" + << "}\n" + << "\n" + << "template\n" + << "static InsnType fieldFromInstruction(InsnType insn, unsigned " + "startBit,\n" << " unsigned numBits) {\n" - << " assert(startBit + numBits <= (sizeof(InsnType)*8) &&\n" - << " \"Instruction field out of bounds!\");\n" - << " InsnType fieldMask;\n" - << " if (numBits == sizeof(InsnType)*8)\n" - << " fieldMask = (InsnType)(-1LL);\n" - << " else\n" - << " fieldMask = (((InsnType)1 << numBits) - 1) << startBit;\n" - << " return (insn & fieldMask) >> startBit;\n" + << " assert(startBit + numBits <= 64 && \"Cannot support >64-bit " + "extractions!\");\n" + << " return fieldFromInstruction(insn, startBit, numBits, " + "std::is_integral());\n" << "}\n\n"; }