primitive locals
This commit is contained in:
@@ -28,6 +28,7 @@ bool Window::draw(Frontend &frontend)
|
||||
case source:
|
||||
return std::get<SourceWindow>(this->data).draw(frontend);
|
||||
break;
|
||||
case watch: return std::get<WatchWindow>(this->data).draw(frontend);
|
||||
default: printf("Unhandled window draw: %u\n", this->type); exit(1);
|
||||
}
|
||||
}
|
||||
@@ -88,6 +89,15 @@ Window Window::create_source(size_t id)
|
||||
SourceWindow{.id = id_str, .open = true, .first = true}};
|
||||
}
|
||||
|
||||
Window Window::create_watch(size_t id)
|
||||
{
|
||||
auto id_str = std::string{"Watch##"};
|
||||
id_str.append(std::to_string(id));
|
||||
|
||||
return Window{.type = WindowType::watch,
|
||||
.data = WatchWindow{.id = id_str, .open = true, .first = true}};
|
||||
}
|
||||
|
||||
bool RegWindow::draw(const Frontend &frontend)
|
||||
{
|
||||
//ImGui::SetNextWindowDockID(frontend.dock_id, ImGuiCond_Appearing);
|
||||
@@ -970,6 +980,278 @@ bool SourceWindow::draw(Frontend &frontend)
|
||||
return false;
|
||||
}
|
||||
|
||||
bool WatchWindow::draw(Frontend &frontend)
|
||||
{
|
||||
if (!ImGui::Begin(this->id.c_str()))
|
||||
{
|
||||
ImGui::End();
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!frontend.target)
|
||||
{
|
||||
this->first = true;
|
||||
ImGui::End();
|
||||
return false;
|
||||
}
|
||||
|
||||
if (frontend.target->state == TargetState::stopped
|
||||
|| frontend.target->state == TargetState::startup)
|
||||
{
|
||||
ImGui::End();
|
||||
return false;
|
||||
}
|
||||
|
||||
// TODO: we need to clean up the initializations/sync of the DAG somehow
|
||||
if (first)
|
||||
{
|
||||
this->locals_src_id = frontend.target->data_node_id++;
|
||||
using namespace data::source;
|
||||
frontend.target->backend->add_data_node(Node{.id = this->locals_src_id,
|
||||
.type = Node::Type::locals,
|
||||
.data = std::monostate{}});
|
||||
|
||||
first = false;
|
||||
}
|
||||
|
||||
// ImGuiTableFlags_SizingFixedFit
|
||||
if (ImGui::BeginTable("##Variables", 2))
|
||||
{
|
||||
ImGui::TableSetupColumn("Name");
|
||||
ImGui::TableSetupColumn("Value");
|
||||
ImGui::TableHeadersRow();
|
||||
|
||||
auto locals_idx = frontend.target->data_idx_for_src_id(this->locals_src_id);
|
||||
if (locals_idx)
|
||||
{
|
||||
const auto &local_node = *frontend.target->data_res_nodes[*locals_idx];
|
||||
const auto &locals_data = local_node.vec_data();
|
||||
size_t cur_off = 0;
|
||||
size_t cur_idx = 0;
|
||||
while (cur_off < locals_data.size())
|
||||
{
|
||||
if (cur_off + 2 > locals_data.size())
|
||||
{
|
||||
break;
|
||||
}
|
||||
auto str_len =
|
||||
*reinterpret_cast<const uint16_t *>(locals_data.data() + cur_off);
|
||||
if (cur_off + 2 + str_len > locals_data.size())
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
auto name = std::string_view{
|
||||
reinterpret_cast<const char *>(locals_data.data() + cur_off + 2),
|
||||
str_len};
|
||||
auto node_idx = local_node.children[cur_idx];
|
||||
this->draw_value(frontend,
|
||||
frontend.target->data_res_nodes[node_idx]->type_id,
|
||||
name, node_idx, 0);
|
||||
|
||||
cur_idx += 1;
|
||||
cur_off += 2 + str_len;
|
||||
}
|
||||
}
|
||||
|
||||
ImGui::EndTable();
|
||||
}
|
||||
|
||||
ImGui::End();
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
void WatchWindow::draw_value(Frontend &frontend,
|
||||
data::type_info::TypeID type_id,
|
||||
std::string_view name,
|
||||
data::result::NodeIdx node_idx, size_t off)
|
||||
{
|
||||
ImGui::TableNextRow();
|
||||
ImGui::TableSetColumnIndex(0);
|
||||
const auto &node_opt = frontend.target->data_res_nodes[node_idx];
|
||||
if (!node_opt || !node_opt->success)
|
||||
{
|
||||
ImGui::TextUnformatted(name.begin(), name.end());
|
||||
ImGui::TableNextColumn();
|
||||
ImGui::TextDisabled("<unavailable>");
|
||||
return;
|
||||
}
|
||||
|
||||
const auto &node = *node_opt;
|
||||
using namespace data::type_info;
|
||||
while (type_id.type == Type::alias)
|
||||
{
|
||||
type_id =
|
||||
std::get<TypeID>(frontend.target->types[type_id.idx].member_types);
|
||||
}
|
||||
|
||||
auto tree_open = false;
|
||||
auto pop_id = false;
|
||||
if (type_id.type == Type::complex || type_id.type == Type::array)
|
||||
{
|
||||
ImGui::PushID(name.begin(), name.end());
|
||||
pop_id = true;
|
||||
|
||||
tree_open =
|
||||
ImGui::TreeNodeEx((void *)node_idx, ImGuiTreeNodeFlags_SpanFullWidth,
|
||||
"%.*s", static_cast<int>(name.size()), name.data());
|
||||
|
||||
if (tree_open)
|
||||
{
|
||||
if (type_id.type == Type::complex)
|
||||
{
|
||||
const auto &members = frontend.target->types[type_id.idx].member_vec();
|
||||
for (size_t i = 0; i < members.size(); ++i)
|
||||
{
|
||||
const auto &member = members[i];
|
||||
// Skip bitfield
|
||||
if (member.bitfield_size)
|
||||
{
|
||||
ImGui::TableNextRow();
|
||||
ImGui::TableSetColumnIndex(0);
|
||||
ImGui::Text("%s", member.name.c_str());
|
||||
ImGui::TableNextColumn();
|
||||
ImGui::TextDisabled("<bitfield not supported>");
|
||||
continue;
|
||||
}
|
||||
|
||||
this->draw_value(frontend, member.type_id, member.name, node_idx,
|
||||
off + member.offset);
|
||||
}
|
||||
} else
|
||||
{
|
||||
// array
|
||||
auto member_ty_id =
|
||||
std::get<TypeID>(frontend.target->types[type_id.idx].member_types);
|
||||
auto member_size = member_ty_id.byte_size(frontend.target->types);
|
||||
size_t el_count =
|
||||
frontend.target->types[type_id.idx].byte_size / member_size;
|
||||
|
||||
char buf[32];
|
||||
size_t member_off = 0;
|
||||
for (size_t i = 0; i < el_count; ++i)
|
||||
{
|
||||
std::snprintf(buf, sizeof(buf), "[%lu]", i);
|
||||
this->draw_value(frontend, member_ty_id, buf, node_idx,
|
||||
off + member_off);
|
||||
member_off += member_size;
|
||||
}
|
||||
}
|
||||
|
||||
ImGui::TreePop();
|
||||
}
|
||||
|
||||
ImGui::PopID();
|
||||
} else
|
||||
{
|
||||
ImGui::TextUnformatted(name.begin(), name.end());
|
||||
ImGui::TableSetColumnIndex(1);
|
||||
switch (type_id.type)
|
||||
{
|
||||
using enum Type;
|
||||
case i8:
|
||||
{
|
||||
auto val = node.get_primitive<int8_t>(off);
|
||||
if (std::isprint(val))
|
||||
{
|
||||
ImGui::Text("%c", val);
|
||||
} else
|
||||
{
|
||||
ImGui::Text("%d", val);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case u8: ImGui::Text("%lu", node.get_primitive<uint8_t>(off)); break;
|
||||
case u16: ImGui::Text("%lu", node.get_primitive<uint16_t>(off)); break;
|
||||
case u32: ImGui::Text("%lu", node.get_primitive<uint32_t>(off)); break;
|
||||
case u64: ImGui::Text("%lu", node.get_primitive<uint64_t>(off)); break;
|
||||
case i16: ImGui::Text("%ld", node.get_primitive<int16_t>(off)); break;
|
||||
case i32: ImGui::Text("%ld", node.get_primitive<int32_t>(off)); break;
|
||||
case i64: ImGui::Text("%ld", node.get_primitive<int64_t>(off)); break;
|
||||
case _bool:
|
||||
{
|
||||
auto val = node.get_primitive<uint8_t>(off);
|
||||
if (val)
|
||||
{
|
||||
ImGui::TextUnformatted("true");
|
||||
} else
|
||||
{
|
||||
ImGui::TextUnformatted("false");
|
||||
}
|
||||
break;
|
||||
}
|
||||
// TODO
|
||||
case f128:
|
||||
case i128:
|
||||
case u128:
|
||||
{
|
||||
const auto &data = node.vec_data();
|
||||
const auto lo = node.get_primitive<uint64_t>(off);
|
||||
const auto hi = node.get_primitive<uint64_t>(off + 8);
|
||||
ImGui::Text("%16lX-%16lX", hi, lo);
|
||||
break;
|
||||
}
|
||||
case f32:
|
||||
{
|
||||
ImGui::Text("%f", node.get_primitive<float>(off));
|
||||
break;
|
||||
}
|
||||
case f64:
|
||||
{
|
||||
ImGui::Text("%f", node.get_primitive<double>(off));
|
||||
break;
|
||||
}
|
||||
case ptr:
|
||||
{
|
||||
// TODO: ptr size
|
||||
ImGui::Text("%lX", node.get_primitive<uint64_t>(off));
|
||||
break;
|
||||
}
|
||||
case _enum:
|
||||
{
|
||||
// TODO: robustness
|
||||
uint64_t val;
|
||||
const auto byte_size = frontend.target->types[type_id.idx].byte_size;
|
||||
if (byte_size == 8)
|
||||
{
|
||||
val = node.get_primitive<uint64_t>(off);
|
||||
} else if (byte_size == 4)
|
||||
{
|
||||
val = node.get_primitive<uint32_t>(off);
|
||||
} else if (byte_size == 2)
|
||||
{
|
||||
val = node.get_primitive<uint16_t>(off);
|
||||
} else if (byte_size == 1)
|
||||
{
|
||||
val = node.get_primitive<uint8_t>(off);
|
||||
} else
|
||||
{
|
||||
assert(0);
|
||||
val = 0;
|
||||
}
|
||||
const auto &members = frontend.target->types[type_id.idx].member_vec();
|
||||
auto printed = false;
|
||||
for (const auto &member : members)
|
||||
{
|
||||
if (val == member.enum_val)
|
||||
{
|
||||
ImGui::Text("%s", member.name.c_str());
|
||||
printed = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!printed)
|
||||
{
|
||||
ImGui::Text("<invalid: %lu>", val);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Window::handle_source_updated(Target &target, size_t id)
|
||||
{
|
||||
switch (this->type)
|
||||
|
||||
Reference in New Issue
Block a user