| //===----------------------------------------------------------------------===// | |
| // | |
| // 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<const CheckAnyNode *>(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<const CheckAllNode *>(Node); | |
| unsigned Size = 0; | |
| for (const DecoderTreeNode *Child : N->children()) | |
| Size += computeNodeSize(Child); | |
| return Size; | |
| } | |
| case DecoderTreeNode::CheckField: { | |
| const auto *N = static_cast<const CheckFieldNode *>(Node); | |
| return OpcodeSize + getULEB128Size(N->getStartBit()) + FieldWidthSize + | |
| getULEB128Size(N->getValue()); | |
| } | |
| case DecoderTreeNode::SwitchField: { | |
| const auto *N = static_cast<const SwitchFieldNode *>(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<const CheckPredicateNode *>(Node); | |
| unsigned PredicateIndex = N->getPredicateIndex(); | |
| return OpcodeSize + getULEB128Size(PredicateIndex); | |
| } | |
| case DecoderTreeNode::SoftFail: { | |
| const auto *N = static_cast<const SoftFailNode *>(Node); | |
| return OpcodeSize + getULEB128Size(N->getPositiveMask()) + | |
| getULEB128Size(N->getNegativeMask()); | |
| } | |
| case DecoderTreeNode::Decode: { | |
| const auto *N = static_cast<const DecodeNode *>(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<unsigned>(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<const CheckAnyNode *>(N), Indent); | |
| case DecoderTreeNode::CheckAll: | |
| return emitCheckAllNode(static_cast<const CheckAllNode *>(N), Indent); | |
| case DecoderTreeNode::SwitchField: | |
| return emitSwitchFieldNode(static_cast<const SwitchFieldNode *>(N), Indent); | |
| case DecoderTreeNode::CheckField: | |
| return emitCheckFieldNode(static_cast<const CheckFieldNode *>(N), Indent); | |
| case DecoderTreeNode::CheckPredicate: | |
| return emitCheckPredicateNode(static_cast<const CheckPredicateNode *>(N), | |
| Indent); | |
| case DecoderTreeNode::SoftFail: | |
| return emitSoftFailNode(static_cast<const SoftFailNode *>(N), Indent); | |
| case DecoderTreeNode::Decode: | |
| return emitDecodeNode(static_cast<const DecodeNode *>(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"; | |
| } |