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 valobj = std::get_if<ValueObjectSP>(&d)) {
75 os <<
"object(" << valobj->get()->GetValueAsCString() <<
')';
76 }
else if (
auto type = std::get_if<CompilerType>(&d)) {
77 os <<
'(' << type->GetTypeName(
true) <<
')';
78 }
else if (
auto sel = std::get_if<FormatterBytecode::Selectors>(&d)) {
91 auto fmt = data.
Pop<std::string>();
93 llvm::formatv_object_base::parseFormatString(fmt, 0,
false);
95 llvm::raw_string_ostream os(s);
96 unsigned num_args = 0;
97 for (
const auto &r : replacements)
98 if (r.Type == llvm::ReplacementType::Format)
99 num_args = std::max(num_args, r.Index + 1);
101 if (data.size() < num_args)
102 return llvm::createStringError(
"not enough arguments");
104 for (
const auto &r : replacements) {
105 if (r.Type == llvm::ReplacementType::Literal) {
109 using namespace llvm::support::detail;
110 auto arg = data[data.size() - num_args + r.Index];
111 auto format = [&](FormatFunctorRef &&adapter) {
112 llvm::FmtAlign
Align(adapter, r.Where, r.Width, r.Pad);
113 Align.format(os, r.Options);
116 if (
auto s = std::get_if<std::string>(&arg))
117 format(FormatFunctor(s->c_str()));
118 else if (
auto u = std::get_if<uint64_t>(&arg))
119 format(FormatFunctor(u));
120 else if (
auto i = std::get_if<int64_t>(&arg))
121 format(FormatFunctor(i));
122 else if (
auto valobj = std::get_if<ValueObjectSP>(&arg)) {
124 format(FormatFunctor(
"null object"));
126 format(FormatFunctor(valobj->get()->GetValueAsCString()));
127 }
else if (
auto type = std::get_if<CompilerType>(&arg))
128 format(FormatFunctor(type->GetDisplayTypeName()));
129 else if (
auto sel = std::get_if<FormatterBytecode::Selectors>(&arg))
130 format(FormatFunctor(
toString(*sel)));
133 return llvm::Error::success();
136static llvm::Error
TypeCheck(llvm::ArrayRef<DataStackElement> data,
139 return llvm::createStringError(
"not enough elements on data stack");
141 auto &elem = data.back();
146 if (!std::holds_alternative<std::string>(elem))
147 return llvm::createStringError(
"expected String");
150 if (!std::holds_alternative<uint64_t>(elem))
151 return llvm::createStringError(
"expected UInt");
154 if (!std::holds_alternative<int64_t>(elem))
155 return llvm::createStringError(
"expected Int");
158 if (!std::holds_alternative<ValueObjectSP>(elem))
159 return llvm::createStringError(
"expected Object");
162 if (!std::holds_alternative<CompilerType>(elem))
163 return llvm::createStringError(
"expected Type");
166 if (!std::holds_alternative<Selectors>(elem))
167 return llvm::createStringError(
"expected Selector");
170 return llvm::Error::success();
189 return llvm::Error::success();
192 llvm::DataExtractor cur_block(control.back(),
true);
193 llvm::DataExtractor::Cursor
pc(0);
195 while (!control.empty()) {
197 auto activate_block = [&]() {
199 if (control.size() > 1)
200 control[control.size() - 2] = cur_block.getData().drop_front(
pc.tell());
201 cur_block = llvm::DataExtractor(control.back(),
true);
203 pc = llvm::DataExtractor::Cursor(0);
207 auto next_byte = [&]() -> uint8_t {
209 while (
pc.tell() >= cur_block.size() && !control.empty()) {
210 if (control.size() == 1) {
219 return cur_block.getU8(
pc);
224 if (control.empty() || !
pc)
225 return pc.takeError();
228 "[eval {0}] opcode={1}, control={2}, data={3}",
233#define TYPE_CHECK(...) \
234 if (auto error = TypeCheck(data, __VA_ARGS__)) \
237 auto error = [&](llvm::Twine msg) {
238 return llvm::createStringError(msg +
"(opcode=" +
toString(opcode) +
")");
245 data.
Push(data.back());
253 uint64_t idx = data.
Pop<uint64_t>();
254 if (idx >= data.size())
255 return error(
"index out of bounds");
256 data.
Push(data[idx]);
261 data.
Push(data[data.size() - 2]);
284 uint64_t length = cur_block.getULEB128(
pc);
286 return pc.takeError();
287 llvm::StringRef block = cur_block.getBytes(
pc, length);
289 return pc.takeError();
290 control.push_back(block);
295 if (data.
Pop<uint64_t>() != 0) {
296 if (!cur_block.size())
297 return error(
"empty control stack");
304 if (cur_block.size() < 2)
305 return error(
"empty control stack");
306 if (data.
Pop<uint64_t>() == 0)
307 control[control.size() - 2] = control.back();
313 return pc.takeError();
317 data.
Push(cur_block.getULEB128(
pc));
320 data.
Push(cur_block.getSLEB128(
pc));
322 case op_lit_selector:
325 case op_lit_string: {
326 uint64_t length = cur_block.getULEB128(
pc);
327 llvm::StringRef bytes = cur_block.getBytes(
pc, length);
328 data.
Push(bytes.str());
334 int64_t val = data.
Pop<int64_t>();
335 memcpy(&casted, &val,
sizeof(val));
342 uint64_t val = data.
Pop<uint64_t>();
343 memcpy(&casted, &val,
sizeof(val));
354#define BINOP_IMPL(OP, CHECK_ZERO) \
356 TYPE_CHECK(Any, Any); \
357 auto y = data.PopAny(); \
358 if (std::holds_alternative<uint64_t>(y)) { \
359 if (CHECK_ZERO && !std::get<uint64_t>(y)) \
360 return error(#OP " by zero"); \
362 data.Push((uint64_t)(data.Pop<uint64_t>() OP std::get<uint64_t>(y))); \
363 } else if (std::holds_alternative<int64_t>(y)) { \
364 if (CHECK_ZERO && !std::get<int64_t>(y)) \
365 return error(#OP " by zero"); \
367 data.Push((int64_t)(data.Pop<int64_t>() OP std::get<int64_t>(y))); \
369 return error("unsupported data types"); \
371#define BINOP(OP) BINOP_IMPL(OP, false)
372#define BINOP_CHECKZERO(OP) BINOP_IMPL(OP, true)
389#define SHIFTOP(OP, LEFT) \
391 TYPE_CHECK(Any, UInt); \
392 uint64_t y = data.Pop<uint64_t>(); \
394 return error("shift out of bounds"); \
395 if (std::holds_alternative<uint64_t>(data.back())) { \
396 uint64_t x = data.Pop<uint64_t>(); \
398 } else if (std::holds_alternative<int64_t>(data.back())) { \
399 int64_t x = data.Pop<int64_t>(); \
401 return error("left shift of negative value"); \
403 return error("shift out of bounds"); \
406 return error("unsupported data types"); \
424 data.
Push(~data.
Pop<uint64_t>());
449#define POP_VALOBJ(VALOBJ) \
450 auto VALOBJ = data.Pop<ValueObjectSP>(); \
452 return error("null object");
454 auto sel_error = [&](
const char *msg) {
455 return llvm::createStringErrorV(
"{0} (opcode={1}, selector={2})", msg,
464 const char *summary = valobj->GetSummaryAsCString();
465 data.
Push(summary ? std::string(valobj->GetSummaryAsCString())
469 case sel_get_num_children: {
472 auto result = valobj->GetNumChildren();
474 return result.takeError();
475 data.
Push((uint64_t)*result);
478 case sel_get_child_at_index: {
480 auto index = data.
Pop<uint64_t>();
482 data.
Push(valobj->GetChildAtIndex(index));
485 case sel_get_child_with_name: {
487 auto name = data.
Pop<std::string>();
489 data.
Push(valobj->GetChildMemberWithName(name));
492 case sel_get_child_index: {
494 auto name = data.
Pop<std::string>();
496 if (
auto index_or_err = valobj->GetIndexOfChildWithName(name))
497 data.
Push((uint64_t)*index_or_err);
499 return index_or_err.takeError();
502 case sel_get_parent: {
505 auto *parent = valobj->GetParent();
513 data.
Push(valobj->GetTypeImpl().GetCompilerType(
false));
516 case sel_get_template_argument_type: {
518 auto index = data.
Pop<uint64_t>();
521 data.
Push(type.GetTypeTemplateArgument(index,
true));
524 case sel_get_synthetic_value: {
527 data.
Push(valobj->GetSyntheticValue());
530 case sel_get_non_synthetic_value: {
533 data.
Push(valobj->GetNonSyntheticValue());
536 case sel_get_value: {
539 data.
Push(std::string(valobj->GetValueAsCString()));
542 case sel_get_value_as_unsigned: {
546 uint64_t val = valobj->GetValueAsUnsigned(0, &success);
549 return sel_error(
"failed to get value");
552 case sel_get_value_as_signed: {
556 int64_t val = valobj->GetValueAsSigned(0, &success);
559 return sel_error(
"failed to get value");
562 case sel_get_value_as_address: {
566 uint64_t addr = valobj->GetValueAsUnsigned(0, &success);
568 return sel_error(
"failed to get value");
569 if (
auto process_sp = valobj->GetProcessSP())
570 addr = process_sp->FixDataAddress(addr);
578 data.
Push(valobj->Cast(type));
583 auto new_name = data.
Pop<std::string>();
585 data.
Push(valobj->Clone(new_name));
590 data.
Push((uint64_t)data.
Pop<std::string>().size());
600 return sel_error(
"selector not implemented");
605 return error(
"opcode not implemented");
607 return pc.takeError();