--- /dev/null
+
+std::map<uint64_t, uint32_t> GetOpcodeAndNumOperandsHist() {
+ return std::map<uint64_t, uint32_t>({
+ { CombineOpcodeAndNumOperands(SpvOpExtInst, 7), 158282 },
+ { CombineOpcodeAndNumOperands(SpvOpDot, 4), 151035 },
+ { CombineOpcodeAndNumOperands(SpvOpVectorShuffle, 6), 183292 },
+ { CombineOpcodeAndNumOperands(SpvOpImageSampleImplicitLod, 4), 126492 },
+ { CombineOpcodeAndNumOperands(SpvOpExecutionMode, 2), 13311 },
+ { CombineOpcodeAndNumOperands(SpvOpFNegate, 3), 29952 },
+ { CombineOpcodeAndNumOperands(SpvOpExtInst, 5), 106847 },
+ { CombineOpcodeAndNumOperands(SpvOpImageSampleExplicitLod, 7), 26350 },
+ { CombineOpcodeAndNumOperands(SpvOpImageSampleExplicitLod, 6), 28186 },
+ { CombineOpcodeAndNumOperands(SpvOpFDiv, 4), 41635 },
+ { CombineOpcodeAndNumOperands(SpvOpFMul, 4), 412786 },
+ { CombineOpcodeAndNumOperands(SpvOpFunction, 4), 62905 },
+ { CombineOpcodeAndNumOperands(SpvOpVectorShuffle, 8), 118614 },
+ { CombineOpcodeAndNumOperands(SpvOpDecorate, 2), 100735 },
+ { CombineOpcodeAndNumOperands(SpvOpReturnValue, 1), 40852 },
+ { CombineOpcodeAndNumOperands(SpvOpVectorTimesScalar, 4), 157091 },
+ { CombineOpcodeAndNumOperands(SpvOpExtInst, 6), 122100 },
+ { CombineOpcodeAndNumOperands(SpvOpAccessChain, 5), 82930 },
+ { CombineOpcodeAndNumOperands(SpvOpFSub, 4), 161019 },
+ { CombineOpcodeAndNumOperands(SpvOpConstant, 3), 466014 },
+ { CombineOpcodeAndNumOperands(SpvOpCompositeExtract, 5), 107126 },
+ { CombineOpcodeAndNumOperands(SpvOpTypeImage, 8), 34775 },
+ { CombineOpcodeAndNumOperands(SpvOpImageSampleDrefExplicitLod, 7), 26146 },
+ { CombineOpcodeAndNumOperands(SpvOpMemoryModel, 2), 18879 },
+ { CombineOpcodeAndNumOperands(SpvOpDecorate, 3), 485251 },
+ { CombineOpcodeAndNumOperands(SpvOpCompositeConstruct, 4), 78011 },
+ { CombineOpcodeAndNumOperands(SpvOpTypeFloat, 2), 18879 },
+ { CombineOpcodeAndNumOperands(SpvOpVectorTimesMatrix, 4), 15848 },
+ { CombineOpcodeAndNumOperands(SpvOpTypeVector, 3), 69404 },
+ { CombineOpcodeAndNumOperands(SpvOpTypeFunction, 3), 19998 },
+ { CombineOpcodeAndNumOperands(SpvOpConstantComposite, 6), 40228 },
+ { CombineOpcodeAndNumOperands(SpvOpCapability, 1), 22510 },
+ { CombineOpcodeAndNumOperands(SpvOpTypeArray, 3), 37585 },
+ { CombineOpcodeAndNumOperands(SpvOpTypeInt, 3), 30454 },
+ { CombineOpcodeAndNumOperands(SpvOpFunctionCall, 4), 29021 },
+ { CombineOpcodeAndNumOperands(SpvOpFAdd, 4), 342237 },
+ { CombineOpcodeAndNumOperands(SpvOpTypeMatrix, 3), 24449 },
+ { CombineOpcodeAndNumOperands(SpvOpLabel, 1), 129408 },
+ { CombineOpcodeAndNumOperands(SpvOpTypePointer, 3), 246535 },
+ { CombineOpcodeAndNumOperands(SpvOpAccessChain, 4), 503456 },
+ { CombineOpcodeAndNumOperands(SpvOpTypeFunction, 2), 19779 },
+ { CombineOpcodeAndNumOperands(SpvOpBranchConditional, 3), 24139 },
+ { CombineOpcodeAndNumOperands(SpvOpVariable, 3), 697946 },
+ { CombineOpcodeAndNumOperands(SpvOpConstantComposite, 5), 55769 },
+ { CombineOpcodeAndNumOperands(SpvOpTypeVoid, 1), 18879 },
+ { CombineOpcodeAndNumOperands(SpvOpCompositeConstruct, 6), 145508 },
+ { CombineOpcodeAndNumOperands(SpvOpFunctionParameter, 2), 85583 },
+ { CombineOpcodeAndNumOperands(SpvOpTypeSampledImage, 2), 34775 },
+ { CombineOpcodeAndNumOperands(SpvOpConstantComposite, 4), 66362 },
+ { CombineOpcodeAndNumOperands(SpvOpLoad, 3), 1272902 },
+ { CombineOpcodeAndNumOperands(SpvOpReturn, 0), 22122 },
+ { CombineOpcodeAndNumOperands(SpvOpCompositeExtract, 4), 861008 },
+ { CombineOpcodeAndNumOperands(SpvOpFunctionEnd, 0), 62905 },
+ { CombineOpcodeAndNumOperands(SpvOpExtInstImport, 2), 18879 },
+ { CombineOpcodeAndNumOperands(SpvOpSelectionMerge, 2), 22009 },
+ { CombineOpcodeAndNumOperands(SpvOpBranch, 1), 38275 },
+ { CombineOpcodeAndNumOperands(SpvOpTypeBool, 1), 12208 },
+ { CombineOpcodeAndNumOperands(SpvOpSampledImage, 4), 95518 },
+ { CombineOpcodeAndNumOperands(SpvOpMemberDecorate, 3), 94887 },
+ { CombineOpcodeAndNumOperands(SpvOpMemberDecorate, 4), 1942215 },
+ { CombineOpcodeAndNumOperands(SpvOpCompositeConstruct, 5), 205266 },
+ { CombineOpcodeAndNumOperands(SpvOpUndef, 2), 22157 },
+ { CombineOpcodeAndNumOperands(SpvOpCompositeInsert, 5), 142749 },
+ { CombineOpcodeAndNumOperands(SpvOpCompositeInsert, 6), 24420 },
+ { CombineOpcodeAndNumOperands(SpvOpCompositeExtract, 6), 16896 },
+ { CombineOpcodeAndNumOperands(SpvOpStore, 2), 604982 },
+ { CombineOpcodeAndNumOperands(SpvOpIAdd, 4), 14471 },
+ { CombineOpcodeAndNumOperands(SpvOpVectorShuffle, 7), 269658 },
+ { kMarkvNoneOfTheAbove, 399895 },
+ });
+}
+
+std::map<uint32_t, std::unique_ptr<HuffmanCodec<uint64_t>>>
+GetOpcodeAndNumOperandsMarkovHuffmanCodecs() {
+ std::map<uint32_t, std::unique_ptr<HuffmanCodec<uint64_t>>> codecs;
+ {
+ std::unique_ptr<HuffmanCodec<uint64_t>> codec(new HuffmanCodec<uint64_t>(51, {
+ {0, 0, 0},
+ {131134, 0, 0},
+ {196669, 0, 0},
+ {262209, 0, 0},
+ {262224, 0, 0},
+ {262225, 0, 0},
+ {262231, 0, 0},
+ {262273, 0, 0},
+ {262275, 0, 0},
+ {262277, 0, 0},
+ {262286, 0, 0},
+ {262292, 0, 0},
+ {327692, 0, 0},
+ {327745, 0, 0},
+ {327760, 0, 0},
+ {327761, 0, 0},
+ {327762, 0, 0},
+ {393228, 0, 0},
+ {393281, 0, 0},
+ {393295, 0, 0},
+ {393296, 0, 0},
+ {393297, 0, 0},
+ {393298, 0, 0},
+ {458764, 0, 0},
+ {458831, 0, 0},
+ {524367, 0, 0},
+ {1111111111111111111, 0, 0},
+ {0, 18, 6},
+ {0, 13, 27},
+ {0, 19, 12},
+ {0, 15, 22},
+ {0, 28, 21},
+ {0, 29, 16},
+ {0, 30, 10},
+ {0, 17, 20},
+ {0, 11, 25},
+ {0, 26, 31},
+ {0, 4, 32},
+ {0, 34, 33},
+ {0, 24, 35},
+ {0, 23, 36},
+ {0, 37, 14},
+ {0, 38, 8},
+ {0, 1, 39},
+ {0, 3, 9},
+ {0, 41, 40},
+ {0, 42, 2},
+ {0, 43, 5},
+ {0, 45, 44},
+ {0, 47, 46},
+ {0, 48, 7},
+ {0, 50, 49},
+ }));
+
+ codecs.emplace(SpvOpFMul, std::move(codec));
+ }
+
+ {
+ std::unique_ptr<HuffmanCodec<uint64_t>> codec(new HuffmanCodec<uint64_t>(53, {
+ {0, 0, 0},
+ {131134, 0, 0},
+ {196669, 0, 0},
+ {262209, 0, 0},
+ {262224, 0, 0},
+ {262225, 0, 0},
+ {262230, 0, 0},
+ {262231, 0, 0},
+ {262273, 0, 0},
+ {262275, 0, 0},
+ {262277, 0, 0},
+ {262286, 0, 0},
+ {262292, 0, 0},
+ {327692, 0, 0},
+ {327745, 0, 0},
+ {327760, 0, 0},
+ {327761, 0, 0},
+ {327762, 0, 0},
+ {393228, 0, 0},
+ {393281, 0, 0},
+ {393295, 0, 0},
+ {393296, 0, 0},
+ {393297, 0, 0},
+ {393303, 0, 0},
+ {458764, 0, 0},
+ {458831, 0, 0},
+ {524367, 0, 0},
+ {1111111111111111111, 0, 0},
+ {0, 9, 23},
+ {0, 21, 28},
+ {0, 20, 29},
+ {0, 14, 30},
+ {0, 19, 8},
+ {0, 31, 16},
+ {0, 25, 11},
+ {0, 32, 18},
+ {0, 33, 15},
+ {0, 4, 12},
+ {0, 22, 26},
+ {0, 17, 34},
+ {0, 13, 6},
+ {0, 24, 35},
+ {0, 27, 36},
+ {0, 3, 37},
+ {0, 39, 38},
+ {0, 2, 40},
+ {0, 42, 41},
+ {0, 7, 1},
+ {0, 10, 43},
+ {0, 5, 44},
+ {0, 46, 45},
+ {0, 48, 47},
+ {0, 50, 49},
+ {0, 52, 51},
+ }));
+
+ codecs.emplace(SpvOpFAdd, std::move(codec));
+ }
+
+ {
+ std::unique_ptr<HuffmanCodec<uint64_t>> codec(new HuffmanCodec<uint64_t>(19, {
+ {0, 0, 0},
+ {196631, 0, 0},
+ {196640, 0, 0},
+ {196641, 0, 0},
+ {196651, 0, 0},
+ {196667, 0, 0},
+ {262188, 0, 0},
+ {327724, 0, 0},
+ {393260, 0, 0},
+ {524313, 0, 0},
+ {1111111111111111111, 0, 0},
+ {0, 6, 8},
+ {0, 7, 11},
+ {0, 1, 12},
+ {0, 13, 9},
+ {0, 14, 3},
+ {0, 15, 10},
+ {0, 4, 2},
+ {0, 17, 16},
+ {0, 5, 18},
+ }));
+
+ codecs.emplace(SpvOpTypePointer, std::move(codec));
+ }
+
+ {
+ std::unique_ptr<HuffmanCodec<uint64_t>> codec(new HuffmanCodec<uint64_t>(49, {
+ {0, 0, 0},
+ {65790, 0, 0},
+ {131134, 0, 0},
+ {196669, 0, 0},
+ {262209, 0, 0},
+ {262224, 0, 0},
+ {262225, 0, 0},
+ {262273, 0, 0},
+ {262275, 0, 0},
+ {262277, 0, 0},
+ {262280, 0, 0},
+ {262286, 0, 0},
+ {262292, 0, 0},
+ {262328, 0, 0},
+ {327692, 0, 0},
+ {327745, 0, 0},
+ {327760, 0, 0},
+ {327761, 0, 0},
+ {327762, 0, 0},
+ {393228, 0, 0},
+ {393295, 0, 0},
+ {393296, 0, 0},
+ {458764, 0, 0},
+ {458831, 0, 0},
+ {524367, 0, 0},
+ {1111111111111111111, 0, 0},
+ {0, 21, 24},
+ {0, 25, 26},
+ {0, 15, 20},
+ {0, 23, 13},
+ {0, 5, 10},
+ {0, 11, 27},
+ {0, 17, 7},
+ {0, 28, 18},
+ {0, 1, 29},
+ {0, 30, 2},
+ {0, 31, 19},
+ {0, 32, 16},
+ {0, 33, 8},
+ {0, 4, 3},
+ {0, 9, 34},
+ {0, 35, 6},
+ {0, 12, 22},
+ {0, 37, 36},
+ {0, 39, 38},
+ {0, 40, 14},
+ {0, 42, 41},
+ {0, 44, 43},
+ {0, 46, 45},
+ {0, 48, 47},
+ }));
+
+ codecs.emplace(SpvOpFSub, std::move(codec));
+ }
+
+ {
+ std::unique_ptr<HuffmanCodec<uint64_t>> codec(new HuffmanCodec<uint64_t>(51, {
+ {0, 0, 0},
+ {131134, 0, 0},
+ {196669, 0, 0},
+ {262209, 0, 0},
+ {262224, 0, 0},
+ {262225, 0, 0},
+ {262231, 0, 0},
+ {262273, 0, 0},
+ {262275, 0, 0},
+ {262277, 0, 0},
+ {262286, 0, 0},
+ {262292, 0, 0},
+ {327692, 0, 0},
+ {327745, 0, 0},
+ {327760, 0, 0},
+ {327761, 0, 0},
+ {327762, 0, 0},
+ {393228, 0, 0},
+ {393295, 0, 0},
+ {393296, 0, 0},
+ {393297, 0, 0},
+ {393298, 0, 0},
+ {458764, 0, 0},
+ {458831, 0, 0},
+ {458842, 0, 0},
+ {524367, 0, 0},
+ {1111111111111111111, 0, 0},
+ {0, 20, 13},
+ {0, 21, 27},
+ {0, 6, 16},
+ {0, 22, 28},
+ {0, 29, 1},
+ {0, 30, 12},
+ {0, 31, 18},
+ {0, 3, 4},
+ {0, 2, 25},
+ {0, 11, 32},
+ {0, 33, 23},
+ {0, 24, 34},
+ {0, 35, 10},
+ {0, 8, 15},
+ {0, 7, 36},
+ {0, 37, 17},
+ {0, 38, 26},
+ {0, 40, 39},
+ {0, 41, 14},
+ {0, 9, 42},
+ {0, 43, 19},
+ {0, 45, 44},
+ {0, 47, 46},
+ {0, 49, 48},
+ {0, 50, 5},
+ }));
+
+ codecs.emplace(SpvOpCompositeExtract, std::move(codec));
+ }
+
+ {
+ std::unique_ptr<HuffmanCodec<uint64_t>> codec(new HuffmanCodec<uint64_t>(49, {
+ {0, 0, 0},
+ {65562, 0, 0},
+ {131099, 0, 0},
+ {131134, 0, 0},
+ {196629, 0, 0},
+ {196631, 0, 0},
+ {196640, 0, 0},
+ {196651, 0, 0},
+ {196667, 0, 0},
+ {196669, 0, 0},
+ {262188, 0, 0},
+ {262209, 0, 0},
+ {262225, 0, 0},
+ {262275, 0, 0},
+ {262292, 0, 0},
+ {327692, 0, 0},
+ {327724, 0, 0},
+ {327745, 0, 0},
+ {393228, 0, 0},
+ {393260, 0, 0},
+ {393295, 0, 0},
+ {393296, 0, 0},
+ {458831, 0, 0},
+ {524313, 0, 0},
+ {524367, 0, 0},
+ {1111111111111111111, 0, 0},
+ {0, 21, 14},
+ {0, 13, 26},
+ {0, 27, 20},
+ {0, 18, 28},
+ {0, 24, 29},
+ {0, 30, 12},
+ {0, 31, 22},
+ {0, 3, 15},
+ {0, 33, 32},
+ {0, 34, 10},
+ {0, 35, 17},
+ {0, 1, 19},
+ {0, 5, 11},
+ {0, 36, 23},
+ {0, 4, 16},
+ {0, 2, 37},
+ {0, 39, 38},
+ {0, 25, 9},
+ {0, 41, 40},
+ {0, 43, 42},
+ {0, 6, 44},
+ {0, 7, 45},
+ {0, 47, 46},
+ {0, 8, 48},
+ }));
+
+ codecs.emplace(SpvOpVariable, std::move(codec));
+ }
+
+ {
+ std::unique_ptr<HuffmanCodec<uint64_t>> codec(new HuffmanCodec<uint64_t>(5, {
+ {0, 0, 0},
+ {131134, 0, 0},
+ {196669, 0, 0},
+ {1111111111111111111, 0, 0},
+ {0, 1, 3},
+ {0, 2, 4},
+ }));
+
+ codecs.emplace(SpvOpAccessChain, std::move(codec));
+ }
+
+ {
+ std::unique_ptr<HuffmanCodec<uint64_t>> codec(new HuffmanCodec<uint64_t>(49, {
+ {0, 0, 0},
+ {252, 0, 0},
+ {65785, 0, 0},
+ {131134, 0, 0},
+ {131319, 0, 0},
+ {196667, 0, 0},
+ {196669, 0, 0},
+ {262209, 0, 0},
+ {262225, 0, 0},
+ {262273, 0, 0},
+ {262275, 0, 0},
+ {262277, 0, 0},
+ {262286, 0, 0},
+ {262292, 0, 0},
+ {327692, 0, 0},
+ {327745, 0, 0},
+ {327761, 0, 0},
+ {327762, 0, 0},
+ {393228, 0, 0},
+ {393295, 0, 0},
+ {393296, 0, 0},
+ {393298, 0, 0},
+ {393461, 0, 0},
+ {458831, 0, 0},
+ {524367, 0, 0},
+ {1111111111111111111, 0, 0},
+ {0, 18, 16},
+ {0, 14, 26},
+ {0, 10, 27},
+ {0, 28, 17},
+ {0, 12, 29},
+ {0, 24, 20},
+ {0, 31, 30},
+ {0, 32, 11},
+ {0, 33, 21},
+ {0, 34, 13},
+ {0, 35, 9},
+ {0, 15, 23},
+ {0, 36, 4},
+ {0, 37, 19},
+ {0, 38, 3},
+ {0, 7, 1},
+ {0, 8, 39},
+ {0, 2, 25},
+ {0, 22, 40},
+ {0, 42, 41},
+ {0, 44, 43},
+ {0, 46, 45},
+ {0, 6, 5},
+ {0, 48, 47},
+ }));
+
+ codecs.emplace(SpvOpLabel, std::move(codec));
+ }
+
+ {
+ std::unique_ptr<HuffmanCodec<uint64_t>> codec(new HuffmanCodec<uint64_t>(51, {
+ {0, 0, 0},
+ {253, 0, 0},
+ {65785, 0, 0},
+ {131134, 0, 0},
+ {196669, 0, 0},
+ {262201, 0, 0},
+ {262209, 0, 0},
+ {262224, 0, 0},
+ {262225, 0, 0},
+ {262273, 0, 0},
+ {262275, 0, 0},
+ {262277, 0, 0},
+ {262286, 0, 0},
+ {262292, 0, 0},
+ {327692, 0, 0},
+ {327745, 0, 0},
+ {327760, 0, 0},
+ {327761, 0, 0},
+ {327762, 0, 0},
+ {393228, 0, 0},
+ {393281, 0, 0},
+ {393295, 0, 0},
+ {393296, 0, 0},
+ {458764, 0, 0},
+ {458831, 0, 0},
+ {524367, 0, 0},
+ {1111111111111111111, 0, 0},
+ {0, 20, 23},
+ {0, 19, 27},
+ {0, 28, 13},
+ {0, 9, 29},
+ {0, 18, 30},
+ {0, 10, 31},
+ {0, 12, 22},
+ {0, 32, 14},
+ {0, 33, 16},
+ {0, 34, 24},
+ {0, 35, 25},
+ {0, 36, 21},
+ {0, 11, 7},
+ {0, 38, 37},
+ {0, 40, 39},
+ {0, 8, 41},
+ {0, 1, 2},
+ {0, 42, 5},
+ {0, 17, 26},
+ {0, 15, 43},
+ {0, 45, 44},
+ {0, 46, 3},
+ {0, 48, 47},
+ {0, 4, 6},
+ {0, 50, 49},
+ }));
+
+ codecs.emplace(SpvOpStore, std::move(codec));
+ }
+
+ {
+ std::unique_ptr<HuffmanCodec<uint64_t>> codec(new HuffmanCodec<uint64_t>(57, {
+ {0, 0, 0},
+ {65790, 0, 0},
+ {131134, 0, 0},
+ {196669, 0, 0},
+ {262209, 0, 0},
+ {262224, 0, 0},
+ {262225, 0, 0},
+ {262230, 0, 0},
+ {262231, 0, 0},
+ {262273, 0, 0},
+ {262275, 0, 0},
+ {262277, 0, 0},
+ {262286, 0, 0},
+ {262292, 0, 0},
+ {327692, 0, 0},
+ {327745, 0, 0},
+ {327760, 0, 0},
+ {327761, 0, 0},
+ {327762, 0, 0},
+ {393228, 0, 0},
+ {393281, 0, 0},
+ {393295, 0, 0},
+ {393296, 0, 0},
+ {393297, 0, 0},
+ {393304, 0, 0},
+ {458764, 0, 0},
+ {458817, 0, 0},
+ {458831, 0, 0},
+ {524367, 0, 0},
+ {1111111111111111111, 0, 0},
+ {0, 20, 26},
+ {0, 23, 30},
+ {0, 17, 31},
+ {0, 25, 5},
+ {0, 14, 32},
+ {0, 24, 15},
+ {0, 1, 33},
+ {0, 34, 22},
+ {0, 35, 16},
+ {0, 36, 10},
+ {0, 8, 19},
+ {0, 18, 13},
+ {0, 12, 37},
+ {0, 38, 9},
+ {0, 28, 39},
+ {0, 7, 40},
+ {0, 29, 6},
+ {0, 11, 41},
+ {0, 42, 21},
+ {0, 43, 27},
+ {0, 4, 44},
+ {0, 45, 2},
+ {0, 3, 46},
+ {0, 48, 47},
+ {0, 50, 49},
+ {0, 52, 51},
+ {0, 54, 53},
+ {0, 56, 55},
+ }));
+
+ codecs.emplace(SpvOpLoad, std::move(codec));
+ }
+
+ {
+ std::unique_ptr<HuffmanCodec<uint64_t>> codec(new HuffmanCodec<uint64_t>(53, {
+ {0, 0, 0},
+ {131134, 0, 0},
+ {196669, 0, 0},
+ {262209, 0, 0},
+ {262224, 0, 0},
+ {262225, 0, 0},
+ {262231, 0, 0},
+ {262273, 0, 0},
+ {262275, 0, 0},
+ {262277, 0, 0},
+ {262280, 0, 0},
+ {262286, 0, 0},
+ {262288, 0, 0},
+ {262292, 0, 0},
+ {327692, 0, 0},
+ {327745, 0, 0},
+ {327760, 0, 0},
+ {327761, 0, 0},
+ {327762, 0, 0},
+ {393228, 0, 0},
+ {393281, 0, 0},
+ {393295, 0, 0},
+ {393296, 0, 0},
+ {393304, 0, 0},
+ {458764, 0, 0},
+ {458831, 0, 0},
+ {524367, 0, 0},
+ {1111111111111111111, 0, 0},
+ {0, 15, 20},
+ {0, 17, 28},
+ {0, 29, 19},
+ {0, 6, 11},
+ {0, 31, 30},
+ {0, 14, 26},
+ {0, 23, 32},
+ {0, 12, 4},
+ {0, 21, 25},
+ {0, 10, 33},
+ {0, 22, 7},
+ {0, 34, 27},
+ {0, 18, 13},
+ {0, 35, 8},
+ {0, 36, 16},
+ {0, 37, 3},
+ {0, 39, 38},
+ {0, 41, 40},
+ {0, 42, 2},
+ {0, 9, 43},
+ {0, 44, 5},
+ {0, 24, 45},
+ {0, 46, 1},
+ {0, 48, 47},
+ {0, 50, 49},
+ {0, 52, 51},
+ }));
+
+ codecs.emplace(SpvOpCompositeConstruct, std::move(codec));
+ }
+
+ {
+ std::unique_ptr<HuffmanCodec<uint64_t>> codec(new HuffmanCodec<uint64_t>(9, {
+ {0, 0, 0},
+ {131143, 0, 0},
+ {196679, 0, 0},
+ {196680, 0, 0},
+ {262216, 0, 0},
+ {1111111111111111111, 0, 0},
+ {0, 5, 2},
+ {0, 3, 6},
+ {0, 7, 1},
+ {0, 4, 8},
+ }));
+
+ codecs.emplace(SpvOpMemberDecorate, std::move(codec));
+ }
+
+ {
+ std::unique_ptr<HuffmanCodec<uint64_t>> codec(new HuffmanCodec<uint64_t>(19, {
+ {0, 0, 0},
+ {65556, 0, 0},
+ {196631, 0, 0},
+ {196640, 0, 0},
+ {196651, 0, 0},
+ {196667, 0, 0},
+ {262188, 0, 0},
+ {327724, 0, 0},
+ {393260, 0, 0},
+ {524313, 0, 0},
+ {1111111111111111111, 0, 0},
+ {0, 8, 10},
+ {0, 1, 2},
+ {0, 7, 11},
+ {0, 3, 12},
+ {0, 9, 13},
+ {0, 14, 6},
+ {0, 15, 5},
+ {0, 17, 16},
+ {0, 4, 18},
+ }));
+
+ codecs.emplace(SpvOpConstantComposite, std::move(codec));
+ }
+
+ {
+ std::unique_ptr<HuffmanCodec<uint64_t>> codec(new HuffmanCodec<uint64_t>(11, {
+ {0, 0, 0},
+ {65555, 0, 0},
+ {131143, 0, 0},
+ {196679, 0, 0},
+ {196680, 0, 0},
+ {262216, 0, 0},
+ {1111111111111111111, 0, 0},
+ {0, 4, 6},
+ {0, 1, 2},
+ {0, 8, 7},
+ {0, 5, 9},
+ {0, 3, 10},
+ }));
+
+ codecs.emplace(SpvOpDecorate, std::move(codec));
+ }
+
+ {
+ std::unique_ptr<HuffmanCodec<uint64_t>> codec(new HuffmanCodec<uint64_t>(19, {
+ {0, 0, 0},
+ {196632, 0, 0},
+ {196636, 0, 0},
+ {196640, 0, 0},
+ {196651, 0, 0},
+ {196667, 0, 0},
+ {262188, 0, 0},
+ {327724, 0, 0},
+ {393260, 0, 0},
+ {524313, 0, 0},
+ {1111111111111111111, 0, 0},
+ {0, 1, 9},
+ {0, 2, 10},
+ {0, 12, 11},
+ {0, 7, 8},
+ {0, 13, 3},
+ {0, 14, 6},
+ {0, 15, 5},
+ {0, 17, 16},
+ {0, 18, 4},
+ }));
+
+ codecs.emplace(SpvOpConstant, std::move(codec));
+ }
+
+ {
+ std::unique_ptr<HuffmanCodec<uint64_t>> codec(new HuffmanCodec<uint64_t>(51, {
+ {0, 0, 0},
+ {65790, 0, 0},
+ {131134, 0, 0},
+ {196669, 0, 0},
+ {196735, 0, 0},
+ {262209, 0, 0},
+ {262224, 0, 0},
+ {262225, 0, 0},
+ {262231, 0, 0},
+ {262273, 0, 0},
+ {262275, 0, 0},
+ {262277, 0, 0},
+ {262286, 0, 0},
+ {262292, 0, 0},
+ {327692, 0, 0},
+ {327745, 0, 0},
+ {327760, 0, 0},
+ {327761, 0, 0},
+ {327762, 0, 0},
+ {393228, 0, 0},
+ {393281, 0, 0},
+ {393295, 0, 0},
+ {393296, 0, 0},
+ {458764, 0, 0},
+ {458831, 0, 0},
+ {524367, 0, 0},
+ {1111111111111111111, 0, 0},
+ {0, 8, 20},
+ {0, 22, 27},
+ {0, 9, 28},
+ {0, 15, 29},
+ {0, 13, 30},
+ {0, 21, 17},
+ {0, 1, 18},
+ {0, 4, 26},
+ {0, 23, 31},
+ {0, 12, 6},
+ {0, 33, 32},
+ {0, 34, 25},
+ {0, 35, 19},
+ {0, 14, 36},
+ {0, 24, 37},
+ {0, 2, 38},
+ {0, 11, 10},
+ {0, 40, 39},
+ {0, 5, 16},
+ {0, 42, 41},
+ {0, 7, 43},
+ {0, 3, 44},
+ {0, 46, 45},
+ {0, 48, 47},
+ {0, 50, 49},
+ }));
+
+ codecs.emplace(SpvOpExtInst, std::move(codec));
+ }
+
+ {
+ std::unique_ptr<HuffmanCodec<uint64_t>> codec(new HuffmanCodec<uint64_t>(45, {
+ {0, 0, 0},
+ {131134, 0, 0},
+ {196669, 0, 0},
+ {262209, 0, 0},
+ {262224, 0, 0},
+ {262225, 0, 0},
+ {262231, 0, 0},
+ {262273, 0, 0},
+ {262275, 0, 0},
+ {262277, 0, 0},
+ {262286, 0, 0},
+ {262292, 0, 0},
+ {327692, 0, 0},
+ {327745, 0, 0},
+ {327760, 0, 0},
+ {327762, 0, 0},
+ {393228, 0, 0},
+ {393295, 0, 0},
+ {393296, 0, 0},
+ {393303, 0, 0},
+ {458764, 0, 0},
+ {458831, 0, 0},
+ {524367, 0, 0},
+ {1111111111111111111, 0, 0},
+ {0, 19, 13},
+ {0, 6, 24},
+ {0, 16, 25},
+ {0, 17, 26},
+ {0, 27, 12},
+ {0, 28, 20},
+ {0, 9, 29},
+ {0, 23, 14},
+ {0, 22, 15},
+ {0, 11, 30},
+ {0, 31, 21},
+ {0, 4, 18},
+ {0, 3, 32},
+ {0, 5, 33},
+ {0, 10, 34},
+ {0, 8, 35},
+ {0, 36, 1},
+ {0, 2, 37},
+ {0, 39, 38},
+ {0, 7, 40},
+ {0, 42, 41},
+ {0, 44, 43},
+ }));
+
+ codecs.emplace(SpvOpVectorTimesScalar, std::move(codec));
+ }
+
+ {
+ std::unique_ptr<HuffmanCodec<uint64_t>> codec(new HuffmanCodec<uint64_t>(47, {
+ {0, 0, 0},
+ {131134, 0, 0},
+ {196669, 0, 0},
+ {262209, 0, 0},
+ {262224, 0, 0},
+ {262225, 0, 0},
+ {262231, 0, 0},
+ {262273, 0, 0},
+ {262275, 0, 0},
+ {262277, 0, 0},
+ {262286, 0, 0},
+ {262292, 0, 0},
+ {327692, 0, 0},
+ {327745, 0, 0},
+ {327760, 0, 0},
+ {327761, 0, 0},
+ {327762, 0, 0},
+ {393228, 0, 0},
+ {393295, 0, 0},
+ {393296, 0, 0},
+ {393303, 0, 0},
+ {458764, 0, 0},
+ {458831, 0, 0},
+ {524367, 0, 0},
+ {1111111111111111111, 0, 0},
+ {0, 19, 20},
+ {0, 4, 25},
+ {0, 13, 26},
+ {0, 15, 27},
+ {0, 21, 23},
+ {0, 28, 8},
+ {0, 29, 12},
+ {0, 14, 17},
+ {0, 18, 30},
+ {0, 24, 3},
+ {0, 10, 22},
+ {0, 11, 31},
+ {0, 32, 16},
+ {0, 34, 33},
+ {0, 35, 5},
+ {0, 36, 6},
+ {0, 37, 2},
+ {0, 9, 38},
+ {0, 39, 7},
+ {0, 40, 1},
+ {0, 42, 41},
+ {0, 44, 43},
+ {0, 46, 45},
+ }));
+
+ codecs.emplace(SpvOpVectorShuffle, std::move(codec));
+ }
+
+ {
+ std::unique_ptr<HuffmanCodec<uint64_t>> codec(new HuffmanCodec<uint64_t>(29, {
+ {0, 0, 0},
+ {131134, 0, 0},
+ {196669, 0, 0},
+ {262209, 0, 0},
+ {262225, 0, 0},
+ {262231, 0, 0},
+ {262273, 0, 0},
+ {262277, 0, 0},
+ {262286, 0, 0},
+ {262292, 0, 0},
+ {327745, 0, 0},
+ {393281, 0, 0},
+ {393295, 0, 0},
+ {393296, 0, 0},
+ {458831, 0, 0},
+ {1111111111111111111, 0, 0},
+ {0, 11, 10},
+ {0, 9, 16},
+ {0, 7, 17},
+ {0, 8, 18},
+ {0, 19, 13},
+ {0, 20, 6},
+ {0, 5, 21},
+ {0, 15, 22},
+ {0, 3, 23},
+ {0, 12, 2},
+ {0, 25, 24},
+ {0, 26, 1},
+ {0, 4, 27},
+ {0, 28, 14},
+ }));
+
+ codecs.emplace(SpvOpImageSampleImplicitLod, std::move(codec));
+ }
+
+ {
+ std::unique_ptr<HuffmanCodec<uint64_t>> codec(new HuffmanCodec<uint64_t>(47, {
+ {0, 0, 0},
+ {131134, 0, 0},
+ {196669, 0, 0},
+ {262209, 0, 0},
+ {262224, 0, 0},
+ {262225, 0, 0},
+ {262273, 0, 0},
+ {262275, 0, 0},
+ {262277, 0, 0},
+ {262280, 0, 0},
+ {262286, 0, 0},
+ {262292, 0, 0},
+ {327692, 0, 0},
+ {327745, 0, 0},
+ {327760, 0, 0},
+ {327761, 0, 0},
+ {327762, 0, 0},
+ {393228, 0, 0},
+ {393281, 0, 0},
+ {393295, 0, 0},
+ {393296, 0, 0},
+ {393298, 0, 0},
+ {458764, 0, 0},
+ {458831, 0, 0},
+ {1111111111111111111, 0, 0},
+ {0, 5, 18},
+ {0, 1, 25},
+ {0, 24, 23},
+ {0, 16, 12},
+ {0, 4, 26},
+ {0, 6, 27},
+ {0, 2, 28},
+ {0, 20, 19},
+ {0, 9, 29},
+ {0, 3, 17},
+ {0, 30, 10},
+ {0, 21, 31},
+ {0, 13, 7},
+ {0, 8, 15},
+ {0, 33, 32},
+ {0, 34, 14},
+ {0, 11, 35},
+ {0, 37, 36},
+ {0, 39, 38},
+ {0, 22, 40},
+ {0, 42, 41},
+ {0, 44, 43},
+ {0, 46, 45},
+ }));
+
+ codecs.emplace(SpvOpDot, std::move(codec));
+ }
+
+ {
+ std::unique_ptr<HuffmanCodec<uint64_t>> codec(new HuffmanCodec<uint64_t>(49, {
+ {0, 0, 0},
+ {65785, 0, 0},
+ {131134, 0, 0},
+ {196669, 0, 0},
+ {262209, 0, 0},
+ {262221, 0, 0},
+ {262224, 0, 0},
+ {262225, 0, 0},
+ {262230, 0, 0},
+ {262273, 0, 0},
+ {262275, 0, 0},
+ {262277, 0, 0},
+ {262286, 0, 0},
+ {262292, 0, 0},
+ {327692, 0, 0},
+ {327760, 0, 0},
+ {327761, 0, 0},
+ {327762, 0, 0},
+ {393228, 0, 0},
+ {393295, 0, 0},
+ {393296, 0, 0},
+ {393298, 0, 0},
+ {458764, 0, 0},
+ {458831, 0, 0},
+ {524367, 0, 0},
+ {1111111111111111111, 0, 0},
+ {0, 9, 13},
+ {0, 26, 10},
+ {0, 15, 27},
+ {0, 18, 22},
+ {0, 29, 28},
+ {0, 5, 30},
+ {0, 6, 20},
+ {0, 31, 12},
+ {0, 11, 2},
+ {0, 1, 24},
+ {0, 14, 25},
+ {0, 33, 32},
+ {0, 23, 34},
+ {0, 36, 35},
+ {0, 17, 16},
+ {0, 37, 19},
+ {0, 38, 21},
+ {0, 8, 4},
+ {0, 40, 39},
+ {0, 42, 41},
+ {0, 44, 43},
+ {0, 3, 7},
+ {0, 46, 45},
+ {0, 48, 47},
+ }));
+
+ codecs.emplace(SpvOpCompositeInsert, std::move(codec));
+ }
+
+ return codecs;
+}
+
+std::map<uint32_t, std::unique_ptr<HuffmanCodec<std::string>>>
+GetLiteralStringHuffmanCodecs() {
+ std::map<uint32_t, std::unique_ptr<HuffmanCodec<std::string>>> codecs;
+ {
+ std::unique_ptr<HuffmanCodec<std::string>> codec(new HuffmanCodec<std::string>(7, {
+ {"", 0, 0},
+ {"MainPs", 0, 0},
+ {"MainVs", 0, 0},
+ {"kMarkvNoneOfTheAbove", 0, 0},
+ {"main", 0, 0},
+ {"", 2, 3},
+ {"", 1, 5},
+ {"", 4, 6},
+ }));
+
+ codecs.emplace(SpvOpEntryPoint, std::move(codec));
+ }
+
+ {
+ std::unique_ptr<HuffmanCodec<std::string>> codec(new HuffmanCodec<std::string>(3, {
+ {"", 0, 0},
+ {"GLSL.std.450", 0, 0},
+ {"kMarkvNoneOfTheAbove", 0, 0},
+ {"", 1, 2},
+ }));
+
+ codecs.emplace(SpvOpExtInstImport, std::move(codec));
+ }
+
+ return codecs;
+}
+
+std::map<std::pair<uint32_t, uint32_t>, std::unique_ptr<HuffmanCodec<uint64_t>>>
+GetNonIdWordHuffmanCodecs() {
+ std::map<std::pair<uint32_t, uint32_t>, std::unique_ptr<HuffmanCodec<uint64_t>>> codecs;
+ {
+ std::unique_ptr<HuffmanCodec<uint64_t>> codec(new HuffmanCodec<uint64_t>(23, {
+ {0, 0, 0},
+ {4, 0, 0},
+ {8, 0, 0},
+ {26, 0, 0},
+ {31, 0, 0},
+ {40, 0, 0},
+ {43, 0, 0},
+ {46, 0, 0},
+ {49, 0, 0},
+ {68, 0, 0},
+ {69, 0, 0},
+ {71, 0, 0},
+ {1111111111111111111, 0, 0},
+ {0, 11, 8},
+ {0, 1, 9},
+ {0, 13, 4},
+ {0, 14, 2},
+ {0, 15, 12},
+ {0, 16, 3},
+ {0, 18, 17},
+ {0, 7, 10},
+ {0, 5, 6},
+ {0, 20, 19},
+ {0, 22, 21},
+ }));
+
+ codecs.emplace(std::pair<uint32_t, uint32_t>(SpvOpExtInst, 3), std::move(codec));
+ }
+
+ {
+ std::unique_ptr<HuffmanCodec<uint64_t>> codec(new HuffmanCodec<uint64_t>(3, {
+ {0, 0, 0},
+ {0, 0, 0},
+ {1111111111111111111, 0, 0},
+ {0, 1, 2},
+ }));
+
+ codecs.emplace(std::pair<uint32_t, uint32_t>(SpvOpMemoryModel, 0), std::move(codec));
+ }
+
+ {
+ std::unique_ptr<HuffmanCodec<uint64_t>> codec(new HuffmanCodec<uint64_t>(3, {
+ {0, 0, 0},
+ {1, 0, 0},
+ {1111111111111111111, 0, 0},
+ {0, 1, 2},
+ }));
+
+ codecs.emplace(std::pair<uint32_t, uint32_t>(SpvOpMemoryModel, 1), std::move(codec));
+ }
+
+ {
+ std::unique_ptr<HuffmanCodec<uint64_t>> codec(new HuffmanCodec<uint64_t>(5, {
+ {0, 0, 0},
+ {0, 0, 0},
+ {4, 0, 0},
+ {1111111111111111111, 0, 0},
+ {0, 1, 3},
+ {0, 2, 4},
+ }));
+
+ codecs.emplace(std::pair<uint32_t, uint32_t>(SpvOpEntryPoint, 0), std::move(codec));
+ }
+
+ {
+ std::unique_ptr<HuffmanCodec<uint64_t>> codec(new HuffmanCodec<uint64_t>(3, {
+ {0, 0, 0},
+ {7, 0, 0},
+ {1111111111111111111, 0, 0},
+ {0, 1, 2},
+ }));
+
+ codecs.emplace(std::pair<uint32_t, uint32_t>(SpvOpExecutionMode, 1), std::move(codec));
+ }
+
+ {
+ std::unique_ptr<HuffmanCodec<uint64_t>> codec(new HuffmanCodec<uint64_t>(11, {
+ {0, 0, 0},
+ {1, 0, 0},
+ {2, 0, 0},
+ {3, 0, 0},
+ {4, 0, 0},
+ {18, 0, 0},
+ {1111111111111111111, 0, 0},
+ {0, 4, 2},
+ {0, 6, 5},
+ {0, 7, 1},
+ {0, 3, 8},
+ {0, 10, 9},
+ }));
+
+ codecs.emplace(std::pair<uint32_t, uint32_t>(SpvOpExecutionMode, 2), std::move(codec));
+ }
+
+ {
+ std::unique_ptr<HuffmanCodec<uint64_t>> codec(new HuffmanCodec<uint64_t>(5, {
+ {0, 0, 0},
+ {1, 0, 0},
+ {32, 0, 0},
+ {1111111111111111111, 0, 0},
+ {0, 2, 3},
+ {0, 1, 4},
+ }));
+
+ codecs.emplace(std::pair<uint32_t, uint32_t>(SpvOpCapability, 0), std::move(codec));
+ }
+
+ {
+ std::unique_ptr<HuffmanCodec<uint64_t>> codec(new HuffmanCodec<uint64_t>(3, {
+ {0, 0, 0},
+ {32, 0, 0},
+ {1111111111111111111, 0, 0},
+ {0, 1, 2},
+ }));
+
+ codecs.emplace(std::pair<uint32_t, uint32_t>(SpvOpTypeInt, 1), std::move(codec));
+ }
+
+ {
+ std::unique_ptr<HuffmanCodec<uint64_t>> codec(new HuffmanCodec<uint64_t>(5, {
+ {0, 0, 0},
+ {0, 0, 0},
+ {1, 0, 0},
+ {1111111111111111111, 0, 0},
+ {0, 2, 3},
+ {0, 1, 4},
+ }));
+
+ codecs.emplace(std::pair<uint32_t, uint32_t>(SpvOpTypeInt, 2), std::move(codec));
+ }
+
+ {
+ std::unique_ptr<HuffmanCodec<uint64_t>> codec(new HuffmanCodec<uint64_t>(3, {
+ {0, 0, 0},
+ {32, 0, 0},
+ {1111111111111111111, 0, 0},
+ {0, 1, 2},
+ }));
+
+ codecs.emplace(std::pair<uint32_t, uint32_t>(SpvOpTypeFloat, 1), std::move(codec));
+ }
+
+ {
+ std::unique_ptr<HuffmanCodec<uint64_t>> codec(new HuffmanCodec<uint64_t>(7, {
+ {0, 0, 0},
+ {2, 0, 0},
+ {3, 0, 0},
+ {4, 0, 0},
+ {1111111111111111111, 0, 0},
+ {0, 2, 4},
+ {0, 1, 5},
+ {0, 6, 3},
+ }));
+
+ codecs.emplace(std::pair<uint32_t, uint32_t>(SpvOpTypeVector, 2), std::move(codec));
+ }
+
+ {
+ std::unique_ptr<HuffmanCodec<uint64_t>> codec(new HuffmanCodec<uint64_t>(7, {
+ {0, 0, 0},
+ {2, 0, 0},
+ {3, 0, 0},
+ {4, 0, 0},
+ {1111111111111111111, 0, 0},
+ {0, 1, 4},
+ {0, 2, 5},
+ {0, 3, 6},
+ }));
+
+ codecs.emplace(std::pair<uint32_t, uint32_t>(SpvOpTypeMatrix, 2), std::move(codec));
+ }
+
+ {
+ std::unique_ptr<HuffmanCodec<uint64_t>> codec(new HuffmanCodec<uint64_t>(7, {
+ {0, 0, 0},
+ {1, 0, 0},
+ {2, 0, 0},
+ {3, 0, 0},
+ {1111111111111111111, 0, 0},
+ {0, 3, 4},
+ {0, 2, 5},
+ {0, 1, 6},
+ }));
+
+ codecs.emplace(std::pair<uint32_t, uint32_t>(SpvOpTypeImage, 2), std::move(codec));
+ }
+
+ {
+ std::unique_ptr<HuffmanCodec<uint64_t>> codec(new HuffmanCodec<uint64_t>(5, {
+ {0, 0, 0},
+ {0, 0, 0},
+ {1, 0, 0},
+ {1111111111111111111, 0, 0},
+ {0, 2, 3},
+ {0, 1, 4},
+ }));
+
+ codecs.emplace(std::pair<uint32_t, uint32_t>(SpvOpTypeImage, 3), std::move(codec));
+ }
+
+ {
+ std::unique_ptr<HuffmanCodec<uint64_t>> codec(new HuffmanCodec<uint64_t>(3, {
+ {0, 0, 0},
+ {0, 0, 0},
+ {1111111111111111111, 0, 0},
+ {0, 1, 2},
+ }));
+
+ codecs.emplace(std::pair<uint32_t, uint32_t>(SpvOpTypeImage, 4), std::move(codec));
+ }
+
+ {
+ std::unique_ptr<HuffmanCodec<uint64_t>> codec(new HuffmanCodec<uint64_t>(3, {
+ {0, 0, 0},
+ {0, 0, 0},
+ {1111111111111111111, 0, 0},
+ {0, 1, 2},
+ }));
+
+ codecs.emplace(std::pair<uint32_t, uint32_t>(SpvOpTypeImage, 5), std::move(codec));
+ }
+
+ {
+ std::unique_ptr<HuffmanCodec<uint64_t>> codec(new HuffmanCodec<uint64_t>(3, {
+ {0, 0, 0},
+ {1, 0, 0},
+ {1111111111111111111, 0, 0},
+ {0, 1, 2},
+ }));
+
+ codecs.emplace(std::pair<uint32_t, uint32_t>(SpvOpTypeImage, 6), std::move(codec));
+ }
+
+ {
+ std::unique_ptr<HuffmanCodec<uint64_t>> codec(new HuffmanCodec<uint64_t>(3, {
+ {0, 0, 0},
+ {0, 0, 0},
+ {1111111111111111111, 0, 0},
+ {0, 1, 2},
+ }));
+
+ codecs.emplace(std::pair<uint32_t, uint32_t>(SpvOpTypeImage, 7), std::move(codec));
+ }
+
+ {
+ std::unique_ptr<HuffmanCodec<uint64_t>> codec(new HuffmanCodec<uint64_t>(13, {
+ {0, 0, 0},
+ {0, 0, 0},
+ {1, 0, 0},
+ {2, 0, 0},
+ {3, 0, 0},
+ {6, 0, 0},
+ {7, 0, 0},
+ {1111111111111111111, 0, 0},
+ {0, 5, 7},
+ {0, 6, 8},
+ {0, 1, 4},
+ {0, 2, 9},
+ {0, 10, 3},
+ {0, 12, 11},
+ }));
+
+ codecs.emplace(std::pair<uint32_t, uint32_t>(SpvOpTypePointer, 1), std::move(codec));
+ }
+
+ {
+ std::unique_ptr<HuffmanCodec<uint64_t>> codec(new HuffmanCodec<uint64_t>(35, {
+ {0, 0, 0},
+ {0, 0, 0},
+ {1, 0, 0},
+ {2, 0, 0},
+ {3, 0, 0},
+ {4, 0, 0},
+ {5, 0, 0},
+ {6, 0, 0},
+ {7, 0, 0},
+ {8, 0, 0},
+ {10, 0, 0},
+ {981668463, 0, 0},
+ {1055437881, 0, 0},
+ {1056964608, 0, 0},
+ {1065353216, 0, 0},
+ {1073741824, 0, 0},
+ {3212836864, 0, 0},
+ {3332128768, 0, 0},
+ {1111111111111111111, 0, 0},
+ {0, 10, 11},
+ {0, 9, 17},
+ {0, 7, 8},
+ {0, 6, 16},
+ {0, 5, 12},
+ {0, 20, 19},
+ {0, 21, 15},
+ {0, 22, 13},
+ {0, 4, 14},
+ {0, 2, 23},
+ {0, 3, 24},
+ {0, 26, 25},
+ {0, 1, 27},
+ {0, 29, 28},
+ {0, 31, 30},
+ {0, 33, 32},
+ {0, 18, 34},
+ }));
+
+ codecs.emplace(std::pair<uint32_t, uint32_t>(SpvOpConstant, 2), std::move(codec));
+ }
+
+ {
+ std::unique_ptr<HuffmanCodec<uint64_t>> codec(new HuffmanCodec<uint64_t>(3, {
+ {0, 0, 0},
+ {0, 0, 0},
+ {1111111111111111111, 0, 0},
+ {0, 1, 2},
+ }));
+
+ codecs.emplace(std::pair<uint32_t, uint32_t>(SpvOpFunction, 2), std::move(codec));
+ }
+
+ {
+ std::unique_ptr<HuffmanCodec<uint64_t>> codec(new HuffmanCodec<uint64_t>(13, {
+ {0, 0, 0},
+ {0, 0, 0},
+ {1, 0, 0},
+ {2, 0, 0},
+ {3, 0, 0},
+ {6, 0, 0},
+ {7, 0, 0},
+ {1111111111111111111, 0, 0},
+ {0, 3, 7},
+ {0, 4, 8},
+ {0, 9, 2},
+ {0, 1, 5},
+ {0, 10, 6},
+ {0, 12, 11},
+ }));
+
+ codecs.emplace(std::pair<uint32_t, uint32_t>(SpvOpVariable, 2), std::move(codec));
+ }
+
+ {
+ std::unique_ptr<HuffmanCodec<uint64_t>> codec(new HuffmanCodec<uint64_t>(15, {
+ {0, 0, 0},
+ {0, 0, 0},
+ {2, 0, 0},
+ {6, 0, 0},
+ {11, 0, 0},
+ {30, 0, 0},
+ {33, 0, 0},
+ {34, 0, 0},
+ {1111111111111111111, 0, 0},
+ {0, 4, 8},
+ {0, 9, 1},
+ {0, 3, 10},
+ {0, 6, 11},
+ {0, 12, 2},
+ {0, 7, 5},
+ {0, 14, 13},
+ }));
+
+ codecs.emplace(std::pair<uint32_t, uint32_t>(SpvOpDecorate, 1), std::move(codec));
+ }
+
+ {
+ std::unique_ptr<HuffmanCodec<uint64_t>> codec(new HuffmanCodec<uint64_t>(25, {
+ {0, 0, 0},
+ {0, 0, 0},
+ {1, 0, 0},
+ {2, 0, 0},
+ {3, 0, 0},
+ {4, 0, 0},
+ {5, 0, 0},
+ {6, 0, 0},
+ {7, 0, 0},
+ {8, 0, 0},
+ {15, 0, 0},
+ {16, 0, 0},
+ {64, 0, 0},
+ {1111111111111111111, 0, 0},
+ {0, 10, 9},
+ {0, 14, 8},
+ {0, 7, 12},
+ {0, 5, 6},
+ {0, 15, 11},
+ {0, 13, 4},
+ {0, 16, 3},
+ {0, 18, 17},
+ {0, 2, 19},
+ {0, 21, 20},
+ {0, 23, 22},
+ {0, 1, 24},
+ }));
+
+ codecs.emplace(std::pair<uint32_t, uint32_t>(SpvOpDecorate, 2), std::move(codec));
+ }
+
+ {
+ std::unique_ptr<HuffmanCodec<uint64_t>> codec(new HuffmanCodec<uint64_t>(73, {
+ {0, 0, 0},
+ {0, 0, 0},
+ {1, 0, 0},
+ {2, 0, 0},
+ {3, 0, 0},
+ {4, 0, 0},
+ {5, 0, 0},
+ {6, 0, 0},
+ {7, 0, 0},
+ {8, 0, 0},
+ {9, 0, 0},
+ {10, 0, 0},
+ {11, 0, 0},
+ {12, 0, 0},
+ {13, 0, 0},
+ {14, 0, 0},
+ {15, 0, 0},
+ {16, 0, 0},
+ {17, 0, 0},
+ {18, 0, 0},
+ {19, 0, 0},
+ {20, 0, 0},
+ {21, 0, 0},
+ {22, 0, 0},
+ {23, 0, 0},
+ {24, 0, 0},
+ {25, 0, 0},
+ {26, 0, 0},
+ {27, 0, 0},
+ {28, 0, 0},
+ {29, 0, 0},
+ {30, 0, 0},
+ {31, 0, 0},
+ {32, 0, 0},
+ {33, 0, 0},
+ {34, 0, 0},
+ {37, 0, 0},
+ {1111111111111111111, 0, 0},
+ {0, 34, 35},
+ {0, 32, 33},
+ {0, 30, 31},
+ {0, 27, 29},
+ {0, 26, 28},
+ {0, 23, 25},
+ {0, 36, 22},
+ {0, 39, 38},
+ {0, 41, 40},
+ {0, 21, 42},
+ {0, 19, 20},
+ {0, 17, 18},
+ {0, 14, 15},
+ {0, 12, 10},
+ {0, 16, 13},
+ {0, 9, 11},
+ {0, 7, 8},
+ {0, 6, 5},
+ {0, 24, 37},
+ {0, 44, 43},
+ {0, 3, 4},
+ {0, 45, 2},
+ {0, 1, 46},
+ {0, 48, 47},
+ {0, 50, 49},
+ {0, 52, 51},
+ {0, 54, 53},
+ {0, 56, 55},
+ {0, 58, 57},
+ {0, 60, 59},
+ {0, 62, 61},
+ {0, 64, 63},
+ {0, 66, 65},
+ {0, 68, 67},
+ {0, 70, 69},
+ {0, 72, 71},
+ }));
+
+ codecs.emplace(std::pair<uint32_t, uint32_t>(SpvOpMemberDecorate, 1), std::move(codec));
+ }
+
+ {
+ std::unique_ptr<HuffmanCodec<uint64_t>> codec(new HuffmanCodec<uint64_t>(7, {
+ {0, 0, 0},
+ {4, 0, 0},
+ {7, 0, 0},
+ {35, 0, 0},
+ {1111111111111111111, 0, 0},
+ {0, 1, 4},
+ {0, 5, 2},
+ {0, 3, 6},
+ }));
+
+ codecs.emplace(std::pair<uint32_t, uint32_t>(SpvOpMemberDecorate, 2), std::move(codec));
+ }
+
+ {
+ std::unique_ptr<HuffmanCodec<uint64_t>> codec(new HuffmanCodec<uint64_t>(59, {
+ {0, 0, 0},
+ {0, 0, 0},
+ {16, 0, 0},
+ {28, 0, 0},
+ {32, 0, 0},
+ {40, 0, 0},
+ {44, 0, 0},
+ {48, 0, 0},
+ {60, 0, 0},
+ {64, 0, 0},
+ {76, 0, 0},
+ {80, 0, 0},
+ {92, 0, 0},
+ {96, 0, 0},
+ {108, 0, 0},
+ {112, 0, 0},
+ {120, 0, 0},
+ {128, 0, 0},
+ {140, 0, 0},
+ {144, 0, 0},
+ {148, 0, 0},
+ {152, 0, 0},
+ {156, 0, 0},
+ {160, 0, 0},
+ {176, 0, 0},
+ {192, 0, 0},
+ {204, 0, 0},
+ {208, 0, 0},
+ {224, 0, 0},
+ {256, 0, 0},
+ {1111111111111111111, 0, 0},
+ {0, 16, 14},
+ {0, 12, 20},
+ {0, 6, 26},
+ {0, 3, 5},
+ {0, 27, 21},
+ {0, 8, 28},
+ {0, 10, 22},
+ {0, 29, 18},
+ {0, 32, 31},
+ {0, 19, 24},
+ {0, 15, 23},
+ {0, 13, 11},
+ {0, 4, 7},
+ {0, 34, 33},
+ {0, 36, 35},
+ {0, 17, 25},
+ {0, 37, 9},
+ {0, 39, 38},
+ {0, 40, 1},
+ {0, 42, 41},
+ {0, 44, 43},
+ {0, 46, 45},
+ {0, 2, 47},
+ {0, 49, 48},
+ {0, 51, 50},
+ {0, 53, 52},
+ {0, 55, 54},
+ {0, 30, 56},
+ {0, 58, 57},
+ }));
+
+ codecs.emplace(std::pair<uint32_t, uint32_t>(SpvOpMemberDecorate, 3), std::move(codec));
+ }
+
+ {
+ std::unique_ptr<HuffmanCodec<uint64_t>> codec(new HuffmanCodec<uint64_t>(11, {
+ {0, 0, 0},
+ {0, 0, 0},
+ {1, 0, 0},
+ {2, 0, 0},
+ {3, 0, 0},
+ {4, 0, 0},
+ {1111111111111111111, 0, 0},
+ {0, 2, 6},
+ {0, 4, 7},
+ {0, 8, 3},
+ {0, 9, 5},
+ {0, 1, 10},
+ }));
+
+ codecs.emplace(std::pair<uint32_t, uint32_t>(SpvOpVectorShuffle, 4), std::move(codec));
+ }
+
+ {
+ std::unique_ptr<HuffmanCodec<uint64_t>> codec(new HuffmanCodec<uint64_t>(13, {
+ {0, 0, 0},
+ {0, 0, 0},
+ {1, 0, 0},
+ {2, 0, 0},
+ {3, 0, 0},
+ {4, 0, 0},
+ {5, 0, 0},
+ {1111111111111111111, 0, 0},
+ {0, 3, 7},
+ {0, 8, 5},
+ {0, 9, 1},
+ {0, 4, 10},
+ {0, 11, 6},
+ {0, 2, 12},
+ }));
+
+ codecs.emplace(std::pair<uint32_t, uint32_t>(SpvOpVectorShuffle, 5), std::move(codec));
+ }
+
+ {
+ std::unique_ptr<HuffmanCodec<uint64_t>> codec(new HuffmanCodec<uint64_t>(15, {
+ {0, 0, 0},
+ {0, 0, 0},
+ {1, 0, 0},
+ {2, 0, 0},
+ {3, 0, 0},
+ {4, 0, 0},
+ {5, 0, 0},
+ {6, 0, 0},
+ {1111111111111111111, 0, 0},
+ {0, 6, 8},
+ {0, 5, 2},
+ {0, 10, 9},
+ {0, 1, 4},
+ {0, 12, 11},
+ {0, 7, 13},
+ {0, 3, 14},
+ }));
+
+ codecs.emplace(std::pair<uint32_t, uint32_t>(SpvOpVectorShuffle, 6), std::move(codec));
+ }
+
+ {
+ std::unique_ptr<HuffmanCodec<uint64_t>> codec(new HuffmanCodec<uint64_t>(13, {
+ {0, 0, 0},
+ {0, 0, 0},
+ {1, 0, 0},
+ {2, 0, 0},
+ {3, 0, 0},
+ {5, 0, 0},
+ {6, 0, 0},
+ {1111111111111111111, 0, 0},
+ {0, 7, 6},
+ {0, 8, 3},
+ {0, 9, 2},
+ {0, 5, 1},
+ {0, 11, 10},
+ {0, 4, 12},
+ }));
+
+ codecs.emplace(std::pair<uint32_t, uint32_t>(SpvOpVectorShuffle, 7), std::move(codec));
+ }
+
+ {
+ std::unique_ptr<HuffmanCodec<uint64_t>> codec(new HuffmanCodec<uint64_t>(27, {
+ {0, 0, 0},
+ {0, 0, 0},
+ {1, 0, 0},
+ {2, 0, 0},
+ {3, 0, 0},
+ {4, 0, 0},
+ {5, 0, 0},
+ {8, 0, 0},
+ {9, 0, 0},
+ {10, 0, 0},
+ {12, 0, 0},
+ {16, 0, 0},
+ {23, 0, 0},
+ {24, 0, 0},
+ {1111111111111111111, 0, 0},
+ {0, 11, 9},
+ {0, 13, 10},
+ {0, 7, 8},
+ {0, 15, 5},
+ {0, 17, 16},
+ {0, 12, 6},
+ {0, 19, 18},
+ {0, 21, 20},
+ {0, 14, 4},
+ {0, 3, 22},
+ {0, 23, 2},
+ {0, 24, 1},
+ {0, 26, 25},
+ }));
+
+ codecs.emplace(std::pair<uint32_t, uint32_t>(SpvOpCompositeExtract, 3), std::move(codec));
+ }
+
+ {
+ std::unique_ptr<HuffmanCodec<uint64_t>> codec(new HuffmanCodec<uint64_t>(9, {
+ {0, 0, 0},
+ {0, 0, 0},
+ {1, 0, 0},
+ {2, 0, 0},
+ {3, 0, 0},
+ {1111111111111111111, 0, 0},
+ {0, 3, 2},
+ {0, 5, 4},
+ {0, 6, 1},
+ {0, 8, 7},
+ }));
+
+ codecs.emplace(std::pair<uint32_t, uint32_t>(SpvOpCompositeExtract, 4), std::move(codec));
+ }
+
+ {
+ std::unique_ptr<HuffmanCodec<uint64_t>> codec(new HuffmanCodec<uint64_t>(9, {
+ {0, 0, 0},
+ {0, 0, 0},
+ {1, 0, 0},
+ {2, 0, 0},
+ {3, 0, 0},
+ {1111111111111111111, 0, 0},
+ {0, 1, 5},
+ {0, 3, 2},
+ {0, 6, 4},
+ {0, 8, 7},
+ }));
+
+ codecs.emplace(std::pair<uint32_t, uint32_t>(SpvOpCompositeExtract, 5), std::move(codec));
+ }
+
+ {
+ std::unique_ptr<HuffmanCodec<uint64_t>> codec(new HuffmanCodec<uint64_t>(21, {
+ {0, 0, 0},
+ {0, 0, 0},
+ {1, 0, 0},
+ {2, 0, 0},
+ {3, 0, 0},
+ {4, 0, 0},
+ {5, 0, 0},
+ {6, 0, 0},
+ {7, 0, 0},
+ {8, 0, 0},
+ {9, 0, 0},
+ {1111111111111111111, 0, 0},
+ {0, 10, 11},
+ {0, 9, 12},
+ {0, 7, 5},
+ {0, 8, 6},
+ {0, 4, 13},
+ {0, 15, 14},
+ {0, 16, 3},
+ {0, 17, 2},
+ {0, 18, 1},
+ {0, 20, 19},
+ }));
+
+ codecs.emplace(std::pair<uint32_t, uint32_t>(SpvOpCompositeInsert, 4), std::move(codec));
+ }
+
+ {
+ std::unique_ptr<HuffmanCodec<uint64_t>> codec(new HuffmanCodec<uint64_t>(9, {
+ {0, 0, 0},
+ {0, 0, 0},
+ {1, 0, 0},
+ {2, 0, 0},
+ {3, 0, 0},
+ {1111111111111111111, 0, 0},
+ {0, 3, 5},
+ {0, 2, 6},
+ {0, 7, 1},
+ {0, 4, 8},
+ }));
+
+ codecs.emplace(std::pair<uint32_t, uint32_t>(SpvOpCompositeInsert, 5), std::move(codec));
+ }
+
+ {
+ std::unique_ptr<HuffmanCodec<uint64_t>> codec(new HuffmanCodec<uint64_t>(3, {
+ {0, 0, 0},
+ {1, 0, 0},
+ {1111111111111111111, 0, 0},
+ {0, 1, 2},
+ }));
+
+ codecs.emplace(std::pair<uint32_t, uint32_t>(SpvOpImageSampleImplicitLod, 4), std::move(codec));
+ }
+
+ {
+ std::unique_ptr<HuffmanCodec<uint64_t>> codec(new HuffmanCodec<uint64_t>(5, {
+ {0, 0, 0},
+ {2, 0, 0},
+ {10, 0, 0},
+ {1111111111111111111, 0, 0},
+ {0, 2, 3},
+ {0, 1, 4},
+ }));
+
+ codecs.emplace(std::pair<uint32_t, uint32_t>(SpvOpImageSampleExplicitLod, 4), std::move(codec));
+ }
+
+ {
+ std::unique_ptr<HuffmanCodec<uint64_t>> codec(new HuffmanCodec<uint64_t>(3, {
+ {0, 0, 0},
+ {2, 0, 0},
+ {1111111111111111111, 0, 0},
+ {0, 1, 2},
+ }));
+
+ codecs.emplace(std::pair<uint32_t, uint32_t>(SpvOpImageSampleDrefExplicitLod, 5), std::move(codec));
+ }
+
+ {
+ std::unique_ptr<HuffmanCodec<uint64_t>> codec(new HuffmanCodec<uint64_t>(3, {
+ {0, 0, 0},
+ {0, 0, 0},
+ {1111111111111111111, 0, 0},
+ {0, 1, 2},
+ }));
+
+ codecs.emplace(std::pair<uint32_t, uint32_t>(SpvOpSelectionMerge, 1), std::move(codec));
+ }
+
+ return codecs;
+}
+
+std::map<std::pair<uint32_t, uint32_t>, std::unique_ptr<HuffmanCodec<uint64_t>>>
+GetIdDescriptorHuffmanCodecs() {
+ std::map<std::pair<uint32_t, uint32_t>, std::unique_ptr<HuffmanCodec<uint64_t>>> codecs;
+ {
+ std::unique_ptr<HuffmanCodec<uint64_t>> codec(new HuffmanCodec<uint64_t>(9, {
+ {0, 0, 0},
+ {679771963, 0, 0},
+ {1951208733, 0, 0},
+ {2320303498, 0, 0},
+ {3334207724, 0, 0},
+ {1111111111111111111, 0, 0},
+ {0, 3, 5},
+ {0, 4, 6},
+ {0, 1, 7},
+ {0, 2, 8},
+ }));
+
+ codecs.emplace(std::pair<uint32_t, uint32_t>(SpvOpExtInst, 0), std::move(codec));
+ }
+
+ {
+ std::unique_ptr<HuffmanCodec<uint64_t>> codec(new HuffmanCodec<uint64_t>(3, {
+ {0, 0, 0},
+ {2161102232, 0, 0},
+ {1111111111111111111, 0, 0},
+ {0, 2, 1},
+ }));
+
+ codecs.emplace(std::pair<uint32_t, uint32_t>(SpvOpExtInst, 1), std::move(codec));
+ }
+
+ {
+ std::unique_ptr<HuffmanCodec<uint64_t>> codec(new HuffmanCodec<uint64_t>(3, {
+ {0, 0, 0},
+ {4228502127, 0, 0},
+ {1111111111111111111, 0, 0},
+ {0, 1, 2},
+ }));
+
+ codecs.emplace(std::pair<uint32_t, uint32_t>(SpvOpExtInst, 2), std::move(codec));
+ }
+
+ {
+ std::unique_ptr<HuffmanCodec<uint64_t>> codec(new HuffmanCodec<uint64_t>(19, {
+ {0, 0, 0},
+ {139011596, 0, 0},
+ {810488476, 0, 0},
+ {870594305, 0, 0},
+ {1742737136, 0, 0},
+ {2096388952, 0, 0},
+ {2855506940, 0, 0},
+ {3044188332, 0, 0},
+ {3487022798, 0, 0},
+ {3701632935, 0, 0},
+ {1111111111111111111, 0, 0},
+ {0, 3, 9},
+ {0, 2, 8},
+ {0, 4, 7},
+ {0, 11, 5},
+ {0, 13, 12},
+ {0, 14, 1},
+ {0, 6, 15},
+ {0, 17, 16},
+ {0, 10, 18},
+ }));
+
+ codecs.emplace(std::pair<uint32_t, uint32_t>(SpvOpExtInst, 4), std::move(codec));
+ }
+
+ {
+ std::unique_ptr<HuffmanCodec<uint64_t>> codec(new HuffmanCodec<uint64_t>(15, {
+ {0, 0, 0},
+ {139011596, 0, 0},
+ {296981500, 0, 0},
+ {1367301635, 0, 0},
+ {2855506940, 0, 0},
+ {3233393284, 0, 0},
+ {3251128023, 0, 0},
+ {3582002820, 0, 0},
+ {1111111111111111111, 0, 0},
+ {0, 5, 7},
+ {0, 1, 3},
+ {0, 2, 9},
+ {0, 6, 10},
+ {0, 12, 11},
+ {0, 4, 13},
+ {0, 8, 14},
+ }));
+
+ codecs.emplace(std::pair<uint32_t, uint32_t>(SpvOpExtInst, 5), std::move(codec));
+ }
+
+ {
+ std::unique_ptr<HuffmanCodec<uint64_t>> codec(new HuffmanCodec<uint64_t>(11, {
+ {0, 0, 0},
+ {296981500, 0, 0},
+ {508217552, 0, 0},
+ {2683080096, 0, 0},
+ {3547456240, 0, 0},
+ {3753486980, 0, 0},
+ {1111111111111111111, 0, 0},
+ {0, 3, 4},
+ {0, 5, 2},
+ {0, 8, 7},
+ {0, 1, 9},
+ {0, 6, 10},
+ }));
+
+ codecs.emplace(std::pair<uint32_t, uint32_t>(SpvOpExtInst, 6), std::move(codec));
+ }
+
+ {
+ std::unique_ptr<HuffmanCodec<uint64_t>> codec(new HuffmanCodec<uint64_t>(65, {
+ {0, 0, 0},
+ {135486769, 0, 0},
+ {440421571, 0, 0},
+ {450406196, 0, 0},
+ {503094540, 0, 0},
+ {543621065, 0, 0},
+ {827698488, 0, 0},
+ {907126242, 0, 0},
+ {908777857, 0, 0},
+ {910429472, 0, 0},
+ {1294403159, 0, 0},
+ {1296054774, 0, 0},
+ {1297706389, 0, 0},
+ {1322549027, 0, 0},
+ {1784441183, 0, 0},
+ {2080953106, 0, 0},
+ {2194691858, 0, 0},
+ {2448331885, 0, 0},
+ {2468230023, 0, 0},
+ {2547657777, 0, 0},
+ {2549309392, 0, 0},
+ {2550961007, 0, 0},
+ {2934934694, 0, 0},
+ {2936586309, 0, 0},
+ {2938237924, 0, 0},
+ {3094180193, 0, 0},
+ {3094857332, 0, 0},
+ {3095831808, 0, 0},
+ {3183924418, 0, 0},
+ {3561562003, 0, 0},
+ {3563213618, 0, 0},
+ {3564865233, 0, 0},
+ {4028622909, 0, 0},
+ {1111111111111111111, 0, 0},
+ {0, 23, 3},
+ {0, 18, 24},
+ {0, 14, 22},
+ {0, 17, 9},
+ {0, 1, 26},
+ {0, 4, 15},
+ {0, 31, 25},
+ {0, 8, 7},
+ {0, 34, 2},
+ {0, 12, 30},
+ {0, 36, 35},
+ {0, 13, 11},
+ {0, 6, 10},
+ {0, 5, 37},
+ {0, 38, 27},
+ {0, 40, 39},
+ {0, 42, 41},
+ {0, 16, 28},
+ {0, 44, 43},
+ {0, 21, 45},
+ {0, 20, 46},
+ {0, 47, 32},
+ {0, 48, 19},
+ {0, 29, 49},
+ {0, 51, 50},
+ {0, 53, 52},
+ {0, 55, 54},
+ {0, 57, 56},
+ {0, 58, 33},
+ {0, 60, 59},
+ {0, 62, 61},
+ {0, 64, 63},
+ }));
+
+ codecs.emplace(std::pair<uint32_t, uint32_t>(SpvOpTypePointer, 0), std::move(codec));
+ }
+
+ {
+ std::unique_ptr<HuffmanCodec<uint64_t>> codec(new HuffmanCodec<uint64_t>(35, {
+ {0, 0, 0},
+ {119981689, 0, 0},
+ {162255877, 0, 0},
+ {679771963, 0, 0},
+ {1154919607, 0, 0},
+ {1343794461, 0, 0},
+ {1674803691, 0, 0},
+ {1951208733, 0, 0},
+ {2263349224, 0, 0},
+ {2320303498, 0, 0},
+ {2924146124, 0, 0},
+ {2984325996, 0, 0},
+ {3334207724, 0, 0},
+ {3410158390, 0, 0},
+ {3489360962, 0, 0},
+ {3866587616, 0, 0},
+ {3868239231, 0, 0},
+ {3869890846, 0, 0},
+ {1111111111111111111, 0, 0},
+ {0, 14, 15},
+ {0, 6, 1},
+ {0, 8, 13},
+ {0, 19, 5},
+ {0, 20, 16},
+ {0, 11, 2},
+ {0, 22, 21},
+ {0, 17, 10},
+ {0, 4, 23},
+ {0, 25, 24},
+ {0, 7, 26},
+ {0, 9, 27},
+ {0, 28, 3},
+ {0, 29, 18},
+ {0, 30, 12},
+ {0, 32, 31},
+ {0, 34, 33},
+ }));
+
+ codecs.emplace(std::pair<uint32_t, uint32_t>(SpvOpTypePointer, 2), std::move(codec));
+ }
+
+ {
+ std::unique_ptr<HuffmanCodec<uint64_t>> codec(new HuffmanCodec<uint64_t>(7, {
+ {0, 0, 0},
+ {789872778, 0, 0},
+ {1951208733, 0, 0},
+ {2430404313, 0, 0},
+ {1111111111111111111, 0, 0},
+ {0, 3, 4},
+ {0, 1, 5},
+ {0, 2, 6},
+ }));
+
+ codecs.emplace(std::pair<uint32_t, uint32_t>(SpvOpConstant, 0), std::move(codec));
+ }
+
+ {
+ std::unique_ptr<HuffmanCodec<uint64_t>> codec(new HuffmanCodec<uint64_t>(45, {
+ {0, 0, 0},
+ {142465290, 0, 0},
+ {144116905, 0, 0},
+ {210116709, 0, 0},
+ {296981500, 0, 0},
+ {529742207, 0, 0},
+ {959681532, 0, 0},
+ {1156369516, 0, 0},
+ {1158021131, 0, 0},
+ {1543646433, 0, 0},
+ {1782996825, 0, 0},
+ {1784648440, 0, 0},
+ {2170273742, 0, 0},
+ {2321729979, 0, 0},
+ {2444465148, 0, 0},
+ {2524697596, 0, 0},
+ {2557550659, 0, 0},
+ {2796901051, 0, 0},
+ {2798552666, 0, 0},
+ {2855506940, 0, 0},
+ {3184177968, 0, 0},
+ {3810805277, 0, 0},
+ {3929248764, 0, 0},
+ {1111111111111111111, 0, 0},
+ {0, 16, 13},
+ {0, 9, 15},
+ {0, 5, 20},
+ {0, 14, 8},
+ {0, 12, 11},
+ {0, 2, 3},
+ {0, 24, 21},
+ {0, 1, 7},
+ {0, 17, 10},
+ {0, 22, 25},
+ {0, 27, 26},
+ {0, 18, 6},
+ {0, 19, 28},
+ {0, 29, 4},
+ {0, 31, 30},
+ {0, 33, 32},
+ {0, 35, 34},
+ {0, 37, 36},
+ {0, 39, 38},
+ {0, 41, 40},
+ {0, 43, 42},
+ {0, 23, 44},
+ }));
+
+ codecs.emplace(std::pair<uint32_t, uint32_t>(SpvOpConstant, 1), std::move(codec));
+ }
+
+ {
+ std::unique_ptr<HuffmanCodec<uint64_t>> codec(new HuffmanCodec<uint64_t>(9, {
+ {0, 0, 0},
+ {679771963, 0, 0},
+ {1247793383, 0, 0},
+ {2320303498, 0, 0},
+ {3334207724, 0, 0},
+ {1111111111111111111, 0, 0},
+ {0, 2, 5},
+ {0, 4, 6},
+ {0, 1, 3},
+ {0, 8, 7},
+ }));
+
+ codecs.emplace(std::pair<uint32_t, uint32_t>(SpvOpConstantComposite, 0), std::move(codec));
+ }
+
+ {
+ std::unique_ptr<HuffmanCodec<uint64_t>> codec(new HuffmanCodec<uint64_t>(59, {
+ {0, 0, 0},
+ {15502752, 0, 0},
+ {139011596, 0, 0},
+ {249378857, 0, 0},
+ {251209228, 0, 0},
+ {503145996, 0, 0},
+ {1325348861, 0, 0},
+ {1558001705, 0, 0},
+ {1646147798, 0, 0},
+ {1679946323, 0, 0},
+ {1766401548, 0, 0},
+ {1992893964, 0, 0},
+ {2123388694, 0, 0},
+ {2162986400, 0, 0},
+ {2580096524, 0, 0},
+ {2598189097, 0, 0},
+ {2683080096, 0, 0},
+ {2698156268, 0, 0},
+ {3133016299, 0, 0},
+ {3251128023, 0, 0},
+ {3504158761, 0, 0},
+ {3538592682, 0, 0},
+ {3540244297, 0, 0},
+ {3541895912, 0, 0},
+ {3570219049, 0, 0},
+ {3653838348, 0, 0},
+ {3764205609, 0, 0},
+ {3882634684, 0, 0},
+ {3913885196, 0, 0},
+ {4243119782, 0, 0},
+ {1111111111111111111, 0, 0},
+ {0, 7, 4},
+ {0, 24, 15},
+ {0, 11, 13},
+ {0, 5, 14},
+ {0, 6, 3},
+ {0, 9, 8},
+ {0, 17, 12},
+ {0, 27, 18},
+ {0, 1, 29},
+ {0, 21, 31},
+ {0, 23, 22},
+ {0, 33, 32},
+ {0, 10, 34},
+ {0, 25, 28},
+ {0, 36, 35},
+ {0, 38, 37},
+ {0, 16, 39},
+ {0, 40, 26},
+ {0, 41, 19},
+ {0, 20, 42},
+ {0, 2, 43},
+ {0, 45, 44},
+ {0, 47, 46},
+ {0, 49, 48},
+ {0, 50, 30},
+ {0, 52, 51},
+ {0, 54, 53},
+ {0, 56, 55},
+ {0, 58, 57},
+ }));
+
+ codecs.emplace(std::pair<uint32_t, uint32_t>(SpvOpConstantComposite, 1), std::move(codec));
+ }
+
+ {
+ std::unique_ptr<HuffmanCodec<uint64_t>> codec(new HuffmanCodec<uint64_t>(41, {
+ {0, 0, 0},
+ {142465290, 0, 0},
+ {158160339, 0, 0},
+ {169135842, 0, 0},
+ {210116709, 0, 0},
+ {296981500, 0, 0},
+ {910398460, 0, 0},
+ {959681532, 0, 0},
+ {1039111164, 0, 0},
+ {1087394637, 0, 0},
+ {1156369516, 0, 0},
+ {2444465148, 0, 0},
+ {2732195517, 0, 0},
+ {2796901051, 0, 0},
+ {2855506940, 0, 0},
+ {3202349435, 0, 0},
+ {3362723943, 0, 0},
+ {3712763835, 0, 0},
+ {3929248764, 0, 0},
+ {4016096296, 0, 0},
+ {4248015868, 0, 0},
+ {1111111111111111111, 0, 0},
+ {0, 20, 6},
+ {0, 7, 8},
+ {0, 3, 2},
+ {0, 12, 9},
+ {0, 16, 15},
+ {0, 19, 17},
+ {0, 10, 22},
+ {0, 1, 13},
+ {0, 23, 11},
+ {0, 25, 24},
+ {0, 27, 26},
+ {0, 28, 18},
+ {0, 29, 4},
+ {0, 31, 30},
+ {0, 33, 32},
+ {0, 21, 34},
+ {0, 35, 5},
+ {0, 37, 36},
+ {0, 38, 14},
+ {0, 40, 39},
+ }));
+
+ codecs.emplace(std::pair<uint32_t, uint32_t>(SpvOpConstantComposite, 2), std::move(codec));
+ }
+
+ {
+ std::unique_ptr<HuffmanCodec<uint64_t>> codec(new HuffmanCodec<uint64_t>(39, {
+ {0, 0, 0},
+ {52882140, 0, 0},
+ {210116709, 0, 0},
+ {296981500, 0, 0},
+ {385229009, 0, 0},
+ {910398460, 0, 0},
+ {959681532, 0, 0},
+ {1031290113, 0, 0},
+ {1039111164, 0, 0},
+ {1172110445, 0, 0},
+ {1622381564, 0, 0},
+ {1782996825, 0, 0},
+ {1971252067, 0, 0},
+ {2444465148, 0, 0},
+ {2490492987, 0, 0},
+ {2678954464, 0, 0},
+ {2855506940, 0, 0},
+ {3912967080, 0, 0},
+ {3929248764, 0, 0},
+ {4248015868, 0, 0},
+ {1111111111111111111, 0, 0},
+ {0, 5, 10},
+ {0, 8, 19},
+ {0, 6, 21},
+ {0, 4, 1},
+ {0, 9, 7},
+ {0, 14, 12},
+ {0, 17, 15},
+ {0, 13, 22},
+ {0, 24, 23},
+ {0, 26, 25},
+ {0, 18, 27},
+ {0, 28, 2},
+ {0, 29, 20},
+ {0, 31, 30},
+ {0, 32, 11},
+ {0, 33, 3},
+ {0, 35, 34},
+ {0, 36, 16},
+ {0, 38, 37},
+ }));
+
+ codecs.emplace(std::pair<uint32_t, uint32_t>(SpvOpConstantComposite, 3), std::move(codec));
+ }
+
+ {
+ std::unique_ptr<HuffmanCodec<uint64_t>> codec(new HuffmanCodec<uint64_t>(35, {
+ {0, 0, 0},
+ {210116709, 0, 0},
+ {296981500, 0, 0},
+ {615748604, 0, 0},
+ {910398460, 0, 0},
+ {959681532, 0, 0},
+ {1039111164, 0, 0},
+ {1543672828, 0, 0},
+ {1612361408, 0, 0},
+ {2100532220, 0, 0},
+ {2326636627, 0, 0},
+ {2444465148, 0, 0},
+ {2524697596, 0, 0},
+ {2763232252, 0, 0},
+ {2855506940, 0, 0},
+ {3929248764, 0, 0},
+ {4172568578, 0, 0},
+ {4248015868, 0, 0},
+ {1111111111111111111, 0, 0},
+ {0, 7, 3},
+ {0, 13, 9},
+ {0, 10, 8},
+ {0, 4, 16},
+ {0, 19, 17},
+ {0, 20, 6},
+ {0, 21, 12},
+ {0, 22, 18},
+ {0, 23, 5},
+ {0, 24, 15},
+ {0, 26, 25},
+ {0, 27, 11},
+ {0, 1, 28},
+ {0, 30, 29},
+ {0, 14, 31},
+ {0, 2, 32},
+ {0, 34, 33},
+ }));
+
+ codecs.emplace(std::pair<uint32_t, uint32_t>(SpvOpConstantComposite, 4), std::move(codec));
+ }
+
+ {
+ std::unique_ptr<HuffmanCodec<uint64_t>> codec(new HuffmanCodec<uint64_t>(33, {
+ {0, 0, 0},
+ {296981500, 0, 0},
+ {615748604, 0, 0},
+ {959681532, 0, 0},
+ {1039111164, 0, 0},
+ {1450415100, 0, 0},
+ {1543672828, 0, 0},
+ {1939359710, 0, 0},
+ {2100532220, 0, 0},
+ {2113115132, 0, 0},
+ {2326636627, 0, 0},
+ {2444465148, 0, 0},
+ {2763232252, 0, 0},
+ {2855506940, 0, 0},
+ {3929248764, 0, 0},
+ {4172568578, 0, 0},
+ {4248015868, 0, 0},
+ {1111111111111111111, 0, 0},
+ {0, 5, 17},
+ {0, 11, 3},
+ {0, 16, 2},
+ {0, 8, 6},
+ {0, 18, 12},
+ {0, 10, 7},
+ {0, 9, 15},
+ {0, 19, 14},
+ {0, 4, 20},
+ {0, 22, 21},
+ {0, 24, 23},
+ {0, 26, 25},
+ {0, 27, 1},
+ {0, 29, 28},
+ {0, 31, 30},
+ {0, 32, 13},
+ }));
+
+ codecs.emplace(std::pair<uint32_t, uint32_t>(SpvOpConstantComposite, 5), std::move(codec));
+ }
+
+ {
+ std::unique_ptr<HuffmanCodec<uint64_t>> codec(new HuffmanCodec<uint64_t>(37, {
+ {0, 0, 0},
+ {543621065, 0, 0},
+ {827698488, 0, 0},
+ {1294403159, 0, 0},
+ {1296054774, 0, 0},
+ {1297706389, 0, 0},
+ {1322549027, 0, 0},
+ {2194691858, 0, 0},
+ {2468230023, 0, 0},
+ {2547657777, 0, 0},
+ {2549309392, 0, 0},
+ {2550961007, 0, 0},
+ {2934934694, 0, 0},
+ {2936586309, 0, 0},
+ {2938237924, 0, 0},
+ {3095831808, 0, 0},
+ {3183924418, 0, 0},
+ {3561562003, 0, 0},
+ {4028622909, 0, 0},
+ {1111111111111111111, 0, 0},
+ {0, 16, 6},
+ {0, 18, 10},
+ {0, 13, 14},
+ {0, 11, 20},
+ {0, 21, 5},
+ {0, 22, 2},
+ {0, 3, 23},
+ {0, 7, 15},
+ {0, 1, 24},
+ {0, 8, 17},
+ {0, 9, 12},
+ {0, 4, 25},
+ {0, 19, 26},
+ {0, 28, 27},
+ {0, 30, 29},
+ {0, 32, 31},
+ {0, 34, 33},
+ {0, 36, 35},
+ }));
+
+ codecs.emplace(std::pair<uint32_t, uint32_t>(SpvOpVariable, 0), std::move(codec));
+ }
+
+ {
+ std::unique_ptr<HuffmanCodec<uint64_t>> codec(new HuffmanCodec<uint64_t>(37, {
+ {0, 0, 0},
+ {37459569, 0, 0},
+ {137840602, 0, 0},
+ {565334834, 0, 0},
+ {625975427, 0, 0},
+ {630964591, 0, 0},
+ {680016782, 0, 0},
+ {1009983433, 0, 0},
+ {1572088444, 0, 0},
+ {1584774136, 0, 0},
+ {1918481917, 0, 0},
+ {2790624748, 0, 0},
+ {3181646225, 0, 0},
+ {3560665067, 0, 0},
+ {3662767579, 0, 0},
+ {4053789056, 0, 0},
+ {4064212479, 0, 0},
+ {4192247221, 0, 0},
+ {4224872590, 0, 0},
+ {1111111111111111111, 0, 0},
+ {0, 4, 3},
+ {0, 6, 15},
+ {0, 2, 7},
+ {0, 5, 20},
+ {0, 21, 14},
+ {0, 22, 18},
+ {0, 10, 23},
+ {0, 1, 16},
+ {0, 9, 24},
+ {0, 8, 17},
+ {0, 12, 13},
+ {0, 11, 25},
+ {0, 19, 26},
+ {0, 28, 27},
+ {0, 30, 29},
+ {0, 32, 31},
+ {0, 34, 33},
+ {0, 36, 35},
+ }));
+
+ codecs.emplace(std::pair<uint32_t, uint32_t>(SpvOpVariable, 1), std::move(codec));
+ }
+
+ {
+ std::unique_ptr<HuffmanCodec<uint64_t>> codec(new HuffmanCodec<uint64_t>(15, {
+ {0, 0, 0},
+ {162255877, 0, 0},
+ {679771963, 0, 0},
+ {1951208733, 0, 0},
+ {2320303498, 0, 0},
+ {2984325996, 0, 0},
+ {3334207724, 0, 0},
+ {3869890846, 0, 0},
+ {1111111111111111111, 0, 0},
+ {0, 7, 5},
+ {0, 8, 1},
+ {0, 9, 4},
+ {0, 2, 10},
+ {0, 6, 11},
+ {0, 3, 12},
+ {0, 14, 13},
+ }));
+
+ codecs.emplace(std::pair<uint32_t, uint32_t>(SpvOpLoad, 0), std::move(codec));
+ }
+
+ {
+ std::unique_ptr<HuffmanCodec<uint64_t>> codec(new HuffmanCodec<uint64_t>(37, {
+ {0, 0, 0},
+ {543558236, 0, 0},
+ {810488476, 0, 0},
+ {870594305, 0, 0},
+ {883854656, 0, 0},
+ {1570165302, 0, 0},
+ {1684282922, 0, 0},
+ {1901166356, 0, 0},
+ {1949759310, 0, 0},
+ {2087004702, 0, 0},
+ {2096388952, 0, 0},
+ {2517964682, 0, 0},
+ {2622612602, 0, 0},
+ {2970183398, 0, 0},
+ {3091876332, 0, 0},
+ {3187066832, 0, 0},
+ {3496407048, 0, 0},
+ {3570411982, 0, 0},
+ {3692647551, 0, 0},
+ {1111111111111111111, 0, 0},
+ {0, 14, 18},
+ {0, 3, 7},
+ {0, 5, 9},
+ {0, 6, 13},
+ {0, 21, 20},
+ {0, 2, 11},
+ {0, 15, 22},
+ {0, 16, 23},
+ {0, 4, 1},
+ {0, 12, 24},
+ {0, 17, 8},
+ {0, 26, 25},
+ {0, 27, 10},
+ {0, 29, 28},
+ {0, 31, 30},
+ {0, 33, 32},
+ {0, 35, 34},
+ {0, 36, 19},
+ }));
+
+ codecs.emplace(std::pair<uint32_t, uint32_t>(SpvOpLoad, 1), std::move(codec));
+ }
+
+ {
+ std::unique_ptr<HuffmanCodec<uint64_t>> codec(new HuffmanCodec<uint64_t>(37, {
+ {0, 0, 0},
+ {37459569, 0, 0},
+ {137840602, 0, 0},
+ {522971108, 0, 0},
+ {630964591, 0, 0},
+ {1572088444, 0, 0},
+ {1584774136, 0, 0},
+ {1918481917, 0, 0},
+ {1957218950, 0, 0},
+ {2313593054, 0, 0},
+ {2790624748, 0, 0},
+ {2838165089, 0, 0},
+ {3181646225, 0, 0},
+ {3364388739, 0, 0},
+ {3560665067, 0, 0},
+ {3662767579, 0, 0},
+ {4064212479, 0, 0},
+ {4224872590, 0, 0},
+ {4239834800, 0, 0},
+ {1111111111111111111, 0, 0},
+ {0, 9, 11},
+ {0, 13, 8},
+ {0, 15, 18},
+ {0, 5, 2},
+ {0, 21, 20},
+ {0, 17, 4},
+ {0, 3, 22},
+ {0, 14, 23},
+ {0, 1, 16},
+ {0, 7, 24},
+ {0, 12, 6},
+ {0, 26, 25},
+ {0, 27, 10},
+ {0, 29, 28},
+ {0, 31, 30},
+ {0, 33, 32},
+ {0, 35, 34},
+ {0, 36, 19},
+ }));
+
+ codecs.emplace(std::pair<uint32_t, uint32_t>(SpvOpLoad, 2), std::move(codec));
+ }
+
+ {
+ std::unique_ptr<HuffmanCodec<uint64_t>> codec(new HuffmanCodec<uint64_t>(19, {
+ {0, 0, 0},
+ {137840602, 0, 0},
+ {1009983433, 0, 0},
+ {1572088444, 0, 0},
+ {1918481917, 0, 0},
+ {2790624748, 0, 0},
+ {3560665067, 0, 0},
+ {3662767579, 0, 0},
+ {4192247221, 0, 0},
+ {4224872590, 0, 0},
+ {1111111111111111111, 0, 0},
+ {0, 1, 2},
+ {0, 11, 7},
+ {0, 8, 9},
+ {0, 4, 3},
+ {0, 12, 6},
+ {0, 5, 13},
+ {0, 15, 14},
+ {0, 16, 10},
+ {0, 18, 17},
+ }));
+
+ codecs.emplace(std::pair<uint32_t, uint32_t>(SpvOpStore, 0), std::move(codec));
+ }
+
+ {
+ std::unique_ptr<HuffmanCodec<uint64_t>> codec(new HuffmanCodec<uint64_t>(25, {
+ {0, 0, 0},
+ {177111659, 0, 0},
+ {296981500, 0, 0},
+ {408465899, 0, 0},
+ {2055836767, 0, 0},
+ {2087004702, 0, 0},
+ {2096388952, 0, 0},
+ {2622612602, 0, 0},
+ {2855506940, 0, 0},
+ {2959147533, 0, 0},
+ {3187066832, 0, 0},
+ {3570411982, 0, 0},
+ {3831290364, 0, 0},
+ {1111111111111111111, 0, 0},
+ {0, 2, 1},
+ {0, 12, 11},
+ {0, 9, 3},
+ {0, 7, 4},
+ {0, 14, 8},
+ {0, 10, 6},
+ {0, 5, 15},
+ {0, 17, 16},
+ {0, 19, 18},
+ {0, 21, 20},
+ {0, 23, 22},
+ {0, 13, 24},
+ }));
+
+ codecs.emplace(std::pair<uint32_t, uint32_t>(SpvOpStore, 1), std::move(codec));
+ }
+
+ {
+ std::unique_ptr<HuffmanCodec<uint64_t>> codec(new HuffmanCodec<uint64_t>(25, {
+ {0, 0, 0},
+ {440421571, 0, 0},
+ {827698488, 0, 0},
+ {907126242, 0, 0},
+ {908777857, 0, 0},
+ {910429472, 0, 0},
+ {1294403159, 0, 0},
+ {1296054774, 0, 0},
+ {1297706389, 0, 0},
+ {2080953106, 0, 0},
+ {2468230023, 0, 0},
+ {2547657777, 0, 0},
+ {3561562003, 0, 0},
+ {1111111111111111111, 0, 0},
+ {0, 7, 5},
+ {0, 12, 11},
+ {0, 9, 8},
+ {0, 13, 14},
+ {0, 15, 4},
+ {0, 17, 16},
+ {0, 18, 3},
+ {0, 19, 10},
+ {0, 6, 1},
+ {0, 21, 20},
+ {0, 22, 2},
+ {0, 24, 23},
+ }));
+
+ codecs.emplace(std::pair<uint32_t, uint32_t>(SpvOpAccessChain, 0), std::move(codec));
+ }
+
+ {
+ std::unique_ptr<HuffmanCodec<uint64_t>> codec(new HuffmanCodec<uint64_t>(29, {
+ {0, 0, 0},
+ {1079999262, 0, 0},
+ {2311941439, 0, 0},
+ {2313593054, 0, 0},
+ {2838165089, 0, 0},
+ {2839816704, 0, 0},
+ {2841468319, 0, 0},
+ {3364388739, 0, 0},
+ {3366040354, 0, 0},
+ {3367691969, 0, 0},
+ {3369343584, 0, 0},
+ {4239834800, 0, 0},
+ {4241486415, 0, 0},
+ {4243138030, 0, 0},
+ {4244789645, 0, 0},
+ {1111111111111111111, 0, 0},
+ {0, 9, 10},
+ {0, 14, 12},
+ {0, 6, 13},
+ {0, 8, 1},
+ {0, 2, 5},
+ {0, 3, 4},
+ {0, 17, 16},
+ {0, 11, 18},
+ {0, 7, 19},
+ {0, 21, 20},
+ {0, 23, 22},
+ {0, 25, 24},
+ {0, 27, 26},
+ {0, 15, 28},
+ }));
+
+ codecs.emplace(std::pair<uint32_t, uint32_t>(SpvOpAccessChain, 1), std::move(codec));
+ }
+
+ {
+ std::unique_ptr<HuffmanCodec<uint64_t>> codec(new HuffmanCodec<uint64_t>(49, {
+ {0, 0, 0},
+ {112745085, 0, 0},
+ {116376005, 0, 0},
+ {400248103, 0, 0},
+ {406044930, 0, 0},
+ {522971108, 0, 0},
+ {625975427, 0, 0},
+ {680016782, 0, 0},
+ {1009983433, 0, 0},
+ {1062250709, 0, 0},
+ {1410849099, 0, 0},
+ {1918481917, 0, 0},
+ {2190437442, 0, 0},
+ {2790624748, 0, 0},
+ {2879917723, 0, 0},
+ {2882994691, 0, 0},
+ {3181646225, 0, 0},
+ {3263901372, 0, 0},
+ {3390051757, 0, 0},
+ {3560665067, 0, 0},
+ {3662767579, 0, 0},
+ {3717523241, 0, 0},
+ {3945795573, 0, 0},
+ {4101009465, 0, 0},
+ {4290024976, 0, 0},
+ {1111111111111111111, 0, 0},
+ {0, 1, 23},
+ {0, 8, 22},
+ {0, 3, 21},
+ {0, 9, 5},
+ {0, 2, 10},
+ {0, 26, 17},
+ {0, 27, 14},
+ {0, 16, 4},
+ {0, 29, 28},
+ {0, 12, 30},
+ {0, 15, 31},
+ {0, 32, 18},
+ {0, 6, 7},
+ {0, 20, 33},
+ {0, 24, 34},
+ {0, 35, 13},
+ {0, 19, 36},
+ {0, 11, 37},
+ {0, 39, 38},
+ {0, 41, 40},
+ {0, 43, 42},
+ {0, 44, 25},
+ {0, 46, 45},
+ {0, 48, 47},
+ }));
+
+ codecs.emplace(std::pair<uint32_t, uint32_t>(SpvOpAccessChain, 2), std::move(codec));
+ }
+
+ {
+ std::unique_ptr<HuffmanCodec<uint64_t>> codec(new HuffmanCodec<uint64_t>(35, {
+ {0, 0, 0},
+ {142465290, 0, 0},
+ {144116905, 0, 0},
+ {529742207, 0, 0},
+ {1156369516, 0, 0},
+ {1158021131, 0, 0},
+ {1543646433, 0, 0},
+ {1782996825, 0, 0},
+ {1784648440, 0, 0},
+ {1930923350, 0, 0},
+ {2170273742, 0, 0},
+ {2557550659, 0, 0},
+ {2705477184, 0, 0},
+ {2796901051, 0, 0},
+ {2798552666, 0, 0},
+ {3184177968, 0, 0},
+ {3810805277, 0, 0},
+ {4198082194, 0, 0},
+ {1111111111111111111, 0, 0},
+ {0, 11, 9},
+ {0, 6, 17},
+ {0, 3, 19},
+ {0, 15, 12},
+ {0, 20, 16},
+ {0, 10, 13},
+ {0, 21, 4},
+ {0, 1, 22},
+ {0, 14, 23},
+ {0, 5, 24},
+ {0, 26, 25},
+ {0, 2, 8},
+ {0, 27, 18},
+ {0, 7, 28},
+ {0, 30, 29},
+ {0, 32, 31},
+ {0, 34, 33},
+ }));
+
+ codecs.emplace(std::pair<uint32_t, uint32_t>(SpvOpAccessChain, 3), std::move(codec));
+ }
+
+ {
+ std::unique_ptr<HuffmanCodec<uint64_t>> codec(new HuffmanCodec<uint64_t>(41, {
+ {0, 0, 0},
+ {142465290, 0, 0},
+ {144116905, 0, 0},
+ {198967948, 0, 0},
+ {529742207, 0, 0},
+ {825595257, 0, 0},
+ {1156369516, 0, 0},
+ {1158021131, 0, 0},
+ {1452222566, 0, 0},
+ {1782996825, 0, 0},
+ {1784648440, 0, 0},
+ {1839499483, 0, 0},
+ {2170273742, 0, 0},
+ {2466126792, 0, 0},
+ {2796901051, 0, 0},
+ {2798552666, 0, 0},
+ {3184177968, 0, 0},
+ {3480031018, 0, 0},
+ {3810805277, 0, 0},
+ {4106658327, 0, 0},
+ {4198082194, 0, 0},
+ {1111111111111111111, 0, 0},
+ {0, 3, 20},
+ {0, 16, 13},
+ {0, 11, 5},
+ {0, 4, 17},
+ {0, 19, 8},
+ {0, 18, 12},
+ {0, 23, 22},
+ {0, 25, 24},
+ {0, 27, 26},
+ {0, 6, 28},
+ {0, 14, 29},
+ {0, 1, 30},
+ {0, 15, 2},
+ {0, 10, 31},
+ {0, 9, 32},
+ {0, 34, 33},
+ {0, 35, 7},
+ {0, 21, 36},
+ {0, 38, 37},
+ {0, 40, 39},
+ }));
+
+ codecs.emplace(std::pair<uint32_t, uint32_t>(SpvOpAccessChain, 4), std::move(codec));
+ }
+
+ {
+ std::unique_ptr<HuffmanCodec<uint64_t>> codec(new HuffmanCodec<uint64_t>(9, {
+ {0, 0, 0},
+ {144116905, 0, 0},
+ {1158021131, 0, 0},
+ {1784648440, 0, 0},
+ {2798552666, 0, 0},
+ {1111111111111111111, 0, 0},
+ {0, 1, 5},
+ {0, 4, 2},
+ {0, 6, 3},
+ {0, 8, 7},
+ }));
+
+ codecs.emplace(std::pair<uint32_t, uint32_t>(SpvOpAccessChain, 5), std::move(codec));
+ }
+
+ {
+ std::unique_ptr<HuffmanCodec<uint64_t>> codec(new HuffmanCodec<uint64_t>(5, {
+ {0, 0, 0},
+ {142465290, 0, 0},
+ {1782996825, 0, 0},
+ {1111111111111111111, 0, 0},
+ {0, 2, 1},
+ {0, 4, 3},
+ }));
+
+ codecs.emplace(std::pair<uint32_t, uint32_t>(SpvOpAccessChain, 6), std::move(codec));
+ }
+
+ {
+ std::unique_ptr<HuffmanCodec<uint64_t>> codec(new HuffmanCodec<uint64_t>(7, {
+ {0, 0, 0},
+ {679771963, 0, 0},
+ {2320303498, 0, 0},
+ {3334207724, 0, 0},
+ {1111111111111111111, 0, 0},
+ {0, 3, 4},
+ {0, 2, 5},
+ {0, 6, 1},
+ }));
+
+ codecs.emplace(std::pair<uint32_t, uint32_t>(SpvOpVectorShuffle, 0), std::move(codec));
+ }
+
+ {
+ std::unique_ptr<HuffmanCodec<uint64_t>> codec(new HuffmanCodec<uint64_t>(19, {
+ {0, 0, 0},
+ {177111659, 0, 0},
+ {837715723, 0, 0},
+ {1203545131, 0, 0},
+ {1352628475, 0, 0},
+ {1367301635, 0, 0},
+ {2055836767, 0, 0},
+ {2204920111, 0, 0},
+ {3619787319, 0, 0},
+ {3701632935, 0, 0},
+ {1111111111111111111, 0, 0},
+ {0, 1, 4},
+ {0, 2, 7},
+ {0, 11, 9},
+ {0, 6, 12},
+ {0, 8, 5},
+ {0, 3, 13},
+ {0, 15, 14},
+ {0, 17, 16},
+ {0, 10, 18},
+ }));
+
+ codecs.emplace(std::pair<uint32_t, uint32_t>(SpvOpVectorShuffle, 1), std::move(codec));
+ }
+
+ {
+ std::unique_ptr<HuffmanCodec<uint64_t>> codec(new HuffmanCodec<uint64_t>(17, {
+ {0, 0, 0},
+ {488500848, 0, 0},
+ {495107308, 0, 0},
+ {2096388952, 0, 0},
+ {2157103435, 0, 0},
+ {2622612602, 0, 0},
+ {3496407048, 0, 0},
+ {3570411982, 0, 0},
+ {3713290482, 0, 0},
+ {1111111111111111111, 0, 0},
+ {0, 1, 8},
+ {0, 3, 4},
+ {0, 10, 2},
+ {0, 12, 11},
+ {0, 6, 13},
+ {0, 7, 5},
+ {0, 15, 14},
+ {0, 9, 16},
+ }));
+
+ codecs.emplace(std::pair<uint32_t, uint32_t>(SpvOpVectorShuffle, 2), std::move(codec));
+ }
+
+ {
+ std::unique_ptr<HuffmanCodec<uint64_t>> codec(new HuffmanCodec<uint64_t>(11, {
+ {0, 0, 0},
+ {495107308, 0, 0},
+ {2096388952, 0, 0},
+ {2622612602, 0, 0},
+ {3496407048, 0, 0},
+ {3570411982, 0, 0},
+ {1111111111111111111, 0, 0},
+ {0, 1, 2},
+ {0, 3, 7},
+ {0, 8, 4},
+ {0, 9, 5},
+ {0, 6, 10},
+ }));
+
+ codecs.emplace(std::pair<uint32_t, uint32_t>(SpvOpVectorShuffle, 3), std::move(codec));
+ }
+
+ {
+ std::unique_ptr<HuffmanCodec<uint64_t>> codec(new HuffmanCodec<uint64_t>(7, {
+ {0, 0, 0},
+ {679771963, 0, 0},
+ {2320303498, 0, 0},
+ {3334207724, 0, 0},
+ {1111111111111111111, 0, 0},
+ {0, 2, 4},
+ {0, 3, 5},
+ {0, 6, 1},
+ }));
+
+ codecs.emplace(std::pair<uint32_t, uint32_t>(SpvOpCompositeConstruct, 0), std::move(codec));
+ }
+
+ {
+ std::unique_ptr<HuffmanCodec<uint64_t>> codec(new HuffmanCodec<uint64_t>(5, {
+ {0, 0, 0},
+ {1319785741, 0, 0},
+ {3753486980, 0, 0},
+ {1111111111111111111, 0, 0},
+ {0, 2, 1},
+ {0, 3, 4},
+ }));
+
+ codecs.emplace(std::pair<uint32_t, uint32_t>(SpvOpCompositeConstruct, 1), std::move(codec));
+ }
+
+ {
+ std::unique_ptr<HuffmanCodec<uint64_t>> codec(new HuffmanCodec<uint64_t>(11, {
+ {0, 0, 0},
+ {296981500, 0, 0},
+ {959681532, 0, 0},
+ {1141965917, 0, 0},
+ {2855506940, 0, 0},
+ {3091876332, 0, 0},
+ {1111111111111111111, 0, 0},
+ {0, 5, 2},
+ {0, 4, 3},
+ {0, 1, 7},
+ {0, 9, 8},
+ {0, 6, 10},
+ }));
+
+ codecs.emplace(std::pair<uint32_t, uint32_t>(SpvOpCompositeConstruct, 2), std::move(codec));
+ }
+
+ {
+ std::unique_ptr<HuffmanCodec<uint64_t>> codec(new HuffmanCodec<uint64_t>(11, {
+ {0, 0, 0},
+ {269823086, 0, 0},
+ {296981500, 0, 0},
+ {959681532, 0, 0},
+ {2219733501, 0, 0},
+ {2855506940, 0, 0},
+ {1111111111111111111, 0, 0},
+ {0, 1, 4},
+ {0, 7, 3},
+ {0, 5, 2},
+ {0, 9, 8},
+ {0, 6, 10},
+ }));
+
+ codecs.emplace(std::pair<uint32_t, uint32_t>(SpvOpCompositeConstruct, 3), std::move(codec));
+ }
+
+ {
+ std::unique_ptr<HuffmanCodec<uint64_t>> codec(new HuffmanCodec<uint64_t>(11, {
+ {0, 0, 0},
+ {296981500, 0, 0},
+ {959681532, 0, 0},
+ {1227221002, 0, 0},
+ {2855506940, 0, 0},
+ {3692647551, 0, 0},
+ {1111111111111111111, 0, 0},
+ {0, 2, 3},
+ {0, 1, 5},
+ {0, 4, 7},
+ {0, 9, 8},
+ {0, 6, 10},
+ }));
+
+ codecs.emplace(std::pair<uint32_t, uint32_t>(SpvOpCompositeConstruct, 4), std::move(codec));
+ }
+
+ {
+ std::unique_ptr<HuffmanCodec<uint64_t>> codec(new HuffmanCodec<uint64_t>(11, {
+ {0, 0, 0},
+ {18776483, 0, 0},
+ {296981500, 0, 0},
+ {959681532, 0, 0},
+ {2855506940, 0, 0},
+ {3874089391, 0, 0},
+ {1111111111111111111, 0, 0},
+ {0, 5, 1},
+ {0, 7, 3},
+ {0, 4, 8},
+ {0, 9, 2},
+ {0, 6, 10},
+ }));
+
+ codecs.emplace(std::pair<uint32_t, uint32_t>(SpvOpCompositeConstruct, 5), std::move(codec));
+ }
+
+ {
+ std::unique_ptr<HuffmanCodec<uint64_t>> codec(new HuffmanCodec<uint64_t>(9, {
+ {0, 0, 0},
+ {679771963, 0, 0},
+ {1951208733, 0, 0},
+ {2320303498, 0, 0},
+ {3334207724, 0, 0},
+ {1111111111111111111, 0, 0},
+ {0, 3, 5},
+ {0, 1, 6},
+ {0, 7, 4},
+ {0, 2, 8},
+ }));
+
+ codecs.emplace(std::pair<uint32_t, uint32_t>(SpvOpCompositeExtract, 0), std::move(codec));
+ }
+
+ {
+ std::unique_ptr<HuffmanCodec<uint64_t>> codec(new HuffmanCodec<uint64_t>(1, {
+ {0, 0, 0},
+ {1111111111111111111, 0, 0},
+ }));
+
+ codecs.emplace(std::pair<uint32_t, uint32_t>(SpvOpCompositeExtract, 1), std::move(codec));
+ }
+
+ {
+ std::unique_ptr<HuffmanCodec<uint64_t>> codec(new HuffmanCodec<uint64_t>(17, {
+ {0, 0, 0},
+ {495107308, 0, 0},
+ {850497536, 0, 0},
+ {1584369690, 0, 0},
+ {1890300748, 0, 0},
+ {2043873558, 0, 0},
+ {2338272340, 0, 0},
+ {3312467582, 0, 0},
+ {3504158761, 0, 0},
+ {1111111111111111111, 0, 0},
+ {0, 1, 8},
+ {0, 10, 4},
+ {0, 7, 3},
+ {0, 6, 11},
+ {0, 12, 5},
+ {0, 13, 2},
+ {0, 15, 14},
+ {0, 9, 16},
+ }));
+
+ codecs.emplace(std::pair<uint32_t, uint32_t>(SpvOpCompositeExtract, 2), std::move(codec));
+ }
+
+ {
+ std::unique_ptr<HuffmanCodec<uint64_t>> codec(new HuffmanCodec<uint64_t>(35, {
+ {0, 0, 0},
+ {545678922, 0, 0},
+ {630592085, 0, 0},
+ {679771963, 0, 0},
+ {899570100, 0, 0},
+ {929101967, 0, 0},
+ {1100599986, 0, 0},
+ {1103903216, 0, 0},
+ {1369578001, 0, 0},
+ {2320303498, 0, 0},
+ {2926633629, 0, 0},
+ {3334207724, 0, 0},
+ {3486057732, 0, 0},
+ {3705139860, 0, 0},
+ {3800912395, 0, 0},
+ {3822983876, 0, 0},
+ {4141567741, 0, 0},
+ {4292991777, 0, 0},
+ {1111111111111111111, 0, 0},
+ {0, 10, 2},
+ {0, 12, 17},
+ {0, 13, 7},
+ {0, 20, 19},
+ {0, 5, 16},
+ {0, 15, 21},
+ {0, 3, 22},
+ {0, 23, 18},
+ {0, 1, 9},
+ {0, 8, 24},
+ {0, 11, 14},
+ {0, 4, 25},
+ {0, 27, 26},
+ {0, 6, 28},
+ {0, 30, 29},
+ {0, 32, 31},
+ {0, 34, 33},
+ }));
+
+ codecs.emplace(std::pair<uint32_t, uint32_t>(SpvOpCompositeInsert, 0), std::move(codec));
+ }
+
+ {
+ std::unique_ptr<HuffmanCodec<uint64_t>> codec(new HuffmanCodec<uint64_t>(1, {
+ {0, 0, 0},
+ {1111111111111111111, 0, 0},
+ }));
+
+ codecs.emplace(std::pair<uint32_t, uint32_t>(SpvOpCompositeInsert, 1), std::move(codec));
+ }
+
+ {
+ std::unique_ptr<HuffmanCodec<uint64_t>> codec(new HuffmanCodec<uint64_t>(13, {
+ {0, 0, 0},
+ {296981500, 0, 0},
+ {2517964682, 0, 0},
+ {2855506940, 0, 0},
+ {3044188332, 0, 0},
+ {3570411982, 0, 0},
+ {3764205609, 0, 0},
+ {1111111111111111111, 0, 0},
+ {0, 4, 1},
+ {0, 8, 6},
+ {0, 9, 2},
+ {0, 10, 3},
+ {0, 11, 5},
+ {0, 7, 12},
+ }));
+
+ codecs.emplace(std::pair<uint32_t, uint32_t>(SpvOpCompositeInsert, 2), std::move(codec));
+ }
+
+ {
+ std::unique_ptr<HuffmanCodec<uint64_t>> codec(new HuffmanCodec<uint64_t>(9, {
+ {0, 0, 0},
+ {371428004, 0, 0},
+ {1543280290, 0, 0},
+ {2162986400, 0, 0},
+ {3808408202, 0, 0},
+ {1111111111111111111, 0, 0},
+ {0, 2, 3},
+ {0, 4, 1},
+ {0, 7, 6},
+ {0, 5, 8},
+ }));
+
+ codecs.emplace(std::pair<uint32_t, uint32_t>(SpvOpCompositeInsert, 3), std::move(codec));
+ }
+
+ {
+ std::unique_ptr<HuffmanCodec<uint64_t>> codec(new HuffmanCodec<uint64_t>(3, {
+ {0, 0, 0},
+ {3334207724, 0, 0},
+ {1111111111111111111, 0, 0},
+ {0, 1, 2},
+ }));
+
+ codecs.emplace(std::pair<uint32_t, uint32_t>(SpvOpImageSampleImplicitLod, 0), std::move(codec));
+ }
+
+ {
+ std::unique_ptr<HuffmanCodec<uint64_t>> codec(new HuffmanCodec<uint64_t>(15, {
+ {0, 0, 0},
+ {236660303, 0, 0},
+ {488500848, 0, 0},
+ {495107308, 0, 0},
+ {1858116930, 0, 0},
+ {2231688008, 0, 0},
+ {2693892518, 0, 0},
+ {3566035349, 0, 0},
+ {1111111111111111111, 0, 0},
+ {0, 6, 5},
+ {0, 4, 7},
+ {0, 10, 9},
+ {0, 1, 2},
+ {0, 12, 11},
+ {0, 13, 3},
+ {0, 8, 14},
+ }));
+
+ codecs.emplace(std::pair<uint32_t, uint32_t>(SpvOpImageSampleImplicitLod, 1), std::move(codec));
+ }
+
+ {
+ std::unique_ptr<HuffmanCodec<uint64_t>> codec(new HuffmanCodec<uint64_t>(13, {
+ {0, 0, 0},
+ {883854656, 0, 0},
+ {2036361232, 0, 0},
+ {2356768706, 0, 0},
+ {2637132451, 0, 0},
+ {3237903670, 0, 0},
+ {3829682756, 0, 0},
+ {1111111111111111111, 0, 0},
+ {0, 5, 7},
+ {0, 8, 6},
+ {0, 3, 4},
+ {0, 10, 9},
+ {0, 2, 11},
+ {0, 12, 1},
+ }));
+
+ codecs.emplace(std::pair<uint32_t, uint32_t>(SpvOpImageSampleImplicitLod, 2), std::move(codec));
+ }
+
+ {
+ std::unique_ptr<HuffmanCodec<uint64_t>> codec(new HuffmanCodec<uint64_t>(15, {
+ {0, 0, 0},
+ {646282397, 0, 0},
+ {1352628475, 0, 0},
+ {1543798545, 0, 0},
+ {1545450160, 0, 0},
+ {2517964682, 0, 0},
+ {2532518896, 0, 0},
+ {3619787319, 0, 0},
+ {1111111111111111111, 0, 0},
+ {0, 3, 6},
+ {0, 1, 4},
+ {0, 10, 9},
+ {0, 5, 2},
+ {0, 12, 11},
+ {0, 13, 7},
+ {0, 8, 14},
+ }));
+
+ codecs.emplace(std::pair<uint32_t, uint32_t>(SpvOpImageSampleImplicitLod, 3), std::move(codec));
+ }
+
+ {
+ std::unique_ptr<HuffmanCodec<uint64_t>> codec(new HuffmanCodec<uint64_t>(7, {
+ {0, 0, 0},
+ {2855506940, 0, 0},
+ {3266548732, 0, 0},
+ {3732640764, 0, 0},
+ {1111111111111111111, 0, 0},
+ {0, 2, 1},
+ {0, 5, 4},
+ {0, 3, 6},
+ }));
+
+ codecs.emplace(std::pair<uint32_t, uint32_t>(SpvOpImageSampleImplicitLod, 5), std::move(codec));
+ }
+
+ {
+ std::unique_ptr<HuffmanCodec<uint64_t>> codec(new HuffmanCodec<uint64_t>(9, {
+ {0, 0, 0},
+ {679771963, 0, 0},
+ {1951208733, 0, 0},
+ {2320303498, 0, 0},
+ {3334207724, 0, 0},
+ {1111111111111111111, 0, 0},
+ {0, 4, 5},
+ {0, 2, 6},
+ {0, 1, 3},
+ {0, 8, 7},
+ }));
+
+ codecs.emplace(std::pair<uint32_t, uint32_t>(SpvOpFAdd, 0), std::move(codec));
+ }
+
+ {
+ std::unique_ptr<HuffmanCodec<uint64_t>> codec(new HuffmanCodec<uint64_t>(1, {
+ {0, 0, 0},
+ {1111111111111111111, 0, 0},
+ }));
+
+ codecs.emplace(std::pair<uint32_t, uint32_t>(SpvOpFAdd, 1), std::move(codec));
+ }
+
+ {
+ std::unique_ptr<HuffmanCodec<uint64_t>> codec(new HuffmanCodec<uint64_t>(11, {
+ {0, 0, 0},
+ {296981500, 0, 0},
+ {959681532, 0, 0},
+ {1570165302, 0, 0},
+ {2096388952, 0, 0},
+ {3653838348, 0, 0},
+ {1111111111111111111, 0, 0},
+ {0, 1, 5},
+ {0, 3, 2},
+ {0, 8, 7},
+ {0, 9, 4},
+ {0, 6, 10},
+ }));
+
+ codecs.emplace(std::pair<uint32_t, uint32_t>(SpvOpFAdd, 2), std::move(codec));
+ }
+
+ {
+ std::unique_ptr<HuffmanCodec<uint64_t>> codec(new HuffmanCodec<uint64_t>(11, {
+ {0, 0, 0},
+ {643418617, 0, 0},
+ {959681532, 0, 0},
+ {1092948665, 0, 0},
+ {2517964682, 0, 0},
+ {2683080096, 0, 0},
+ {1111111111111111111, 0, 0},
+ {0, 5, 3},
+ {0, 4, 1},
+ {0, 8, 7},
+ {0, 9, 2},
+ {0, 6, 10},
+ }));
+
+ codecs.emplace(std::pair<uint32_t, uint32_t>(SpvOpFAdd, 3), std::move(codec));
+ }
+
+ {
+ std::unique_ptr<HuffmanCodec<uint64_t>> codec(new HuffmanCodec<uint64_t>(9, {
+ {0, 0, 0},
+ {679771963, 0, 0},
+ {1951208733, 0, 0},
+ {2320303498, 0, 0},
+ {3334207724, 0, 0},
+ {1111111111111111111, 0, 0},
+ {0, 3, 5},
+ {0, 4, 6},
+ {0, 1, 7},
+ {0, 2, 8},
+ }));
+
+ codecs.emplace(std::pair<uint32_t, uint32_t>(SpvOpFSub, 0), std::move(codec));
+ }
+
+ {
+ std::unique_ptr<HuffmanCodec<uint64_t>> codec(new HuffmanCodec<uint64_t>(17, {
+ {0, 0, 0},
+ {615982737, 0, 0},
+ {1139547465, 0, 0},
+ {1178317551, 0, 0},
+ {2330636993, 0, 0},
+ {2589449658, 0, 0},
+ {3579593979, 0, 0},
+ {3730093054, 0, 0},
+ {3944781937, 0, 0},
+ {1111111111111111111, 0, 0},
+ {0, 3, 6},
+ {0, 5, 7},
+ {0, 8, 1},
+ {0, 10, 4},
+ {0, 11, 2},
+ {0, 13, 12},
+ {0, 15, 14},
+ {0, 9, 16},
+ }));
+
+ codecs.emplace(std::pair<uint32_t, uint32_t>(SpvOpFSub, 1), std::move(codec));
+ }
+
+ {
+ std::unique_ptr<HuffmanCodec<uint64_t>> codec(new HuffmanCodec<uint64_t>(23, {
+ {0, 0, 0},
+ {249378857, 0, 0},
+ {296981500, 0, 0},
+ {1203545131, 0, 0},
+ {1265796414, 0, 0},
+ {1319785741, 0, 0},
+ {2855506940, 0, 0},
+ {3091876332, 0, 0},
+ {3187066832, 0, 0},
+ {3508792859, 0, 0},
+ {3619787319, 0, 0},
+ {3653838348, 0, 0},
+ {1111111111111111111, 0, 0},
+ {0, 5, 9},
+ {0, 4, 1},
+ {0, 7, 10},
+ {0, 13, 8},
+ {0, 3, 14},
+ {0, 6, 15},
+ {0, 11, 16},
+ {0, 18, 17},
+ {0, 20, 19},
+ {0, 21, 2},
+ {0, 22, 12},
+ }));
+
+ codecs.emplace(std::pair<uint32_t, uint32_t>(SpvOpFSub, 2), std::move(codec));
+ }
+
+ {
+ std::unique_ptr<HuffmanCodec<uint64_t>> codec(new HuffmanCodec<uint64_t>(33, {
+ {0, 0, 0},
+ {296981500, 0, 0},
+ {443558693, 0, 0},
+ {1203545131, 0, 0},
+ {1265796414, 0, 0},
+ {1319785741, 0, 0},
+ {1558001705, 0, 0},
+ {1955104493, 0, 0},
+ {2234361374, 0, 0},
+ {2598189097, 0, 0},
+ {2775815164, 0, 0},
+ {3244209297, 0, 0},
+ {3753486980, 0, 0},
+ {3886529747, 0, 0},
+ {4069810315, 0, 0},
+ {4164704452, 0, 0},
+ {4273793488, 0, 0},
+ {1111111111111111111, 0, 0},
+ {0, 10, 7},
+ {0, 15, 13},
+ {0, 8, 16},
+ {0, 6, 2},
+ {0, 3, 9},
+ {0, 14, 5},
+ {0, 11, 18},
+ {0, 20, 19},
+ {0, 22, 21},
+ {0, 23, 12},
+ {0, 24, 1},
+ {0, 25, 4},
+ {0, 27, 26},
+ {0, 29, 28},
+ {0, 31, 30},
+ {0, 17, 32},
+ }));
+
+ codecs.emplace(std::pair<uint32_t, uint32_t>(SpvOpFSub, 3), std::move(codec));
+ }
+
+ {
+ std::unique_ptr<HuffmanCodec<uint64_t>> codec(new HuffmanCodec<uint64_t>(9, {
+ {0, 0, 0},
+ {679771963, 0, 0},
+ {1951208733, 0, 0},
+ {2320303498, 0, 0},
+ {3334207724, 0, 0},
+ {1111111111111111111, 0, 0},
+ {0, 4, 5},
+ {0, 3, 6},
+ {0, 1, 7},
+ {0, 8, 2},
+ }));
+
+ codecs.emplace(std::pair<uint32_t, uint32_t>(SpvOpFMul, 0), std::move(codec));
+ }
+
+ {
+ std::unique_ptr<HuffmanCodec<uint64_t>> codec(new HuffmanCodec<uint64_t>(1, {
+ {0, 0, 0},
+ {1111111111111111111, 0, 0},
+ }));
+
+ codecs.emplace(std::pair<uint32_t, uint32_t>(SpvOpFMul, 1), std::move(codec));
+ }
+
+ {
+ std::unique_ptr<HuffmanCodec<uint64_t>> codec(new HuffmanCodec<uint64_t>(15, {
+ {0, 0, 0},
+ {810488476, 0, 0},
+ {1054461787, 0, 0},
+ {1158929937, 0, 0},
+ {1203545131, 0, 0},
+ {2096388952, 0, 0},
+ {3929248764, 0, 0},
+ {4008405264, 0, 0},
+ {1111111111111111111, 0, 0},
+ {0, 3, 2},
+ {0, 7, 6},
+ {0, 1, 4},
+ {0, 5, 9},
+ {0, 11, 10},
+ {0, 13, 12},
+ {0, 8, 14},
+ }));
+
+ codecs.emplace(std::pair<uint32_t, uint32_t>(SpvOpFMul, 2), std::move(codec));
+ }
+
+ {
+ std::unique_ptr<HuffmanCodec<uint64_t>> codec(new HuffmanCodec<uint64_t>(13, {
+ {0, 0, 0},
+ {171307615, 0, 0},
+ {593829839, 0, 0},
+ {959681532, 0, 0},
+ {1684282922, 0, 0},
+ {1811839150, 0, 0},
+ {3929248764, 0, 0},
+ {1111111111111111111, 0, 0},
+ {0, 5, 1},
+ {0, 6, 3},
+ {0, 4, 2},
+ {0, 9, 8},
+ {0, 11, 10},
+ {0, 7, 12},
+ }));
+
+ codecs.emplace(std::pair<uint32_t, uint32_t>(SpvOpFMul, 3), std::move(codec));
+ }
+
+ {
+ std::unique_ptr<HuffmanCodec<uint64_t>> codec(new HuffmanCodec<uint64_t>(7, {
+ {0, 0, 0},
+ {679771963, 0, 0},
+ {2320303498, 0, 0},
+ {3334207724, 0, 0},
+ {1111111111111111111, 0, 0},
+ {0, 3, 4},
+ {0, 2, 5},
+ {0, 1, 6},
+ }));
+
+ codecs.emplace(std::pair<uint32_t, uint32_t>(SpvOpVectorTimesScalar, 0), std::move(codec));
+ }
+
+ {
+ std::unique_ptr<HuffmanCodec<uint64_t>> codec(new HuffmanCodec<uint64_t>(11, {
+ {0, 0, 0},
+ {2504802016, 0, 0},
+ {3032677281, 0, 0},
+ {3560552546, 0, 0},
+ {3797961332, 0, 0},
+ {3886529747, 0, 0},
+ {1111111111111111111, 0, 0},
+ {0, 2, 1},
+ {0, 4, 3},
+ {0, 7, 5},
+ {0, 9, 8},
+ {0, 6, 10},
+ }));
+
+ codecs.emplace(std::pair<uint32_t, uint32_t>(SpvOpVectorTimesScalar, 1), std::move(codec));
+ }
+
+ {
+ std::unique_ptr<HuffmanCodec<uint64_t>> codec(new HuffmanCodec<uint64_t>(35, {
+ {0, 0, 0},
+ {354479447, 0, 0},
+ {1325348861, 0, 0},
+ {1367301635, 0, 0},
+ {1368383673, 0, 0},
+ {1646147798, 0, 0},
+ {1679946323, 0, 0},
+ {1766401548, 0, 0},
+ {2096388952, 0, 0},
+ {2123388694, 0, 0},
+ {2362972044, 0, 0},
+ {2660843182, 0, 0},
+ {2698156268, 0, 0},
+ {2970183398, 0, 0},
+ {3133016299, 0, 0},
+ {3187066832, 0, 0},
+ {3882634684, 0, 0},
+ {4243119782, 0, 0},
+ {1111111111111111111, 0, 0},
+ {0, 2, 11},
+ {0, 6, 5},
+ {0, 12, 9},
+ {0, 16, 14},
+ {0, 4, 17},
+ {0, 10, 7},
+ {0, 3, 1},
+ {0, 19, 13},
+ {0, 21, 20},
+ {0, 23, 22},
+ {0, 25, 24},
+ {0, 27, 26},
+ {0, 29, 28},
+ {0, 8, 15},
+ {0, 31, 30},
+ {0, 33, 32},
+ {0, 18, 34},
+ }));
+
+ codecs.emplace(std::pair<uint32_t, uint32_t>(SpvOpVectorTimesScalar, 2), std::move(codec));
+ }
+
+ {
+ std::unique_ptr<HuffmanCodec<uint64_t>> codec(new HuffmanCodec<uint64_t>(37, {
+ {0, 0, 0},
+ {810488476, 0, 0},
+ {959681532, 0, 0},
+ {1232501371, 0, 0},
+ {1372785527, 0, 0},
+ {1526654696, 0, 0},
+ {1684282922, 0, 0},
+ {1901166356, 0, 0},
+ {2244928358, 0, 0},
+ {2314864456, 0, 0},
+ {2524697596, 0, 0},
+ {2568098594, 0, 0},
+ {3117071189, 0, 0},
+ {3188115516, 0, 0},
+ {3554463148, 0, 0},
+ {3691770462, 0, 0},
+ {3929248764, 0, 0},
+ {4060703604, 0, 0},
+ {4092487128, 0, 0},
+ {1111111111111111111, 0, 0},
+ {0, 4, 7},
+ {0, 12, 8},
+ {0, 17, 13},
+ {0, 15, 18},
+ {0, 14, 10},
+ {0, 9, 5},
+ {0, 2, 1},
+ {0, 20, 6},
+ {0, 22, 21},
+ {0, 3, 23},
+ {0, 11, 24},
+ {0, 26, 25},
+ {0, 28, 27},
+ {0, 30, 29},
+ {0, 32, 31},
+ {0, 33, 16},
+ {0, 35, 34},
+ {0, 19, 36},
+ }));
+
+ codecs.emplace(std::pair<uint32_t, uint32_t>(SpvOpVectorTimesScalar, 3), std::move(codec));
+ }
+
+ {
+ std::unique_ptr<HuffmanCodec<uint64_t>> codec(new HuffmanCodec<uint64_t>(3, {
+ {0, 0, 0},
+ {1951208733, 0, 0},
+ {1111111111111111111, 0, 0},
+ {0, 1, 2},
+ }));
+
+ codecs.emplace(std::pair<uint32_t, uint32_t>(SpvOpDot, 0), std::move(codec));
+ }
+
+ {
+ std::unique_ptr<HuffmanCodec<uint64_t>> codec(new HuffmanCodec<uint64_t>(15, {
+ {0, 0, 0},
+ {170690025, 0, 0},
+ {669982125, 0, 0},
+ {1625742020, 0, 0},
+ {2071351379, 0, 0},
+ {2291766425, 0, 0},
+ {3104643263, 0, 0},
+ {3602108619, 0, 0},
+ {1111111111111111111, 0, 0},
+ {0, 5, 1},
+ {0, 6, 7},
+ {0, 2, 3},
+ {0, 9, 4},
+ {0, 11, 10},
+ {0, 13, 12},
+ {0, 8, 14},
+ }));
+
+ codecs.emplace(std::pair<uint32_t, uint32_t>(SpvOpDot, 1), std::move(codec));
+ }
+
+ {
+ std::unique_ptr<HuffmanCodec<uint64_t>> codec(new HuffmanCodec<uint64_t>(45, {
+ {0, 0, 0},
+ {50385656, 0, 0},
+ {615982737, 0, 0},
+ {837715723, 0, 0},
+ {1237148906, 0, 0},
+ {1364157225, 0, 0},
+ {1499923635, 0, 0},
+ {1766401548, 0, 0},
+ {2012838864, 0, 0},
+ {2096388952, 0, 0},
+ {2161102232, 0, 0},
+ {2197874825, 0, 0},
+ {2279700640, 0, 0},
+ {2362972044, 0, 0},
+ {2589449658, 0, 0},
+ {2881302403, 0, 0},
+ {2936040203, 0, 0},
+ {2970183398, 0, 0},
+ {3187066832, 0, 0},
+ {3362830643, 0, 0},
+ {3538158875, 0, 0},
+ {3635542517, 0, 0},
+ {3997432565, 0, 0},
+ {1111111111111111111, 0, 0},
+ {0, 19, 10},
+ {0, 3, 1},
+ {0, 5, 6},
+ {0, 20, 2},
+ {0, 4, 22},
+ {0, 25, 24},
+ {0, 26, 12},
+ {0, 16, 15},
+ {0, 17, 9},
+ {0, 14, 13},
+ {0, 27, 21},
+ {0, 7, 18},
+ {0, 8, 28},
+ {0, 11, 29},
+ {0, 31, 30},
+ {0, 33, 32},
+ {0, 35, 34},
+ {0, 37, 36},
+ {0, 39, 38},
+ {0, 41, 40},
+ {0, 43, 42},
+ {0, 23, 44},
+ }));
+
+ codecs.emplace(std::pair<uint32_t, uint32_t>(SpvOpDot, 2), std::move(codec));
+ }
+
+ {
+ std::unique_ptr<HuffmanCodec<uint64_t>> codec(new HuffmanCodec<uint64_t>(41, {
+ {0, 0, 0},
+ {139011596, 0, 0},
+ {342159236, 0, 0},
+ {837715723, 0, 0},
+ {876867882, 0, 0},
+ {1356063462, 0, 0},
+ {1766401548, 0, 0},
+ {2096388952, 0, 0},
+ {2197874825, 0, 0},
+ {2362972044, 0, 0},
+ {2517964682, 0, 0},
+ {2589449658, 0, 0},
+ {2683080096, 0, 0},
+ {2919626325, 0, 0},
+ {2936040203, 0, 0},
+ {2970183398, 0, 0},
+ {2996594997, 0, 0},
+ {3187066832, 0, 0},
+ {3913885196, 0, 0},
+ {3997432565, 0, 0},
+ {4010499223, 0, 0},
+ {1111111111111111111, 0, 0},
+ {0, 2, 3},
+ {0, 5, 4},
+ {0, 20, 16},
+ {0, 19, 1},
+ {0, 11, 9},
+ {0, 14, 13},
+ {0, 22, 17},
+ {0, 23, 12},
+ {0, 15, 24},
+ {0, 8, 7},
+ {0, 26, 25},
+ {0, 6, 27},
+ {0, 28, 18},
+ {0, 30, 29},
+ {0, 32, 31},
+ {0, 34, 33},
+ {0, 36, 35},
+ {0, 37, 10},
+ {0, 39, 38},
+ {0, 21, 40},
+ }));
+
+ codecs.emplace(std::pair<uint32_t, uint32_t>(SpvOpDot, 3), std::move(codec));
+ }
+
+ {
+ std::unique_ptr<HuffmanCodec<uint64_t>> codec(new HuffmanCodec<uint64_t>(3, {
+ {0, 0, 0},
+ {1036475267, 0, 0},
+ {1111111111111111111, 0, 0},
+ {0, 1, 2},
+ }));
+
+ codecs.emplace(std::pair<uint32_t, uint32_t>(SpvOpLabel, 0), std::move(codec));
+ }
+
+ return codecs;
+}
#include <cstring>
#include <functional>
#include <iostream>
+#include <iterator>
#include <list>
#include <memory>
#include <numeric>
#include <string>
#include <vector>
+#include "spirv/1.2/GLSL.std.450.h"
+#include "spirv/1.2/OpenCL.std.h"
+#include "spirv/1.2/spirv.h"
+
#include "binary.h"
#include "diagnostic.h"
#include "enum_string_mapping.h"
#include "extensions.h"
#include "ext_inst.h"
+#include "id_descriptor.h"
#include "instruction.h"
+#include "markv_autogen.h"
#include "opcode.h"
#include "operand.h"
#include "spirv-tools/libspirv.h"
#include "spirv_endian.h"
#include "spirv_validator_options.h"
#include "util/bit_stream.h"
+#include "util/huffman_codec.h"
+#include "util/move_to_front.h"
#include "util/parse_number.h"
#include "validate.h"
#include "val/instruction.h"
#include "val/validation_state.h"
+using libspirv::IdDescriptorCollection;
using libspirv::Instruction;
using libspirv::ValidationState_t;
using spvtools::ValidateInstructionAndUpdateValidationState;
using spvutils::BitReaderWord64;
using spvutils::BitWriterWord64;
+using spvutils::HuffmanCodec;
+using MoveToFront = spvutils::MoveToFront<uint32_t>;
+using MultiMoveToFront = spvutils::MultiMoveToFront<uint32_t>;
struct spv_markv_encoder_options_t {
};
const uint32_t kSpirvMagicNumber = SpvMagicNumber;
const uint32_t kMarkvMagicNumber = 0x07230303;
-enum {
- kMarkvFirstOpcode = 65536,
- kMarkvOpNextInstructionEncodesResultId = 65536,
+// Handles for move-to-front sequences. Enums which end with "Begin" define
+// handle spaces which start at that value and span 16 or 32 bit wide.
+enum : uint64_t {
+ kMtfNone = 0,
+ // All ids.
+ kMtfAll,
+ // All forward declared ids.
+ kMtfForwardDeclared,
+ // All type ids except for generated by OpTypeFunction.
+ kMtfTypeNonFunction,
+ // All labels.
+ kMtfLabel,
+ // All ids created by instructions which had type_id.
+ kMtfObject,
+ // All types generated by OpTypeFloat, OpTypeInt, OpTypeBool.
+ kMtfTypeScalar,
+ // All composite types.
+ kMtfTypeComposite,
+ // Boolean type or any vector type of it.
+ kMtfTypeBoolScalarOrVector,
+ // All float types or any vector floats type.
+ kMtfTypeFloatScalarOrVector,
+ // All int types or any vector int type.
+ kMtfTypeIntScalarOrVector,
+ // All types declared as return types in OpTypeFunction.
+ kMtfTypeReturnedByFunction,
+ // All object ids which are integer constants.
+ kMtfConstInteger,
+ // All composite objects.
+ kMtfComposite,
+ // All bool objects or vectors of bools.
+ kMtfBoolScalarOrVector,
+ // All float objects or vectors of float.
+ kMtfFloatScalarOrVector,
+ // All int objects or vectors of int.
+ kMtfIntScalarOrVector,
+ // All pointer types which point to composited.
+ kMtfTypePointerToComposite,
+ // Used by EncodeMtfRankHuffman.
+ kMtfGenericNonZeroRank,
+ // Handle space for ids of specific type.
+ kMtfIdOfTypeBegin = 0x10000,
+ // Handle space for ids generated by specific opcode.
+ kMtfIdGeneratedByOpcode = 0x20000,
+ // Handle space for ids of objects with type generated by specific opcode.
+ kMtfIdWithTypeGeneratedByOpcodeBegin = 0x30000,
+ // All vectors of specific component type.
+ kMtfVectorOfComponentTypeBegin = 0x40000,
+ // All vector types of specific size.
+ kMtfTypeVectorOfSizeBegin = 0x50000,
+ // All pointer types to specific type.
+ kMtfPointerToTypeBegin = 0x60000,
+ // All function types which return specific type.
+ kMtfFunctionTypeWithReturnTypeBegin = 0x70000,
+ // All function objects which return specific type.
+ kMtfFunctionWithReturnTypeBegin = 0x80000,
+ // All float vectors of specific size.
+ kMtfFloatVectorOfSizeBegin = 0x90000,
+ // Id descriptor space (32-bit).
+ kMtfIdDescriptorSpaceBegin = 0x100000000,
};
+// Used by "presumed index" technique which does special treatment of integer
+// constants no greater than this value.
+const uint32_t kMarkvMaxPresumedAccessIndex = 31;
+
+// Signals that the value is not in the coding scheme and a fallback method
+// needs to be used.
+const uint64_t kMarkvNoneOfTheAbove = GetMarkvNonOfTheAbove();
+
+// Mtf ranks smaller than this are encoded with Huffman coding.
+const uint32_t kMtfSmallestRankEncodedByValue = 10;
+
+// Signals that the mtf rank is too large to be encoded with Huffman.
+const uint32_t kMtfRankEncodedByValueSignal =
+ std::numeric_limits<uint32_t>::max();
+
const size_t kCommentNumWhitespaces = 2;
-// TODO(atgoo@github.com): This is a placeholder for an autogenerated flatbuffer
-// containing MARK-V model for a specific dataset.
+const size_t kByteBreakAfterInstIfLessThanUntilNextByte = 8;
+
+// Returns a set of mtf rank codecs based on a plausible hand-coded
+// distribution.
+std::map<uint64_t, std::unique_ptr<HuffmanCodec<uint32_t>>>
+GetMtfHuffmanCodecs() {
+ std::map<uint64_t, std::unique_ptr<HuffmanCodec<uint32_t>>> codecs;
+
+ std::unique_ptr<HuffmanCodec<uint32_t>> codec;
+
+ codec.reset(new HuffmanCodec<uint32_t>(std::map<uint32_t, uint32_t>({
+ { 0, 5 },
+ { 1, 40 },
+ { 2, 10 },
+ { 3, 5 },
+ { 4, 5 },
+ { 5, 5 },
+ { 6, 3 },
+ { 7, 3 },
+ { 8, 3 },
+ { 9, 3 },
+ { kMtfRankEncodedByValueSignal, 10 },
+ })));
+ codecs.emplace(kMtfAll, std::move(codec));
+
+ codec.reset(new HuffmanCodec<uint32_t>(std::map<uint32_t, uint32_t>({
+ { 1, 50 },
+ { 2, 20 },
+ { 3, 5 },
+ { 4, 5 },
+ { 5, 2 },
+ { 6, 1 },
+ { 7, 1 },
+ { 8, 1 },
+ { 9, 1 },
+ { kMtfRankEncodedByValueSignal, 10 },
+ })));
+ codecs.emplace(kMtfGenericNonZeroRank, std::move(codec));
+
+ return codecs;
+}
+
+// Encoding/decoding model containing various constants and codecs.
class MarkvModel {
public:
+ MarkvModel()
+ : mtf_huffman_codecs_(GetMtfHuffmanCodecs()),
+ opcode_and_num_operands_huffman_codec_(GetOpcodeAndNumOperandsHist()),
+ opcode_and_num_operands_markov_huffman_codecs_(
+ GetOpcodeAndNumOperandsMarkovHuffmanCodecs()),
+ non_id_word_huffman_codecs_(GetNonIdWordHuffmanCodecs()),
+ id_descriptor_huffman_codecs_(GetIdDescriptorHuffmanCodecs()),
+ literal_string_huffman_codecs_(GetLiteralStringHuffmanCodecs()) {}
+
size_t opcode_chunk_length() const { return 7; }
size_t num_operands_chunk_length() const { return 3; }
- size_t id_index_chunk_length() const { return 3; }
+ size_t mtf_rank_chunk_length() const { return 5; }
size_t u16_chunk_length() const { return 4; }
size_t s16_chunk_length() const { return 4; }
size_t u64_chunk_length() const { return 8; }
size_t s64_chunk_length() const { return 8; }
size_t s64_block_exponent() const { return 10; }
+
+ // Returns Huffman codec for ranks of the mtf with given |handle|.
+ // Different mtfs can use different rank distributions.
+ // May return nullptr if the codec doesn't exist.
+ const HuffmanCodec<uint32_t>* GetMtfHuffmanCodec(uint64_t handle) const {
+ const auto it = mtf_huffman_codecs_.find(handle);
+ if (it == mtf_huffman_codecs_.end())
+ return nullptr;
+ return it->second.get();
+ }
+
+ // Returns a codec for common opcode_and_num_operands words for the given
+ // previous opcode. May return nullptr if the codec doesn't exist.
+ const HuffmanCodec<uint64_t>* GetOpcodeAndNumOperandsMarkovHuffmanCodec(
+ uint32_t prev_opcode) const {
+ if (prev_opcode == SpvOpNop)
+ return &opcode_and_num_operands_huffman_codec_;
+
+ const auto it =
+ opcode_and_num_operands_markov_huffman_codecs_.find(prev_opcode);
+ if (it == opcode_and_num_operands_markov_huffman_codecs_.end())
+ return nullptr;
+ return it->second.get();
+ }
+
+ // Returns a codec for common non-id words used for given operand slot.
+ // Operand slot is defined by the opcode and the operand index.
+ // May return nullptr if the codec doesn't exist.
+ const HuffmanCodec<uint64_t>* GetNonIdWordHuffmanCodec(
+ uint32_t opcode, uint32_t operand_index) const {
+ const auto it = non_id_word_huffman_codecs_.find(
+ std::pair<uint32_t, uint32_t>(opcode, operand_index));
+ if (it == non_id_word_huffman_codecs_.end())
+ return nullptr;
+ return it->second.get();
+ }
+
+ // Returns a codec for common id descriptos used for given operand slot.
+ // Operand slot is defined by the opcode and the operand index.
+ // May return nullptr if the codec doesn't exist.
+ const HuffmanCodec<uint64_t>* GetIdDescriptorHuffmanCodec(
+ uint32_t opcode, uint32_t operand_index) const {
+ const auto it = id_descriptor_huffman_codecs_.find(
+ std::pair<uint32_t, uint32_t>(opcode, operand_index));
+ if (it == id_descriptor_huffman_codecs_.end())
+ return nullptr;
+ return it->second.get();
+ }
+
+ // Returns a codec for common strings used by the given opcode.
+ // Operand slot is defined by the opcode and the operand index.
+ // May return nullptr if the codec doesn't exist.
+ const HuffmanCodec<std::string>* GetLiteralStringHuffmanCodec(
+ uint32_t opcode) const {
+ const auto it = literal_string_huffman_codecs_.find(opcode);
+ if (it == literal_string_huffman_codecs_.end())
+ return nullptr;
+ return it->second.get();
+ }
+
+ private:
+ // Huffman codecs for move-to-front ranks. The map key is mtf handle. Doesn't
+ // need to contain a different codec for every handle as most use one and the
+ // same.
+ std::map<uint64_t, std::unique_ptr<HuffmanCodec<uint32_t>>>
+ mtf_huffman_codecs_;
+
+ // Huffman codec for base-rate of opcode_and_num_operands.
+ HuffmanCodec<uint64_t> opcode_and_num_operands_huffman_codec_;
+
+ // Huffman codecs for opcode_and_num_operands. The map key is previous opcode.
+ std::map<uint32_t, std::unique_ptr<HuffmanCodec<uint64_t>>>
+ opcode_and_num_operands_markov_huffman_codecs_;
+
+ // Huffman codecs for non-id single-word operand values.
+ // The map key is pair <opcode, operand_index>.
+ std::map<std::pair<uint32_t, uint32_t>,
+ std::unique_ptr<HuffmanCodec<uint64_t>>>
+ non_id_word_huffman_codecs_;
+
+ // Huffman codecs for id descriptors. The map key is pair
+ // <opcode, operand_index>.
+ std::map<std::pair<uint32_t, uint32_t>,
+ std::unique_ptr<HuffmanCodec<uint64_t>>>
+ id_descriptor_huffman_codecs_;
+
+ // Huffman codecs for literal strings. The map key is the opcode of the
+ // current instruction. This assumes, that there is no more than one literal
+ // string operand per instruction, but would still work even if this is not
+ // the case. Names and debug information strings are not collected.
+ std::map<uint32_t, std::unique_ptr<HuffmanCodec<std::string>>>
+ literal_string_huffman_codecs_;
};
const MarkvModel* GetDefaultModel() {
case SPV_OPERAND_TYPE_SELECTION_CONTROL:
return 4;
case SPV_OPERAND_TYPE_EXTENSION_INSTRUCTION_NUMBER:
+ case SPV_OPERAND_TYPE_TYPED_LITERAL_NUMBER:
return 6;
default:
return 0;
return (8 - (bit_pos % 8)) % 8;
}
-bool ShouldByteBreak(size_t bit_pos) {
- const size_t num_bits_to_next_byte = GetNumBitsToNextByte(bit_pos);
- return num_bits_to_next_byte > 0; // && num_bits_to_next_byte <= 2;
-}
-
// Defines and returns current MARK-V version.
uint32_t GetMarkvVersion() {
const uint32_t kVersionMajor = 1;
- const uint32_t kVersionMinor = 0;
+ const uint32_t kVersionMinor = 1;
return kVersionMinor | (kVersionMajor << 16);
}
return ValidateInstructionAndUpdateValidationState(&vstate_, &inst);
}
- // Returns the current instruction (the one last processed by the validator).
- const Instruction& GetCurrentInstruction() const {
- return vstate_.ordered_instructions().back();
+ // Returns instruction which created |id| or nullptr if such instruction was
+ // not registered.
+ const Instruction* GetDefInst(uint32_t id) const {
+ const auto it = vstate_.all_definitions().find(id);
+ if (it == vstate_.all_definitions().end())
+ return nullptr;
+ return it->second;
+ }
+
+ // Returns type id of vector type component.
+ uint32_t GetVectorComponentType(uint32_t vector_type_id) const {
+ const auto it = vstate_.all_definitions().find(vector_type_id);
+ assert(it != vstate_.all_definitions().end());
+ const Instruction* type_inst = it->second;
+ assert(type_inst->opcode() == SpvOpTypeVector);
+
+ const uint32_t component_type =
+ type_inst->word(type_inst->operands()[1].offset);
+ return component_type;
+ }
+
+ // Returns mtf handle for ids of given type.
+ uint64_t GetMtfIdOfType(uint32_t type_id) const {
+ return kMtfIdOfTypeBegin + type_id;
+ }
+
+ // Returns mtf handle for ids generated by given opcode.
+ uint64_t GetMtfIdGeneratedByOpcode(SpvOp opcode) const {
+ return kMtfIdGeneratedByOpcode + opcode;
+ }
+
+ // Returns mtf handle for ids of type generated by given opcode.
+ uint64_t GetMtfIdWithTypeGeneratedByOpcode(SpvOp opcode) const {
+ return kMtfIdWithTypeGeneratedByOpcodeBegin + opcode;
}
- spv_validator_options validator_options_;
+ // Returns mtf handle for vectors of specific component type.
+ uint64_t GetMtfVectorOfComponentType(uint32_t type_id) const {
+ return kMtfVectorOfComponentTypeBegin + type_id;
+ }
+
+ // Returns mtf handle for float vectors of specific size.
+ uint64_t GetMtfFloatVectorOfSize(uint32_t size) const {
+ return kMtfFloatVectorOfSizeBegin + size;
+ }
+
+ // Returns mtf handle for vector type of specific size.
+ uint64_t GetMtfTypeVectorOfSize(uint32_t size) const {
+ return kMtfTypeVectorOfSizeBegin + size;
+ }
+
+ // Returns mtf handle for pointers to specific size.
+ uint64_t GetMtfPointerToType(uint32_t type_id) const {
+ return kMtfPointerToTypeBegin + type_id;
+ }
+
+ // Returns mtf handle for function types with given return type.
+ uint64_t GetMtfFunctionTypeWithReturnType(uint32_t type_id) const {
+ return kMtfFunctionTypeWithReturnTypeBegin + type_id;
+ }
+
+ // Returns mtf handle for functions with given return type.
+ uint64_t GetMtfFunctionWithReturnType(uint32_t type_id) const {
+ return kMtfFunctionWithReturnTypeBegin + type_id;
+ }
+
+ // Returns mtf handle for the given id descriptor.
+ uint64_t GetMtfIdDescriptor(uint32_t descriptor) const {
+ return kMtfIdDescriptorSpaceBegin + descriptor;
+ }
+
+ // Process data from the current instruction. This would update MTFs and
+ // other data containers.
+ void ProcessCurInstruction();
+
+ // Returns move-to-front handle to be used for the current operand slot.
+ // Mtf handle is chosen based on a set of rules defined by SPIR-V grammar.
+ uint64_t GetRuleBasedMtf();
+
+ // Returns words of the current instruction. Decoder has a different
+ // implementation and the array is valid only until the previously decoded
+ // word.
+ virtual const uint32_t* GetInstWords() const {
+ return inst_.words;
+ }
+
+ // Returns the opcode of the previous instruction.
+ SpvOp GetPrevOpcode() const {
+ if (instructions_.empty())
+ return SpvOpNop;
+
+ return instructions_.back()->opcode();
+ }
+
+ spv_validator_options validator_options_ = nullptr;
ValidationState_t vstate_;
const libspirv::AssemblyGrammar grammar_;
MarkvHeader header_;
- const MarkvModel* model_;
+ const MarkvModel* model_ = nullptr;
+
+ // Current instruction, current operand and current operand index.
+ spv_parsed_instruction_t inst_;
+ spv_parsed_operand_t operand_;
+ uint32_t operand_index_;
+
+ // Maps a result ID to its type ID. By convention:
+ // - a result ID that is a type definition maps to itself.
+ // - a result ID without a type maps to 0. (E.g. for OpLabel)
+ std::unordered_map<uint32_t, uint32_t> id_to_type_id_;
+
+ // Container for all move-to-front sequences.
+ MultiMoveToFront multi_mtf_;
+
+ // Id of the current function or zero if outside of function.
+ uint32_t cur_function_id_ = 0;
+
+ // Return type of the current function.
+ uint32_t cur_function_return_type_ = 0;
+
+ // Remaining function parameter types. This container is filled on OpFunction,
+ // and drained on OpFunctionParameter.
+ std::list<uint32_t> remaining_function_parameter_types_;
+
+ // List of ids local to the current function.
+ std::vector<uint32_t> ids_local_to_cur_function_;
- // Move-to-front list of all ids.
- // TODO(atgoo@github.com) Consider a better move-to-front implementation.
- std::list<uint32_t> move_to_front_ids_;
+ // List of instructions in the order they are given in the module.
+ std::vector<const Instruction*> instructions_;
+
+ // Maps used for the 'presumed id' techniques. Maps small constant integer
+ // value to its id and back.
+ std::map<uint32_t, uint32_t> presumed_index_to_id_;
+ std::map<uint32_t, uint32_t> id_to_presumed_index_;
+
+ // Container/computer for id descriptors.
+ IdDescriptorCollection id_descriptors_;
};
// SPIR-V to MARK-V encoder. Exposes functions EncodeHeader and
assert(writer_.GetData());
std::memcpy(markv_binary->data, &header_, sizeof(header_));
std::memcpy(markv_binary->data + sizeof(header_),
- writer_.GetData(), writer_.GetDataSizeBytes());
+ writer_.GetData(), writer_.GetDataSizeBytes());
return markv_binary;
}
return spvValidatorOptionsCreate();
}
- // Writes a single word to bit stream. |type| determines if the word is
+ // Writes a single word to bit stream. operand_.type determines if the word is
// encoded and how.
- void EncodeOperandWord(spv_operand_type_t type, uint32_t word) {
- const size_t chunk_length =
- GetOperandVariableWidthChunkLength(type);
- if (chunk_length) {
- writer_.WriteVariableWidthU32(word, chunk_length);
- } else {
- writer_.WriteUnencoded(word);
- }
- }
+ spv_result_t EncodeNonIdWord(uint32_t word);
- // Returns id index and updates move-to-front.
- // Index is uint16 as SPIR-V module is guaranteed to have no more than 65535
- // instructions.
- uint16_t GetIdIndex(uint32_t id) {
- if (all_known_ids_.count(id)) {
- uint16_t index = 0;
- for (auto it = move_to_front_ids_.begin();
- it != move_to_front_ids_.end(); ++it) {
- if (*it == id) {
- if (index != 0) {
- move_to_front_ids_.erase(it);
- move_to_front_ids_.push_front(id);
- }
- return index;
- }
- ++index;
- }
- assert(0 && "Id not found in move_to_front_ids_");
- return 0;
- } else {
- all_known_ids_.insert(id);
- move_to_front_ids_.push_front(id);
- return static_cast<uint16_t>(move_to_front_ids_.size() - 1);
- }
- }
+ // Writes both opcode and num_operands as a single code.
+ // Returns SPV_UNSUPPORTED iff no suitable codec was found.
+ spv_result_t EncodeOpcodeAndNumOperands(uint32_t opcode, uint32_t num_operands);
- void AddByteBreakIfAgreed() {
- if (!ShouldByteBreak(writer_.GetNumBits()))
- return;
+ // Writes mtf rank to bit stream. |mtf| is used to determine the codec
+ // scheme. |fallback_method| is used if no codec defined for |mtf|.
+ spv_result_t EncodeMtfRankHuffman(uint32_t rank, uint64_t mtf,
+ uint64_t fallback_method);
- if (logger_) {
- logger_->AppendWhitespaces(kCommentNumWhitespaces);
- logger_->AppendText("ByteBreak:");
- }
+ // Writes id using coding based on mtf associated with the id descriptor.
+ // Returns SPV_UNSUPPORTED iff fallback method needs to be used.
+ spv_result_t EncodeIdWithDescriptor(uint32_t id);
- writer_.WriteBits(0, GetNumBitsToNextByte(writer_.GetNumBits()));
- }
+ // Writes id using coding based on the given |mtf|, which is expected to
+ // contain the given |id|.
+ spv_result_t EncodeExistingId(uint64_t mtf, uint32_t id);
+
+ // Writes type id of the current instruction if can't be inferred.
+ spv_result_t EncodeTypeId();
+
+ // Writes result id of the current instruction if can't be inferred.
+ spv_result_t EncodeResultId();
+
+ // Writes ids which are neither type nor result ids.
+ spv_result_t EncodeRefId(uint32_t id);
+
+ // Writes bits to the stream until the beginning of the next byte if the
+ // number of bits until the next byte is less than |byte_break_if_less_than|.
+ void AddByteBreak(size_t byte_break_if_less_than);
// Encodes a literal number operand and writes it to the bit stream.
- void EncodeLiteralNumber(const Instruction& instruction,
- const spv_parsed_operand_t& operand);
+ spv_result_t EncodeLiteralNumber(const Instruction& instruction,
+ const spv_parsed_operand_t& operand);
spv_const_markv_encoder_options options_;
// If not nullptr, disassembled instruction lines will be written to comments.
// Format: \n separated instruction lines, no header.
std::unique_ptr<std::stringstream> disassembly_;
-
- // All ids which were previosly encountered in the module.
- std::unordered_set<uint32_t> all_known_ids_;
};
// Decodes MARK-V buffers written by MarkvEncoder.
(void) options_;
vstate_.setIdBound(1);
parsed_operands_.reserve(25);
+ inst_words_.reserve(25);
}
// Decodes SPIR-V from MARK-V and stores the words in |spirv_binary|.
return spvValidatorOptionsCreate();
}
- // Reads a single word from bit stream. |type| determines if the word needs
- // to be decoded and how. Returns false if read fails.
- bool DecodeOperandWord(spv_operand_type_t type, uint32_t* word) {
- const size_t chunk_length = GetOperandVariableWidthChunkLength(type);
- if (chunk_length) {
- return reader_.ReadVariableWidthU32(word, chunk_length);
- } else {
- return reader_.ReadUnencoded(word);
- }
- }
+ // Reads a single bit from reader_. The read bit is stored in |bit|.
+ // Returns false iff reader_ fails.
+ bool ReadBit(bool* bit) {
+ uint64_t bits = 0;
+ const bool result = reader_.ReadBits(&bits, 1);
+ if (result)
+ *bit = bits ? true : false;
+ return result;
+ };
- // Fetches the id from the move-to-front list and moves it to front.
- uint32_t GetIdAndMoveToFront(uint16_t index) {
- if (index >= move_to_front_ids_.size()) {
- // Issue new id.
- const uint32_t id = vstate_.getIdBound();
- move_to_front_ids_.push_front(id);
- vstate_.setIdBound(id + 1);
- return id;
- } else {
- if (index == 0)
- return move_to_front_ids_.front();
-
- // Iterate to index.
- auto it = move_to_front_ids_.begin();
- for (size_t i = 0; i < index; ++i)
- ++it;
- const uint32_t id = *it;
- move_to_front_ids_.erase(it);
- move_to_front_ids_.push_front(id);
- return id;
- }
+ // Returns ReadBit bound to the class object.
+ std::function<bool(bool*)> GetReadBitCallback() {
+ return std::bind(&MarkvDecoder::ReadBit, this, std::placeholders::_1);
}
- // Decodes id index and fetches the id from move-to-front list.
- bool DecodeId(uint32_t* id) {
- uint16_t index = 0;
- if (!reader_.ReadVariableWidthU16(&index, model_->id_index_chunk_length()))
- return false;
+ // Reads a single non-id word from bit stream. operand_.type determines if
+ // the word needs to be decoded and how.
+ spv_result_t DecodeNonIdWord(uint32_t* word);
- *id = GetIdAndMoveToFront(index);
- return true;
- }
+ // Reads and decodes both opcode and num_operands as a single code.
+ // Returns SPV_UNSUPPORTED iff no suitable codec was found.
+ spv_result_t DecodeOpcodeAndNumberOfOperands(uint32_t* opcode,
+ uint32_t* num_operands);
- bool ReadToByteBreakIfAgreed() {
- if (!ShouldByteBreak(reader_.GetNumReadBits()))
- return true;
+ // Reads mtf rank from bit stream. |mtf| is used to determine the codec
+ // scheme. |fallback_method| is used if no codec defined for |mtf|.
+ spv_result_t DecodeMtfRankHuffman(uint64_t mtf, uint32_t fallback_method,
+ uint32_t* rank);
- uint64_t bits = 0;
- if (!reader_.ReadBits(&bits,
- GetNumBitsToNextByte(reader_.GetNumReadBits())))
- return false;
+ // Reads id using coding based on mtf associated with the id descriptor.
+ // Returns SPV_UNSUPPORTED iff fallback method needs to be used.
+ spv_result_t DecodeIdWithDescriptor(uint32_t* id);
- if (bits != 0)
- return false;
+ // Reads id using coding based on the given |mtf|, which is expected to
+ // contain the needed |id|.
+ spv_result_t DecodeExistingId(uint64_t mtf, uint32_t* id);
- return true;
+ // Reads type id of the current instruction if can't be inferred.
+ spv_result_t DecodeTypeId();
+
+ // Reads result id of the current instruction if can't be inferred.
+ spv_result_t DecodeResultId();
+
+ // Reads id which is neither type nor result id.
+ spv_result_t DecodeRefId(uint32_t* id);
+
+ // Reads and discards bits until the beginning of the next byte if the
+ // number of bits until the next byte is less than |byte_break_if_less_than|.
+ bool ReadToByteBreak(size_t byte_break_if_less_than);
+
+ // Returns instruction words decoded up to this point.
+ const uint32_t* GetInstWords() const override {
+ return inst_words_.data();
}
// Reads a literal number as it is described in |operand| from the bit stream,
// Reads instruction from bit stream, decodes and validates it.
// Decoded instruction is valid until the next call of DecodeInstruction().
- spv_result_t DecodeInstruction(spv_parsed_instruction_t* inst);
+ spv_result_t DecodeInstruction();
// Read operand from the stream decodes and validates it.
- spv_result_t DecodeOperand(size_t instruction_offset, size_t operand_offset,
- spv_parsed_instruction_t* inst,
+ spv_result_t DecodeOperand(size_t operand_offset,
const spv_operand_type_t type,
- spv_operand_pattern_t* expected_operands,
- bool read_result_id);
+ spv_operand_pattern_t* expected_operands);
// Records the numeric type for an operand according to the type information
// associated with the given non-zero type Id. This can fail if the type Id
spv_result_t SetNumericTypeInfoForType(spv_parsed_operand_t* parsed_operand,
uint32_t type_id);
- // Records the number type for the given instruction, if that
- // instruction generates a type. For types that aren't scalar numbers,
- // record something with number kind SPV_NUMBER_NONE.
- void RecordNumberType(const spv_parsed_instruction_t& inst);
+ // Records the number type for the current instruction, if it generates a
+ // type. For types that aren't scalar numbers, record something with number
+ // kind SPV_NUMBER_NONE.
+ void RecordNumberType();
spv_const_markv_decoder_options options_;
// Valid until next DecodeInstruction call.
std::vector<spv_parsed_operand_t> parsed_operands_;
- // Maps a result ID to its type ID. By convention:
- // - a result ID that is a type definition maps to itself.
- // - a result ID without a type maps to 0. (E.g. for OpLabel)
- std::unordered_map<uint32_t, uint32_t> id_to_type_id_;
+ // Temporary storage for current instruction words.
+ // Valid until next DecodeInstruction call.
+ std::vector<uint32_t> inst_words_;
+
// Maps a type ID to its number type description.
std::unordered_map<uint32_t, NumberType> type_id_to_number_type_info_;
+
// Maps an ExtInstImport id to the extended instruction type.
std::unordered_map<uint32_t, spv_ext_inst_type_t> import_id_to_ext_inst_type_;
};
-void MarkvEncoder::EncodeLiteralNumber(const Instruction& instruction,
- const spv_parsed_operand_t& operand) {
- if (operand.number_bit_width == 32) {
- const uint32_t word = instruction.word(operand.offset);
- if (operand.number_kind == SPV_NUMBER_UNSIGNED_INT) {
- writer_.WriteVariableWidthU32(word, model_->u32_chunk_length());
- } else if (operand.number_kind == SPV_NUMBER_SIGNED_INT) {
- int32_t val = 0;
- std::memcpy(&val, &word, 4);
- writer_.WriteVariableWidthS32(val, model_->s32_chunk_length(),
- model_->s32_block_exponent());
- } else if (operand.number_kind == SPV_NUMBER_FLOATING) {
- writer_.WriteUnencoded(word);
- } else {
- assert(0);
- }
- } else if (operand.number_bit_width == 16) {
- const uint16_t word =
- static_cast<uint16_t>(instruction.word(operand.offset));
- if (operand.number_kind == SPV_NUMBER_UNSIGNED_INT) {
- writer_.WriteVariableWidthU16(word, model_->u16_chunk_length());
- } else if (operand.number_kind == SPV_NUMBER_SIGNED_INT) {
- int16_t val = 0;
- std::memcpy(&val, &word, 2);
- writer_.WriteVariableWidthS16(val, model_->s16_chunk_length(),
- model_->s16_block_exponent());
- } else if (operand.number_kind == SPV_NUMBER_FLOATING) {
- // TODO(atgoo@github.com) Write only 16 bits.
- writer_.WriteUnencoded(word);
- } else {
- assert(0);
+void MarkvCodecBase::ProcessCurInstruction() {
+ const SpvOp opcode = SpvOp(inst_.opcode);
+
+ if (inst_.result_id) {
+ // Collect ids local to the current function.
+ if (cur_function_id_){
+ ids_local_to_cur_function_.push_back(inst_.result_id);
}
- } else {
- assert(operand.number_bit_width == 64);
- const uint64_t word =
- uint64_t(instruction.word(operand.offset)) |
- (uint64_t(instruction.word(operand.offset + 1)) << 32);
- if (operand.number_kind == SPV_NUMBER_UNSIGNED_INT) {
- writer_.WriteVariableWidthU64(word, model_->u64_chunk_length());
- } else if (operand.number_kind == SPV_NUMBER_SIGNED_INT) {
- int64_t val = 0;
- std::memcpy(&val, &word, 8);
- writer_.WriteVariableWidthS64(val, model_->s64_chunk_length(),
- model_->s64_block_exponent());
- } else if (operand.number_kind == SPV_NUMBER_FLOATING) {
- writer_.WriteUnencoded(word);
- } else {
- assert(0);
+
+ // Starting new function.
+ if (opcode == SpvOpFunction) {
+ cur_function_id_ = inst_.result_id;
+ cur_function_return_type_ = inst_.type_id;
+ multi_mtf_.Insert(GetMtfFunctionWithReturnType(inst_.type_id),
+ inst_.result_id);
+
+ // Store function parameter types in a queue, so that we know which types
+ // to expect in the following OpFunctionParameter instructions.
+ const Instruction* def_inst = GetDefInst(inst_.words[4]);
+ assert(def_inst);
+ assert(def_inst->opcode() == SpvOpTypeFunction);
+ for (uint32_t i = 3; i < def_inst->words().size(); ++i) {
+ remaining_function_parameter_types_.push_back(def_inst->word(i));
+ }
}
}
-}
-
-spv_result_t MarkvEncoder::EncodeInstruction(
- const spv_parsed_instruction_t& inst) {
- const spv_result_t validation_result = UpdateValidationState(inst);
- if (validation_result != SPV_SUCCESS)
- return validation_result;
- bool result_id_was_forward_declared = false;
- if (all_known_ids_.count(inst.result_id)) {
- // Result id of the instruction was forward declared.
- // Write a service opcode to signal this to the decoder.
- writer_.WriteVariableWidthU32(kMarkvOpNextInstructionEncodesResultId,
- model_->opcode_chunk_length());
- result_id_was_forward_declared = true;
+ // Remove local ids from MTFs if function end.
+ if (opcode == SpvOpFunctionEnd) {
+ cur_function_id_ = 0;
+ for (uint32_t id : ids_local_to_cur_function_)
+ multi_mtf_.RemoveFromAll(id);
+ ids_local_to_cur_function_.clear();
+ assert(remaining_function_parameter_types_.empty());
}
- const Instruction& instruction = GetCurrentInstruction();
- const auto& operands = instruction.operands();
+ if (!inst_.result_id)
+ return;
+
+ {
+ // Save the result ID to type ID mapping.
+ // In the grammar, type ID always appears before result ID.
+ // A regular value maps to its type. Some instructions (e.g. OpLabel)
+ // have no type Id, and will map to 0. The result Id for a
+ // type-generating instruction (e.g. OpTypeInt) maps to itself.
+ auto insertion_result = id_to_type_id_.emplace(
+ inst_.result_id,
+ spvOpcodeGeneratesType(SpvOp(inst_.opcode)) ?
+ inst_.result_id : inst_.type_id);
+ (void)insertion_result;
+ assert(insertion_result.second);
+ }
- LogDisassemblyInstruction();
+ // Add result_id to MTFs.
- // Write opcode.
- writer_.WriteVariableWidthU32(inst.opcode, model_->opcode_chunk_length());
+ switch (opcode) {
+ case SpvOpTypeFloat:
+ case SpvOpTypeInt:
+ case SpvOpTypeBool:
+ case SpvOpTypeVector:
+ case SpvOpTypePointer:
+ case SpvOpExtInstImport:
+ case SpvOpTypeSampledImage:
+ case SpvOpTypeImage:
+ case SpvOpTypeSampler:
+ multi_mtf_.Insert(GetMtfIdGeneratedByOpcode(opcode), inst_.result_id);
+ break;
+ default:
+ break;
+ }
- if (!OpcodeHasFixedNumberOfOperands(SpvOp(inst.opcode))) {
- // If the opcode has a variable number of operands, encode the number of
- // operands with the instruction.
+ if (spvOpcodeIsComposite(opcode)) {
+ multi_mtf_.Insert(kMtfTypeComposite, inst_.result_id);
+ }
- if (logger_)
- logger_->AppendWhitespaces(kCommentNumWhitespaces);
+ if (opcode == SpvOpLabel) {
+ multi_mtf_.InsertOrPromote(kMtfLabel, inst_.result_id);
+ }
- writer_.WriteVariableWidthU16(inst.num_operands,
- model_->num_operands_chunk_length());
+ if (opcode == SpvOpTypeInt) {
+ multi_mtf_.Insert(kMtfTypeScalar, inst_.result_id);
+ multi_mtf_.Insert(kMtfTypeIntScalarOrVector, inst_.result_id);
}
- // Write operands.
- for (const auto& operand : operands) {
- if (operand.type == SPV_OPERAND_TYPE_RESULT_ID &&
- !result_id_was_forward_declared) {
- // Register the id, but don't encode it.
- GetIdIndex(instruction.word(operand.offset));
- continue;
- }
+ if (opcode == SpvOpTypeFloat) {
+ multi_mtf_.Insert(kMtfTypeScalar, inst_.result_id);
+ multi_mtf_.Insert(kMtfTypeFloatScalarOrVector, inst_.result_id);
+ }
- if (logger_)
- logger_->AppendWhitespaces(kCommentNumWhitespaces);
+ if (opcode == SpvOpTypeBool) {
+ multi_mtf_.Insert(kMtfTypeScalar, inst_.result_id);
+ multi_mtf_.Insert(kMtfTypeBoolScalarOrVector, inst_.result_id);
+ }
- if (operand.type == SPV_OPERAND_TYPE_TYPED_LITERAL_NUMBER) {
- EncodeLiteralNumber(instruction, operand);
- } else if (operand.type == SPV_OPERAND_TYPE_LITERAL_STRING) {
- const char* src =
- reinterpret_cast<const char*>(&instruction.words()[operand.offset]);
- const size_t length = spv_strnlen_s(src, operand.num_words * 4);
- if (length == operand.num_words * 4)
- return vstate_.diag(SPV_ERROR_INVALID_BINARY)
- << "Failed to find terminal character of literal string";
- for (size_t i = 0; i < length + 1; ++i)
- writer_.WriteUnencoded(src[i]);
- } else if (spvIsIdType(operand.type)) {
- const uint16_t id_index = GetIdIndex(instruction.word(operand.offset));
- writer_.WriteVariableWidthU16(id_index, model_->id_index_chunk_length());
- } else {
- for (int i = 0; i < operand.num_words; ++i) {
- const uint32_t word = instruction.word(operand.offset + i);
- EncodeOperandWord(operand.type, word);
- }
+ if (opcode == SpvOpTypeVector) {
+ const uint32_t component_type_id = inst_.words[2];
+ const uint32_t size = inst_.words[3];
+ if (multi_mtf_.HasValue(GetMtfIdGeneratedByOpcode(SpvOpTypeFloat),
+ component_type_id)) {
+ multi_mtf_.Insert(kMtfTypeFloatScalarOrVector, inst_.result_id);
+ } else if (multi_mtf_.HasValue(GetMtfIdGeneratedByOpcode(SpvOpTypeInt),
+ component_type_id)) {
+ multi_mtf_.Insert(kMtfTypeIntScalarOrVector, inst_.result_id);
+ } else if (multi_mtf_.HasValue(GetMtfIdGeneratedByOpcode(SpvOpTypeBool),
+ component_type_id)) {
+ multi_mtf_.Insert(kMtfTypeBoolScalarOrVector, inst_.result_id);
}
+ multi_mtf_.Insert(GetMtfTypeVectorOfSize(size), inst_.result_id);
}
- AddByteBreakIfAgreed();
-
- if (logger_) {
- logger_->NewLine();
- logger_->NewLine();
+ if (inst_.opcode == SpvOpTypeFunction) {
+ const uint32_t return_type = inst_.words[2];
+ multi_mtf_.Insert(kMtfTypeReturnedByFunction, return_type);
+ multi_mtf_.Insert(GetMtfFunctionTypeWithReturnType(return_type),
+ inst_.result_id);
}
- return SPV_SUCCESS;
-}
+ if (inst_.type_id) {
+ const Instruction* type_inst = GetDefInst(inst_.type_id);
+ assert(type_inst);
-spv_result_t MarkvDecoder::DecodeLiteralNumber(
- const spv_parsed_operand_t& operand) {
- if (operand.number_bit_width == 32) {
- uint32_t word = 0;
- if (operand.number_kind == SPV_NUMBER_UNSIGNED_INT) {
- if (!reader_.ReadVariableWidthU32(&word, model_->u32_chunk_length()))
- return vstate_.diag(SPV_ERROR_INVALID_BINARY)
- << "Failed to read literal U32";
- } else if (operand.number_kind == SPV_NUMBER_SIGNED_INT) {
- int32_t val = 0;
- if (!reader_.ReadVariableWidthS32(&val, model_->s32_chunk_length(),
- model_->s32_block_exponent()))
- return vstate_.diag(SPV_ERROR_INVALID_BINARY)
- << "Failed to read literal S32";
- std::memcpy(&word, &val, 4);
- } else if (operand.number_kind == SPV_NUMBER_FLOATING) {
- if (!reader_.ReadUnencoded(&word))
- return vstate_.diag(SPV_ERROR_INVALID_BINARY)
- << "Failed to read literal F32";
- } else {
- assert(0);
+ multi_mtf_.Insert(kMtfObject, inst_.result_id);
+
+ multi_mtf_.Insert(GetMtfIdOfType(inst_.type_id), inst_.result_id);
+
+ if (multi_mtf_.HasValue(kMtfTypeFloatScalarOrVector, inst_.type_id)) {
+ multi_mtf_.Insert(kMtfFloatScalarOrVector, inst_.result_id);
}
- spirv_.push_back(word);
- } else if (operand.number_bit_width == 16) {
- uint32_t word = 0;
- if (operand.number_kind == SPV_NUMBER_UNSIGNED_INT) {
- uint16_t val = 0;
- if (!reader_.ReadVariableWidthU16(&val, model_->u16_chunk_length()))
- return vstate_.diag(SPV_ERROR_INVALID_BINARY)
- << "Failed to read literal U16";
- word = val;
- } else if (operand.number_kind == SPV_NUMBER_SIGNED_INT) {
- int16_t val = 0;
- if (!reader_.ReadVariableWidthS16(&val, model_->s16_chunk_length(),
- model_->s16_block_exponent()))
- return vstate_.diag(SPV_ERROR_INVALID_BINARY)
- << "Failed to read literal S16";
- // Int16 is stored as int32 in SPIR-V, not as bits.
- int32_t val32 = val;
- std::memcpy(&word, &val32, 4);
- } else if (operand.number_kind == SPV_NUMBER_FLOATING) {
- uint16_t word16 = 0;
- if (!reader_.ReadUnencoded(&word16))
- return vstate_.diag(SPV_ERROR_INVALID_BINARY)
- << "Failed to read literal F16";
- word = word16;
- } else {
- assert(0);
+
+ if (multi_mtf_.HasValue(kMtfTypeIntScalarOrVector, inst_.type_id))
+ multi_mtf_.Insert(kMtfIntScalarOrVector, inst_.result_id);
+
+ if (multi_mtf_.HasValue(kMtfTypeBoolScalarOrVector, inst_.type_id))
+ multi_mtf_.Insert(kMtfBoolScalarOrVector, inst_.result_id);
+
+ if (multi_mtf_.HasValue(kMtfTypeComposite, inst_.type_id))
+ multi_mtf_.Insert(kMtfComposite, inst_.result_id);
+
+ if (inst_.opcode == SpvOpConstant) {
+ if (multi_mtf_.HasValue(
+ GetMtfIdGeneratedByOpcode(SpvOpTypeInt), inst_.type_id)) {
+ multi_mtf_.Insert(kMtfConstInteger, inst_.result_id);
+ const uint32_t presumed_index = inst_.words[3];
+ if (presumed_index <= kMarkvMaxPresumedAccessIndex) {
+ const auto result =
+ presumed_index_to_id_.emplace(presumed_index, inst_.result_id);
+ if (result.second) {
+ id_to_presumed_index_.emplace(inst_.result_id, presumed_index);
+ }
+ }
+ }
}
- spirv_.push_back(word);
- } else {
- assert(operand.number_bit_width == 64);
- uint64_t word = 0;
- if (operand.number_kind == SPV_NUMBER_UNSIGNED_INT) {
- if (!reader_.ReadVariableWidthU64(&word, model_->u64_chunk_length()))
- return vstate_.diag(SPV_ERROR_INVALID_BINARY)
- << "Failed to read literal U64";
- } else if (operand.number_kind == SPV_NUMBER_SIGNED_INT) {
- int64_t val = 0;
- if (!reader_.ReadVariableWidthS64(&val, model_->s64_chunk_length(),
- model_->s64_block_exponent()))
- return vstate_.diag(SPV_ERROR_INVALID_BINARY)
- << "Failed to read literal S64";
- std::memcpy(&word, &val, 8);
- } else if (operand.number_kind == SPV_NUMBER_FLOATING) {
- if (!reader_.ReadUnencoded(&word))
- return vstate_.diag(SPV_ERROR_INVALID_BINARY)
- << "Failed to read literal F64";
- } else {
- assert(0);
+
+ switch (type_inst->opcode()) {
+ case SpvOpTypeInt:
+ case SpvOpTypeBool:
+ case SpvOpTypePointer:
+ case SpvOpTypeVector:
+ case SpvOpTypeImage:
+ case SpvOpTypeSampledImage:
+ case SpvOpTypeSampler:
+ multi_mtf_.Insert(GetMtfIdWithTypeGeneratedByOpcode(
+ type_inst->opcode()), inst_.result_id);
+ break;
+ default:
+ break;
}
- spirv_.push_back(static_cast<uint32_t>(word));
- spirv_.push_back(static_cast<uint32_t>(word >> 32));
- }
- return SPV_SUCCESS;
-}
-spv_result_t MarkvDecoder::DecodeModule(std::vector<uint32_t>* spirv_binary) {
- const bool header_read_success =
- reader_.ReadUnencoded(&header_.magic_number) &&
- reader_.ReadUnencoded(&header_.markv_version) &&
- reader_.ReadUnencoded(&header_.markv_model) &&
- reader_.ReadUnencoded(&header_.markv_length_in_bits) &&
- reader_.ReadUnencoded(&header_.spirv_version) &&
- reader_.ReadUnencoded(&header_.spirv_generator);
+ if (type_inst->opcode() == SpvOpTypeVector) {
+ const uint32_t component_type = type_inst->word(2);
+ multi_mtf_.Insert(GetMtfVectorOfComponentType(component_type),
+ inst_.result_id);
+ }
- if (!header_read_success)
- return vstate_.diag(SPV_ERROR_INVALID_BINARY)
- << "Unable to read MARK-V header";
+ if (type_inst->opcode() == SpvOpTypePointer) {
+ assert(type_inst->operands().size() > 2);
+ assert(type_inst->words().size() > type_inst->operands()[2].offset);
+ const uint32_t data_type =
+ type_inst->word(type_inst->operands()[2].offset);
+ multi_mtf_.Insert(GetMtfPointerToType(data_type), inst_.result_id);
- assert(header_.magic_number == kMarkvMagicNumber);
- assert(header_.markv_length_in_bits > 0);
+ if (multi_mtf_.HasValue(kMtfTypeComposite, data_type))
+ multi_mtf_.Insert(kMtfTypePointerToComposite, inst_.result_id);
+ }
+ }
- if (header_.magic_number != kMarkvMagicNumber)
- return vstate_.diag(SPV_ERROR_INVALID_BINARY)
- << "MARK-V binary has incorrect magic number";
+ if (spvOpcodeGeneratesType(opcode)) {
+ if (opcode != SpvOpTypeFunction) {
+ multi_mtf_.Insert(kMtfTypeNonFunction, inst_.result_id);
+ }
+ }
- // TODO(atgoo@github.com): Print version strings.
- if (header_.markv_version != GetMarkvVersion())
- return vstate_.diag(SPV_ERROR_INVALID_BINARY)
- << "MARK-V binary and the codec have different versions";
+ const uint32_t descriptor = id_descriptors_.ProcessInstruction(inst_);
- spirv_.reserve(header_.markv_length_in_bits / 2); // Heuristic.
- spirv_.resize(5, 0);
- spirv_[0] = kSpirvMagicNumber;
- spirv_[1] = header_.spirv_version;
- spirv_[2] = header_.spirv_generator;
+ multi_mtf_.Insert(GetMtfIdDescriptor(descriptor), inst_.result_id);
+}
- while (reader_.GetNumReadBits() < header_.markv_length_in_bits) {
- spv_parsed_instruction_t inst = {};
- const spv_result_t decode_result = DecodeInstruction(&inst);
+uint64_t MarkvCodecBase::GetRuleBasedMtf() {
+ // This function is only called for id operands (but not result ids).
+ assert(spvIsIdType(operand_.type) ||
+ operand_.type == SPV_OPERAND_TYPE_OPTIONAL_ID);
+ assert(operand_.type != SPV_OPERAND_TYPE_RESULT_ID);
+
+ const SpvOp opcode = static_cast<SpvOp>(inst_.opcode);
+
+ // All operand slots which expect label id.
+ if ((inst_.opcode == SpvOpLoopMerge && operand_index_ <= 1) ||
+ (inst_.opcode == SpvOpSelectionMerge && operand_index_ == 0) ||
+ (inst_.opcode == SpvOpBranch && operand_index_ == 0) ||
+ (inst_.opcode == SpvOpBranchConditional &&
+ (operand_index_ == 1 || operand_index_ == 2 )) ||
+ (inst_.opcode == SpvOpPhi && operand_index_ >= 3 &&
+ operand_index_ % 2 == 1) ||
+ (inst_.opcode == SpvOpSwitch && operand_index_ > 0)) {
+ return kMtfLabel;
+ }
+
+ switch (opcode) {
+ case SpvOpFAdd:
+ case SpvOpFSub:
+ case SpvOpFMul:
+ case SpvOpFDiv:
+ case SpvOpFRem:
+ case SpvOpFMod:
+ case SpvOpFNegate: {
+ if (operand_index_ == 0)
+ return kMtfTypeFloatScalarOrVector;
+
+ return GetMtfIdOfType(inst_.type_id);
+ }
+
+ case SpvOpISub:
+ case SpvOpIAdd:
+ case SpvOpIMul:
+ case SpvOpSDiv:
+ case SpvOpUDiv:
+ case SpvOpSMod:
+ case SpvOpUMod:
+ case SpvOpSRem:
+ case SpvOpSNegate: {
+ if (operand_index_ == 0)
+ return kMtfTypeIntScalarOrVector;
+
+ return kMtfIntScalarOrVector;
+ }
+
+ // TODO(atgoo@github.com) Add OpConvertFToU and other opcodes.
+
+ case SpvOpFOrdEqual:
+ case SpvOpFUnordEqual:
+ case SpvOpFOrdNotEqual:
+ case SpvOpFUnordNotEqual:
+ case SpvOpFOrdLessThan:
+ case SpvOpFUnordLessThan:
+ case SpvOpFOrdGreaterThan:
+ case SpvOpFUnordGreaterThan:
+ case SpvOpFOrdLessThanEqual:
+ case SpvOpFUnordLessThanEqual:
+ case SpvOpFOrdGreaterThanEqual:
+ case SpvOpFUnordGreaterThanEqual: {
+ if (operand_index_ == 0)
+ return kMtfTypeBoolScalarOrVector;
+ if (operand_index_ == 2)
+ return kMtfFloatScalarOrVector;
+ if (operand_index_ == 3) {
+ const uint32_t first_operand_id = GetInstWords()[3];
+ const uint32_t first_operand_type =
+ id_to_type_id_.at(first_operand_id);
+ return GetMtfIdOfType(first_operand_type);
+ }
+ break;
+ }
+
+ case SpvOpVectorShuffle: {
+ if (operand_index_ == 0) {
+ assert(inst_.num_operands > 4);
+ return GetMtfTypeVectorOfSize(inst_.num_operands - 4);
+ }
+
+ assert(inst_.type_id);
+ if (operand_index_ == 2 || operand_index_ == 3)
+ return GetMtfVectorOfComponentType(
+ GetVectorComponentType(inst_.type_id));
+ break;
+ }
+
+ case SpvOpVectorTimesScalar: {
+ if (operand_index_ == 0)
+ return GetMtfIdGeneratedByOpcode(SpvOpTypeVector);
+
+ assert(inst_.type_id);
+ if (operand_index_ == 2)
+ return GetMtfIdOfType(inst_.type_id);
+ if (operand_index_ == 3)
+ return GetMtfIdOfType(GetVectorComponentType(inst_.type_id));
+ break;
+ }
+
+ case SpvOpDot: {
+ if (operand_index_ == 0)
+ return GetMtfIdGeneratedByOpcode(SpvOpTypeFloat);
+
+ assert(inst_.type_id);
+ if (operand_index_ == 2)
+ return GetMtfVectorOfComponentType(inst_.type_id);
+ if (operand_index_ == 3) {
+ const uint32_t vector_id = GetInstWords()[3];
+ const uint32_t vector_type = id_to_type_id_.at(vector_id);
+ return GetMtfIdOfType(vector_type);
+ }
+ break;
+ }
+
+ case SpvOpTypeVector: {
+ if (operand_index_ == 1) {
+ return kMtfTypeScalar;
+ }
+ break;
+ }
+
+ case SpvOpTypeMatrix: {
+ if (operand_index_ == 1) {
+ return GetMtfIdGeneratedByOpcode(SpvOpTypeVector);
+ }
+ break;
+ }
+
+ case SpvOpTypePointer: {
+ if (operand_index_ == 2) {
+ return kMtfTypeNonFunction;
+ }
+ break;
+ }
+
+ case SpvOpTypeStruct: {
+ if (operand_index_ >= 1) {
+ return kMtfTypeNonFunction;
+ }
+ break;
+ }
+
+ case SpvOpTypeFunction: {
+ if (operand_index_ == 1) {
+ return kMtfTypeNonFunction;
+ }
+
+ if (operand_index_ >= 2) {
+ return kMtfTypeNonFunction;
+ }
+ break;
+ }
+
+ case SpvOpLoad: {
+ if (operand_index_ == 0)
+ return kMtfTypeNonFunction;
+
+ if (operand_index_ == 2) {
+ assert(inst_.type_id);
+ return GetMtfPointerToType(inst_.type_id);
+ }
+ break;
+ }
+
+ case SpvOpStore: {
+ if (operand_index_ == 0)
+ return GetMtfIdWithTypeGeneratedByOpcode(SpvOpTypePointer);
+ if (operand_index_ == 1) {
+ const uint32_t pointer_id = GetInstWords()[1];
+ const uint32_t pointer_type = id_to_type_id_.at(pointer_id);
+ const auto it = vstate_.all_definitions().find(pointer_type);
+ assert(it != vstate_.all_definitions().end());
+ const Instruction* pointer_inst = it->second;
+
+ assert(pointer_inst->opcode() == SpvOpTypePointer);
+ const uint32_t data_type =
+ pointer_inst->word(pointer_inst->operands()[2].offset);
+ return GetMtfIdOfType(data_type);
+ }
+ break;
+ }
+
+ case SpvOpVariable: {
+ if (operand_index_ == 0)
+ return GetMtfIdGeneratedByOpcode(SpvOpTypePointer);
+ break;
+ }
+
+ case SpvOpAccessChain: {
+ if (operand_index_ == 0)
+ return GetMtfIdGeneratedByOpcode(SpvOpTypePointer);
+ if (operand_index_ == 2)
+ return kMtfTypePointerToComposite;
+ if (operand_index_ >= 3)
+ return GetMtfIdWithTypeGeneratedByOpcode(SpvOpTypeInt);
+ break;
+ }
+
+ case SpvOpCompositeConstruct: {
+ if (operand_index_ == 0)
+ return kMtfTypeComposite;
+ if (operand_index_ >= 2) {
+ const uint32_t composite_type = GetInstWords()[1];
+ if (multi_mtf_.HasValue(kMtfTypeFloatScalarOrVector, composite_type))
+ return kMtfFloatScalarOrVector;
+ if (multi_mtf_.HasValue(kMtfTypeIntScalarOrVector, composite_type))
+ return kMtfIntScalarOrVector;
+ if (multi_mtf_.HasValue(kMtfTypeBoolScalarOrVector, composite_type))
+ return kMtfBoolScalarOrVector;
+ }
+ break;
+ }
+
+ case SpvOpCompositeExtract: {
+ if (operand_index_ == 2)
+ return kMtfComposite;
+ break;
+ }
+
+ case SpvOpConstantComposite: {
+ if (operand_index_ == 0)
+ return kMtfTypeComposite;
+ if (operand_index_ >= 2) {
+ const Instruction* composite_type_inst = GetDefInst(inst_.type_id);
+ assert(composite_type_inst);
+ if (composite_type_inst->opcode() == SpvOpTypeVector) {
+ return GetMtfIdOfType(composite_type_inst->word(2));
+ }
+ }
+ break;
+ }
+
+ case SpvOpExtInst: {
+ if (operand_index_ == 2)
+ return GetMtfIdGeneratedByOpcode(SpvOpExtInstImport);
+ if (operand_index_ >= 4) {
+ const uint32_t return_type = GetInstWords()[1];
+ const uint32_t ext_inst_type = inst_.ext_inst_type;
+ const uint32_t ext_inst_index = GetInstWords()[4];
+ // TODO(atgoo@github.com) The list of extended instructions is
+ // incomplete. Only common instructions and low-hanging fruits listed.
+ if (ext_inst_type == SPV_EXT_INST_TYPE_GLSL_STD_450) {
+ switch (ext_inst_index) {
+ case GLSLstd450FAbs:
+ case GLSLstd450FClamp:
+ case GLSLstd450FMax:
+ case GLSLstd450FMin:
+ case GLSLstd450FMix:
+ case GLSLstd450Step:
+ case GLSLstd450SmoothStep:
+ case GLSLstd450Fma:
+ case GLSLstd450Pow:
+ case GLSLstd450Exp:
+ case GLSLstd450Exp2:
+ case GLSLstd450Log:
+ case GLSLstd450Log2:
+ case GLSLstd450Sqrt:
+ case GLSLstd450InverseSqrt:
+ case GLSLstd450Fract:
+ case GLSLstd450Floor:
+ case GLSLstd450Ceil:
+ case GLSLstd450Radians:
+ case GLSLstd450Degrees:
+ case GLSLstd450Sin:
+ case GLSLstd450Cos:
+ case GLSLstd450Tan:
+ case GLSLstd450Sinh:
+ case GLSLstd450Cosh:
+ case GLSLstd450Tanh:
+ case GLSLstd450Asin:
+ case GLSLstd450Acos:
+ case GLSLstd450Atan:
+ case GLSLstd450Atan2:
+ case GLSLstd450Asinh:
+ case GLSLstd450Acosh:
+ case GLSLstd450Atanh:
+ case GLSLstd450MatrixInverse:
+ case GLSLstd450Cross:
+ case GLSLstd450Normalize:
+ case GLSLstd450Reflect:
+ case GLSLstd450FaceForward:
+ return GetMtfIdOfType(return_type);
+ case GLSLstd450Length:
+ case GLSLstd450Distance:
+ case GLSLstd450Refract:
+ return kMtfFloatScalarOrVector;
+ default:
+ break;
+ }
+ } else if (ext_inst_type == SPV_EXT_INST_TYPE_OPENCL_STD) {
+ switch (ext_inst_index) {
+ case OpenCLLIB::Fabs:
+ case OpenCLLIB::FClamp:
+ case OpenCLLIB::Fmax:
+ case OpenCLLIB::Fmin:
+ case OpenCLLIB::Step:
+ case OpenCLLIB::Smoothstep:
+ case OpenCLLIB::Fma:
+ case OpenCLLIB::Pow:
+ case OpenCLLIB::Exp:
+ case OpenCLLIB::Exp2:
+ case OpenCLLIB::Log:
+ case OpenCLLIB::Log2:
+ case OpenCLLIB::Sqrt:
+ case OpenCLLIB::Rsqrt:
+ case OpenCLLIB::Fract:
+ case OpenCLLIB::Floor:
+ case OpenCLLIB::Ceil:
+ case OpenCLLIB::Radians:
+ case OpenCLLIB::Degrees:
+ case OpenCLLIB::Sin:
+ case OpenCLLIB::Cos:
+ case OpenCLLIB::Tan:
+ case OpenCLLIB::Sinh:
+ case OpenCLLIB::Cosh:
+ case OpenCLLIB::Tanh:
+ case OpenCLLIB::Asin:
+ case OpenCLLIB::Acos:
+ case OpenCLLIB::Atan:
+ case OpenCLLIB::Atan2:
+ case OpenCLLIB::Asinh:
+ case OpenCLLIB::Acosh:
+ case OpenCLLIB::Atanh:
+ case OpenCLLIB::Cross:
+ case OpenCLLIB::Normalize:
+ return GetMtfIdOfType(return_type);
+ case OpenCLLIB::Length:
+ case OpenCLLIB::Distance:
+ return kMtfFloatScalarOrVector;
+ default:
+ break;
+ }
+ }
+ }
+ break;
+ }
+
+ case SpvOpFunction: {
+ if (operand_index_ == 0)
+ return kMtfTypeReturnedByFunction;
+
+ if (operand_index_ == 3) {
+ const uint32_t return_type = GetInstWords()[1];
+ return GetMtfFunctionTypeWithReturnType(return_type);
+ }
+ break;
+ }
+
+ case SpvOpFunctionCall: {
+ if (operand_index_ == 0)
+ return kMtfTypeReturnedByFunction;
+
+ if (operand_index_ == 2) {
+ const uint32_t return_type = GetInstWords()[1];
+ return GetMtfFunctionWithReturnType(return_type);
+ }
+
+ if (operand_index_ >= 3) {
+ const uint32_t function_id = GetInstWords()[3];
+ const auto function_it = vstate_.all_definitions().find(function_id);
+ if (function_it == vstate_.all_definitions().end())
+ return kMtfObject;
+
+ const Instruction* function_inst = function_it->second;
+ assert(function_inst->opcode() == SpvOpFunction);
+
+ const uint32_t function_type_id = function_inst->word(4);
+ const auto function_type_it =
+ vstate_.all_definitions().find(function_type_id);
+ assert(function_type_it != vstate_.all_definitions().end());
+ const Instruction* function_type_inst = function_type_it->second;
+ assert(function_type_inst->opcode() == SpvOpTypeFunction);
+
+ const uint32_t argument_type =
+ function_type_inst->word(operand_index_);
+ return GetMtfIdOfType(argument_type);
+ }
+ break;
+ }
+
+ case SpvOpReturnValue: {
+ if (operand_index_ == 0)
+ return GetMtfIdOfType(cur_function_return_type_);
+ break;
+ }
+
+ case SpvOpBranchConditional: {
+ if (operand_index_ == 0)
+ return GetMtfIdWithTypeGeneratedByOpcode(SpvOpTypeBool);
+ break;
+ }
+
+ case SpvOpSampledImage: {
+ if (operand_index_ == 0)
+ return GetMtfIdGeneratedByOpcode(SpvOpTypeSampledImage);
+ if (operand_index_ == 2)
+ return GetMtfIdWithTypeGeneratedByOpcode(SpvOpTypeImage);
+ if (operand_index_ == 3)
+ return GetMtfIdWithTypeGeneratedByOpcode(SpvOpTypeSampler);
+ break;
+ }
+
+ case SpvOpImageSampleImplicitLod: {
+ if (operand_index_ == 0)
+ return GetMtfIdGeneratedByOpcode(SpvOpTypeVector);
+ if (operand_index_ == 2)
+ return GetMtfIdWithTypeGeneratedByOpcode(SpvOpTypeSampledImage);
+ if (operand_index_ == 3)
+ return GetMtfIdWithTypeGeneratedByOpcode(SpvOpTypeVector);
+ break;
+ }
+
+ default:
+ break;
+ }
+
+ return kMtfNone;
+}
+
+spv_result_t MarkvEncoder::EncodeNonIdWord(uint32_t word) {
+ auto* codec = model_->GetNonIdWordHuffmanCodec(inst_.opcode, operand_index_);
+
+ if (codec) {
+ uint64_t bits = 0;
+ size_t num_bits = 0;
+ if (codec->Encode(word, &bits, &num_bits)) {
+ // Encoding successful.
+ writer_.WriteBits(bits, num_bits);
+ return SPV_SUCCESS;
+ } else {
+ // Encoding failed, write kMarkvNoneOfTheAbove flag.
+ if (!codec->Encode(kMarkvNoneOfTheAbove, &bits, &num_bits))
+ return vstate_.diag(SPV_ERROR_INTERNAL)
+ << "Non-id word Huffman table for "
+ << spvOpcodeString(SpvOp(inst_.opcode))
+ << " operand index " << operand_index_
+ << " is missing kMarkvNoneOfTheAbove";
+ writer_.WriteBits(bits, num_bits);
+ }
+ }
+
+ // Fallback encoding.
+ const size_t chunk_length = GetOperandVariableWidthChunkLength(operand_.type);
+ if (chunk_length) {
+ writer_.WriteVariableWidthU32(word, chunk_length);
+ } else {
+ writer_.WriteUnencoded(word);
+ }
+ return SPV_SUCCESS;
+}
+
+spv_result_t MarkvDecoder::DecodeNonIdWord(uint32_t* word) {
+ auto* codec = model_->GetNonIdWordHuffmanCodec(inst_.opcode, operand_index_);
+
+ if (codec) {
+ uint64_t decoded_value = 0;
+ if (!codec->DecodeFromStream(GetReadBitCallback(), &decoded_value))
+ return vstate_.diag(SPV_ERROR_INVALID_BINARY)
+ << "Failed to decode non-id word with Huffman";
+
+ if (decoded_value != kMarkvNoneOfTheAbove) {
+ // The word decoded successfully.
+ *word = uint32_t(decoded_value);
+ assert(*word == decoded_value);
+ return SPV_SUCCESS;
+ }
+
+ // Received kMarkvNoneOfTheAbove signal, use fallback decoding.
+ }
+
+ const size_t chunk_length = GetOperandVariableWidthChunkLength(operand_.type);
+ if (chunk_length) {
+ if (!reader_.ReadVariableWidthU32(word, chunk_length))
+ return vstate_.diag(SPV_ERROR_INVALID_BINARY)
+ << "Failed to decode non-id word with varint";
+ } else {
+ if (!reader_.ReadUnencoded(word))
+ return vstate_.diag(SPV_ERROR_INVALID_BINARY)
+ << "Failed to read unencoded non-id word";
+ }
+ return SPV_SUCCESS;
+}
+
+spv_result_t MarkvEncoder::EncodeOpcodeAndNumOperands(
+ uint32_t opcode, uint32_t num_operands) {
+ uint64_t bits = 0;
+ size_t num_bits = 0;
+
+ const uint32_t word = opcode | (num_operands << 16);
+
+ // First try to use the Markov chain codec.
+ auto* codec = model_->GetOpcodeAndNumOperandsMarkovHuffmanCodec(GetPrevOpcode());
+ if (codec) {
+ if (codec->Encode(word, &bits, &num_bits)) {
+ // The word was successfully encoded into bits/num_bits.
+ writer_.WriteBits(bits, num_bits);
+ return SPV_SUCCESS;
+ } else {
+ // The word is not in the Huffman table. Write kMarkvNoneOfTheAbove
+ // and use fallback encoding.
+ if (!codec->Encode(kMarkvNoneOfTheAbove, &bits, &num_bits))
+ return vstate_.diag(SPV_ERROR_INTERNAL)
+ << "opcode_and_num_operands Huffman table for "
+ << spvOpcodeString(GetPrevOpcode())
+ << "is missing kMarkvNoneOfTheAbove";
+ writer_.WriteBits(bits, num_bits);
+ }
+ }
+
+ // Fallback to base-rate codec.
+ codec = model_->GetOpcodeAndNumOperandsMarkovHuffmanCodec(SpvOpNop);
+ assert(codec);
+ if (codec->Encode(word, &bits, &num_bits)) {
+ // The word was successfully encoded into bits/num_bits.
+ writer_.WriteBits(bits, num_bits);
+ return SPV_SUCCESS;
+ } else {
+ // The word is not in the Huffman table. Write kMarkvNoneOfTheAbove
+ // and return false.
+ if (!codec->Encode(kMarkvNoneOfTheAbove, &bits, &num_bits))
+ return vstate_.diag(SPV_ERROR_INTERNAL)
+ << "Global opcode_and_num_operands Huffman table is missing "
+ << "kMarkvNoneOfTheAbove";
+ writer_.WriteBits(bits, num_bits);
+ return SPV_UNSUPPORTED;
+ }
+}
+
+spv_result_t MarkvDecoder::DecodeOpcodeAndNumberOfOperands(
+ uint32_t* opcode, uint32_t* num_operands) {
+ // First try to use the Markov chain codec.
+ auto* codec = model_->GetOpcodeAndNumOperandsMarkovHuffmanCodec(GetPrevOpcode());
+ if (codec) {
+ uint64_t decoded_value = 0;
+ if (!codec->DecodeFromStream(GetReadBitCallback(), &decoded_value))
+ return vstate_.diag(SPV_ERROR_INTERNAL)
+ << "Failed to decode opcode_and_num_operands, previous opcode is "
+ << spvOpcodeString(GetPrevOpcode());
+
+ if (decoded_value != kMarkvNoneOfTheAbove) {
+ // The word was successfully decoded.
+ *opcode = uint32_t(decoded_value & 0xFFFF);
+ *num_operands = uint32_t(decoded_value >> 16);
+ return SPV_SUCCESS;
+ }
+
+ // Received kMarkvNoneOfTheAbove signal, use fallback decoding.
+ }
+
+ // Fallback to base-rate codec.
+ codec = model_->GetOpcodeAndNumOperandsMarkovHuffmanCodec(SpvOpNop);
+ assert(codec);
+ uint64_t decoded_value = 0;
+ if (!codec->DecodeFromStream(GetReadBitCallback(), &decoded_value))
+ return vstate_.diag(SPV_ERROR_INTERNAL)
+ << "Failed to decode opcode_and_num_operands with global codec";
+
+ if (decoded_value == kMarkvNoneOfTheAbove) {
+ // Received kMarkvNoneOfTheAbove signal, fallback further.
+ return SPV_UNSUPPORTED;
+ }
+
+ *opcode = uint32_t(decoded_value & 0xFFFF);
+ *num_operands = uint32_t(decoded_value >> 16);
+ return SPV_SUCCESS;
+}
+
+spv_result_t MarkvEncoder::EncodeMtfRankHuffman(uint32_t rank, uint64_t mtf,
+ uint64_t fallback_method) {
+ const auto* codec = model_->GetMtfHuffmanCodec(mtf);
+ if (!codec) {
+ assert(fallback_method != kMtfNone);
+ codec = model_->GetMtfHuffmanCodec(fallback_method);
+ }
+
+ if (!codec)
+ return vstate_.diag(SPV_ERROR_INTERNAL) << "No codec to encode MTF rank";
+
+ uint64_t bits = 0;
+ size_t num_bits = 0;
+ if (rank < kMtfSmallestRankEncodedByValue) {
+ // Encode using Huffman coding.
+ if (!codec->Encode(rank, &bits, &num_bits))
+ return vstate_.diag(SPV_ERROR_INTERNAL)
+ << "Failed to encode MTF rank with Huffman";
+
+ writer_.WriteBits(bits, num_bits);
+ } else {
+ // Encode by value.
+ if (!codec->Encode(kMtfRankEncodedByValueSignal, &bits, &num_bits))
+ return vstate_.diag(SPV_ERROR_INTERNAL)
+ << "Failed to encode kMtfRankEncodedByValueSignal";
+
+ writer_.WriteBits(bits, num_bits);
+ writer_.WriteVariableWidthU32(rank - kMtfSmallestRankEncodedByValue,
+ model_->mtf_rank_chunk_length());
+ }
+ return SPV_SUCCESS;
+}
+
+spv_result_t MarkvDecoder::DecodeMtfRankHuffman(
+ uint64_t mtf, uint32_t fallback_method, uint32_t* rank) {
+ const auto* codec = model_->GetMtfHuffmanCodec(mtf);
+ if (!codec) {
+ assert(fallback_method != kMtfNone);
+ codec = model_->GetMtfHuffmanCodec(fallback_method);
+ }
+
+ if (!codec)
+ return vstate_.diag(SPV_ERROR_INTERNAL) << "No codec to decode MTF rank";
+
+ uint32_t decoded_value = 0;
+ if (!codec->DecodeFromStream(GetReadBitCallback(), &decoded_value))
+ return vstate_.diag(SPV_ERROR_INTERNAL)
+ << "Failed to decode MTF rank with Huffman";
+
+ if (decoded_value == kMtfRankEncodedByValueSignal) {
+ // Decode by value.
+ if (!reader_.ReadVariableWidthU32(rank, model_->mtf_rank_chunk_length()))
+ return vstate_.diag(SPV_ERROR_INTERNAL)
+ << "Failed to decode MTF rank with varint";
+ *rank += kMtfSmallestRankEncodedByValue;
+ } else {
+ // Decode using Huffman coding.
+ assert(decoded_value < kMtfSmallestRankEncodedByValue);
+ *rank = decoded_value;
+ }
+ return SPV_SUCCESS;
+}
+
+spv_result_t MarkvEncoder::EncodeIdWithDescriptor(uint32_t id) {
+ auto* codec = model_->GetIdDescriptorHuffmanCodec(inst_.opcode,
+ operand_index_);
+ if (!codec)
+ return SPV_UNSUPPORTED;
+
+ uint64_t bits = 0;
+ size_t num_bits = 0;
+
+ // Get the descriptor for id.
+ const uint32_t descriptor = id_descriptors_.GetDescriptor(id);
+
+ if (descriptor && codec->Encode(descriptor, &bits, &num_bits)) {
+ // If the descriptor exists and is in the table, write the descriptor and
+ // proceed to encoding the rank.
+ writer_.WriteBits(bits, num_bits);
+ } else {
+ // The descriptor doesn't exist or we have no coding for it. Write
+ // kMarkvNoneOfTheAbove and go to fallback method.
+ if (!codec->Encode(kMarkvNoneOfTheAbove, &bits, &num_bits))
+ return vstate_.diag(SPV_ERROR_INTERNAL)
+ << "Descriptor Huffman table for "
+ << spvOpcodeString(SpvOp(inst_.opcode))
+ << " operand index " << operand_index_
+ << " is missing kMarkvNoneOfTheAbove";
+
+ writer_.WriteBits(bits, num_bits);
+ return SPV_UNSUPPORTED;
+ }
+
+ // Descriptor has been encoded. Now encode the rank of the id in the
+ // associated mtf sequence.
+ const uint64_t mtf = GetMtfIdDescriptor(descriptor);
+ return EncodeExistingId(mtf, id);
+}
+
+spv_result_t MarkvDecoder::DecodeIdWithDescriptor(uint32_t* id) {
+ auto* codec = model_->GetIdDescriptorHuffmanCodec(inst_.opcode,
+ operand_index_);
+ if (!codec)
+ return SPV_UNSUPPORTED;
+
+ uint64_t decoded_value = 0;
+ if (!codec->DecodeFromStream(GetReadBitCallback(), &decoded_value))
+ return vstate_.diag(SPV_ERROR_INTERNAL)
+ << "Failed to decode descriptor with Huffman";
+
+ if (decoded_value == kMarkvNoneOfTheAbove)
+ return SPV_UNSUPPORTED;
+
+ // If descriptor exists then the id was encoded through descriptor mtf.
+ const uint32_t descriptor = uint32_t(decoded_value);
+ assert(descriptor == decoded_value);
+ assert(descriptor);
+
+ const uint64_t mtf = GetMtfIdDescriptor(descriptor);
+ return DecodeExistingId(mtf, id);
+}
+
+spv_result_t MarkvEncoder::EncodeExistingId(uint64_t mtf, uint32_t id) {
+ assert(multi_mtf_.GetSize(mtf) > 0);
+ if (multi_mtf_.GetSize(mtf) == 1) {
+ // If the sequence has only one element no need to write rank, the decoder
+ // would make the same decision.
+ return SPV_SUCCESS;
+ }
+
+ uint32_t rank = 0;
+ if (!multi_mtf_.RankFromValue(mtf, id, &rank))
+ return vstate_.diag(SPV_ERROR_INTERNAL)
+ << "Id is not in the MTF sequence";
+
+ return EncodeMtfRankHuffman(rank, mtf, kMtfGenericNonZeroRank);
+}
+
+spv_result_t MarkvDecoder::DecodeExistingId(uint64_t mtf, uint32_t* id) {
+ assert(multi_mtf_.GetSize(mtf) > 0);
+ *id = 0;
+
+ uint32_t rank = 0;
+
+ if (multi_mtf_.GetSize(mtf) == 1) {
+ rank = 1;
+ } else {
+ const spv_result_t result =
+ DecodeMtfRankHuffman(mtf, kMtfGenericNonZeroRank, &rank);
+ if (result != SPV_SUCCESS)
+ return result;
+ }
+
+ assert(rank);
+ if (!multi_mtf_.ValueFromRank(mtf, rank, id))
+ return vstate_.diag(SPV_ERROR_INTERNAL)
+ << "MTF rank is out of bounds";
+
+ return SPV_SUCCESS;
+}
+
+spv_result_t MarkvEncoder::EncodeRefId(uint32_t id) {
+ // TODO(atgoo@github.com) This might not be needed as EncodeIdWithDescriptor
+ // can handle SpvOpAccessChain indices if enough statistics is collected.
+ if (inst_.opcode == SpvOpAccessChain && operand_index_ >= 3) {
+ const auto it = id_to_presumed_index_.find(id);
+ if (it != id_to_presumed_index_.end()) {
+ writer_.WriteBits(1, 1);
+ writer_.WriteFixedWidth(it->second, kMarkvMaxPresumedAccessIndex);
+ return SPV_SUCCESS;
+ }
+
+ writer_.WriteBits(0, 1);
+ }
+
+ {
+ // Try to encode using id descriptor mtfs.
+ const spv_result_t result = EncodeIdWithDescriptor(id);
+ if (result != SPV_UNSUPPORTED)
+ return result;
+ // If can't be done continue with other methods.
+ }
+
+ // Encode using rule-based mtf.
+ uint64_t mtf = GetRuleBasedMtf();
+ const bool can_forward_declare =
+ spvOperandCanBeForwardDeclaredFunction(
+ SpvOp(inst_.opcode))(operand_index_);
+
+ if (mtf != kMtfNone && !can_forward_declare) {
+ assert(multi_mtf_.HasValue(kMtfAll, id));
+ return EncodeExistingId(mtf, id);
+ }
+
+ if (mtf == kMtfNone)
+ mtf = kMtfAll;
+
+ uint32_t rank = 0;
+
+ if (!multi_mtf_.RankFromValue(mtf, id, &rank)) {
+ // This is the first occurrence of a forward declared id.
+ multi_mtf_.Insert(kMtfAll, id);
+ multi_mtf_.Insert(kMtfForwardDeclared, id);
+ if (mtf != kMtfAll)
+ multi_mtf_.Insert(mtf, id);
+ rank = 0;
+ }
+
+ return EncodeMtfRankHuffman(rank, mtf, kMtfAll);
+}
+
+spv_result_t MarkvDecoder::DecodeRefId(uint32_t* id) {
+ if (inst_.opcode == SpvOpAccessChain && operand_index_ >= 3) {
+ uint64_t use_presumed_index_technique = 0;
+ if (!reader_.ReadBits(&use_presumed_index_technique, 1))
+ return vstate_.diag(SPV_ERROR_INVALID_BINARY)
+ << "Failed to read use_presumed_index_technique flag";
+
+ if (use_presumed_index_technique) {
+ uint64_t value = 0;
+ if (!reader_.ReadFixedWidth(&value, kMarkvMaxPresumedAccessIndex))
+ return vstate_.diag(SPV_ERROR_INVALID_BINARY)
+ << "Failed to read presumed_index";
+
+ const uint32_t presumed_index = static_cast<uint32_t>(value);
+
+ const auto it = presumed_index_to_id_.find(presumed_index);
+ if (it == presumed_index_to_id_.end()) {
+ assert(0);
+ return vstate_.diag(SPV_ERROR_INTERNAL)
+ << "Presumed index id not found";
+ }
+
+ *id = it->second;
+ return SPV_SUCCESS;
+ }
+ }
+
+ {
+ const spv_result_t result = DecodeIdWithDescriptor(id);
+ if (result != SPV_UNSUPPORTED)
+ return result;
+ }
+
+ uint64_t mtf = GetRuleBasedMtf();
+ const bool can_forward_declare =
+ spvOperandCanBeForwardDeclaredFunction(
+ SpvOp(inst_.opcode))(operand_index_);
+
+ if (mtf != kMtfNone && !can_forward_declare) {
+ return DecodeExistingId(mtf, id);
+ }
+
+ if (mtf == kMtfNone)
+ mtf = kMtfAll;
+
+ *id = 0;
+
+ uint32_t rank = 0;
+
+ {
+ const spv_result_t result = DecodeMtfRankHuffman(mtf, kMtfAll, &rank);
+ if (result != SPV_SUCCESS)
+ return result;
+ }
+
+ if (rank == 0) {
+ // This is the first occurrence of a forward declared id.
+ *id = vstate_.getIdBound();
+ vstate_.setIdBound(*id + 1);
+ multi_mtf_.Insert(kMtfAll, *id);
+ multi_mtf_.Insert(kMtfForwardDeclared, *id);
+ if (mtf != kMtfAll)
+ multi_mtf_.Insert(mtf, *id);
+ } else {
+ if (!multi_mtf_.ValueFromRank(mtf, rank, id))
+ return vstate_.diag(SPV_ERROR_INTERNAL) << "MTF rank out of bounds";
+ }
+
+ assert(*id);
+ return SPV_SUCCESS;
+}
+
+spv_result_t MarkvEncoder::EncodeTypeId() {
+ if (inst_.opcode == SpvOpFunctionParameter) {
+ assert(!remaining_function_parameter_types_.empty());
+ assert(inst_.type_id == remaining_function_parameter_types_.front());
+ remaining_function_parameter_types_.pop_front();
+ return SPV_SUCCESS;
+ }
+
+ {
+ // Try to encode using id descriptor mtfs.
+ const spv_result_t result = EncodeIdWithDescriptor(inst_.type_id);
+ if (result != SPV_UNSUPPORTED)
+ return result;
+ // If can't be done continue with other methods.
+ }
+
+ uint64_t mtf = GetRuleBasedMtf();
+ assert(!spvOperandCanBeForwardDeclaredFunction(
+ SpvOp(inst_.opcode))(operand_index_));
+
+ if (mtf == kMtfNone) {
+ mtf = kMtfTypeNonFunction;
+ // Function types should have been handled by GetRuleBasedMtf.
+ assert(inst_.opcode != SpvOpFunction);
+ }
+
+ return EncodeExistingId(mtf, inst_.type_id);
+}
+
+spv_result_t MarkvDecoder::DecodeTypeId() {
+ if (inst_.opcode == SpvOpFunctionParameter) {
+ assert(!remaining_function_parameter_types_.empty());
+ inst_.type_id = remaining_function_parameter_types_.front();
+ remaining_function_parameter_types_.pop_front();
+ return SPV_SUCCESS;
+ }
+
+ {
+ const spv_result_t result = DecodeIdWithDescriptor(&inst_.type_id);
+ if (result != SPV_UNSUPPORTED)
+ return result;
+ }
+
+ uint64_t mtf = GetRuleBasedMtf();
+ assert(!spvOperandCanBeForwardDeclaredFunction(
+ SpvOp(inst_.opcode))(operand_index_));
+
+ if (mtf == kMtfNone) {
+ mtf = kMtfTypeNonFunction;
+ // Function types should have been handled by GetRuleBasedMtf.
+ assert(inst_.opcode != SpvOpFunction);
+ }
+
+ return DecodeExistingId(mtf, &inst_.type_id);
+}
+
+spv_result_t MarkvEncoder::EncodeResultId() {
+ uint32_t rank = 0;
+
+ const uint64_t num_still_forward_declared =
+ multi_mtf_.GetSize(kMtfForwardDeclared);
+
+ if (num_still_forward_declared) {
+ // We write the rank only if kMtfForwardDeclared is not empty. If it is
+ // empty the decoder knows that there are no forward declared ids to expect.
+ if (multi_mtf_.RankFromValue(kMtfForwardDeclared,
+ inst_.result_id, &rank)) {
+ // This is a definition of a forward declared id. We can remove the id
+ // from kMtfForwardDeclared.
+ if (!multi_mtf_.Remove(kMtfForwardDeclared, inst_.result_id))
+ return vstate_.diag(SPV_ERROR_INTERNAL)
+ << "Failed to remove id from kMtfForwardDeclared";
+ writer_.WriteBits(1, 1);
+ writer_.WriteVariableWidthU32(
+ rank, model_->mtf_rank_chunk_length());
+ } else {
+ rank = 0;
+ writer_.WriteBits(0, 1);
+ }
+ }
+
+ if (!rank) {
+ multi_mtf_.Insert(kMtfAll, inst_.result_id);
+ }
+
+ return SPV_SUCCESS;
+}
+
+spv_result_t MarkvDecoder::DecodeResultId() {
+ uint32_t rank = 0;
+
+ const uint64_t num_still_forward_declared =
+ multi_mtf_.GetSize(kMtfForwardDeclared);
+
+ if (num_still_forward_declared) {
+ // Some ids were forward declared. Check if this id is one of them.
+ uint64_t id_was_forward_declared;
+ if (!reader_.ReadBits(&id_was_forward_declared, 1))
+ return vstate_.diag(SPV_ERROR_INVALID_BINARY)
+ << "Failed to read id_was_forward_declared flag";
+
+ if (id_was_forward_declared) {
+ if (!reader_.ReadVariableWidthU32(
+ &rank, model_->mtf_rank_chunk_length()))
+ return vstate_.diag(SPV_ERROR_INVALID_BINARY)
+ << "Failed to read MTF rank of forward declared id";
+
+ if (rank) {
+ // The id was forward declared, recover it from kMtfForwardDeclared.
+ if (!multi_mtf_.ValueFromRank(kMtfForwardDeclared,
+ rank, &inst_.result_id))
+ return vstate_.diag(SPV_ERROR_INTERNAL)
+ << "Forward declared MTF rank is out of bounds";
+
+ // We can now remove the id from kMtfForwardDeclared.
+ if (!multi_mtf_.Remove(kMtfForwardDeclared, inst_.result_id))
+ return vstate_.diag(SPV_ERROR_INTERNAL)
+ << "Failed to remove id from kMtfForwardDeclared";
+ }
+ }
+ }
+
+ if (inst_.result_id == 0) {
+ // The id was not forward declared, issue a new id.
+ inst_.result_id = vstate_.getIdBound();
+ vstate_.setIdBound(inst_.result_id + 1);
+ }
+
+ if (!rank) {
+ multi_mtf_.Insert(kMtfAll, inst_.result_id);
+ }
+
+ return SPV_SUCCESS;
+}
+
+spv_result_t MarkvEncoder::EncodeLiteralNumber(
+ const Instruction& instruction, const spv_parsed_operand_t& operand) {
+ if (operand.number_bit_width <= 32) {
+ const uint32_t word = instruction.word(operand.offset);
+ return EncodeNonIdWord(word);
+ } else {
+ assert(operand.number_bit_width <= 64);
+ const uint64_t word =
+ uint64_t(instruction.word(operand.offset)) |
+ (uint64_t(instruction.word(operand.offset + 1)) << 32);
+ if (operand.number_kind == SPV_NUMBER_UNSIGNED_INT) {
+ writer_.WriteVariableWidthU64(word, model_->u64_chunk_length());
+ } else if (operand.number_kind == SPV_NUMBER_SIGNED_INT) {
+ int64_t val = 0;
+ std::memcpy(&val, &word, 8);
+ writer_.WriteVariableWidthS64(val, model_->s64_chunk_length(),
+ model_->s64_block_exponent());
+ } else if (operand.number_kind == SPV_NUMBER_FLOATING) {
+ writer_.WriteUnencoded(word);
+ } else {
+ return vstate_.diag(SPV_ERROR_INTERNAL) << "Unsupported bit length";
+ }
+ }
+ return SPV_SUCCESS;
+}
+
+spv_result_t MarkvDecoder::DecodeLiteralNumber(
+ const spv_parsed_operand_t& operand) {
+ if (operand.number_bit_width <= 32) {
+ uint32_t word = 0;
+ const spv_result_t result = DecodeNonIdWord(&word);
+ if (result != SPV_SUCCESS)
+ return result;
+ inst_words_.push_back(word);
+ } else {
+ assert(operand.number_bit_width <= 64);
+ uint64_t word = 0;
+ if (operand.number_kind == SPV_NUMBER_UNSIGNED_INT) {
+ if (!reader_.ReadVariableWidthU64(&word, model_->u64_chunk_length()))
+ return vstate_.diag(SPV_ERROR_INVALID_BINARY)
+ << "Failed to read literal U64";
+ } else if (operand.number_kind == SPV_NUMBER_SIGNED_INT) {
+ int64_t val = 0;
+ if (!reader_.ReadVariableWidthS64(&val, model_->s64_chunk_length(),
+ model_->s64_block_exponent()))
+ return vstate_.diag(SPV_ERROR_INVALID_BINARY)
+ << "Failed to read literal S64";
+ std::memcpy(&word, &val, 8);
+ } else if (operand.number_kind == SPV_NUMBER_FLOATING) {
+ if (!reader_.ReadUnencoded(&word))
+ return vstate_.diag(SPV_ERROR_INVALID_BINARY)
+ << "Failed to read literal F64";
+ } else {
+ return vstate_.diag(SPV_ERROR_INTERNAL) << "Unsupported bit length";
+ }
+ inst_words_.push_back(static_cast<uint32_t>(word));
+ inst_words_.push_back(static_cast<uint32_t>(word >> 32));
+ }
+ return SPV_SUCCESS;
+}
+
+void MarkvEncoder::AddByteBreak(size_t byte_break_if_less_than) {
+ const size_t num_bits_to_next_byte =
+ GetNumBitsToNextByte(writer_.GetNumBits());
+ if (num_bits_to_next_byte == 0 ||
+ num_bits_to_next_byte > byte_break_if_less_than)
+ return;
+
+ if (logger_) {
+ logger_->AppendWhitespaces(kCommentNumWhitespaces);
+ logger_->AppendText("<byte break>");
+ }
+
+ writer_.WriteBits(0, num_bits_to_next_byte);
+}
+
+bool MarkvDecoder::ReadToByteBreak(size_t byte_break_if_less_than) {
+ const size_t num_bits_to_next_byte =
+ GetNumBitsToNextByte(reader_.GetNumReadBits());
+ if (num_bits_to_next_byte == 0 ||
+ num_bits_to_next_byte > byte_break_if_less_than)
+ return true;
+
+
+ uint64_t bits = 0;
+ if (!reader_.ReadBits(&bits, num_bits_to_next_byte))
+ return false;
+
+ assert(bits == 0);
+ if (bits != 0)
+ return false;
+
+ return true;
+}
+
+spv_result_t MarkvEncoder::EncodeInstruction(
+ const spv_parsed_instruction_t& inst) {
+ SpvOp opcode = SpvOp(inst.opcode);
+ inst_ = inst;
+
+ const spv_result_t validation_result = UpdateValidationState(inst);
+ if (validation_result != SPV_SUCCESS)
+ return validation_result;
+
+ const Instruction& instruction = vstate_.ordered_instructions().back();
+ const auto& operands = instruction.operands();
+
+ LogDisassemblyInstruction();
+
+ const spv_result_t opcode_encodig_result =
+ EncodeOpcodeAndNumOperands(opcode, inst.num_operands);
+ if (opcode_encodig_result < 0)
+ return opcode_encodig_result;
+
+ if (opcode_encodig_result != SPV_SUCCESS) {
+ // Fallback encoding for opcode and num_operands.
+ writer_.WriteVariableWidthU32(opcode, model_->opcode_chunk_length());
+
+ if (!OpcodeHasFixedNumberOfOperands(opcode)) {
+ // If the opcode has a variable number of operands, encode the number of
+ // operands with the instruction.
+
+ if (logger_)
+ logger_->AppendWhitespaces(kCommentNumWhitespaces);
+
+ writer_.WriteVariableWidthU16(inst.num_operands,
+ model_->num_operands_chunk_length());
+ }
+ }
+
+ // Write operands.
+ for (operand_index_ = 0; operand_index_ < operands.size(); ++operand_index_) {
+ operand_ = operands[operand_index_];
+
+ if (logger_) {
+ logger_->AppendWhitespaces(kCommentNumWhitespaces);
+ logger_->AppendText("<");
+ logger_->AppendText(spvOperandTypeStr(operand_.type));
+ logger_->AppendText(">");
+ }
+
+ switch (operand_.type) {
+ case SPV_OPERAND_TYPE_RESULT_ID:
+ case SPV_OPERAND_TYPE_TYPE_ID:
+ case SPV_OPERAND_TYPE_ID:
+ case SPV_OPERAND_TYPE_OPTIONAL_ID:
+ case SPV_OPERAND_TYPE_SCOPE_ID:
+ case SPV_OPERAND_TYPE_MEMORY_SEMANTICS_ID: {
+ const uint32_t id = instruction.word(operand_.offset);
+ if (operand_.type == SPV_OPERAND_TYPE_TYPE_ID) {
+ const spv_result_t result = EncodeTypeId();
+ if (result != SPV_SUCCESS)
+ return result;
+ } else if (operand_.type == SPV_OPERAND_TYPE_RESULT_ID) {
+ const spv_result_t result = EncodeResultId();
+ if (result != SPV_SUCCESS)
+ return result;
+ } else {
+ const spv_result_t result = EncodeRefId(id);
+ if (result != SPV_SUCCESS)
+ return result;
+ }
+
+ multi_mtf_.Promote(id);
+ break;
+ }
+
+ case SPV_OPERAND_TYPE_LITERAL_INTEGER: {
+ const spv_result_t result =
+ EncodeNonIdWord(instruction.word(operand_.offset));
+ if (result != SPV_SUCCESS)
+ return result;
+ break;
+ }
+
+ case SPV_OPERAND_TYPE_TYPED_LITERAL_NUMBER: {
+ const spv_result_t result = EncodeLiteralNumber(instruction, operand_);
+ if (result != SPV_SUCCESS)
+ return result;
+ break;
+ }
+
+ case SPV_OPERAND_TYPE_LITERAL_STRING: {
+ const char* src = reinterpret_cast<const char*>(
+ &instruction.words()[operand_.offset]);
+
+ auto* codec = model_->GetLiteralStringHuffmanCodec(opcode);
+ if (codec) {
+ uint64_t bits = 0;
+ size_t num_bits = 0;
+ const std::string str = reinterpret_cast<const char*>(
+ &instruction.words()[operand_.offset]);
+ if (codec->Encode(str, &bits, &num_bits)) {
+ writer_.WriteBits(bits, num_bits);
+ break;
+ } else {
+ bool result = codec->Encode("kMarkvNoneOfTheAbove",
+ &bits, &num_bits);
+ (void)result;
+ assert(result);
+ writer_.WriteBits(bits, num_bits);
+ }
+ }
+
+ const size_t length = spv_strnlen_s(src, operand_.num_words * 4);
+ if (length == operand_.num_words * 4)
+ return vstate_.diag(SPV_ERROR_INVALID_BINARY)
+ << "Failed to find terminal character of literal string";
+ for (size_t i = 0; i < length + 1; ++i)
+ writer_.WriteUnencoded(src[i]);
+ break;
+ }
+
+ default: {
+ for (int i = 0; i < operand_.num_words; ++i) {
+ const uint32_t word = instruction.word(operand_.offset + i);
+ const spv_result_t result = EncodeNonIdWord(word);
+ if (result != SPV_SUCCESS)
+ return result;
+ }
+ break;
+ }
+ }
+ }
+
+ AddByteBreak(kByteBreakAfterInstIfLessThanUntilNextByte);
+
+ if (logger_) {
+ logger_->NewLine();
+ logger_->NewLine();
+ }
+
+ ProcessCurInstruction();
+ instructions_.push_back(&instruction);
+
+ return SPV_SUCCESS;
+}
+
+spv_result_t MarkvDecoder::DecodeModule(std::vector<uint32_t>* spirv_binary) {
+ const bool header_read_success =
+ reader_.ReadUnencoded(&header_.magic_number) &&
+ reader_.ReadUnencoded(&header_.markv_version) &&
+ reader_.ReadUnencoded(&header_.markv_model) &&
+ reader_.ReadUnencoded(&header_.markv_length_in_bits) &&
+ reader_.ReadUnencoded(&header_.spirv_version) &&
+ reader_.ReadUnencoded(&header_.spirv_generator);
+
+ if (!header_read_success)
+ return vstate_.diag(SPV_ERROR_INVALID_BINARY)
+ << "Unable to read MARK-V header";
+
+ if (header_.markv_length_in_bits == 0)
+ return vstate_.diag(SPV_ERROR_INVALID_BINARY)
+ << "Header markv_length_in_bits field is zero";
+
+ if (header_.magic_number != kMarkvMagicNumber)
+ return vstate_.diag(SPV_ERROR_INVALID_BINARY)
+ << "MARK-V binary has incorrect magic number";
+
+ // TODO(atgoo@github.com): Print version strings.
+ if (header_.markv_version != GetMarkvVersion())
+ return vstate_.diag(SPV_ERROR_INVALID_BINARY)
+ << "MARK-V binary and the codec have different versions";
+
+ spirv_.reserve(header_.markv_length_in_bits / 2); // Heuristic.
+ spirv_.resize(5, 0);
+ spirv_[0] = kSpirvMagicNumber;
+ spirv_[1] = header_.spirv_version;
+ spirv_[2] = header_.spirv_generator;
+
+ while (reader_.GetNumReadBits() < header_.markv_length_in_bits) {
+ inst_ = {};
+ const spv_result_t decode_result = DecodeInstruction();
if (decode_result != SPV_SUCCESS)
return decode_result;
- const spv_result_t validation_result = UpdateValidationState(inst);
+ const spv_result_t validation_result = UpdateValidationState(inst_);
if (validation_result != SPV_SUCCESS)
return validation_result;
+
+ instructions_.push_back(&vstate_.ordered_instructions().back());
}
// For now it's better to keep the code independent for experimentation
// purposes.
spv_result_t MarkvDecoder::DecodeOperand(
- size_t instruction_offset, size_t operand_offset,
- spv_parsed_instruction_t* inst, const spv_operand_type_t type,
- spv_operand_pattern_t* expected_operands,
- bool read_result_id) {
- const SpvOp opcode = static_cast<SpvOp>(inst->opcode);
+ size_t operand_offset,
+ const spv_operand_type_t type,
+ spv_operand_pattern_t* expected_operands) {
+ const SpvOp opcode = static_cast<SpvOp>(inst_.opcode);
- spv_parsed_operand_t parsed_operand;
- memset(&parsed_operand, 0, sizeof(parsed_operand));
+ memset(&operand_, 0, sizeof(operand_));
assert((operand_offset >> 16) == 0);
- parsed_operand.offset = static_cast<uint16_t>(operand_offset);
- parsed_operand.type = type;
+ operand_.offset = static_cast<uint16_t>(operand_offset);
+ operand_.type = type;
// Set default values, may be updated later.
- parsed_operand.number_kind = SPV_NUMBER_NONE;
- parsed_operand.number_bit_width = 0;
+ operand_.number_kind = SPV_NUMBER_NONE;
+ operand_.number_bit_width = 0;
- const size_t first_word_index = spirv_.size();
+ const size_t first_word_index = inst_words_.size();
switch (type) {
- case SPV_OPERAND_TYPE_TYPE_ID: {
- if (!DecodeId(&inst->type_id)) {
- return vstate_.diag(SPV_ERROR_INVALID_BINARY)
- << "Failed to read type_id";
- }
-
- if (inst->type_id == 0)
- return vstate_.diag(SPV_ERROR_INVALID_BINARY) << "Decoded type_id is 0";
+ case SPV_OPERAND_TYPE_RESULT_ID: {
+ const spv_result_t result = DecodeResultId();
+ if (result != SPV_SUCCESS)
+ return result;
- spirv_.push_back(inst->type_id);
- vstate_.setIdBound(std::max(vstate_.getIdBound(), inst->type_id + 1));
+ inst_words_.push_back(inst_.result_id);
+ vstate_.setIdBound(std::max(vstate_.getIdBound(), inst_.result_id + 1));
+ multi_mtf_.Promote(inst_.result_id);
break;
}
- case SPV_OPERAND_TYPE_RESULT_ID: {
- if (read_result_id) {
- if (!DecodeId(&inst->result_id))
- return vstate_.diag(SPV_ERROR_INVALID_BINARY)
- << "Failed to read result_id";
- } else {
- inst->result_id = vstate_.getIdBound();
- vstate_.setIdBound(inst->result_id + 1);
- move_to_front_ids_.push_front(inst->result_id);
- }
+ case SPV_OPERAND_TYPE_TYPE_ID: {
+ const spv_result_t result = DecodeTypeId();
+ if (result != SPV_SUCCESS)
+ return result;
- spirv_.push_back(inst->result_id);
-
- // Save the result ID to type ID mapping.
- // In the grammar, type ID always appears before result ID.
- // A regular value maps to its type. Some instructions (e.g. OpLabel)
- // have no type Id, and will map to 0. The result Id for a
- // type-generating instruction (e.g. OpTypeInt) maps to itself.
- auto insertion_result = id_to_type_id_.emplace(
- inst->result_id,
- spvOpcodeGeneratesType(opcode) ? inst->result_id : inst->type_id);
- if(!insertion_result.second) {
- return vstate_.diag(SPV_ERROR_INVALID_ID)
- << "Unexpected behavior: id->type_id pair was already registered";
- }
+ inst_words_.push_back(inst_.type_id);
+ vstate_.setIdBound(std::max(vstate_.getIdBound(), inst_.type_id + 1));
+ multi_mtf_.Promote(inst_.type_id);
break;
}
case SPV_OPERAND_TYPE_SCOPE_ID:
case SPV_OPERAND_TYPE_MEMORY_SEMANTICS_ID: {
uint32_t id = 0;
- if (!DecodeId(&id))
- return vstate_.diag(SPV_ERROR_INVALID_BINARY) << "Failed to read id";
+ const spv_result_t result = DecodeRefId(&id);
+ if (result != SPV_SUCCESS)
+ return result;
if (id == 0)
return vstate_.diag(SPV_ERROR_INVALID_BINARY) << "Decoded id is 0";
- spirv_.push_back(id);
- vstate_.setIdBound(std::max(vstate_.getIdBound(), id + 1));
+ if (type == SPV_OPERAND_TYPE_ID ||
+ type == SPV_OPERAND_TYPE_OPTIONAL_ID) {
- if (type == SPV_OPERAND_TYPE_ID || type == SPV_OPERAND_TYPE_OPTIONAL_ID) {
+ operand_.type = SPV_OPERAND_TYPE_ID;
- parsed_operand.type = SPV_OPERAND_TYPE_ID;
-
- if (opcode == SpvOpExtInst && parsed_operand.offset == 3) {
+ if (opcode == SpvOpExtInst && operand_.offset == 3) {
// The current word is the extended instruction set id.
- // Set the extended instruction set type for the current instruction.
+ // Set the extended instruction set type for the current
+ // instruction.
auto ext_inst_type_iter = import_id_to_ext_inst_type_.find(id);
if (ext_inst_type_iter == import_id_to_ext_inst_type_.end()) {
return vstate_.diag(SPV_ERROR_INVALID_ID)
<< "OpExtInst set id " << id
<< " does not reference an OpExtInstImport result Id";
}
- inst->ext_inst_type = ext_inst_type_iter->second;
+ inst_.ext_inst_type = ext_inst_type_iter->second;
}
}
+
+ inst_words_.push_back(id);
+ vstate_.setIdBound(std::max(vstate_.getIdBound(), id + 1));
+ multi_mtf_.Promote(id);
break;
}
case SPV_OPERAND_TYPE_EXTENSION_INSTRUCTION_NUMBER: {
uint32_t word = 0;
- if (!DecodeOperandWord(type, &word))
- return vstate_.diag(SPV_ERROR_INVALID_BINARY)
- << "Failed to read enum";
+ const spv_result_t result = DecodeNonIdWord(&word);
+ if (result != SPV_SUCCESS)
+ return result;
- spirv_.push_back(word);
+ inst_words_.push_back(word);
assert(SpvOpExtInst == opcode);
- assert(inst->ext_inst_type != SPV_EXT_INST_TYPE_NONE);
+ assert(inst_.ext_inst_type != SPV_EXT_INST_TYPE_NONE);
spv_ext_inst_desc ext_inst;
- if (grammar_.lookupExtInst(inst->ext_inst_type, word, &ext_inst))
+ if (grammar_.lookupExtInst(inst_.ext_inst_type, word, &ext_inst))
return vstate_.diag(SPV_ERROR_INVALID_BINARY)
<< "Invalid extended instruction number: " << word;
spvPushOperandTypes(ext_inst->operandTypes, expected_operands);
case SPV_OPERAND_TYPE_OPTIONAL_LITERAL_INTEGER: {
// These are regular single-word literal integer operands.
// Post-parsing validation should check the range of the parsed value.
- parsed_operand.type = SPV_OPERAND_TYPE_LITERAL_INTEGER;
+ operand_.type = SPV_OPERAND_TYPE_LITERAL_INTEGER;
// It turns out they are always unsigned integers!
- parsed_operand.number_kind = SPV_NUMBER_UNSIGNED_INT;
- parsed_operand.number_bit_width = 32;
+ operand_.number_kind = SPV_NUMBER_UNSIGNED_INT;
+ operand_.number_bit_width = 32;
uint32_t word = 0;
- if (!DecodeOperandWord(type, &word))
- return vstate_.diag(SPV_ERROR_INVALID_BINARY)
- << "Failed to read literal integer";
+ const spv_result_t result = DecodeNonIdWord(&word);
+ if (result != SPV_SUCCESS)
+ return result;
- spirv_.push_back(word);
+ inst_words_.push_back(word);
break;
}
case SPV_OPERAND_TYPE_TYPED_LITERAL_NUMBER:
- case SPV_OPERAND_TYPE_OPTIONAL_TYPED_LITERAL_INTEGER:
- parsed_operand.type = SPV_OPERAND_TYPE_TYPED_LITERAL_NUMBER;
+ case SPV_OPERAND_TYPE_OPTIONAL_TYPED_LITERAL_INTEGER: {
+ operand_.type = SPV_OPERAND_TYPE_TYPED_LITERAL_NUMBER;
if (opcode == SpvOpSwitch) {
// The literal operands have the same type as the value
// referenced by the selector Id.
- const uint32_t selector_id = spirv_.at(instruction_offset + 1);
+ const uint32_t selector_id = inst_words_.at(1);
const auto type_id_iter = id_to_type_id_.find(selector_id);
if (type_id_iter == id_to_type_id_.end() ||
type_id_iter->second == 0) {
<< "Invalid OpSwitch: selector id " << selector_id
<< " is a type, not a value";
}
- if (auto error = SetNumericTypeInfoForType(&parsed_operand, type_id))
+ if (auto error = SetNumericTypeInfoForType(&operand_, type_id))
return error;
- if (parsed_operand.number_kind != SPV_NUMBER_UNSIGNED_INT &&
- parsed_operand.number_kind != SPV_NUMBER_SIGNED_INT) {
+ if (operand_.number_kind != SPV_NUMBER_UNSIGNED_INT &&
+ operand_.number_kind != SPV_NUMBER_SIGNED_INT) {
return vstate_.diag(SPV_ERROR_INVALID_BINARY)
<< "Invalid OpSwitch: selector id " << selector_id
<< " is not a scalar integer";
assert(opcode == SpvOpConstant || opcode == SpvOpSpecConstant);
// The literal number type is determined by the type Id for the
// constant.
- assert(inst->type_id);
- if (auto error =
- SetNumericTypeInfoForType(&parsed_operand, inst->type_id))
+ assert(inst_.type_id);
+ if (auto error = SetNumericTypeInfoForType(&operand_, inst_.type_id))
return error;
}
- if (auto error = DecodeLiteralNumber(parsed_operand))
+ if (auto error = DecodeLiteralNumber(operand_))
return error;
break;
+ }
case SPV_OPERAND_TYPE_LITERAL_STRING:
case SPV_OPERAND_TYPE_OPTIONAL_LITERAL_STRING: {
- parsed_operand.type = SPV_OPERAND_TYPE_LITERAL_STRING;
+ operand_.type = SPV_OPERAND_TYPE_LITERAL_STRING;
std::vector<char> str;
- // The loop is expected to terminate once we encounter '\0' or exhaust
- // the bit stream.
- while (true) {
- char ch = 0;
- if (!reader_.ReadUnencoded(&ch))
+ auto* codec = model_->GetLiteralStringHuffmanCodec(inst_.opcode);
+
+ if (codec) {
+ std::string decoded_string;
+ const bool huffman_result =
+ codec->DecodeFromStream(GetReadBitCallback(), &decoded_string);
+ assert(huffman_result);
+ if (!huffman_result)
return vstate_.diag(SPV_ERROR_INVALID_BINARY)
<< "Failed to read literal string";
- str.push_back(ch);
+ if (decoded_string != "kMarkvNoneOfTheAbove") {
+ std::copy(decoded_string.begin(), decoded_string.end(),
+ std::back_inserter(str));
+ str.push_back('\0');
+ }
+ }
+
+ // The loop is expected to terminate once we encounter '\0' or exhaust
+ // the bit stream.
+ if (str.empty()) {
+ while (true) {
+ char ch = 0;
+ if (!reader_.ReadUnencoded(&ch))
+ return vstate_.diag(SPV_ERROR_INVALID_BINARY)
+ << "Failed to read literal string";
+
+ str.push_back(ch);
- if (ch == '\0')
- break;
+ if (ch == '\0')
+ break;
+ }
}
while (str.size() % 4 != 0)
str.push_back('\0');
- spirv_.resize(spirv_.size() + str.size() / 4);
- std::memcpy(&spirv_[first_word_index], str.data(), str.size());
+ inst_words_.resize(inst_words_.size() + str.size() / 4);
+ std::memcpy(&inst_words_[first_word_index], str.data(), str.size());
if (SpvOpExtInstImport == opcode) {
// Record the extended instruction type for the ID for this import.
}
// We must have parsed a valid result ID. It's a condition
// of the grammar, and we only accept non-zero result Ids.
- assert(inst->result_id);
+ assert(inst_.result_id);
const bool inserted = import_id_to_ext_inst_type_.emplace(
- inst->result_id, ext_inst_type).second;
+ inst_.result_id, ext_inst_type).second;
(void)inserted;
assert(inserted);
}
case SPV_OPERAND_TYPE_KERNEL_PROFILING_INFO: {
// A single word that is a plain enum value.
uint32_t word = 0;
- if (!DecodeOperandWord(type, &word))
- return vstate_.diag(SPV_ERROR_INVALID_BINARY)
- << "Failed to read enum";
+ const spv_result_t result = DecodeNonIdWord(&word);
+ if (result != SPV_SUCCESS)
+ return result;
- spirv_.push_back(word);
+ inst_words_.push_back(word);
// Map an optional operand type to its corresponding concrete type.
if (type == SPV_OPERAND_TYPE_OPTIONAL_ACCESS_QUALIFIER)
- parsed_operand.type = SPV_OPERAND_TYPE_ACCESS_QUALIFIER;
+ operand_.type = SPV_OPERAND_TYPE_ACCESS_QUALIFIER;
spv_operand_desc entry;
if (grammar_.lookupOperand(type, word, &entry)) {
return vstate_.diag(SPV_ERROR_INVALID_BINARY)
<< "Invalid "
- << spvOperandTypeStr(parsed_operand.type)
+ << spvOperandTypeStr(operand_.type)
<< " operand: " << word;
}
case SPV_OPERAND_TYPE_SELECTION_CONTROL: {
// This operand is a mask.
uint32_t word = 0;
- if (!DecodeOperandWord(type, &word))
- return vstate_.diag(SPV_ERROR_INVALID_BINARY)
- << "Failed to read " << spvOperandTypeStr(type)
- << " for " << spvOpcodeString(SpvOp(inst->opcode));
+ const spv_result_t result = DecodeNonIdWord(&word);
+ if (result != SPV_SUCCESS)
+ return result;
- spirv_.push_back(word);
+ inst_words_.push_back(word);
// Map an optional operand type to its corresponding concrete type.
if (type == SPV_OPERAND_TYPE_OPTIONAL_IMAGE)
- parsed_operand.type = SPV_OPERAND_TYPE_IMAGE;
+ operand_.type = SPV_OPERAND_TYPE_IMAGE;
else if (type == SPV_OPERAND_TYPE_OPTIONAL_MEMORY_ACCESS)
- parsed_operand.type = SPV_OPERAND_TYPE_MEMORY_ACCESS;
+ operand_.type = SPV_OPERAND_TYPE_MEMORY_ACCESS;
// Check validity of set mask bits. Also prepare for operands for those
// masks if they have any. To get operand order correct, scan from
spv_operand_desc entry;
if (grammar_.lookupOperand(type, mask, &entry)) {
return vstate_.diag(SPV_ERROR_INVALID_BINARY)
- << "Invalid " << spvOperandTypeStr(parsed_operand.type)
+ << "Invalid " << spvOperandTypeStr(operand_.type)
<< " operand: " << word << " has invalid mask component "
<< mask;
}
<< "Internal error: Unhandled operand type: " << type;
}
- parsed_operand.num_words = uint16_t(spirv_.size() - first_word_index);
+ operand_.num_words = uint16_t(inst_words_.size() - first_word_index);
- assert(int(SPV_OPERAND_TYPE_FIRST_CONCRETE_TYPE) <= int(parsed_operand.type));
- assert(int(SPV_OPERAND_TYPE_LAST_CONCRETE_TYPE) >= int(parsed_operand.type));
+ assert(int(SPV_OPERAND_TYPE_FIRST_CONCRETE_TYPE) <= int(operand_.type));
+ assert(int(SPV_OPERAND_TYPE_LAST_CONCRETE_TYPE) >= int(operand_.type));
- parsed_operands_.push_back(parsed_operand);
+ parsed_operands_.push_back(operand_);
return SPV_SUCCESS;
}
-spv_result_t MarkvDecoder::DecodeInstruction(spv_parsed_instruction_t* inst) {
+spv_result_t MarkvDecoder::DecodeInstruction() {
parsed_operands_.clear();
- const size_t instruction_offset = spirv_.size();
+ inst_words_.clear();
- bool read_result_id = false;
+ // Opcode/num_words placeholder, the word will be filled in later.
+ inst_words_.push_back(0);
- while (true) {
- uint32_t word = 0;
- if (!reader_.ReadVariableWidthU32(&word,
- model_->opcode_chunk_length())) {
- return vstate_.diag(SPV_ERROR_INVALID_BINARY)
- << "Failed to read opcode of instruction";
- }
+ bool num_operands_still_unknown = true;
+ {
+ uint32_t opcode = 0;
+ uint32_t num_operands = 0;
- if (word >= kMarkvFirstOpcode) {
- if (word == kMarkvOpNextInstructionEncodesResultId) {
- read_result_id = true;
- } else {
+ const spv_result_t opcode_decoding_result =
+ DecodeOpcodeAndNumberOfOperands(&opcode, &num_operands);
+ if (opcode_decoding_result < 0)
+ return opcode_decoding_result;
+
+ if (opcode_decoding_result == SPV_SUCCESS) {
+ inst_.num_operands = static_cast<uint16_t>(num_operands);
+ num_operands_still_unknown = false;
+ } else {
+ if (!reader_.ReadVariableWidthU32(
+ &opcode, model_->opcode_chunk_length())) {
return vstate_.diag(SPV_ERROR_INVALID_BINARY)
- << "Encountered unknown MARK-V opcode";
+ << "Failed to read opcode of instruction";
}
- } else {
- inst->opcode = static_cast<uint16_t>(word);
- break;
}
- }
- const SpvOp opcode = static_cast<SpvOp>(inst->opcode);
+ inst_.opcode = static_cast<uint16_t>(opcode);
+ }
- // Opcode/num_words placeholder, the word will be filled in later.
- spirv_.push_back(0);
+ const SpvOp opcode = static_cast<SpvOp>(inst_.opcode);
spv_opcode_desc opcode_desc;
- if (grammar_.lookupOpcode(opcode, &opcode_desc)
- != SPV_SUCCESS) {
+ if (grammar_.lookupOpcode(opcode, &opcode_desc) != SPV_SUCCESS) {
return vstate_.diag(SPV_ERROR_INVALID_BINARY) << "Invalid opcode";
}
spv_operand_pattern_t expected_operands;
expected_operands.reserve(opcode_desc->numTypes);
- for (auto i = 0; i < opcode_desc->numTypes; i++)
- expected_operands.push_back(opcode_desc->operandTypes[opcode_desc->numTypes - i - 1]);
+ for (auto i = 0; i < opcode_desc->numTypes; i++) {
+ expected_operands.push_back(
+ opcode_desc->operandTypes[opcode_desc->numTypes - i - 1]);
+ }
- if (!OpcodeHasFixedNumberOfOperands(opcode)) {
- if (!reader_.ReadVariableWidthU16(&inst->num_operands,
- model_->num_operands_chunk_length()))
- return vstate_.diag(SPV_ERROR_INVALID_BINARY)
- << "Failed to read num_operands of instruction";
- } else {
- inst->num_operands = static_cast<uint16_t>(expected_operands.size());
+ if (num_operands_still_unknown) {
+ if (!OpcodeHasFixedNumberOfOperands(opcode)) {
+ if (!reader_.ReadVariableWidthU16(&inst_.num_operands,
+ model_->num_operands_chunk_length()))
+ return vstate_.diag(SPV_ERROR_INVALID_BINARY)
+ << "Failed to read num_operands of instruction";
+ } else {
+ inst_.num_operands = static_cast<uint16_t>(expected_operands.size());
+ }
}
- for (size_t operand_index = 0;
- operand_index < static_cast<size_t>(inst->num_operands);
- ++operand_index) {
+ for (operand_index_ = 0;
+ operand_index_ < static_cast<size_t>(inst_.num_operands);
+ ++operand_index_) {
assert(!expected_operands.empty());
const spv_operand_type_t type =
spvTakeFirstMatchableOperand(&expected_operands);
- const size_t operand_offset = spirv_.size() - instruction_offset;
+ const size_t operand_offset = inst_words_.size();
- const spv_result_t decode_result =
- DecodeOperand(instruction_offset, operand_offset, inst, type,
- &expected_operands, read_result_id);
+ const spv_result_t decode_result = DecodeOperand(
+ operand_offset, type, &expected_operands);
if (decode_result != SPV_SUCCESS)
return decode_result;
}
- assert(inst->num_operands == parsed_operands_.size());
- // Only valid while spirv_ and parsed_operands_ remain unchanged.
- inst->words = &spirv_[instruction_offset];
- inst->operands = parsed_operands_.empty() ? nullptr : parsed_operands_.data();
- inst->num_words = static_cast<uint16_t>(spirv_.size() - instruction_offset);
- spirv_[instruction_offset] =
- spvOpcodeMake(inst->num_words, SpvOp(inst->opcode));
+ assert(inst_.num_operands == parsed_operands_.size());
+
+ // Only valid while inst_words_ and parsed_operands_ remain unchanged (until
+ // next DecodeInstruction call).
+ inst_.words = inst_words_.data();
+ inst_.operands = parsed_operands_.empty() ? nullptr : parsed_operands_.data();
+ inst_.num_words = static_cast<uint16_t>(inst_words_.size());
+ inst_words_[0] = spvOpcodeMake(inst_.num_words, SpvOp(inst_.opcode));
+
+ std::copy(inst_words_.begin(), inst_words_.end(), std::back_inserter(spirv_));
- assert(inst->num_words == std::accumulate(
+ assert(inst_.num_words == std::accumulate(
parsed_operands_.begin(), parsed_operands_.end(), 1,
[](int num_words, const spv_parsed_operand_t& operand) {
return num_words += operand.num_words;
}) && "num_words in instruction doesn't correspond to the sum of num_words"
"in the operands");
- RecordNumberType(*inst);
+ RecordNumberType();
+ ProcessCurInstruction();
- if (!ReadToByteBreakIfAgreed())
+ if (!ReadToByteBreak(kByteBreakAfterInstIfLessThanUntilNextByte))
return vstate_.diag(SPV_ERROR_INVALID_BINARY)
<< "Failed to read to byte break";
return SPV_SUCCESS;
}
-void MarkvDecoder::RecordNumberType(const spv_parsed_instruction_t& inst) {
- const SpvOp opcode = static_cast<SpvOp>(inst.opcode);
+void MarkvDecoder::RecordNumberType() {
+ const SpvOp opcode = static_cast<SpvOp>(inst_.opcode);
if (spvOpcodeGeneratesType(opcode)) {
NumberType info = {SPV_NUMBER_NONE, 0};
if (SpvOpTypeInt == opcode) {
- info.bit_width = inst.words[inst.operands[1].offset];
- info.type = inst.words[inst.operands[2].offset] ?
+ info.bit_width = inst_.words[inst_.operands[1].offset];
+ info.type = inst_.words[inst_.operands[2].offset] ?
SPV_NUMBER_SIGNED_INT : SPV_NUMBER_UNSIGNED_INT;
} else if (SpvOpTypeFloat == opcode) {
- info.bit_width = inst.words[inst.operands[1].offset];
+ info.bit_width = inst_.words[inst_.operands[1].offset];
info.type = SPV_NUMBER_FLOATING;
}
// The *result* Id of a type generating instruction is the type Id.
- type_id_to_number_type_info_[inst.result_id] = info;
+ type_id_to_number_type_info_[inst_.result_id] = info;
}
}
size_t markv_size_bytes,
spv_const_markv_decoder_options options,
spv_binary* spirv_binary,
- spv_text* /* comments */, spv_diagnostic* diagnostic) {
+ spv_text* /* comments */,
+ spv_diagnostic* diagnostic) {
spv_position_t position = {};
spv_context_t hijack_context = *context;
if (diagnostic) {