aboutsummaryrefslogtreecommitdiffstats
path: root/contrib/libs/llvm14/utils/TableGen/WebAssemblyDisassemblerEmitter.cpp
diff options
context:
space:
mode:
authorvitalyisaev <vitalyisaev@yandex-team.com>2023-06-29 10:00:50 +0300
committervitalyisaev <vitalyisaev@yandex-team.com>2023-06-29 10:00:50 +0300
commit6ffe9e53658409f212834330e13564e4952558f6 (patch)
tree85b1e00183517648b228aafa7c8fb07f5276f419 /contrib/libs/llvm14/utils/TableGen/WebAssemblyDisassemblerEmitter.cpp
parent726057070f9c5a91fc10fde0d5024913d10f1ab9 (diff)
downloadydb-6ffe9e53658409f212834330e13564e4952558f6.tar.gz
YQ Connector: support managed ClickHouse
Со стороны dqrun можно обратиться к инстансу коннектора, который работает на streaming стенде, и извлечь данные из облачного CH.
Diffstat (limited to 'contrib/libs/llvm14/utils/TableGen/WebAssemblyDisassemblerEmitter.cpp')
-rw-r--r--contrib/libs/llvm14/utils/TableGen/WebAssemblyDisassemblerEmitter.cpp181
1 files changed, 181 insertions, 0 deletions
diff --git a/contrib/libs/llvm14/utils/TableGen/WebAssemblyDisassemblerEmitter.cpp b/contrib/libs/llvm14/utils/TableGen/WebAssemblyDisassemblerEmitter.cpp
new file mode 100644
index 0000000000..74969053f0
--- /dev/null
+++ b/contrib/libs/llvm14/utils/TableGen/WebAssemblyDisassemblerEmitter.cpp
@@ -0,0 +1,181 @@
+//===- WebAssemblyDisassemblerEmitter.cpp - Disassembler tables -*- C++ -*-===//
+//
+// 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
+//
+//===----------------------------------------------------------------------===//
+//
+// This file is part of the WebAssembly Disassembler Emitter.
+// It contains the implementation of the disassembler tables.
+// Documentation for the disassembler emitter in general can be found in
+// WebAssemblyDisassemblerEmitter.h.
+//
+//===----------------------------------------------------------------------===//
+
+#include "WebAssemblyDisassemblerEmitter.h"
+#include "CodeGenInstruction.h"
+#include "llvm/ADT/STLExtras.h"
+#include "llvm/Support/raw_ostream.h"
+#include "llvm/TableGen/Record.h"
+
+namespace llvm {
+
+static constexpr int WebAssemblyInstructionTableSize = 256;
+
+void emitWebAssemblyDisassemblerTables(
+ raw_ostream &OS,
+ const ArrayRef<const CodeGenInstruction *> &NumberedInstructions) {
+ // First lets organize all opcodes by (prefix) byte. Prefix 0 is the
+ // starting table.
+ std::map<unsigned,
+ std::map<unsigned, std::pair<unsigned, const CodeGenInstruction *>>>
+ OpcodeTable;
+ for (unsigned I = 0; I != NumberedInstructions.size(); ++I) {
+ auto &CGI = *NumberedInstructions[I];
+ auto &Def = *CGI.TheDef;
+ if (!Def.getValue("Inst"))
+ continue;
+ auto &Inst = *Def.getValueAsBitsInit("Inst");
+ auto Opc = static_cast<unsigned>(
+ reinterpret_cast<IntInit *>(Inst.convertInitializerTo(IntRecTy::get()))
+ ->getValue());
+ if (Opc == 0xFFFFFFFF)
+ continue; // No opcode defined.
+ assert(Opc <= 0xFFFFFF);
+ unsigned Prefix;
+ if (Opc <= 0xFFFF) {
+ Prefix = Opc >> 8;
+ Opc = Opc & 0xFF;
+ } else {
+ Prefix = Opc >> 16;
+ Opc = Opc & 0xFFFF;
+ }
+ auto &CGIP = OpcodeTable[Prefix][Opc];
+ // All wasm instructions have a StackBased field of type string, we only
+ // want the instructions for which this is "true".
+ auto StackString =
+ Def.getValue("StackBased")->getValue()->getCastTo(StringRecTy::get());
+ auto IsStackBased =
+ StackString &&
+ reinterpret_cast<const StringInit *>(StackString)->getValue() == "true";
+ if (!IsStackBased)
+ continue;
+ if (CGIP.second) {
+ // We already have an instruction for this slot, so decide which one
+ // should be the canonical one. This determines which variant gets
+ // printed in a disassembly. We want e.g. "call" not "i32.call", and
+ // "end" when we don't know if its "end_loop" or "end_block" etc.
+ auto IsCanonicalExisting = CGIP.second->TheDef->getValue("IsCanonical")
+ ->getValue()
+ ->getAsString() == "1";
+ // We already have one marked explicitly as canonical, so keep it.
+ if (IsCanonicalExisting)
+ continue;
+ auto IsCanonicalNew =
+ Def.getValue("IsCanonical")->getValue()->getAsString() == "1";
+ // If the new one is explicitly marked as canonical, take it.
+ if (!IsCanonicalNew) {
+ // Neither the existing or new instruction is canonical.
+ // Pick the one with the shortest name as heuristic.
+ // Though ideally IsCanonical is always defined for at least one
+ // variant so this never has to apply.
+ if (CGIP.second->AsmString.size() <= CGI.AsmString.size())
+ continue;
+ }
+ }
+ // Set this instruction as the one to use.
+ CGIP = std::make_pair(I, &CGI);
+ }
+ OS << "#include \"MCTargetDesc/WebAssemblyMCTargetDesc.h\"\n";
+ OS << "\n";
+ OS << "namespace llvm {\n\n";
+ OS << "static constexpr int WebAssemblyInstructionTableSize = ";
+ OS << WebAssemblyInstructionTableSize << ";\n\n";
+ OS << "enum EntryType : uint8_t { ";
+ OS << "ET_Unused, ET_Prefix, ET_Instruction };\n\n";
+ OS << "struct WebAssemblyInstruction {\n";
+ OS << " uint16_t Opcode;\n";
+ OS << " EntryType ET;\n";
+ OS << " uint8_t NumOperands;\n";
+ OS << " uint16_t OperandStart;\n";
+ OS << "};\n\n";
+ std::vector<std::string> OperandTable, CurOperandList;
+ // Output one table per prefix.
+ for (auto &PrefixPair : OpcodeTable) {
+ if (PrefixPair.second.empty())
+ continue;
+ OS << "WebAssemblyInstruction InstructionTable" << PrefixPair.first;
+ OS << "[] = {\n";
+ for (unsigned I = 0; I < WebAssemblyInstructionTableSize; I++) {
+ auto InstIt = PrefixPair.second.find(I);
+ if (InstIt != PrefixPair.second.end()) {
+ // Regular instruction.
+ assert(InstIt->second.second);
+ auto &CGI = *InstIt->second.second;
+ OS << " // 0x";
+ OS.write_hex(static_cast<unsigned long long>(I));
+ OS << ": " << CGI.AsmString << "\n";
+ OS << " { " << InstIt->second.first << ", ET_Instruction, ";
+ OS << CGI.Operands.OperandList.size() << ", ";
+ // Collect operand types for storage in a shared list.
+ CurOperandList.clear();
+ for (auto &Op : CGI.Operands.OperandList) {
+ assert(Op.OperandType != "MCOI::OPERAND_UNKNOWN");
+ CurOperandList.push_back(Op.OperandType);
+ }
+ // See if we already have stored this sequence before. This is not
+ // strictly necessary but makes the table really small.
+ size_t OperandStart = OperandTable.size();
+ if (CurOperandList.size() <= OperandTable.size()) {
+ for (size_t J = 0; J <= OperandTable.size() - CurOperandList.size();
+ ++J) {
+ size_t K = 0;
+ for (; K < CurOperandList.size(); ++K) {
+ if (OperandTable[J + K] != CurOperandList[K]) break;
+ }
+ if (K == CurOperandList.size()) {
+ OperandStart = J;
+ break;
+ }
+ }
+ }
+ // Store operands if no prior occurrence.
+ if (OperandStart == OperandTable.size()) {
+ llvm::append_range(OperandTable, CurOperandList);
+ }
+ OS << OperandStart;
+ } else {
+ auto PrefixIt = OpcodeTable.find(I);
+ // If we have a non-empty table for it that's not 0, this is a prefix.
+ if (PrefixIt != OpcodeTable.end() && I && !PrefixPair.first) {
+ OS << " { 0, ET_Prefix, 0, 0";
+ } else {
+ OS << " { 0, ET_Unused, 0, 0";
+ }
+ }
+ OS << " },\n";
+ }
+ OS << "};\n\n";
+ }
+ // Create a table of all operands:
+ OS << "const uint8_t OperandTable[] = {\n";
+ for (auto &Op : OperandTable) {
+ OS << " " << Op << ",\n";
+ }
+ OS << "};\n\n";
+ // Create a table of all extension tables:
+ OS << "struct { uint8_t Prefix; const WebAssemblyInstruction *Table; }\n";
+ OS << "PrefixTable[] = {\n";
+ for (auto &PrefixPair : OpcodeTable) {
+ if (PrefixPair.second.empty() || !PrefixPair.first)
+ continue;
+ OS << " { " << PrefixPair.first << ", InstructionTable"
+ << PrefixPair.first;
+ OS << " },\n";
+ }
+ OS << " { 0, nullptr }\n};\n\n";
+ OS << "} // end namespace llvm\n";
+}
+
+} // namespace llvm