67 llvm::raw_string_ostream os(s);
69 for (
auto &d : data) {
70 if (
auto s = std::get_if<std::string>(&d))
71 os <<
'"' << *s <<
'"';
72 else if (
auto u = std::get_if<uint64_t>(&d))
74 else if (
auto i = std::get_if<int64_t>(&d))
76 else if (
auto ap = std::get_if<llvm::APSInt>(&d))
78 else if (
auto valobj = std::get_if<ValueObjectSP>(&d)) {
82 os <<
"object(" << valobj->get()->GetValueAsCString() <<
')';
83 }
else if (
auto type = std::get_if<CompilerType>(&d)) {
84 os <<
'(' << type->GetTypeName(
true) <<
')';
85 }
else if (
auto sel = std::get_if<FormatterBytecode::Selectors>(&d)) {
87 }
else if (
auto *dict =
88 std::get_if<std::shared_ptr<FormatterBytecode::Dictionary>>(
90 os <<
"dict(" << (*dict ? (*dict)->size() : 0) <<
')';
149 auto fmt = data.
Pop<std::string>();
153 return sanitized.takeError();
154 fmt = std::move(*sanitized);
157 llvm::formatv_object_base::parseFormatString(fmt, 0,
false);
159 llvm::raw_string_ostream os(s);
160 unsigned num_args = 0;
161 for (
const auto &r : replacements)
162 if (r.Type == llvm::ReplacementType::Format)
163 num_args = std::max(num_args, r.Index + 1);
165 if (data.size() < num_args)
166 return llvm::createStringError(
"not enough arguments");
168 for (
const auto &r : replacements) {
169 if (r.Type == llvm::ReplacementType::Literal) {
173 using namespace llvm::support::detail;
174 auto arg = data[data.size() - num_args + r.Index];
175 auto format = [&](FormatFunctorRef &&adapter) {
176 llvm::FmtAlign
Align(adapter, r.Where, r.Width, r.Pad);
177 Align.format(os, r.Options);
180 if (
auto s = std::get_if<std::string>(&arg))
181 format(FormatFunctor(s->c_str()));
182 else if (
auto u = std::get_if<uint64_t>(&arg))
183 format(FormatFunctor(u));
184 else if (
auto i = std::get_if<int64_t>(&arg))
185 format(FormatFunctor(i));
186 else if (
auto ap = std::get_if<llvm::APSInt>(&arg))
187 format(FormatFunctor(*ap));
188 else if (
auto valobj = std::get_if<ValueObjectSP>(&arg)) {
190 format(FormatFunctor(
"null object"));
192 format(FormatFunctor(valobj->get()->GetValueAsCString()));
193 }
else if (
auto type = std::get_if<CompilerType>(&arg))
194 format(FormatFunctor(type->GetDisplayTypeName()));
195 else if (
auto sel = std::get_if<FormatterBytecode::Selectors>(&arg))
196 format(FormatFunctor(
toString(*sel)));
197 else if (std::holds_alternative<DictionarySP>(arg))
198 format(FormatFunctor(
"dict"));
201 data.erase(data.end() - num_args, data.end());
203 return llvm::Error::success();
335 return llvm::Error::success();
338 llvm::DataExtractor cur_block(control.back(),
true);
339 llvm::DataExtractor::Cursor
pc(0);
341 while (!control.empty()) {
343 auto activate_block = [&]() {
345 if (control.size() > 1)
346 control[control.size() - 2] = cur_block.getData().drop_front(
pc.tell());
347 cur_block = llvm::DataExtractor(control.back(),
true);
349 pc = llvm::DataExtractor::Cursor(0);
353 auto next_byte = [&]() -> uint8_t {
355 while (
pc.tell() >= cur_block.size() && !control.empty()) {
356 if (control.size() == 1) {
365 return cur_block.getU8(
pc);
370 if (control.empty() || !
pc)
371 return pc.takeError();
374 "[eval {0}] opcode={1}, control={2}, data={3}",
379#define TYPE_CHECK(...) \
380 if (auto error = TypeCheck(data, __VA_ARGS__)) \
383 auto error = [&](llvm::Twine msg) {
384 return llvm::createStringError(msg +
"(opcode=" +
toString(opcode) +
")");
391 data.
Push(data.back());
399 uint64_t idx = data.
Pop<uint64_t>();
400 if (idx >= data.size())
401 return error(
"index out of bounds");
402 data.
Push(data[idx]);
407 data.
Push(data[data.size() - 2]);
430 uint64_t length = cur_block.getULEB128(
pc);
432 return pc.takeError();
433 llvm::StringRef block = cur_block.getBytes(
pc, length);
435 return pc.takeError();
436 control.push_back(block);
440 auto cond = data.
PopAny();
442 if (
auto *ap = std::get_if<llvm::APSInt>(&cond))
443 truthy = !ap->isZero();
444 else if (
auto *u = std::get_if<uint64_t>(&cond))
448 return error(
"expected Integer or UInt");
450 if (!cur_block.size())
451 return error(
"empty control stack");
458 if (cur_block.size() < 2)
459 return error(
"empty control stack");
460 auto cond = data.
PopAny();
462 if (
auto *ap = std::get_if<llvm::APSInt>(&cond))
463 truthy = !ap->isZero();
464 else if (
auto *u = std::get_if<uint64_t>(&cond))
468 return error(
"expected Integer or UInt");
470 control[control.size() - 2] = control.back();
477 return pc.takeError();
481 data.
Push(cur_block.getULEB128(
pc));
484 data.
Push(cur_block.getSLEB128(
pc));
487 data.
Push(cur_block.getSLEB128APSInt(
pc));
489 case op_lit_selector:
495 case op_lit_string: {
496 uint64_t length = cur_block.getULEB128(
pc);
497 llvm::StringRef bytes = cur_block.getBytes(
pc, length);
498 data.
Push(bytes.str());
504 int64_t val = data.
Pop<int64_t>();
505 memcpy(&casted, &val,
sizeof(val));
512 uint64_t val = data.
Pop<uint64_t>();
513 memcpy(&casted, &val,
sizeof(val));
524#define BINOP_IMPL(OP, CHECK_ZERO) \
526 TYPE_CHECK(Any, Any); \
527 auto y = data.PopAny(); \
528 if (std::holds_alternative<uint64_t>(y)) { \
529 if (CHECK_ZERO && !std::get<uint64_t>(y)) \
530 return error(#OP " by zero"); \
532 data.Push((uint64_t)(data.Pop<uint64_t>() OP std::get<uint64_t>(y))); \
533 } else if (std::holds_alternative<int64_t>(y)) { \
534 if (CHECK_ZERO && !std::get<int64_t>(y)) \
535 return error(#OP " by zero"); \
537 data.Push((int64_t)(data.Pop<int64_t>() OP std::get<int64_t>(y))); \
538 } else if (std::holds_alternative<llvm::APSInt>(y)) { \
539 TYPE_CHECK(Integer); \
540 llvm::APSInt rhs = std::get<llvm::APSInt>(y); \
541 llvm::APSInt lhs = data.Pop<llvm::APSInt>(); \
542 if (lhs.isUnsigned() || rhs.isUnsigned()) \
543 return error("unsupported unsigned value"); \
544 unsigned width = std::max(lhs.getBitWidth(), rhs.getBitWidth()); \
545 lhs = lhs.extend(width); \
546 rhs = rhs.extend(width); \
547 if (CHECK_ZERO && rhs.isZero()) \
548 return error(#OP " by zero"); \
549 data.Push(WrapAPSIntResult(lhs OP rhs, width, lhs.isUnsigned())); \
551 return error("unsupported data types"); \
553#define BINOP(OP) BINOP_IMPL(OP, false)
554#define BINOP_CHECKZERO(OP) BINOP_IMPL(OP, true)
559 TYPE_CHECK(Any, Any); \
560 auto y = data.PopAny(); \
561 if (std::holds_alternative<uint64_t>(y)) { \
563 data.Push((uint64_t)(data.Pop<uint64_t>() OP std::get<uint64_t>(y))); \
564 } else if (std::holds_alternative<int64_t>(y)) { \
566 data.Push((int64_t)(data.Pop<int64_t>() OP std::get<int64_t>(y))); \
567 } else if (std::holds_alternative<llvm::APSInt>(y)) { \
568 TYPE_CHECK(Integer); \
569 llvm::APSInt rhs = std::get<llvm::APSInt>(y); \
570 llvm::APSInt lhs = data.Pop<llvm::APSInt>(); \
571 if (lhs.isUnsigned() || rhs.isUnsigned()) \
572 return error("unsupported unsigned value"); \
573 unsigned width = std::max(lhs.getBitWidth(), rhs.getBitWidth()); \
574 lhs = lhs.extend(width); \
575 rhs = rhs.extend(width); \
576 data.Push(WrapAPSIntResult(lhs OP rhs, width, lhs.isUnsigned())); \
578 return error("unsupported data types"); \
587 TYPE_CHECK(Any, Any); \
588 auto y = data.PopAny(); \
589 if (std::holds_alternative<uint64_t>(y)) { \
591 data.Push((uint64_t)(data.Pop<uint64_t>() OP std::get<uint64_t>(y))); \
592 } else if (std::holds_alternative<int64_t>(y)) { \
594 data.Push((int64_t)(data.Pop<int64_t>() OP std::get<int64_t>(y))); \
595 } else if (std::holds_alternative<llvm::APSInt>(y)) { \
596 TYPE_CHECK(Integer); \
597 llvm::APSInt rhs = std::get<llvm::APSInt>(y); \
598 llvm::APSInt lhs = data.Pop<llvm::APSInt>(); \
599 unsigned width = std::max(lhs.getBitWidth(), rhs.getBitWidth()); \
600 llvm::APInt lhs_bits = \
601 static_cast<const llvm::APInt &>(lhs).zext(width); \
602 llvm::APInt rhs_bits = \
603 static_cast<const llvm::APInt &>(rhs).zext(width); \
604 llvm::APInt bits = lhs_bits OP rhs_bits; \
605 data.Push(llvm::APSInt(std::move(bits), false)); \
607 return error("unsupported data types"); \
626#define SHIFTOP(OP, LEFT) \
628 TYPE_CHECK(Any, UInt); \
629 uint64_t y = data.Pop<uint64_t>(); \
631 return error("shift out of bounds"); \
632 if (std::holds_alternative<uint64_t>(data.back())) { \
633 uint64_t x = data.Pop<uint64_t>(); \
635 } else if (std::holds_alternative<int64_t>(data.back())) { \
636 int64_t x = data.Pop<int64_t>(); \
638 return error("left shift of negative value"); \
640 return error("shift out of bounds"); \
642 } else if (std::holds_alternative<llvm::APSInt>(data.back())) { \
643 llvm::APSInt x = data.Pop<llvm::APSInt>(); \
644 if (y > x.getBitWidth()) \
645 return error("shift out of bounds"); \
646 const llvm::APInt &bits = x; \
647 llvm::APInt shifted = \
648 LEFT ? bits.shl((unsigned)y) : bits.lshr((unsigned)y); \
649 data.Push(llvm::APSInt(std::move(shifted), false)); \
651 return error("unsupported data types"); \
670 if (std::holds_alternative<uint64_t>(x))
671 data.
Push(~std::get<uint64_t>(x));
672 else if (
auto *ap = std::get_if<llvm::APSInt>(&x)) {
673 llvm::APInt
bits = ~static_cast<const llvm::APInt &>(*ap);
674 data.
Push(llvm::APSInt(std::move(
bits),
false));
676 return error(
"unsupported data types");
702#define POP_VALOBJ(VALOBJ) \
703 auto VALOBJ = data.Pop<ValueObjectSP>(); \
705 return error("null object");
707 auto sel_error = [&](
const char *msg) {
708 return llvm::createStringErrorV(
"{0} (opcode={1}, selector={2})", msg,
717 const char *summary = valobj->GetSummaryAsCString();
718 data.
Push(summary ? std::string(valobj->GetSummaryAsCString())
722 case sel_get_num_children: {
725 auto result = valobj->GetNumChildren();
727 return result.takeError();
731 case sel_get_child_at_index: {
735 index = data.
Pop<llvm::APSInt>().getLimitedValue(
UINT32_MAX);
738 index = data.
Pop<uint64_t>();
741 data.
Push(valobj->GetChildAtIndex(index));
744 case sel_get_child_with_name: {
746 auto name = data.
Pop<std::string>();
748 data.
Push(valobj->GetChildMemberWithName(name));
751 case sel_get_child_index: {
753 auto name = data.
Pop<std::string>();
755 if (
auto index_or_err = valobj->GetIndexOfChildWithName(name))
758 return index_or_err.takeError();
761 case sel_get_parent: {
764 auto *parent = valobj->GetParent();
772 data.
Push(valobj->GetTypeImpl().GetCompilerType(
false));
775 case sel_get_template_argument_type: {
779 index = data.
Pop<llvm::APSInt>().getLimitedValue();
782 index = data.
Pop<uint64_t>();
786 data.
Push(type.GetTypeTemplateArgument(index,
true));
789 case sel_get_synthetic_value: {
792 data.
Push(valobj->GetSyntheticValue());
795 case sel_get_non_synthetic_value: {
798 data.
Push(valobj->GetNonSyntheticValue());
801 case sel_get_value: {
804 data.
Push(std::string(valobj->GetValueAsCString()));
807 case sel_get_value_as_unsigned: {
811 uint64_t val = valobj->GetValueAsUnsigned(0, &success);
814 return sel_error(
"failed to get value");
817 case sel_get_value_as_signed: {
821 int64_t val = valobj->GetValueAsSigned(0, &success);
824 return sel_error(
"failed to get value");
827 case sel_get_value_as_address: {
831 uint64_t addr = valobj->GetValueAsUnsigned(0, &success);
833 return sel_error(
"failed to get value");
834 if (
auto process_sp = valobj->GetProcessSP())
835 addr = process_sp->FixDataAddress(addr);
843 data.
Push(valobj->Cast(type));
848 auto new_name = data.
Pop<std::string>();
850 data.
Push(valobj->Clone(new_name));
853 case sel_get_pointee_type: {
856 data.
Push(type.GetPointeeType());
859 case sel_get_byte_size: {
863 llvm::expectedToOptional(type.GetByteSize(
nullptr)).value_or(0);
864 data.
Push(llvm::APSInt::get(size));
867 case sel_create_child_at_offset: {
870 auto offset = data.
Pop<llvm::APSInt>().getLimitedValue(
UINT32_MAX);
873 data.
Push(valobj->GetSyntheticChildAtOffset(offset, type,
true, name));
878 auto size = data.
Pop<std::string>().size();
889 return sel_error(
"selector not implemented");
896 data.
Push(std::make_shared<Dictionary>());
900 auto value = data.
PopAny();
901 auto key = data.
Pop<std::string>();
903 if (
auto *nested_sp = std::get_if<DictionarySP>(&value))
904 if (
Reaches(nested_sp->get(), dict_sp.get()))
905 return error(
"dict_set would create a reference cycle");
906 (*dict_sp)[key] = std::move(value);
911 auto key = data.
Pop<std::string>();
913 auto it = dict_sp->find(key);
914 if (it == dict_sp->end())
915 return error(
"key not found in dictionary");
916 data.
Push(it->second);
921 auto key = data.
Pop<std::string>();
923 bool found = dict_sp->find(key) != dict_sp->end();
924 data.
Push(llvm::APSInt::get(found));
928 return error(
"opcode not implemented");
930 return pc.takeError();