//===----------------------------------------------------------------------===// // // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. // See https://llvm.org/LICENSE.txt for license information. // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// #include "DecoderTableEmitter.h" #include "llvm/ADT/StringExtras.h" #include "llvm/Support/Format.h" #include "llvm/Support/LEB128.h" using namespace llvm; unsigned DecoderTableEmitter::computeNodeSize(const DecoderTreeNode *Node) const { // To make the arithmetic below clearer. static constexpr unsigned OpcodeSize = 1; static constexpr unsigned FieldWidthSize = 1; switch (Node->getKind()) { case DecoderTreeNode::CheckAny: { const auto *N = static_cast(Node); // Pretend the node was optimized. See the comment in emitCheckAnyNode. if (range_size(N->children()) == 1) return computeNodeSize(*N->child_begin()); unsigned Size = 0; // All children except the last one are preceded by OPC_Scope opcode and // the size of the child. for (const DecoderTreeNode *Child : drop_end(N->children())) { unsigned ChildSize = computeNodeSize(Child); Size += OpcodeSize + getULEB128Size(ChildSize) + ChildSize; } const DecoderTreeNode *Child = *std::prev(N->child_end()); return Size + computeNodeSize(Child); } case DecoderTreeNode::CheckAll: { const auto *N = static_cast(Node); unsigned Size = 0; for (const DecoderTreeNode *Child : N->children()) Size += computeNodeSize(Child); return Size; } case DecoderTreeNode::CheckField: { const auto *N = static_cast(Node); return OpcodeSize + getULEB128Size(N->getStartBit()) + FieldWidthSize + getULEB128Size(N->getValue()); } case DecoderTreeNode::SwitchField: { const auto *N = static_cast(Node); unsigned Size = OpcodeSize + getULEB128Size(N->getStartBit()) + FieldWidthSize; for (auto [Val, Child] : drop_end(N->cases())) { unsigned ChildSize = computeNodeSize(Child); Size += getULEB128Size(Val) + getULEB128Size(ChildSize) + ChildSize; } // The last child is emitted with sentinel value 0 instead of the size. // See the comment in emitSwitchFieldNode. auto [Val, Child] = *std::prev(N->case_end()); unsigned ChildSize = computeNodeSize(Child); Size += getULEB128Size(Val) + getULEB128Size(0) + ChildSize; return Size; } case DecoderTreeNode::CheckPredicate: { const auto *N = static_cast(Node); unsigned PredicateIndex = N->getPredicateIndex(); return OpcodeSize + getULEB128Size(PredicateIndex); } case DecoderTreeNode::SoftFail: { const auto *N = static_cast(Node); return OpcodeSize + getULEB128Size(N->getPositiveMask()) + getULEB128Size(N->getNegativeMask()); } case DecoderTreeNode::Decode: { const auto *N = static_cast(Node); return OpcodeSize + getULEB128Size(N->getInstOpcode()) + getULEB128Size(N->getDecoderIndex()); } } llvm_unreachable("Unknown node kind"); } unsigned DecoderTableEmitter::computeTableSize(const DecoderTreeNode *Root, unsigned BitWidth) const { unsigned Size = 0; if (BitWidth) Size += getULEB128Size(BitWidth); Size += computeNodeSize(Root); return Size; } void DecoderTableEmitter::emitStartLine() { LineStartIndex = CurrentIndex; OS.indent(2); } void DecoderTableEmitter::emitOpcode(StringRef Name) { emitStartLine(); OS << Name << ", "; ++CurrentIndex; } void DecoderTableEmitter::emitByte(uint8_t Val) { OS << static_cast(Val) << ", "; ++CurrentIndex; } void DecoderTableEmitter::emitUInt8(unsigned Val) { assert(isUInt<8>(Val)); emitByte(Val); } void DecoderTableEmitter::emitULEB128(uint64_t Val) { while (Val >= 0x80) { emitByte((Val & 0x7F) | 0x80); Val >>= 7; } emitByte(Val); } raw_ostream &DecoderTableEmitter::emitComment(indent Indent) { constexpr unsigned CommentColumn = 45; if (OS.getColumn() > CommentColumn) OS << '\n'; OS.PadToColumn(CommentColumn); OS << "// " << format_decimal(LineStartIndex, IndexWidth) << ": " << Indent; return OS; } namespace { /// Helper class for printing bit ranges. struct BitRange { unsigned MSB, LSB; friend raw_ostream &operator<<(raw_ostream &OS, BitRange R) { if (R.MSB == R.LSB) OS << '[' << R.LSB << ']'; else OS << '[' << R.MSB << ':' << R.LSB << ']'; return OS; } }; } // namespace void DecoderTableEmitter::emitCheckAnyNode(const CheckAnyNode *N, indent Indent) { // TODO: Single-child CheckAny node should be optimized out. For now, // pretend this is the case and print the single child unindented. if (range_size(N->children()) == 1) { emitNode(*N->child_begin(), Indent); return; } ListSeparator LS("} else "); for (const DecoderTreeNode *Child : drop_end(N->children())) { emitOpcode("OPC_Scope"); emitULEB128(computeNodeSize(Child)); emitComment(Indent) << LS << "try {\n"; emitNode(Child, Indent + 1); } // Don't emit OPC_Scope for the last child so that we leave the current scope // if it fails. Otherwise, we would need some kind of OPC_LeaveScope opcode. const DecoderTreeNode *Child = *std::prev(N->child_end()); emitComment(Indent) << LS << "try {\n"; emitNode(Child, Indent + 1); emitComment(Indent) << "}\n"; } void DecoderTableEmitter::emitCheckAllNode(const CheckAllNode *N, indent Indent) { // TODO: Single-child CheckAll should be optimized out. // TODO: Nested CheckAll nodes should be flattened. // TODO: Sibling CheckAll and other Check* nodes should be merged together. for (const DecoderTreeNode *Child : N->children()) emitNode(Child, Indent); } void DecoderTableEmitter::emitSwitchFieldNode(const SwitchFieldNode *N, indent Indent) { unsigned LSB = N->getStartBit(); unsigned Width = N->getNumBits(); unsigned MSB = LSB + Width - 1; emitOpcode("OPC_SwitchField"); emitULEB128(LSB); emitUInt8(Width); emitComment(Indent) << "switch Inst" << BitRange{MSB, LSB} << " {\n"; for (auto [Val, Child] : drop_end(N->cases())) { emitStartLine(); emitULEB128(Val); emitULEB128(computeNodeSize(Child)); emitComment(Indent) << "case " << format_hex(Val, 0) << ": {\n"; emitNode(Child, Indent + 1); emitComment(Indent) << "}\n"; } // Don't emit the size of the last child and instead emit a sentinel value, // which tells the interpreter that this is the last case. The interpreter // doesn't need to know its size because SwitchField node never falls through // (we either successfully decode an instruction, or leave the current scope). auto [Val, Child] = *std::prev(N->case_end()); emitStartLine(); emitULEB128(Val); emitULEB128(0); emitComment(Indent) << "case " << format_hex(Val, 0) << ": {\n"; emitNode(Child, Indent + 1); emitComment(Indent) << "}\n"; emitComment(Indent) << "} // switch Inst" << BitRange{MSB, LSB} << "\n"; } void DecoderTableEmitter::emitCheckFieldNode(const CheckFieldNode *N, indent Indent) { unsigned LSB = N->getStartBit(); unsigned Width = N->getNumBits(); unsigned MSB = LSB + Width - 1; uint64_t Val = N->getValue(); emitOpcode("OPC_CheckField"); emitULEB128(LSB); emitUInt8(Width); emitULEB128(Val); emitComment(Indent) << "check Inst" << BitRange{MSB, LSB} << " == " << format_hex(Val, 0) << '\n'; } void DecoderTableEmitter::emitCheckPredicateNode(const CheckPredicateNode *N, indent Indent) { unsigned PredicateIndex = N->getPredicateIndex(); emitOpcode("OPC_CheckPredicate"); emitULEB128(PredicateIndex); TableInfo.HasCheckPredicate = true; emitComment(Indent) << "check predicate " << PredicateIndex << "\n"; } void DecoderTableEmitter::emitSoftFailNode(const SoftFailNode *N, indent Indent) { uint64_t PositiveMask = N->getPositiveMask(); uint64_t NegativeMask = N->getNegativeMask(); emitOpcode("OPC_SoftFail"); emitULEB128(PositiveMask); emitULEB128(NegativeMask); TableInfo.HasSoftFail = true; emitComment(Indent) << "softfail"; OS << " pos=" << format_hex(PositiveMask, 10); OS << " neg=" << format_hex(NegativeMask, 10) << '\n'; } void DecoderTableEmitter::emitDecodeNode(const DecodeNode *N, indent Indent) { StringRef EncodingName = N->getEncodingName(); unsigned InstOpcode = N->getInstOpcode(); unsigned DecoderIndex = N->getDecoderIndex(); emitOpcode("OPC_Decode"); emitULEB128(InstOpcode); emitULEB128(DecoderIndex); emitComment(Indent) << "decode to " << EncodingName << " using decoder " << DecoderIndex << '\n'; } void DecoderTableEmitter::emitNode(const DecoderTreeNode *N, indent Indent) { switch (N->getKind()) { case DecoderTreeNode::CheckAny: return emitCheckAnyNode(static_cast(N), Indent); case DecoderTreeNode::CheckAll: return emitCheckAllNode(static_cast(N), Indent); case DecoderTreeNode::SwitchField: return emitSwitchFieldNode(static_cast(N), Indent); case DecoderTreeNode::CheckField: return emitCheckFieldNode(static_cast(N), Indent); case DecoderTreeNode::CheckPredicate: return emitCheckPredicateNode(static_cast(N), Indent); case DecoderTreeNode::SoftFail: return emitSoftFailNode(static_cast(N), Indent); case DecoderTreeNode::Decode: return emitDecodeNode(static_cast(N), Indent); } llvm_unreachable("Unknown node kind"); } void DecoderTableEmitter::emitTable(StringRef TableName, unsigned BitWidth, const DecoderTreeNode *Root) { unsigned TableSize = computeTableSize(Root, BitWidth); OS << "static const uint8_t " << TableName << "[" << TableSize << "] = {\n"; // Calculate the number of decimal places for table indices. // This is simply log10 of the table size. IndexWidth = 1; for (unsigned S = TableSize; S /= 10;) ++IndexWidth; CurrentIndex = 0; // When specializing decoders per bit width, each decoder table will begin // with the bitwidth for that table. if (BitWidth) { emitStartLine(); emitULEB128(BitWidth); emitComment(indent(0)) << "BitWidth " << BitWidth << '\n'; } emitNode(Root, indent(0)); assert(CurrentIndex == TableSize && "The size of the emitted table differs from the calculated one"); OS << "};\n"; }