88 auto fmt = data.
Pop<std::string>();
90 llvm::formatv_object_base::parseFormatString(fmt, 0,
false);
92 llvm::raw_string_ostream os(s);
93 unsigned num_args = 0;
94 for (
const auto &r : replacements)
95 if (r.Type == llvm::ReplacementType::Format)
96 num_args = std::max(num_args, r.Index + 1);
98 if (data.size() < num_args)
99 return llvm::createStringError(
"not enough arguments");
101 for (
const auto &r : replacements) {
102 if (r.Type == llvm::ReplacementType::Literal) {
106 using namespace llvm::support::detail;
107 auto arg = data[data.size() - num_args + r.Index];
108 auto format = [&](format_adapter &&adapter) {
109 llvm::FmtAlign
Align(adapter, r.Where, r.Width, r.Pad);
110 Align.format(os, r.Options);
113 if (
auto s = std::get_if<std::string>(&arg))
114 format(build_format_adapter(s->c_str()));
115 else if (
auto u = std::get_if<uint64_t>(&arg))
116 format(build_format_adapter(u));
117 else if (
auto i = std::get_if<int64_t>(&arg))
118 format(build_format_adapter(i));
119 else if (
auto valobj = std::get_if<ValueObjectSP>(&arg)) {
121 format(build_format_adapter(
"null object"));
123 format(build_format_adapter(valobj->get()->GetValueAsCString()));
124 }
else if (
auto type = std::get_if<CompilerType>(&arg))
125 format(build_format_adapter(type->GetDisplayTypeName()));
126 else if (
auto sel = std::get_if<FormatterBytecode::Selectors>(&arg))
127 format(build_format_adapter(
toString(*sel)));
130 return llvm::Error::success();
133static llvm::Error
TypeCheck(llvm::ArrayRef<DataStackElement> data,
136 return llvm::createStringError(
"not enough elements on data stack");
138 auto &elem = data.back();
143 if (!std::holds_alternative<std::string>(elem))
144 return llvm::createStringError(
"expected String");
147 if (!std::holds_alternative<uint64_t>(elem))
148 return llvm::createStringError(
"expected UInt");
151 if (!std::holds_alternative<int64_t>(elem))
152 return llvm::createStringError(
"expected Int");
155 if (!std::holds_alternative<ValueObjectSP>(elem))
156 return llvm::createStringError(
"expected Object");
159 if (!std::holds_alternative<CompilerType>(elem))
160 return llvm::createStringError(
"expected Type");
163 if (!std::holds_alternative<Selectors>(elem))
164 return llvm::createStringError(
"expected Selector");
167 return llvm::Error::success();
184llvm::Error
Interpret(std::vector<ControlStackElement> &control,
187 return llvm::Error::success();
190 llvm::DataExtractor cur_block(control.back(),
true, 64);
191 llvm::DataExtractor::Cursor
pc(0);
193 while (!control.empty()) {
195 auto activate_block = [&]() {
197 if (control.size() > 1)
198 control[control.size() - 2] = cur_block.getData().drop_front(
pc.tell());
199 cur_block = llvm::DataExtractor(control.back(),
true, 64);
201 pc = llvm::DataExtractor::Cursor(0);
205 auto next_byte = [&]() -> uint8_t {
207 while (
pc.tell() >= cur_block.size() && !control.empty()) {
208 if (control.size() == 1) {
217 return cur_block.getU8(
pc);
222 if (control.empty() || !
pc)
223 return pc.takeError();
226 "[eval {0}] opcode={1}, control={2}, data={3}",
toString(sel),
230#define TYPE_CHECK(...) \
231 if (auto error = TypeCheck(data, __VA_ARGS__)) \
234 auto error = [&](llvm::Twine msg) {
235 return llvm::createStringError(msg +
"(opcode=" +
toString(opcode) +
")");
242 data.
Push(data.back());
250 uint64_t idx = data.
Pop<uint64_t>();
251 if (idx >= data.size())
252 return error(
"index out of bounds");
253 data.
Push(data[idx]);
258 data.
Push(data[data.size() - 2]);
281 uint64_t length = cur_block.getULEB128(
pc);
283 return pc.takeError();
284 llvm::StringRef block = cur_block.getBytes(
pc, length);
286 return pc.takeError();
287 control.push_back(block);
292 if (data.
Pop<uint64_t>() != 0) {
293 if (!cur_block.size())
294 return error(
"empty control stack");
301 if (cur_block.size() < 2)
302 return error(
"empty control stack");
303 if (data.
Pop<uint64_t>() == 0)
304 control[control.size() - 2] = control.back();
310 return pc.takeError();
314 data.
Push(cur_block.getULEB128(
pc));
317 data.
Push(cur_block.getSLEB128(
pc));
319 case op_lit_selector:
322 case op_lit_string: {
323 uint64_t length = cur_block.getULEB128(
pc);
324 llvm::StringRef bytes = cur_block.getBytes(
pc, length);
325 data.
Push(bytes.str());
331 int64_t val = data.
Pop<int64_t>();
332 memcpy(&casted, &val,
sizeof(val));
339 uint64_t val = data.
Pop<uint64_t>();
340 memcpy(&casted, &val,
sizeof(val));
351#define BINOP_IMPL(OP, CHECK_ZERO) \
353 TYPE_CHECK(Any, Any); \
354 auto y = data.PopAny(); \
355 if (std::holds_alternative<uint64_t>(y)) { \
356 if (CHECK_ZERO && !std::get<uint64_t>(y)) \
357 return error(#OP " by zero"); \
359 data.Push((uint64_t)(data.Pop<uint64_t>() OP std::get<uint64_t>(y))); \
360 } else if (std::holds_alternative<int64_t>(y)) { \
361 if (CHECK_ZERO && !std::get<int64_t>(y)) \
362 return error(#OP " by zero"); \
364 data.Push((int64_t)(data.Pop<int64_t>() OP std::get<int64_t>(y))); \
366 return error("unsupported data types"); \
368#define BINOP(OP) BINOP_IMPL(OP, false)
369#define BINOP_CHECKZERO(OP) BINOP_IMPL(OP, true)
386#define SHIFTOP(OP, LEFT) \
388 TYPE_CHECK(Any, UInt); \
389 uint64_t y = data.Pop<uint64_t>(); \
391 return error("shift out of bounds"); \
392 if (std::holds_alternative<uint64_t>(data.back())) { \
393 uint64_t x = data.Pop<uint64_t>(); \
395 } else if (std::holds_alternative<int64_t>(data.back())) { \
396 int64_t x = data.Pop<int64_t>(); \
398 return error("left shift of negative value"); \
400 return error("shift out of bounds"); \
403 return error("unsupported data types"); \
421 data.
Push(~data.
Pop<uint64_t>());
446#define POP_VALOBJ(VALOBJ) \
447 auto VALOBJ = data.Pop<ValueObjectSP>(); \
449 return error("null object");
451 auto sel_error = [&](
const char *msg) {
452 return llvm::createStringError(
"{0} (opcode={1}, selector={2})", msg,
461 const char *summary = valobj->GetSummaryAsCString();
462 data.
Push(summary ? std::string(valobj->GetSummaryAsCString())
466 case sel_get_num_children: {
469 auto result = valobj->GetNumChildren();
471 return result.takeError();
472 data.
Push((uint64_t)*result);
475 case sel_get_child_at_index: {
477 auto index = data.
Pop<uint64_t>();
479 data.
Push(valobj->GetChildAtIndex(index));
482 case sel_get_child_with_name: {
484 auto name = data.
Pop<std::string>();
486 data.
Push(valobj->GetChildMemberWithName(name));
489 case sel_get_child_index: {
491 auto name = data.
Pop<std::string>();
493 if (
auto index_or_err = valobj->GetIndexOfChildWithName(name))
494 data.
Push((uint64_t)*index_or_err);
496 return index_or_err.takeError();
503 data.
Push(valobj->GetTypeImpl().GetCompilerType(
false));
506 case sel_get_template_argument_type: {
508 auto index = data.
Pop<uint64_t>();
511 data.
Push(type.GetTypeTemplateArgument(index,
true));
514 case sel_get_value: {
517 data.
Push(std::string(valobj->GetValueAsCString()));
520 case sel_get_value_as_unsigned: {
524 uint64_t val = valobj->GetValueAsUnsigned(0, &success);
527 return sel_error(
"failed to get value");
530 case sel_get_value_as_signed: {
534 int64_t val = valobj->GetValueAsSigned(0, &success);
537 return sel_error(
"failed to get value");
540 case sel_get_value_as_address: {
544 uint64_t addr = valobj->GetValueAsUnsigned(0, &success);
546 return sel_error(
"failed to get value");
547 if (
auto process_sp = valobj->GetProcessSP())
548 addr = process_sp->FixDataAddress(addr);
556 data.
Push(valobj->Cast(type));
561 data.
Push((uint64_t)data.
Pop<std::string>().size());
571 return sel_error(
"selector not implemented");
576 return error(
"opcode not implemented");
578 return pc.takeError();