Skip to content

Commit 8b5f32e

Browse files
authored
Add --dump-info command line argument (#307)
* Add --dump-info command line argument to obtain information about choicepoints and primitives * clang-format + vector include * Fix missing vector include * [[maybe_unused]] * Add functional and string includes * Make find_choice_points (and others) a util function instead of a Module member * All primitives that return something now result in a choice point
1 parent b050c10 commit 8b5f32e

File tree

3 files changed

+100
-0
lines changed

3 files changed

+100
-0
lines changed
Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
#pragma once
2+
#include <functional>
3+
#include <vector>
4+
5+
#include "../../src/WARDuino.h"
6+
7+
inline std::vector<uint8_t *> find_prim_calls(
8+
const Module *m, const std::function<bool(Block *)> &cond,
9+
const bool after = false) {
10+
std::vector<uint8_t *> call_sites;
11+
for (size_t i = m->import_count; i < m->function_count; i++) {
12+
Block *func = &m->functions[i];
13+
uint8_t *pc = func->start_ptr;
14+
while (pc < func->end_ptr) {
15+
uint8_t opcode = *pc;
16+
uint8_t *instruction_start_pc = pc;
17+
if (opcode == 0x10) { // TODO: Support other call instructions
18+
pc++;
19+
uint32_t fidx = read_LEB_32(&pc);
20+
if (fidx < m->import_count) {
21+
const char *module_name = m->functions[fidx].import_module;
22+
if (!strcmp(module_name, "env") &&
23+
cond(&m->functions[fidx])) {
24+
if (!after) {
25+
call_sites.push_back(instruction_start_pc);
26+
} else {
27+
// NOTE: Only works because this is a primitive
28+
// call, if it was a regular call the vm would jump
29+
// into a function and not just to the instruction
30+
// after the call instruction.
31+
call_sites.push_back(pc);
32+
}
33+
}
34+
}
35+
continue;
36+
}
37+
skip_immediates(&pc);
38+
}
39+
}
40+
return call_sites;
41+
}
42+
43+
inline std::vector<uint8_t *> find_choice_points(const Module *m,
44+
const bool after = false) {
45+
return find_prim_calls(
46+
m, [](const Block *prim) { return prim->type->result_count > 0; },
47+
after);
48+
}
49+
50+
inline std::vector<uint8_t *> find_pc_before_primitive_calls(const Module *m) {
51+
return find_prim_calls(
52+
m, []([[maybe_unused]] const Block *prim) { return true; });
53+
}
54+
55+
inline std::vector<uint8_t *> find_pc_after_primitive_calls(const Module *m) {
56+
return find_prim_calls(
57+
m, []([[maybe_unused]] const Block *prim) { return true; }, true);
58+
}

platforms/CLI-Emulator/main.cpp

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,11 +8,14 @@
88
#include <cstdio>
99
#include <cstdlib>
1010
#include <cstring>
11+
#include <iostream>
1112
#include <stdexcept>
1213
#include <thread>
1314

1415
#include "../../src/Debug/debugger.h"
1516
#include "../../src/Utils/macros.h"
17+
#include "../../src/Utils/util.h"
18+
#include "binary-info.h"
1619
#include "warduino/config.h"
1720

1821
// Constants
@@ -267,6 +270,7 @@ int main(int argc, const char *argv[]) {
267270
const char *proxy = nullptr;
268271
const char *baudrate = nullptr;
269272
const char *mode = "interpreter";
273+
bool dump_info = false;
270274

271275
const char *fname = nullptr;
272276
std::vector<StackValue> arguments = std::vector<StackValue>();
@@ -337,6 +341,8 @@ int main(int argc, const char *argv[]) {
337341
arguments.push_back(
338342
parseParameter(number, function.type->params[i]));
339343
}
344+
} else if (!strcmp("--dump-info", arg)) {
345+
dump_info = true;
340346
}
341347
}
342348

@@ -352,6 +358,40 @@ int main(int argc, const char *argv[]) {
352358
}
353359

354360
if (m) {
361+
if (dump_info) {
362+
auto choicepoints = std::vector<uint32_t>();
363+
for (uint8_t *choice_point : find_choice_points(m)) {
364+
choicepoints.push_back(toVirtualAddress(choice_point, m));
365+
}
366+
auto after_choicepoints = std::vector<uint32_t>();
367+
for (uint8_t *choice_point : find_choice_points(m, true)) {
368+
after_choicepoints.push_back(toVirtualAddress(choice_point, m));
369+
}
370+
auto primitive_calls = std::vector<uint32_t>();
371+
for (uint8_t *call_site : find_pc_before_primitive_calls(m)) {
372+
primitive_calls.push_back(toVirtualAddress(call_site, m));
373+
}
374+
auto after_primitive_calls = std::vector<uint32_t>();
375+
for (uint8_t *call_site : find_pc_after_primitive_calls(m)) {
376+
after_primitive_calls.push_back(toVirtualAddress(call_site, m));
377+
}
378+
nlohmann::json json;
379+
json["choicepoints"] = choicepoints;
380+
json["after_choicepoints"] = after_choicepoints;
381+
json["primitive_calls"] = primitive_calls;
382+
json["after_primitive_calls"] = after_primitive_calls;
383+
384+
std::vector<std::string> fidx_mapping = std::vector<std::string>();
385+
for (uint32_t fidx = 0; fidx < m->import_count; fidx++) {
386+
fidx_mapping.emplace_back(m->functions[fidx].import_field);
387+
}
388+
json["primitive_fidx_mapping"] = fidx_mapping;
389+
390+
std::cout << json << std::endl;
391+
wac->unload_module(m);
392+
exit(0);
393+
}
394+
355395
if (strcmp(mode, "proxy") == 0) {
356396
// Run in proxy mode
357397
wac->debugger->proxify();

src/WARDuino.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,8 @@
6161

6262
extern char exception[512];
6363

64+
void skip_immediates(uint8_t **pos);
65+
6466
typedef bool (*Primitive)(Module *);
6567

6668
struct IOStateElement {

0 commit comments

Comments
 (0)