@@ -25,6 +25,9 @@ Debugger::Debugger(Channel *duplex) {
2525 this ->checkpointInterval = 10 ;
2626 this ->instructions_executed = 0 ;
2727 this ->fidx_called = {};
28+ this ->min_return_values = 0 ;
29+ this ->checkpoint_state = nullptr ;
30+ this ->checkpoint_state_size = 0 ;
2831 this ->remaining_instructions = -1 ;
2932}
3033
@@ -965,11 +968,33 @@ void Debugger::inspect(Module *m, const uint16_t sizeStateArray,
965968}
966969
967970void Debugger::setSnapshotPolicy (Module *m, uint8_t *interruptData) {
968- snapshotPolicy = SnapshotPolicy{*interruptData};
971+ uint8_t **data_ptr = &interruptData;
972+ if (*interruptData <= 2 ) {
973+ snapshotPolicy = SnapshotPolicy{*interruptData};
974+ min_return_values = 0 ;
975+ if (checkpoint_state) {
976+ free (checkpoint_state);
977+ }
978+ checkpoint_state = nullptr ;
979+ checkpoint_state_size = 0 ;
980+ } else {
981+ snapshotPolicy = SnapshotPolicy::checkpointing;
982+ *data_ptr += 1 ;
983+ min_return_values = read_LEB_32 (data_ptr);
984+ if (checkpoint_state) {
985+ free (checkpoint_state);
986+ }
987+ checkpoint_state_size = read_LEB_32 (data_ptr);
988+ checkpoint_state = new uint8_t [checkpoint_state_size];
989+ for (uint32_t i = 0 ; i < checkpoint_state_size; i++) {
990+ checkpoint_state[i] = **data_ptr;
991+ *data_ptr += 1 ;
992+ }
993+ }
969994
970995 // Make a checkpoint when you first enable checkpointing
971996 if (snapshotPolicy == SnapshotPolicy::checkpointing) {
972- uint8_t *ptr = interruptData + 1 ;
997+ uint8_t *ptr = *data_ptr + 1 ;
973998 checkpointInterval = read_B32 (&ptr);
974999 checkpoint (m, true );
9751000 }
@@ -1016,11 +1041,24 @@ void Debugger::handleSnapshotPolicy(Module *m) {
10161041 }
10171042}
10181043
1019- void Debugger::checkpoint (Module *m, bool force) {
1044+ void Debugger::checkpoint (Module *m, const bool force) {
10201045 if (instructions_executed == 0 && !force) {
10211046 return ;
10221047 }
10231048
1049+ if (min_return_values != 0 ) {
1050+ if (!fidx_called) {
1051+ // Tracing mode is on, but no primitive was called.
1052+ return ;
1053+ }
1054+
1055+ const Type *type = m->functions [*fidx_called].type ;
1056+ if (type->result_count < min_return_values) {
1057+ // Primitive was called but did not have the required return values.
1058+ return ;
1059+ }
1060+ }
1061+
10241062 this ->channel ->write (R"( CHECKPOINT {"instructions_executed": %d, )" ,
10251063 instructions_executed);
10261064 if (fidx_called) {
@@ -1032,9 +1070,23 @@ void Debugger::checkpoint(Module *m, bool force) {
10321070 comma = true ;
10331071 }
10341072 this ->channel ->write (" ], " );
1073+
1074+ // Return values:
1075+ this ->channel ->write (R"( "returns": [)" );
1076+ comma = false ;
1077+ for (uint32_t i = 0 ; i < func_block.type ->result_count ; i++) {
1078+ channel->write (" %s%d" , comma ? " , " : " " ,
1079+ m->stack [m->sp - i].value .uint32 );
1080+ comma = true ;
1081+ }
1082+ this ->channel ->write (" ], " );
1083+ }
1084+ this ->channel ->write (R"( "snapshot": )" );
1085+ if (!checkpoint_state) {
1086+ snapshot (m);
1087+ } else {
1088+ inspect (m, checkpoint_state_size, checkpoint_state);
10351089 }
1036- this ->channel ->write (R"( "snapshot": )" , instructions_executed);
1037- snapshot (m);
10381090 this ->channel ->write (" }\n " );
10391091 instructions_executed = 0 ;
10401092}
0 commit comments