62 llvm::raw_string_ostream os(s);
64 for (
auto &d : data) {
65 if (
auto s = std::get_if<std::string>(&d))
66 os <<
'"' << *s <<
'"';
67 else if (
auto u = std::get_if<uint64_t>(&d))
69 else if (
auto i = std::get_if<int64_t>(&d))
71 else if (
auto ap = std::get_if<llvm::APSInt>(&d))
73 else if (
auto valobj = std::get_if<ValueObjectSP>(&d)) {
77 os <<
"object(" << valobj->get()->GetValueAsCString() <<
')';
78 }
else if (
auto type = std::get_if<CompilerType>(&d)) {
79 os <<
'(' << type->GetTypeName(
true) <<
')';
80 }
else if (
auto sel = std::get_if<FormatterBytecode::Selectors>(&d)) {
93 auto fmt = data.
Pop<std::string>();
95 llvm::formatv_object_base::parseFormatString(fmt, 0,
false);
97 llvm::raw_string_ostream os(s);
98 unsigned num_args = 0;
99 for (
const auto &r : replacements)
100 if (r.Type == llvm::ReplacementType::Format)
101 num_args = std::max(num_args, r.Index + 1);
103 if (data.size() < num_args)
104 return llvm::createStringError(
"not enough arguments");
106 for (
const auto &r : replacements) {
107 if (r.Type == llvm::ReplacementType::Literal) {
111 using namespace llvm::support::detail;
112 auto arg = data[data.size() - num_args + r.Index];
113 auto format = [&](FormatFunctorRef &&adapter) {
114 llvm::FmtAlign
Align(adapter, r.Where, r.Width, r.Pad);
115 Align.format(os, r.Options);
118 if (
auto s = std::get_if<std::string>(&arg))
119 format(FormatFunctor(s->c_str()));
120 else if (
auto u = std::get_if<uint64_t>(&arg))
121 format(FormatFunctor(u));
122 else if (
auto i = std::get_if<int64_t>(&arg))
123 format(FormatFunctor(i));
124 else if (
auto ap = std::get_if<llvm::APSInt>(&arg))
125 format(FormatFunctor(*ap));
126 else if (
auto valobj = std::get_if<ValueObjectSP>(&arg)) {
128 format(FormatFunctor(
"null object"));
130 format(FormatFunctor(valobj->get()->GetValueAsCString()));
131 }
else if (
auto type = std::get_if<CompilerType>(&arg))
132 format(FormatFunctor(type->GetDisplayTypeName()));
133 else if (
auto sel = std::get_if<FormatterBytecode::Selectors>(&arg))
134 format(FormatFunctor(
toString(*sel)));
137 return llvm::Error::success();
140static llvm::Error
TypeCheck(llvm::ArrayRef<DataStackElement> data,
143 return llvm::createStringError(
"not enough elements on data stack");
145 auto &elem = data.back();
150 if (!std::holds_alternative<std::string>(elem))
151 return llvm::createStringError(
"expected String");
154 if (!std::holds_alternative<uint64_t>(elem))
155 return llvm::createStringError(
"expected UInt");
158 if (!std::holds_alternative<int64_t>(elem))
159 return llvm::createStringError(
"expected Int");
162 if (!std::holds_alternative<ValueObjectSP>(elem))
163 return llvm::createStringError(
"expected Object");
166 if (!std::holds_alternative<CompilerType>(elem))
167 return llvm::createStringError(
"expected Type");
170 if (!std::holds_alternative<Selectors>(elem))
171 return llvm::createStringError(
"expected Selector");
174 if (!std::holds_alternative<llvm::APSInt>(elem))
175 return llvm::createStringError(
"expected Integer");
178 return llvm::Error::success();
210 return llvm::Error::success();
213 llvm::DataExtractor cur_block(control.back(),
true);
214 llvm::DataExtractor::Cursor
pc(0);
216 while (!control.empty()) {
218 auto activate_block = [&]() {
220 if (control.size() > 1)
221 control[control.size() - 2] = cur_block.getData().drop_front(
pc.tell());
222 cur_block = llvm::DataExtractor(control.back(),
true);
224 pc = llvm::DataExtractor::Cursor(0);
228 auto next_byte = [&]() -> uint8_t {
230 while (
pc.tell() >= cur_block.size() && !control.empty()) {
231 if (control.size() == 1) {
240 return cur_block.getU8(
pc);
245 if (control.empty() || !
pc)
246 return pc.takeError();
249 "[eval {0}] opcode={1}, control={2}, data={3}",
254#define TYPE_CHECK(...) \
255 if (auto error = TypeCheck(data, __VA_ARGS__)) \
258 auto error = [&](llvm::Twine msg) {
259 return llvm::createStringError(msg +
"(opcode=" +
toString(opcode) +
")");
266 data.
Push(data.back());
274 uint64_t idx = data.
Pop<uint64_t>();
275 if (idx >= data.size())
276 return error(
"index out of bounds");
277 data.
Push(data[idx]);
282 data.
Push(data[data.size() - 2]);
305 uint64_t length = cur_block.getULEB128(
pc);
307 return pc.takeError();
308 llvm::StringRef block = cur_block.getBytes(
pc, length);
310 return pc.takeError();
311 control.push_back(block);
315 auto cond = data.
PopAny();
317 if (
auto *ap = std::get_if<llvm::APSInt>(&cond))
318 truthy = !ap->isZero();
319 else if (
auto *u = std::get_if<uint64_t>(&cond))
323 return error(
"expected Integer or UInt");
325 if (!cur_block.size())
326 return error(
"empty control stack");
333 if (cur_block.size() < 2)
334 return error(
"empty control stack");
335 auto cond = data.
PopAny();
337 if (
auto *ap = std::get_if<llvm::APSInt>(&cond))
338 truthy = !ap->isZero();
339 else if (
auto *u = std::get_if<uint64_t>(&cond))
343 return error(
"expected Integer or UInt");
345 control[control.size() - 2] = control.back();
352 return pc.takeError();
356 data.
Push(cur_block.getULEB128(
pc));
359 data.
Push(cur_block.getSLEB128(
pc));
362 data.
Push(cur_block.getSLEB128APSInt(
pc));
364 case op_lit_selector:
367 case op_lit_string: {
368 uint64_t length = cur_block.getULEB128(
pc);
369 llvm::StringRef bytes = cur_block.getBytes(
pc, length);
370 data.
Push(bytes.str());
376 int64_t val = data.
Pop<int64_t>();
377 memcpy(&casted, &val,
sizeof(val));
384 uint64_t val = data.
Pop<uint64_t>();
385 memcpy(&casted, &val,
sizeof(val));
396#define BINOP_IMPL(OP, CHECK_ZERO) \
398 TYPE_CHECK(Any, Any); \
399 auto y = data.PopAny(); \
400 if (std::holds_alternative<uint64_t>(y)) { \
401 if (CHECK_ZERO && !std::get<uint64_t>(y)) \
402 return error(#OP " by zero"); \
404 data.Push((uint64_t)(data.Pop<uint64_t>() OP std::get<uint64_t>(y))); \
405 } else if (std::holds_alternative<int64_t>(y)) { \
406 if (CHECK_ZERO && !std::get<int64_t>(y)) \
407 return error(#OP " by zero"); \
409 data.Push((int64_t)(data.Pop<int64_t>() OP std::get<int64_t>(y))); \
410 } else if (std::holds_alternative<llvm::APSInt>(y)) { \
411 TYPE_CHECK(Integer); \
412 llvm::APSInt rhs = std::get<llvm::APSInt>(y); \
413 llvm::APSInt lhs = data.Pop<llvm::APSInt>(); \
414 if (lhs.isUnsigned() || rhs.isUnsigned()) \
415 return error("unsupported unsigned value"); \
416 unsigned width = std::max(lhs.getBitWidth(), rhs.getBitWidth()); \
417 lhs = lhs.extend(width); \
418 rhs = rhs.extend(width); \
419 if (CHECK_ZERO && rhs.isZero()) \
420 return error(#OP " by zero"); \
421 data.Push(WrapAPSIntResult(lhs OP rhs, width, lhs.isUnsigned())); \
423 return error("unsupported data types"); \
425#define BINOP(OP) BINOP_IMPL(OP, false)
426#define BINOP_CHECKZERO(OP) BINOP_IMPL(OP, true)
431 TYPE_CHECK(Any, Any); \
432 auto y = data.PopAny(); \
433 if (std::holds_alternative<uint64_t>(y)) { \
435 data.Push((uint64_t)(data.Pop<uint64_t>() OP std::get<uint64_t>(y))); \
436 } else if (std::holds_alternative<int64_t>(y)) { \
438 data.Push((int64_t)(data.Pop<int64_t>() OP std::get<int64_t>(y))); \
439 } else if (std::holds_alternative<llvm::APSInt>(y)) { \
440 TYPE_CHECK(Integer); \
441 llvm::APSInt rhs = std::get<llvm::APSInt>(y); \
442 llvm::APSInt lhs = data.Pop<llvm::APSInt>(); \
443 if (lhs.isUnsigned() || rhs.isUnsigned()) \
444 return error("unsupported unsigned value"); \
445 unsigned width = std::max(lhs.getBitWidth(), rhs.getBitWidth()); \
446 lhs = lhs.extend(width); \
447 rhs = rhs.extend(width); \
448 data.Push(WrapAPSIntResult(lhs OP rhs, width, lhs.isUnsigned())); \
450 return error("unsupported data types"); \
459 TYPE_CHECK(Any, Any); \
460 auto y = data.PopAny(); \
461 if (std::holds_alternative<uint64_t>(y)) { \
463 data.Push((uint64_t)(data.Pop<uint64_t>() OP std::get<uint64_t>(y))); \
464 } else if (std::holds_alternative<int64_t>(y)) { \
466 data.Push((int64_t)(data.Pop<int64_t>() OP std::get<int64_t>(y))); \
467 } else if (std::holds_alternative<llvm::APSInt>(y)) { \
468 TYPE_CHECK(Integer); \
469 llvm::APSInt rhs = std::get<llvm::APSInt>(y); \
470 llvm::APSInt lhs = data.Pop<llvm::APSInt>(); \
471 unsigned width = std::max(lhs.getBitWidth(), rhs.getBitWidth()); \
472 llvm::APInt lhs_bits = \
473 static_cast<const llvm::APInt &>(lhs).zext(width); \
474 llvm::APInt rhs_bits = \
475 static_cast<const llvm::APInt &>(rhs).zext(width); \
476 llvm::APInt bits = lhs_bits OP rhs_bits; \
477 data.Push(llvm::APSInt(std::move(bits), false)); \
479 return error("unsupported data types"); \
498#define SHIFTOP(OP, LEFT) \
500 TYPE_CHECK(Any, UInt); \
501 uint64_t y = data.Pop<uint64_t>(); \
503 return error("shift out of bounds"); \
504 if (std::holds_alternative<uint64_t>(data.back())) { \
505 uint64_t x = data.Pop<uint64_t>(); \
507 } else if (std::holds_alternative<int64_t>(data.back())) { \
508 int64_t x = data.Pop<int64_t>(); \
510 return error("left shift of negative value"); \
512 return error("shift out of bounds"); \
514 } else if (std::holds_alternative<llvm::APSInt>(data.back())) { \
515 llvm::APSInt x = data.Pop<llvm::APSInt>(); \
516 if (y > x.getBitWidth()) \
517 return error("shift out of bounds"); \
518 const llvm::APInt &bits = x; \
519 llvm::APInt shifted = \
520 LEFT ? bits.shl((unsigned)y) : bits.lshr((unsigned)y); \
521 data.Push(llvm::APSInt(std::move(shifted), false)); \
523 return error("unsupported data types"); \
542 if (std::holds_alternative<uint64_t>(x))
543 data.
Push(~std::get<uint64_t>(x));
544 else if (
auto *ap = std::get_if<llvm::APSInt>(&x)) {
545 llvm::APInt
bits = ~static_cast<const llvm::APInt &>(*ap);
546 data.
Push(llvm::APSInt(std::move(
bits),
false));
548 return error(
"unsupported data types");
574#define POP_VALOBJ(VALOBJ) \
575 auto VALOBJ = data.Pop<ValueObjectSP>(); \
577 return error("null object");
579 auto sel_error = [&](
const char *msg) {
580 return llvm::createStringErrorV(
"{0} (opcode={1}, selector={2})", msg,
589 const char *summary = valobj->GetSummaryAsCString();
590 data.
Push(summary ? std::string(valobj->GetSummaryAsCString())
594 case sel_get_num_children: {
597 auto result = valobj->GetNumChildren();
599 return result.takeError();
600 data.
Push((uint64_t)*result);
603 case sel_get_child_at_index: {
605 auto index = data.
Pop<uint64_t>();
607 data.
Push(valobj->GetChildAtIndex(index));
610 case sel_get_child_with_name: {
612 auto name = data.
Pop<std::string>();
614 data.
Push(valobj->GetChildMemberWithName(name));
617 case sel_get_child_index: {
619 auto name = data.
Pop<std::string>();
621 if (
auto index_or_err = valobj->GetIndexOfChildWithName(name))
622 data.
Push((uint64_t)*index_or_err);
624 return index_or_err.takeError();
627 case sel_get_parent: {
630 auto *parent = valobj->GetParent();
638 data.
Push(valobj->GetTypeImpl().GetCompilerType(
false));
641 case sel_get_template_argument_type: {
643 auto index = data.
Pop<uint64_t>();
646 data.
Push(type.GetTypeTemplateArgument(index,
true));
649 case sel_get_synthetic_value: {
652 data.
Push(valobj->GetSyntheticValue());
655 case sel_get_non_synthetic_value: {
658 data.
Push(valobj->GetNonSyntheticValue());
661 case sel_get_value: {
664 data.
Push(std::string(valobj->GetValueAsCString()));
667 case sel_get_value_as_unsigned: {
671 uint64_t val = valobj->GetValueAsUnsigned(0, &success);
674 return sel_error(
"failed to get value");
677 case sel_get_value_as_signed: {
681 int64_t val = valobj->GetValueAsSigned(0, &success);
684 return sel_error(
"failed to get value");
687 case sel_get_value_as_address: {
691 uint64_t addr = valobj->GetValueAsUnsigned(0, &success);
693 return sel_error(
"failed to get value");
694 if (
auto process_sp = valobj->GetProcessSP())
695 addr = process_sp->FixDataAddress(addr);
703 data.
Push(valobj->Cast(type));
708 auto new_name = data.
Pop<std::string>();
710 data.
Push(valobj->Clone(new_name));
715 data.
Push((uint64_t)data.
Pop<std::string>().size());
725 return sel_error(
"selector not implemented");
730 return error(
"opcode not implemented");
732 return pc.takeError();