primitive locals

This commit is contained in:
T0b1
2023-06-17 01:12:11 +02:00
parent 9ab08de243
commit 679e38e711
13 changed files with 1778 additions and 78 deletions

View File

@@ -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)