ptr WIP
This commit is contained in:
@@ -2146,6 +2146,100 @@ std::optional<std::pair<uint16_t, size_t>>
|
|||||||
return std::make_pair(cache_idx, node.id);
|
return std::make_pair(cache_idx, node.id);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
case read_cstr:
|
||||||
|
{
|
||||||
|
using namespace lldb;
|
||||||
|
uint16_t cache_idx = 0;
|
||||||
|
if (auto found_idx = find_node_for_src_id(node.id); found_idx)
|
||||||
|
{
|
||||||
|
cache_idx = *found_idx;
|
||||||
|
} else
|
||||||
|
{
|
||||||
|
cache_idx = get_free_res_slot();
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t addr_id = std::get<data::source::ReadAsCStr>(node.data).src_id;
|
||||||
|
uint16_t addr_idx = *find_node_for_src_id(addr_id);
|
||||||
|
if (!_data_res[addr_idx] || !_data_res[addr_idx]->node.success)
|
||||||
|
{
|
||||||
|
return check_single_res_changed(data::result::Node{
|
||||||
|
.idx = cache_idx,
|
||||||
|
.type_id = data::type_info::TypeID::none(),
|
||||||
|
.success = false,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
if (_data_res[addr_idx]->node.type_id.type != data::type_info::Type::ptr)
|
||||||
|
{
|
||||||
|
return check_single_res_changed(data::result::Node{
|
||||||
|
.idx = cache_idx,
|
||||||
|
.type_id = data::type_info::TypeID::none(),
|
||||||
|
.success = false,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
auto addr = std::get<uint64_t>(_data_res[addr_idx]->node.data);
|
||||||
|
std::vector<uint8_t> buf{};
|
||||||
|
|
||||||
|
char tmp_buf[256];
|
||||||
|
auto success = true;
|
||||||
|
while (true)
|
||||||
|
{
|
||||||
|
auto lldb_addr = _target.ResolveLoadAddress(addr);
|
||||||
|
auto err = SBError{};
|
||||||
|
err.Clear();
|
||||||
|
auto bytes_read =
|
||||||
|
_target.ReadMemory(lldb_addr, tmp_buf, sizeof(tmp_buf), err);
|
||||||
|
if (bytes_read == 0)
|
||||||
|
{
|
||||||
|
success = false;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto null_pos = std::find(tmp_buf, tmp_buf + bytes_read, '\0');
|
||||||
|
if (null_pos != tmp_buf + bytes_read)
|
||||||
|
{
|
||||||
|
size_t len = null_pos - tmp_buf;
|
||||||
|
auto old_size = buf.size();
|
||||||
|
buf.resize(old_size + len + 1);
|
||||||
|
std::copy(tmp_buf, null_pos + 1, buf.data() + old_size);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (bytes_read != sizeof(tmp_buf))
|
||||||
|
{
|
||||||
|
if (err.Fail())
|
||||||
|
{
|
||||||
|
printf("ReadAsCStr failed: %s\n", err.GetCString());
|
||||||
|
success = false;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
auto old_size = buf.size();
|
||||||
|
buf.resize(old_size + bytes_read);
|
||||||
|
std::copy(tmp_buf, tmp_buf + bytes_read, buf.data() + old_size);
|
||||||
|
|
||||||
|
addr += bytes_read;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!success)
|
||||||
|
{
|
||||||
|
return check_single_res_changed(data::result::Node{
|
||||||
|
.idx = cache_idx,
|
||||||
|
.type_id = data::type_info::TypeID::none(),
|
||||||
|
.success = false,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO: embed the array size into the TypeID and then make this
|
||||||
|
// an i8 array type?
|
||||||
|
return check_single_res_changed(
|
||||||
|
data::result::Node{.idx = cache_idx,
|
||||||
|
.type_id = data::type_info::TypeID::custom(),
|
||||||
|
.success = true,
|
||||||
|
.data = std::move(buf)});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
printf("Unhandled data type\n");
|
printf("Unhandled data type\n");
|
||||||
@@ -3045,7 +3139,7 @@ dbgui::data::result::NodeIdx LLDBBackend::build_nodes_for_var_uncached(
|
|||||||
// TODO: always get child info for first level
|
// TODO: always get child info for first level
|
||||||
// TODO: depending on what is previewed?
|
// TODO: depending on what is previewed?
|
||||||
|
|
||||||
res_node.success = true;
|
res_node.success = err.Success();
|
||||||
to_send.push_back(res_node);
|
to_send.push_back(res_node);
|
||||||
_data_res[res_idx] =
|
_data_res[res_idx] =
|
||||||
CachedDataRes{.node = std::move(res_node),
|
CachedDataRes{.node = std::move(res_node),
|
||||||
@@ -3132,7 +3226,7 @@ void LLDBBackend::build_nodes_for_var_cached(
|
|||||||
// TODO: always get child info for first level
|
// TODO: always get child info for first level
|
||||||
// TODO: depending on what is previewed?
|
// TODO: depending on what is previewed?
|
||||||
|
|
||||||
res_node.success = true;
|
res_node.success = err.Success();
|
||||||
if (!_data_res[cache_idx]->node.success
|
if (!_data_res[cache_idx]->node.success
|
||||||
|| _data_res[cache_idx]->node.data != res_node.data)
|
|| _data_res[cache_idx]->node.data != res_node.data)
|
||||||
{
|
{
|
||||||
|
|||||||
15
src/data.h
15
src/data.h
@@ -321,7 +321,8 @@ namespace dbgui::data
|
|||||||
uint16_t idx;
|
uint16_t idx;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct Variable {
|
struct Variable
|
||||||
|
{
|
||||||
std::string expr_path;
|
std::string expr_path;
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -343,6 +344,14 @@ namespace dbgui::data
|
|||||||
size_t src_id;
|
size_t src_id;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// need this as length is unbounded
|
||||||
|
// note: does not support wchar strings right now
|
||||||
|
struct ReadAsCStr
|
||||||
|
{
|
||||||
|
// node that provides the address to read at
|
||||||
|
size_t src_id;
|
||||||
|
};
|
||||||
|
|
||||||
struct Node
|
struct Node
|
||||||
{
|
{
|
||||||
enum class Type : uint8_t
|
enum class Type : uint8_t
|
||||||
@@ -351,12 +360,14 @@ namespace dbgui::data
|
|||||||
disassemble,
|
disassemble,
|
||||||
line_entry,
|
line_entry,
|
||||||
locals,
|
locals,
|
||||||
|
read_cstr,
|
||||||
};
|
};
|
||||||
|
|
||||||
size_t id;
|
size_t id;
|
||||||
Type type;
|
Type type;
|
||||||
// when adding something here, remember to update LLDBBackend::add_data_node
|
// when adding something here, remember to update LLDBBackend::add_data_node
|
||||||
std::variant<std::monostate, Source, Disassemble, LineEntry> data;
|
std::variant<std::monostate, Source, Disassemble, LineEntry, ReadAsCStr>
|
||||||
|
data;
|
||||||
};
|
};
|
||||||
} // namespace source
|
} // namespace source
|
||||||
|
|
||||||
|
|||||||
@@ -62,6 +62,14 @@ void Frontend::run_frame()
|
|||||||
|
|
||||||
if (ImGui::Begin("Test", nullptr, win_flags))
|
if (ImGui::Begin("Test", nullptr, win_flags))
|
||||||
{
|
{
|
||||||
|
if (this->target)
|
||||||
|
{
|
||||||
|
for (auto &entry : this->target->expr_cache)
|
||||||
|
{
|
||||||
|
entry.used_this_frame = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// TODO: if we just do SetNextWindowDockID in each of the windows
|
// TODO: if we just do SetNextWindowDockID in each of the windows
|
||||||
// this seems to crash once the first window is docked to it?
|
// this seems to crash once the first window is docked to it?
|
||||||
// so some id change is necessary
|
// so some id change is necessary
|
||||||
@@ -85,6 +93,22 @@ void Frontend::run_frame()
|
|||||||
}
|
}
|
||||||
//this->dock_id = ImGui::GetWindowDockID();
|
//this->dock_id = ImGui::GetWindowDockID();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (this->target)
|
||||||
|
{
|
||||||
|
for (size_t i = 0; i < this->target->expr_cache.size();)
|
||||||
|
{
|
||||||
|
auto &entry = this->target->expr_cache[i];
|
||||||
|
if (!entry.used_this_frame)
|
||||||
|
{
|
||||||
|
this->target->backend->remove_data_node(entry.id);
|
||||||
|
this->target->expr_cache.erase(this->target->expr_cache.begin() + i);
|
||||||
|
} else
|
||||||
|
{
|
||||||
|
++i;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
ImGui::End();
|
ImGui::End();
|
||||||
|
|
||||||
|
|||||||
@@ -78,6 +78,13 @@ namespace dbgui::frontend
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct ExprCacheEntry
|
||||||
|
{
|
||||||
|
std::string expr_path;
|
||||||
|
size_t id;
|
||||||
|
bool used_this_frame = false;
|
||||||
|
};
|
||||||
|
|
||||||
Target(std::string filename);
|
Target(std::string filename);
|
||||||
|
|
||||||
std::optional<uint16_t> data_idx_for_src_id(size_t id)
|
std::optional<uint16_t> data_idx_for_src_id(size_t id)
|
||||||
@@ -108,6 +115,29 @@ namespace dbgui::frontend
|
|||||||
return &*data_res_nodes[*idx];
|
return &*data_res_nodes[*idx];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
size_t find_or_create_expr_path(std::string &&path)
|
||||||
|
{
|
||||||
|
for (auto &entry : expr_cache)
|
||||||
|
{
|
||||||
|
if (entry.expr_path == path)
|
||||||
|
{
|
||||||
|
entry.used_this_frame = true;
|
||||||
|
return entry.id;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
using namespace data::source;
|
||||||
|
auto id = this->id++;
|
||||||
|
this->backend->add_data_node(
|
||||||
|
Node{.id = id,
|
||||||
|
.type = Node::Type::source,
|
||||||
|
.data = Source{.type = Source::Type::variable,
|
||||||
|
.data = Source::Variable{.expr_path = path}}});
|
||||||
|
expr_cache.push_back(ExprCacheEntry{
|
||||||
|
.expr_path = std::move(path), .id = id, .used_this_frame = true});
|
||||||
|
return id;
|
||||||
|
}
|
||||||
|
|
||||||
TargetState state = TargetState::stopped;
|
TargetState state = TargetState::stopped;
|
||||||
std::string filename;
|
std::string filename;
|
||||||
uint64_t id;
|
uint64_t id;
|
||||||
@@ -124,6 +154,7 @@ namespace dbgui::frontend
|
|||||||
std::vector<std::pair<size_t, uint16_t>> src_id_to_data_idx;
|
std::vector<std::pair<size_t, uint16_t>> src_id_to_data_idx;
|
||||||
std::vector<std::optional<data::result::Node>> data_res_nodes;
|
std::vector<std::optional<data::result::Node>> data_res_nodes;
|
||||||
std::vector<data::type_info::TypeInfo> types;
|
std::vector<data::type_info::TypeInfo> types;
|
||||||
|
std::vector<ExprCacheEntry> expr_cache;
|
||||||
|
|
||||||
std::shared_ptr<backend::Backend> backend = nullptr;
|
std::shared_ptr<backend::Backend> backend = nullptr;
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -1014,6 +1014,8 @@ bool WatchWindow::draw(Frontend &frontend)
|
|||||||
first = false;
|
first = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
auto expr_path_vec = std::vector<ExprPathPart>{};
|
||||||
|
|
||||||
// ImGuiTableFlags_SizingFixedFit
|
// ImGuiTableFlags_SizingFixedFit
|
||||||
if (ImGui::BeginTable("##Variables", 2,
|
if (ImGui::BeginTable("##Variables", 2,
|
||||||
ImGuiTableFlags_RowBg | ImGuiTableFlags_Resizable))
|
ImGuiTableFlags_RowBg | ImGuiTableFlags_Resizable))
|
||||||
@@ -1053,9 +1055,10 @@ bool WatchWindow::draw(Frontend &frontend)
|
|||||||
reinterpret_cast<const char *>(locals_data.data() + cur_off + 2),
|
reinterpret_cast<const char *>(locals_data.data() + cur_off + 2),
|
||||||
str_len};
|
str_len};
|
||||||
auto node_idx = local_node.children[cur_idx];
|
auto node_idx = local_node.children[cur_idx];
|
||||||
|
expr_path_vec.clear();
|
||||||
this->draw_value(frontend,
|
this->draw_value(frontend,
|
||||||
frontend.target->data_res_nodes[node_idx]->type_id,
|
frontend.target->data_res_nodes[node_idx]->type_id,
|
||||||
name, node_idx, 0);
|
name, node_idx, 0, expr_path_vec);
|
||||||
|
|
||||||
cur_idx += 1;
|
cur_idx += 1;
|
||||||
cur_off += 2 + str_len;
|
cur_off += 2 + str_len;
|
||||||
@@ -1078,8 +1081,9 @@ bool WatchWindow::draw(Frontend &frontend)
|
|||||||
no_success = false;
|
no_success = false;
|
||||||
const auto &child_node =
|
const auto &child_node =
|
||||||
*frontend.target->data_res_nodes[node.children[0]];
|
*frontend.target->data_res_nodes[node.children[0]];
|
||||||
|
expr_path_vec.clear();
|
||||||
this->draw_value(frontend, child_node.type_id, &extra_slots[i],
|
this->draw_value(frontend, child_node.type_id, &extra_slots[i],
|
||||||
node.children[0], 0);
|
node.children[0], 0, expr_path_vec);
|
||||||
|
|
||||||
if (extra_slots[i].bak == "")
|
if (extra_slots[i].bak == "")
|
||||||
{
|
{
|
||||||
@@ -1192,7 +1196,8 @@ bool WatchWindow::draw(Frontend &frontend)
|
|||||||
void WatchWindow::draw_value(Frontend &frontend,
|
void WatchWindow::draw_value(Frontend &frontend,
|
||||||
data::type_info::TypeID type_id,
|
data::type_info::TypeID type_id,
|
||||||
std::variant<std::string_view, ExtraSlot *> name,
|
std::variant<std::string_view, ExtraSlot *> name,
|
||||||
data::result::NodeIdx node_idx, size_t off)
|
data::result::NodeIdx node_idx, size_t off,
|
||||||
|
std::vector<ExprPathPart> &expr_path)
|
||||||
{
|
{
|
||||||
ImGui::TableNextRow();
|
ImGui::TableNextRow();
|
||||||
ImGui::TableSetColumnIndex(0);
|
ImGui::TableSetColumnIndex(0);
|
||||||
@@ -1367,8 +1372,12 @@ void WatchWindow::draw_value(Frontend &frontend,
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
expr_path.push_back(ExprPathPart{
|
||||||
|
.ident = std::string_view{name_begin, name_end - name_begin},
|
||||||
|
.deref = false});
|
||||||
this->draw_value(frontend, member.type_id, member.name, node_idx,
|
this->draw_value(frontend, member.type_id, member.name, node_idx,
|
||||||
off + member.offset);
|
off + member.offset, expr_path);
|
||||||
|
expr_path.pop_back();
|
||||||
}
|
}
|
||||||
} else
|
} else
|
||||||
{
|
{
|
||||||
@@ -1379,15 +1388,21 @@ void WatchWindow::draw_value(Frontend &frontend,
|
|||||||
size_t el_count =
|
size_t el_count =
|
||||||
frontend.target->types[type_id.idx].byte_size / member_size;
|
frontend.target->types[type_id.idx].byte_size / member_size;
|
||||||
|
|
||||||
|
expr_path.push_back(ExprPathPart{
|
||||||
|
.ident = std::string_view{name_begin, name_end - name_begin},
|
||||||
|
.array = true});
|
||||||
|
|
||||||
char buf[32];
|
char buf[32];
|
||||||
size_t member_off = 0;
|
size_t member_off = 0;
|
||||||
for (size_t i = 0; i < el_count; ++i)
|
for (size_t i = 0; i < el_count; ++i)
|
||||||
{
|
{
|
||||||
std::snprintf(buf, sizeof(buf), "[%lu]", i);
|
std::snprintf(buf, sizeof(buf), "[%lu]", i);
|
||||||
this->draw_value(frontend, member_ty_id, buf, node_idx,
|
this->draw_value(frontend, member_ty_id, buf, node_idx,
|
||||||
off + member_off);
|
off + member_off, expr_path);
|
||||||
member_off += member_size;
|
member_off += member_size;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
expr_path.pop_back();
|
||||||
}
|
}
|
||||||
|
|
||||||
ImGui::TreePop();
|
ImGui::TreePop();
|
||||||
@@ -1435,17 +1450,22 @@ void WatchWindow::draw_value(Frontend &frontend,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
auto tree_open = false;
|
||||||
if (!is_editing)
|
if (!is_editing)
|
||||||
{
|
{
|
||||||
char tree_id_buf[128];
|
char tree_id_buf[128];
|
||||||
std::snprintf(tree_id_buf, sizeof(tree_id_buf), "%u#off%lu", node_idx,
|
std::snprintf(tree_id_buf, sizeof(tree_id_buf), "%u#off%lu", node_idx,
|
||||||
off);
|
off);
|
||||||
|
ImGuiTreeNodeFlags flags = ImGuiTreeNodeFlags_SpanFullWidth;
|
||||||
|
if (type_id.type != Type::ptr)
|
||||||
|
{
|
||||||
|
flags |= ImGuiTreeNodeFlags_Leaf | ImGuiTreeNodeFlags_NoTreePushOnOpen;
|
||||||
|
}
|
||||||
|
|
||||||
// TODO: better id
|
// TODO: better id
|
||||||
ImGui::TreeNodeEx(
|
tree_open =
|
||||||
tree_id_buf,
|
ImGui::TreeNodeEx(tree_id_buf, flags, "%.*s",
|
||||||
ImGuiTreeNodeFlags_SpanFullWidth | ImGuiTreeNodeFlags_Leaf
|
static_cast<int>(name_end - name_begin), name_begin);
|
||||||
| ImGuiTreeNodeFlags_NoTreePushOnOpen,
|
|
||||||
"%.*s", static_cast<int>(name_end - name_begin), name_begin);
|
|
||||||
//ImGui::TextUnformatted(name_begin, name_end);
|
//ImGui::TextUnformatted(name_begin, name_end);
|
||||||
if (name.index() == 1
|
if (name.index() == 1
|
||||||
&& ImGui::IsMouseDoubleClicked(ImGuiMouseButton_Left)
|
&& ImGui::IsMouseDoubleClicked(ImGuiMouseButton_Left)
|
||||||
@@ -1518,6 +1538,43 @@ void WatchWindow::draw_value(Frontend &frontend,
|
|||||||
{
|
{
|
||||||
// TODO: ptr size
|
// TODO: ptr size
|
||||||
ImGui::Text("%lX", node.get_primitive<uint64_t>(off));
|
ImGui::Text("%lX", node.get_primitive<uint64_t>(off));
|
||||||
|
if (tree_open)
|
||||||
|
{
|
||||||
|
// TODO: make this func be able to not print the "outer" line
|
||||||
|
// and just accept a bool to only draw the containing value
|
||||||
|
std::string path{"*"};
|
||||||
|
// why cant i just path name_begin, name_end to string_view? :[
|
||||||
|
construct_expr_path(
|
||||||
|
path, expr_path,
|
||||||
|
std::string_view{name_begin,
|
||||||
|
static_cast<size_t>(name_end - name_begin)});
|
||||||
|
|
||||||
|
auto src_id =
|
||||||
|
frontend.target->find_or_create_expr_path(std::move(path));
|
||||||
|
auto res_idx = frontend.target->data_idx_for_src_id(src_id);
|
||||||
|
if (res_idx)
|
||||||
|
{
|
||||||
|
const auto &node = *frontend.target->data_res_nodes[*res_idx];
|
||||||
|
if (node.success && node.children.size() == 1)
|
||||||
|
{
|
||||||
|
auto data_idx = node.children[0];
|
||||||
|
const auto &data_node =
|
||||||
|
*frontend.target->data_res_nodes[data_idx];
|
||||||
|
expr_path.push_back(ExprPathPart{
|
||||||
|
.ident = std::string_view{name_begin, static_cast<size_t>(
|
||||||
|
name_end - name_begin)},
|
||||||
|
.deref = true});
|
||||||
|
|
||||||
|
this->draw_value(frontend, data_node.type_id,
|
||||||
|
std::string_view{"<pointee>"}, data_idx, 0,
|
||||||
|
expr_path);
|
||||||
|
|
||||||
|
expr_path.pop_back();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ImGui::TreePop();
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case _enum:
|
case _enum:
|
||||||
@@ -1563,6 +1620,30 @@ void WatchWindow::draw_value(Frontend &frontend,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void WatchWindow::construct_expr_path(std::string &out,
|
||||||
|
const std::vector<ExprPathPart> &path,
|
||||||
|
std::string_view tail)
|
||||||
|
{
|
||||||
|
for (const auto &entry : path)
|
||||||
|
{
|
||||||
|
// FIXME: BIGGEST HACK in cinema history
|
||||||
|
if (entry.ident == "<pointee>")
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
out += entry.ident;
|
||||||
|
if (entry.deref)
|
||||||
|
{
|
||||||
|
out += "->";
|
||||||
|
} else if (!entry.array)
|
||||||
|
{
|
||||||
|
out += '.';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
out += tail;
|
||||||
|
}
|
||||||
|
|
||||||
void Window::handle_source_updated(Target &target, size_t id)
|
void Window::handle_source_updated(Target &target, size_t id)
|
||||||
{
|
{
|
||||||
switch (this->type)
|
switch (this->type)
|
||||||
|
|||||||
@@ -135,11 +135,23 @@ namespace dbgui::frontend
|
|||||||
bool edit_was_started = false;
|
bool edit_was_started = false;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// TODO: cache the expr_path by node_idx + off or smth?
|
||||||
|
struct ExprPathPart
|
||||||
|
{
|
||||||
|
std::string_view ident;
|
||||||
|
bool deref = false;
|
||||||
|
bool array = false;
|
||||||
|
};
|
||||||
|
|
||||||
bool draw(Frontend &);
|
bool draw(Frontend &);
|
||||||
void draw_value(Frontend &, data::type_info::TypeID,
|
void draw_value(Frontend &, data::type_info::TypeID,
|
||||||
std::variant<std::string_view, ExtraSlot *> name,
|
std::variant<std::string_view, ExtraSlot *> name,
|
||||||
data::result::NodeIdx node_idx, size_t off);
|
data::result::NodeIdx node_idx, size_t off,
|
||||||
|
std::vector<ExprPathPart> &expr_path);
|
||||||
// void handle_source_updated(Target& target, size_t id);
|
// void handle_source_updated(Target& target, size_t id);
|
||||||
|
void construct_expr_path(std::string &out,
|
||||||
|
const std::vector<ExprPathPart> &,
|
||||||
|
std::string_view tail);
|
||||||
|
|
||||||
std::string id;
|
std::string id;
|
||||||
bool open;
|
bool open;
|
||||||
|
|||||||
@@ -16,6 +16,7 @@ namespace test {
|
|||||||
uint32_t test_bits : 20;
|
uint32_t test_bits : 20;
|
||||||
uint32_t test_bits2: 12;
|
uint32_t test_bits2: 12;
|
||||||
MyEnum enum_val;
|
MyEnum enum_val;
|
||||||
|
std::string* ptr = nullptr;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -26,7 +27,7 @@ void helper_fn() {
|
|||||||
unsigned int y = 30;
|
unsigned int y = 30;
|
||||||
sleep(tmp.data);
|
sleep(tmp.data);
|
||||||
{
|
{
|
||||||
test::MyType tmp = test::MyType{2};
|
test::MyType tmp = test::MyType{.data = 2, .ptr = &test};
|
||||||
sleep(tmp.data);
|
sleep(tmp.data);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,3 +3,4 @@
|
|||||||
- memory + cpu statistics like VS
|
- memory + cpu statistics like VS
|
||||||
- visualization for branches (draw arror if branch is taken (or in both cases?))
|
- visualization for branches (draw arror if branch is taken (or in both cases?))
|
||||||
- allow (partial) path override for symbol source paths
|
- allow (partial) path override for symbol source paths
|
||||||
|
- check if classes with base classes work
|
||||||
|
|||||||
Reference in New Issue
Block a user