diff options
| author | Sylvestre Ledru <sylvestre@debian.org> | 2024-12-10 23:59:54 +0100 |
|---|---|---|
| committer | Sylvestre Ledru <sylvestre@debian.org> | 2024-12-11 00:00:44 +0100 |
| commit | a2fb70523ac310af6d8a4d9663dfe7c9cd370c53 (patch) | |
| tree | 78b2ea08853a809c0ab7e4e0021caf96ee5addd8 /lldb/source/DataFormatters/FormatterBytecode.cpp | |
| parent | cf27e8ea04c39a0f20d465563241bdf2872f2bd7 (diff) | |
Revert "[lldb] Add cast to fix compile error on 32-bit platforms"
This reverts commit f6012a209dca6b1866d00e6b4f96279469884320.
Revert "[lldb] Add cast to fix compile error on 32-but platforms"
This reverts commit d300337e93da4ed96b044557e4b0a30001967cf0.
Revert "[lldb] Improve log message to include missing strings"
This reverts commit 0be33484853557bc0fd9dfb94e0b6c15dda136ce.
Revert "[lldb] Add comment"
This reverts commit e2bb47443d2e5c022c7851dd6029e3869fc8835c.
Revert "[lldb] Implement a formatter bytecode interpreter in C++"
This reverts commit 9a9c1d4a6155a96ce9be494cec7e25731d36b33e.
Diffstat (limited to 'lldb/source/DataFormatters/FormatterBytecode.cpp')
| -rw-r--r-- | lldb/source/DataFormatters/FormatterBytecode.cpp | 575 |
1 files changed, 0 insertions, 575 deletions
diff --git a/lldb/source/DataFormatters/FormatterBytecode.cpp b/lldb/source/DataFormatters/FormatterBytecode.cpp deleted file mode 100644 index 21e90e75202f..000000000000 --- a/lldb/source/DataFormatters/FormatterBytecode.cpp +++ /dev/null @@ -1,575 +0,0 @@ -//===-- FormatterBytecode.cpp ---------------------------------------------===// -// -// 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 "FormatterBytecode.h" -#include "lldb/Utility/LLDBLog.h" -#include "lldb/ValueObject/ValueObject.h" -#include "llvm/ADT/StringExtras.h" -#include "llvm/Support/DataExtractor.h" -#include "llvm/Support/Format.h" -#include "llvm/Support/FormatProviders.h" -#include "llvm/Support/FormatVariadicDetails.h" - -using namespace lldb; -namespace lldb_private { - -std::string toString(FormatterBytecode::OpCodes op) { - switch (op) { -#define DEFINE_OPCODE(OP, MNEMONIC, NAME) \ - case OP: { \ - const char *s = MNEMONIC; \ - return s ? s : #NAME; \ - } -#include "FormatterBytecode.def" -#undef DEFINE_SIGNATURE - } - return llvm::utostr(op); -} - -std::string toString(FormatterBytecode::Selectors sel) { - switch (sel) { -#define DEFINE_SELECTOR(ID, NAME) \ - case ID: \ - return "@" #NAME; -#include "FormatterBytecode.def" -#undef DEFINE_SIGNATURE - } - return "@" + llvm::utostr(sel); -} - -std::string toString(FormatterBytecode::Signatures sig) { - switch (sig) { -#define DEFINE_SIGNATURE(ID, NAME) \ - case ID: \ - return "@" #NAME; -#include "FormatterBytecode.def" -#undef DEFINE_SIGNATURE - } - return llvm::utostr(sig); -} - -std::string toString(const FormatterBytecode::DataStack &data) { - std::string s; - llvm::raw_string_ostream os(s); - os << "[ "; - for (auto &d : data) { - if (auto s = std::get_if<std::string>(&d)) - os << '"' << *s << '"'; - else if (auto u = std::get_if<uint64_t>(&d)) - os << *u << 'u'; - else if (auto i = std::get_if<int64_t>(&d)) - os << *i; - else if (auto valobj = std::get_if<ValueObjectSP>(&d)) { - if (!valobj->get()) - os << "null"; - else - os << "object(" << valobj->get()->GetValueAsCString() << ')'; - } else if (auto type = std::get_if<CompilerType>(&d)) { - os << '(' << type->GetTypeName(true) << ')'; - } else if (auto sel = std::get_if<FormatterBytecode::Selectors>(&d)) { - os << toString(*sel); - } - os << ' '; - } - os << ']'; - return s; -} - -namespace FormatterBytecode { - -/// Implement the @format function. -static llvm::Error FormatImpl(DataStack &data) { - auto fmt = data.Pop<std::string>(); - auto replacements = - llvm::formatv_object_base::parseFormatString(fmt, 0, false); - std::string s; - llvm::raw_string_ostream os(s); - unsigned num_args = 0; - for (const auto &r : replacements) - if (r.Type == llvm::ReplacementType::Format) - num_args = std::max(num_args, r.Index + 1); - - if (data.size() < num_args) - return llvm::createStringError("not enough arguments"); - - for (const auto &r : replacements) { - if (r.Type == llvm::ReplacementType::Literal) { - os << r.Spec; - continue; - } - using namespace llvm::support::detail; - auto arg = data[data.size() - num_args + r.Index]; - auto format = [&](format_adapter &&adapter) { - llvm::FmtAlign Align(adapter, r.Where, r.Width, r.Pad); - Align.format(os, r.Options); - }; - - if (auto s = std::get_if<std::string>(&arg)) - format(build_format_adapter(s->c_str())); - else if (auto u = std::get_if<uint64_t>(&arg)) - format(build_format_adapter(u)); - else if (auto i = std::get_if<int64_t>(&arg)) - format(build_format_adapter(i)); - else if (auto valobj = std::get_if<ValueObjectSP>(&arg)) { - if (!valobj->get()) - format(build_format_adapter("null object")); - else - format(build_format_adapter(valobj->get()->GetValueAsCString())); - } else if (auto type = std::get_if<CompilerType>(&arg)) - format(build_format_adapter(type->GetDisplayTypeName())); - else if (auto sel = std::get_if<FormatterBytecode::Selectors>(&arg)) - format(build_format_adapter(toString(*sel))); - } - data.Push(s); - return llvm::Error::success(); -} - -static llvm::Error TypeCheck(llvm::ArrayRef<DataStackElement> data, - DataType type) { - if (data.size() < 1) - return llvm::createStringError("not enough elements on data stack"); - - auto &elem = data.back(); - switch (type) { - case Any: - break; - case String: - if (!std::holds_alternative<std::string>(elem)) - return llvm::createStringError("expected String"); - break; - case UInt: - if (!std::holds_alternative<uint64_t>(elem)) - return llvm::createStringError("expected UInt"); - break; - case Int: - if (!std::holds_alternative<int64_t>(elem)) - return llvm::createStringError("expected Int"); - break; - case Object: - if (!std::holds_alternative<ValueObjectSP>(elem)) - return llvm::createStringError("expected Object"); - break; - case Type: - if (!std::holds_alternative<CompilerType>(elem)) - return llvm::createStringError("expected Type"); - break; - case Selector: - if (!std::holds_alternative<Selectors>(elem)) - return llvm::createStringError("expected Selector"); - break; - } - return llvm::Error::success(); -} - -static llvm::Error TypeCheck(llvm::ArrayRef<DataStackElement> data, - DataType type1, DataType type2) { - if (auto error = TypeCheck(data, type2)) - return error; - return TypeCheck(data.drop_back(), type1); -} - -static llvm::Error TypeCheck(llvm::ArrayRef<DataStackElement> data, - DataType type1, DataType type2, DataType type3) { - if (auto error = TypeCheck(data, type3)) - return error; - return TypeCheck(data.drop_back(1), type2, type1); -} - -llvm::Error Interpret(std::vector<ControlStackElement> &control, - DataStack &data, Selectors sel) { - if (control.empty()) - return llvm::Error::success(); - // Since the only data types are single endian and ULEBs, the - // endianness should not matter. - llvm::DataExtractor cur_block(control.back(), true, 64); - llvm::DataExtractor::Cursor pc(0); - - while (!control.empty()) { - /// Activate the top most block from the control stack. - auto activate_block = [&]() { - // Save the return address. - if (control.size() > 1) - control[control.size() - 2] = cur_block.getData().drop_front(pc.tell()); - cur_block = llvm::DataExtractor(control.back(), true, 64); - if (pc) - pc = llvm::DataExtractor::Cursor(0); - }; - - /// Fetch the next byte in the instruction stream. - auto next_byte = [&]() -> uint8_t { - // At the end of the current block? - while (pc.tell() >= cur_block.size() && !control.empty()) { - if (control.size() == 1) { - control.pop_back(); - return 0; - } - control.pop_back(); - activate_block(); - } - - // Fetch the next instruction. - return cur_block.getU8(pc); - }; - - // Fetch the next opcode. - OpCodes opcode = (OpCodes)next_byte(); - if (control.empty() || !pc) - return pc.takeError(); - - LLDB_LOGV(GetLog(LLDBLog::DataFormatters), - "[eval {0}] opcode={1}, control={2}, data={3}", toString(sel), - toString(opcode), control.size(), toString(data)); - - // Various shorthands to improve the readability of error handling. -#define TYPE_CHECK(...) \ - if (auto error = TypeCheck(data, __VA_ARGS__)) \ - return error; - - auto error = [&](llvm::Twine msg) { - return llvm::createStringError(msg + "(opcode=" + toString(opcode) + ")"); - }; - - switch (opcode) { - // Data stack manipulation. - case op_dup: - TYPE_CHECK(Any); - data.Push(data.back()); - continue; - case op_drop: - TYPE_CHECK(Any); - data.pop_back(); - continue; - case op_pick: { - TYPE_CHECK(UInt); - uint64_t idx = data.Pop<uint64_t>(); - if (idx >= data.size()) - return error("index out of bounds"); - data.Push(data[idx]); - continue; - } - case op_over: - TYPE_CHECK(Any, Any); - data.Push(data[data.size() - 2]); - continue; - case op_swap: { - TYPE_CHECK(Any, Any); - auto x = data.PopAny(); - auto y = data.PopAny(); - data.Push(x); - data.Push(y); - continue; - } - case op_rot: { - TYPE_CHECK(Any, Any, Any); - auto z = data.PopAny(); - auto y = data.PopAny(); - auto x = data.PopAny(); - data.Push(z); - data.Push(x); - data.Push(y); - continue; - } - - // Control stack manipulation. - case op_begin: { - uint64_t length = cur_block.getULEB128(pc); - if (!pc) - return pc.takeError(); - llvm::StringRef block = cur_block.getBytes(pc, length); - if (!pc) - return pc.takeError(); - control.push_back(block); - continue; - } - case op_if: - TYPE_CHECK(UInt); - if (data.Pop<uint64_t>() != 0) { - if (!cur_block.size()) - return error("empty control stack"); - activate_block(); - } else - control.pop_back(); - continue; - case op_ifelse: - TYPE_CHECK(UInt); - if (cur_block.size() < 2) - return error("empty control stack"); - if (data.Pop<uint64_t>() == 0) - control[control.size() - 2] = control.back(); - control.pop_back(); - activate_block(); - continue; - - // Literals. - case op_lit_uint: - data.Push(cur_block.getULEB128(pc)); - continue; - case op_lit_int: - data.Push(cur_block.getSLEB128(pc)); - continue; - case op_lit_selector: - data.Push(Selectors(cur_block.getU8(pc))); - continue; - case op_lit_string: { - uint64_t length = cur_block.getULEB128(pc); - llvm::StringRef bytes = cur_block.getBytes(pc, length); - data.Push(bytes.str()); - continue; - } - case op_as_uint: { - TYPE_CHECK(Int); - uint64_t casted; - int64_t val = data.Pop<int64_t>(); - memcpy(&casted, &val, sizeof(val)); - data.Push(casted); - continue; - } - case op_as_int: { - TYPE_CHECK(UInt); - int64_t casted; - uint64_t val = data.Pop<uint64_t>(); - memcpy(&casted, &val, sizeof(val)); - data.Push(casted); - continue; - } - case op_is_null: { - TYPE_CHECK(Object); - data.Push(data.Pop<ValueObjectSP>() ? 0ULL : 1ULL); - continue; - } - - // Arithmetic, logic, etc. -#define BINOP_IMPL(OP, CHECK_ZERO) \ - { \ - TYPE_CHECK(Any, Any); \ - auto y = data.PopAny(); \ - if (std::holds_alternative<uint64_t>(y)) { \ - if (CHECK_ZERO && !std::get<uint64_t>(y)) \ - return error(#OP " by zero"); \ - TYPE_CHECK(UInt); \ - data.Push((uint64_t)(data.Pop<uint64_t>() OP std::get<uint64_t>(y))); \ - } else if (std::holds_alternative<int64_t>(y)) { \ - if (CHECK_ZERO && !std::get<int64_t>(y)) \ - return error(#OP " by zero"); \ - TYPE_CHECK(Int); \ - data.Push((int64_t)(data.Pop<int64_t>() OP std::get<int64_t>(y))); \ - } else \ - return error("unsupported data types"); \ - } -#define BINOP(OP) BINOP_IMPL(OP, false) -#define BINOP_CHECKZERO(OP) BINOP_IMPL(OP, true) - case op_plus: - BINOP(+); - continue; - case op_minus: - BINOP(-); - continue; - case op_mul: - BINOP(*); - continue; - case op_div: - BINOP_CHECKZERO(/); - continue; - case op_mod: - BINOP_CHECKZERO(%); - continue; - case op_shl: -#define SHIFTOP(OP) \ - { \ - TYPE_CHECK(Any, UInt); \ - uint64_t y = data.Pop<uint64_t>(); \ - if (y > 64) \ - return error("shift out of bounds"); \ - if (std::holds_alternative<uint64_t>(data.back())) { \ - uint64_t x = data.Pop<uint64_t>(); \ - data.Push(x OP y); \ - } else if (std::holds_alternative<int64_t>(data.back())) { \ - int64_t x = data.Pop<int64_t>(); \ - if (y > 64) \ - return error("shift out of bounds"); \ - if (y < 0) \ - return error("shift out of bounds"); \ - data.Push(x OP y); \ - } else \ - return error("unsupported data types"); \ - } - SHIFTOP(<<); - continue; - case op_shr: - SHIFTOP(<<); - continue; - case op_and: - BINOP(&); - continue; - case op_or: - BINOP(|); - continue; - case op_xor: - BINOP(^); - continue; - case op_not: - TYPE_CHECK(UInt); - data.Push(~data.Pop<uint64_t>()); - continue; - case op_eq: - BINOP(==); - continue; - case op_neq: - BINOP(!=); - continue; - case op_lt: - BINOP(<); - continue; - case op_gt: - BINOP(>); - continue; - case op_le: - BINOP(<=); - continue; - case op_ge: - BINOP(>=); - continue; - case op_call: { - TYPE_CHECK(Selector); - Selectors sel = data.Pop<Selectors>(); - - // Shorthand to improve readability. -#define POP_VALOBJ(VALOBJ) \ - auto VALOBJ = data.Pop<ValueObjectSP>(); \ - if (!VALOBJ) \ - return error("null object"); - - auto sel_error = [&](const char *msg) { - return llvm::createStringError("{0} (opcode={1}, selector={2})", msg, - toString(opcode).c_str(), - toString(sel).c_str()); - }; - - switch (sel) { - case sel_summary: { - TYPE_CHECK(Object); - POP_VALOBJ(valobj); - const char *summary = valobj->GetSummaryAsCString(); - data.Push(summary ? std::string(valobj->GetSummaryAsCString()) - : std::string()); - break; - } - case sel_get_num_children: { - TYPE_CHECK(Object); - POP_VALOBJ(valobj); - auto result = valobj->GetNumChildren(); - if (!result) - return result.takeError(); - data.Push((uint64_t)*result); - break; - } - case sel_get_child_at_index: { - TYPE_CHECK(Object, UInt); - auto index = data.Pop<uint64_t>(); - POP_VALOBJ(valobj); - data.Push(valobj->GetChildAtIndex(index)); - break; - } - case sel_get_child_with_name: { - TYPE_CHECK(Object, String); - auto name = data.Pop<std::string>(); - POP_VALOBJ(valobj); - data.Push(valobj->GetChildMemberWithName(name)); - break; - } - case sel_get_child_index: { - TYPE_CHECK(Object, String); - auto name = data.Pop<std::string>(); - POP_VALOBJ(valobj); - data.Push((uint64_t)valobj->GetIndexOfChildWithName(name)); - break; - } - case sel_get_type: { - TYPE_CHECK(Object); - POP_VALOBJ(valobj); - // FIXME: do we need to control dynamic type resolution? - data.Push(valobj->GetTypeImpl().GetCompilerType(false)); - break; - } - case sel_get_template_argument_type: { - TYPE_CHECK(Type, UInt); - auto index = data.Pop<uint64_t>(); - auto type = data.Pop<CompilerType>(); - // FIXME: There is more code in SBType::GetTemplateArgumentType(). - data.Push(type.GetTypeTemplateArgument(index, true)); - break; - } - case sel_get_value: { - TYPE_CHECK(Object); - POP_VALOBJ(valobj); - data.Push(std::string(valobj->GetValueAsCString())); - break; - } - case sel_get_value_as_unsigned: { - TYPE_CHECK(Object); - POP_VALOBJ(valobj); - bool success; - uint64_t val = valobj->GetValueAsUnsigned(0, &success); - data.Push(val); - if (!success) - return sel_error("failed to get value"); - break; - } - case sel_get_value_as_signed: { - TYPE_CHECK(Object); - POP_VALOBJ(valobj); - bool success; - int64_t val = valobj->GetValueAsSigned(0, &success); - data.Push(val); - if (!success) - return sel_error("failed to get value"); - break; - } - case sel_get_value_as_address: { - TYPE_CHECK(Object); - POP_VALOBJ(valobj); - bool success; - uint64_t addr = valobj->GetValueAsUnsigned(0, &success); - if (!success) - return sel_error("failed to get value"); - if (auto process_sp = valobj->GetProcessSP()) - addr = process_sp->FixDataAddress(addr); - data.Push(addr); - break; - } - case sel_cast: { - TYPE_CHECK(Object, Type); - auto type = data.Pop<CompilerType>(); - POP_VALOBJ(valobj); - data.Push(valobj->Cast(type)); - break; - } - case sel_strlen: { - TYPE_CHECK(String); - data.Push((uint64_t)data.Pop<std::string>().size()); - break; - } - case sel_fmt: { - TYPE_CHECK(String); - if (auto error = FormatImpl(data)) - return error; - break; - } - default: - return sel_error("selector not implemented"); - } - continue; - } - } - return error("opcode not implemented"); - } - return pc.takeError(); -} -} // namespace FormatterBytecode - -} // namespace lldb_private |
