65 llvm::raw_string_ostream os(s);
67 for (
auto &d : data) {
68 if (
auto s = std::get_if<std::string>(&d))
69 os <<
'"' << *s <<
'"';
70 else if (
auto u = std::get_if<uint64_t>(&d))
72 else if (
auto i = std::get_if<int64_t>(&d))
74 else if (
auto ap = std::get_if<llvm::APSInt>(&d))
76 else if (
auto valobj = std::get_if<ValueObjectSP>(&d)) {
80 os <<
"object(" << valobj->get()->GetValueAsCString() <<
')';
81 }
else if (
auto type = std::get_if<CompilerType>(&d)) {
82 os <<
'(' << type->GetTypeName(
true) <<
')';
83 }
else if (
auto sel = std::get_if<FormatterBytecode::Selectors>(&d)) {
85 }
else if (
auto *dict =
86 std::get_if<std::shared_ptr<FormatterBytecode::Dictionary>>(
88 os <<
"dict(" << (*dict ? (*dict)->size() : 0) <<
')';
100 auto fmt = data.
Pop<std::string>();
102 llvm::formatv_object_base::parseFormatString(fmt, 0,
false);
104 llvm::raw_string_ostream os(s);
105 unsigned num_args = 0;
106 for (
const auto &r : replacements)
107 if (r.Type == llvm::ReplacementType::Format)
108 num_args = std::max(num_args, r.Index + 1);
110 if (data.size() < num_args)
111 return llvm::createStringError(
"not enough arguments");
113 for (
const auto &r : replacements) {
114 if (r.Type == llvm::ReplacementType::Literal) {
118 using namespace llvm::support::detail;
119 auto arg = data[data.size() - num_args + r.Index];
120 auto format = [&](FormatFunctorRef &&adapter) {
121 llvm::FmtAlign
Align(adapter, r.Where, r.Width, r.Pad);
122 Align.format(os, r.Options);
125 if (
auto s = std::get_if<std::string>(&arg))
126 format(FormatFunctor(s->c_str()));
127 else if (
auto u = std::get_if<uint64_t>(&arg))
128 format(FormatFunctor(u));
129 else if (
auto i = std::get_if<int64_t>(&arg))
130 format(FormatFunctor(i));
131 else if (
auto ap = std::get_if<llvm::APSInt>(&arg))
132 format(FormatFunctor(*ap));
133 else if (
auto valobj = std::get_if<ValueObjectSP>(&arg)) {
135 format(FormatFunctor(
"null object"));
137 format(FormatFunctor(valobj->get()->GetValueAsCString()));
138 }
else if (
auto type = std::get_if<CompilerType>(&arg))
139 format(FormatFunctor(type->GetDisplayTypeName()));
140 else if (
auto sel = std::get_if<FormatterBytecode::Selectors>(&arg))
141 format(FormatFunctor(
toString(*sel)));
142 else if (std::holds_alternative<DictionarySP>(arg))
143 format(FormatFunctor(
"dict"));
146 return llvm::Error::success();
149static llvm::Error
TypeCheck(llvm::ArrayRef<DataStackElement> data,
152 return llvm::createStringError(
"not enough elements on data stack");
154 auto &elem = data.back();
159 if (!std::holds_alternative<std::string>(elem))
160 return llvm::createStringError(
"expected String");
163 if (!std::holds_alternative<uint64_t>(elem))
164 return llvm::createStringError(
"expected UInt");
167 if (!std::holds_alternative<int64_t>(elem))
168 return llvm::createStringError(
"expected Int");
171 if (!std::holds_alternative<ValueObjectSP>(elem))
172 return llvm::createStringError(
"expected Object");
175 if (!std::holds_alternative<CompilerType>(elem))
176 return llvm::createStringError(
"expected Type");
179 if (!std::holds_alternative<Selectors>(elem))
180 return llvm::createStringError(
"expected Selector");
183 if (!std::holds_alternative<llvm::APSInt>(elem))
184 return llvm::createStringError(
"expected Integer");
187 if (!std::holds_alternative<std::shared_ptr<FormatterBytecode::Dictionary>>(
189 return llvm::createStringError(
"expected Dictionary");
192 return llvm::Error::success();
245 return llvm::Error::success();
248 llvm::DataExtractor cur_block(control.back(),
true);
249 llvm::DataExtractor::Cursor
pc(0);
251 while (!control.empty()) {
253 auto activate_block = [&]() {
255 if (control.size() > 1)
256 control[control.size() - 2] = cur_block.getData().drop_front(
pc.tell());
257 cur_block = llvm::DataExtractor(control.back(),
true);
259 pc = llvm::DataExtractor::Cursor(0);
263 auto next_byte = [&]() -> uint8_t {
265 while (
pc.tell() >= cur_block.size() && !control.empty()) {
266 if (control.size() == 1) {
275 return cur_block.getU8(
pc);
280 if (control.empty() || !
pc)
281 return pc.takeError();
284 "[eval {0}] opcode={1}, control={2}, data={3}",
289#define TYPE_CHECK(...) \
290 if (auto error = TypeCheck(data, __VA_ARGS__)) \
293 auto error = [&](llvm::Twine msg) {
294 return llvm::createStringError(msg +
"(opcode=" +
toString(opcode) +
")");
301 data.
Push(data.back());
309 uint64_t idx = data.
Pop<uint64_t>();
310 if (idx >= data.size())
311 return error(
"index out of bounds");
312 data.
Push(data[idx]);
317 data.
Push(data[data.size() - 2]);
340 uint64_t length = cur_block.getULEB128(
pc);
342 return pc.takeError();
343 llvm::StringRef block = cur_block.getBytes(
pc, length);
345 return pc.takeError();
346 control.push_back(block);
350 auto cond = data.
PopAny();
352 if (
auto *ap = std::get_if<llvm::APSInt>(&cond))
353 truthy = !ap->isZero();
354 else if (
auto *u = std::get_if<uint64_t>(&cond))
358 return error(
"expected Integer or UInt");
360 if (!cur_block.size())
361 return error(
"empty control stack");
368 if (cur_block.size() < 2)
369 return error(
"empty control stack");
370 auto cond = data.
PopAny();
372 if (
auto *ap = std::get_if<llvm::APSInt>(&cond))
373 truthy = !ap->isZero();
374 else if (
auto *u = std::get_if<uint64_t>(&cond))
378 return error(
"expected Integer or UInt");
380 control[control.size() - 2] = control.back();
387 return pc.takeError();
391 data.
Push(cur_block.getULEB128(
pc));
394 data.
Push(cur_block.getSLEB128(
pc));
397 data.
Push(cur_block.getSLEB128APSInt(
pc));
399 case op_lit_selector:
405 case op_lit_string: {
406 uint64_t length = cur_block.getULEB128(
pc);
407 llvm::StringRef bytes = cur_block.getBytes(
pc, length);
408 data.
Push(bytes.str());
414 int64_t val = data.
Pop<int64_t>();
415 memcpy(&casted, &val,
sizeof(val));
422 uint64_t val = data.
Pop<uint64_t>();
423 memcpy(&casted, &val,
sizeof(val));
434#define BINOP_IMPL(OP, CHECK_ZERO) \
436 TYPE_CHECK(Any, Any); \
437 auto y = data.PopAny(); \
438 if (std::holds_alternative<uint64_t>(y)) { \
439 if (CHECK_ZERO && !std::get<uint64_t>(y)) \
440 return error(#OP " by zero"); \
442 data.Push((uint64_t)(data.Pop<uint64_t>() OP std::get<uint64_t>(y))); \
443 } else if (std::holds_alternative<int64_t>(y)) { \
444 if (CHECK_ZERO && !std::get<int64_t>(y)) \
445 return error(#OP " by zero"); \
447 data.Push((int64_t)(data.Pop<int64_t>() OP std::get<int64_t>(y))); \
448 } else if (std::holds_alternative<llvm::APSInt>(y)) { \
449 TYPE_CHECK(Integer); \
450 llvm::APSInt rhs = std::get<llvm::APSInt>(y); \
451 llvm::APSInt lhs = data.Pop<llvm::APSInt>(); \
452 if (lhs.isUnsigned() || rhs.isUnsigned()) \
453 return error("unsupported unsigned value"); \
454 unsigned width = std::max(lhs.getBitWidth(), rhs.getBitWidth()); \
455 lhs = lhs.extend(width); \
456 rhs = rhs.extend(width); \
457 if (CHECK_ZERO && rhs.isZero()) \
458 return error(#OP " by zero"); \
459 data.Push(WrapAPSIntResult(lhs OP rhs, width, lhs.isUnsigned())); \
461 return error("unsupported data types"); \
463#define BINOP(OP) BINOP_IMPL(OP, false)
464#define BINOP_CHECKZERO(OP) BINOP_IMPL(OP, true)
469 TYPE_CHECK(Any, Any); \
470 auto y = data.PopAny(); \
471 if (std::holds_alternative<uint64_t>(y)) { \
473 data.Push((uint64_t)(data.Pop<uint64_t>() OP std::get<uint64_t>(y))); \
474 } else if (std::holds_alternative<int64_t>(y)) { \
476 data.Push((int64_t)(data.Pop<int64_t>() OP std::get<int64_t>(y))); \
477 } else if (std::holds_alternative<llvm::APSInt>(y)) { \
478 TYPE_CHECK(Integer); \
479 llvm::APSInt rhs = std::get<llvm::APSInt>(y); \
480 llvm::APSInt lhs = data.Pop<llvm::APSInt>(); \
481 if (lhs.isUnsigned() || rhs.isUnsigned()) \
482 return error("unsupported unsigned value"); \
483 unsigned width = std::max(lhs.getBitWidth(), rhs.getBitWidth()); \
484 lhs = lhs.extend(width); \
485 rhs = rhs.extend(width); \
486 data.Push(WrapAPSIntResult(lhs OP rhs, width, lhs.isUnsigned())); \
488 return error("unsupported data types"); \
497 TYPE_CHECK(Any, Any); \
498 auto y = data.PopAny(); \
499 if (std::holds_alternative<uint64_t>(y)) { \
501 data.Push((uint64_t)(data.Pop<uint64_t>() OP std::get<uint64_t>(y))); \
502 } else if (std::holds_alternative<int64_t>(y)) { \
504 data.Push((int64_t)(data.Pop<int64_t>() OP std::get<int64_t>(y))); \
505 } else if (std::holds_alternative<llvm::APSInt>(y)) { \
506 TYPE_CHECK(Integer); \
507 llvm::APSInt rhs = std::get<llvm::APSInt>(y); \
508 llvm::APSInt lhs = data.Pop<llvm::APSInt>(); \
509 unsigned width = std::max(lhs.getBitWidth(), rhs.getBitWidth()); \
510 llvm::APInt lhs_bits = \
511 static_cast<const llvm::APInt &>(lhs).zext(width); \
512 llvm::APInt rhs_bits = \
513 static_cast<const llvm::APInt &>(rhs).zext(width); \
514 llvm::APInt bits = lhs_bits OP rhs_bits; \
515 data.Push(llvm::APSInt(std::move(bits), false)); \
517 return error("unsupported data types"); \
536#define SHIFTOP(OP, LEFT) \
538 TYPE_CHECK(Any, UInt); \
539 uint64_t y = data.Pop<uint64_t>(); \
541 return error("shift out of bounds"); \
542 if (std::holds_alternative<uint64_t>(data.back())) { \
543 uint64_t x = data.Pop<uint64_t>(); \
545 } else if (std::holds_alternative<int64_t>(data.back())) { \
546 int64_t x = data.Pop<int64_t>(); \
548 return error("left shift of negative value"); \
550 return error("shift out of bounds"); \
552 } else if (std::holds_alternative<llvm::APSInt>(data.back())) { \
553 llvm::APSInt x = data.Pop<llvm::APSInt>(); \
554 if (y > x.getBitWidth()) \
555 return error("shift out of bounds"); \
556 const llvm::APInt &bits = x; \
557 llvm::APInt shifted = \
558 LEFT ? bits.shl((unsigned)y) : bits.lshr((unsigned)y); \
559 data.Push(llvm::APSInt(std::move(shifted), false)); \
561 return error("unsupported data types"); \
580 if (std::holds_alternative<uint64_t>(x))
581 data.
Push(~std::get<uint64_t>(x));
582 else if (
auto *ap = std::get_if<llvm::APSInt>(&x)) {
583 llvm::APInt
bits = ~static_cast<const llvm::APInt &>(*ap);
584 data.
Push(llvm::APSInt(std::move(
bits),
false));
586 return error(
"unsupported data types");
612#define POP_VALOBJ(VALOBJ) \
613 auto VALOBJ = data.Pop<ValueObjectSP>(); \
615 return error("null object");
617 auto sel_error = [&](
const char *msg) {
618 return llvm::createStringErrorV(
"{0} (opcode={1}, selector={2})", msg,
627 const char *summary = valobj->GetSummaryAsCString();
628 data.
Push(summary ? std::string(valobj->GetSummaryAsCString())
632 case sel_get_num_children: {
635 auto result = valobj->GetNumChildren();
637 return result.takeError();
638 data.
Push((uint64_t)*result);
641 case sel_get_child_at_index: {
643 auto index = data.
Pop<uint64_t>();
645 data.
Push(valobj->GetChildAtIndex(index));
648 case sel_get_child_with_name: {
650 auto name = data.
Pop<std::string>();
652 data.
Push(valobj->GetChildMemberWithName(name));
655 case sel_get_child_index: {
657 auto name = data.
Pop<std::string>();
659 if (
auto index_or_err = valobj->GetIndexOfChildWithName(name))
660 data.
Push((uint64_t)*index_or_err);
662 return index_or_err.takeError();
665 case sel_get_parent: {
668 auto *parent = valobj->GetParent();
676 data.
Push(valobj->GetTypeImpl().GetCompilerType(
false));
679 case sel_get_template_argument_type: {
681 auto index = data.
Pop<uint64_t>();
684 data.
Push(type.GetTypeTemplateArgument(index,
true));
687 case sel_get_synthetic_value: {
690 data.
Push(valobj->GetSyntheticValue());
693 case sel_get_non_synthetic_value: {
696 data.
Push(valobj->GetNonSyntheticValue());
699 case sel_get_value: {
702 data.
Push(std::string(valobj->GetValueAsCString()));
705 case sel_get_value_as_unsigned: {
709 uint64_t val = valobj->GetValueAsUnsigned(0, &success);
712 return sel_error(
"failed to get value");
715 case sel_get_value_as_signed: {
719 int64_t val = valobj->GetValueAsSigned(0, &success);
722 return sel_error(
"failed to get value");
725 case sel_get_value_as_address: {
729 uint64_t addr = valobj->GetValueAsUnsigned(0, &success);
731 return sel_error(
"failed to get value");
732 if (
auto process_sp = valobj->GetProcessSP())
733 addr = process_sp->FixDataAddress(addr);
741 data.
Push(valobj->Cast(type));
746 auto new_name = data.
Pop<std::string>();
748 data.
Push(valobj->Clone(new_name));
753 data.
Push((uint64_t)data.
Pop<std::string>().size());
763 return sel_error(
"selector not implemented");
770 data.
Push(std::make_shared<Dictionary>());
774 auto value = data.
PopAny();
775 auto key = data.
Pop<std::string>();
777 if (
auto *nested_sp = std::get_if<DictionarySP>(&value))
778 if (
Reaches(nested_sp->get(), dict_sp.get()))
779 return error(
"dict_set would create a reference cycle");
780 (*dict_sp)[key] = std::move(value);
785 auto key = data.
Pop<std::string>();
787 auto it = dict_sp->find(key);
788 if (it == dict_sp->end())
789 return error(
"key not found in dictionary");
790 data.
Push(it->second);
795 auto key = data.
Pop<std::string>();
797 bool found = dict_sp->find(key) != dict_sp->end();
798 data.
Push(llvm::APSInt::get(found));
802 return error(
"opcode not implemented");
804 return pc.takeError();