33
44#include " concrete_rt.hpp"
55#include " controls.hpp"
6+ #include " utils.hpp"
67#include < cassert>
78#include < cstddef>
89#include < cstdio>
@@ -71,6 +72,8 @@ struct SymVal {
7172 SymVal gt (const SymVal &other) const ;
7273 SymVal geq (const SymVal &other) const ;
7374 SymVal negate () const ;
75+
76+ bool is_concrete () const ;
7477};
7578
7679static SymVal make_symbolic (int index) {
@@ -145,6 +148,10 @@ inline SymVal SymVal::makeSymbolic() const {
145148 }
146149}
147150
151+ inline bool SymVal::is_concrete () const {
152+ return dynamic_cast <SymConcrete *>(symptr.get ()) != nullptr ;
153+ }
154+
148155class Snapshot_t ;
149156
150157class SymStack_t {
@@ -186,6 +193,8 @@ class SymStack_t {
186193
187194 size_t size () const { return stack.size (); }
188195
196+ SymVal operator [](size_t index) const { return stack[index]; }
197+
189198private:
190199 std::vector<SymVal> stack;
191200};
@@ -222,9 +231,17 @@ class SymFrames_t {
222231
223232 void reuse (Snapshot_t snapshot);
224233
234+ size_t size () const { return stack.size (); }
235+
236+ SymVal operator [](size_t index) const { return stack[index]; }
237+
238+ private:
225239 std::vector<SymVal> stack;
226240};
227241
242+ struct NodeBox ;
243+ struct SymEnv_t ;
244+
228245// A snapshot of the symbolic state and execution context (control)
229246class Snapshot_t {
230247public:
@@ -233,6 +250,8 @@ class Snapshot_t {
233250 SymStack_t get_stack () const { return stack; }
234251 SymFrames_t get_frames () const { return frames; }
235252
253+ std::monostate resume_execution (SymEnv_t &sym_env, NodeBox *node) const ;
254+
236255private:
237256 SymStack_t stack;
238257 SymFrames_t frames;
@@ -391,6 +410,7 @@ struct UnExploredNode : Node {
391410struct SnapshotNode : Node {
392411 SnapshotNode (Snapshot_t snapshot) : snapshot(snapshot) {}
393412 std::string to_string () override { return " SnapshotNode" ; }
413+ const Snapshot_t &get_snapshot () const { return snapshot; }
394414
395415protected:
396416 void generate_dot (std::ostream &os, int parent_dot_id,
@@ -479,6 +499,7 @@ inline std::monostate NodeBox::fillSnapshotNode(Snapshot_t snapshot) {
479499}
480500
481501inline std::monostate NodeBox::fillFinishedNode () {
502+ GENSYM_DBG (" Filling with a Finished Node" );
482503 if (this ->isUnexplored ()) {
483504 node = std::make_unique<Finished>();
484505 } else {
@@ -491,6 +512,11 @@ inline std::monostate NodeBox::fillFailedNode() {
491512 if (this ->isUnexplored ()) {
492513 node = std::make_unique<Failed>();
493514 } else {
515+ if (auto if_else_node = dynamic_cast <IfElseNode *>(node.get ())) {
516+ GENSYM_DBG (typeid (*if_else_node).name ());
517+ } else if (auto finished_node = dynamic_cast <Finished *>(node.get ())) {
518+ GENSYM_DBG (typeid (*finished_node).name ());
519+ }
494520 assert (dynamic_cast <Failed *>(node.get ()) != nullptr );
495521 }
496522 return std::monostate ();
@@ -533,24 +559,6 @@ inline std::vector<SymVal> NodeBox::collect_path_conds() {
533559 return result;
534560}
535561
536- class Reuse_t {
537- public:
538- Reuse_t () : reuse_flag(false ) {}
539- bool is_reusing () {
540- // we are in reuse mode and the flag is set
541- return REUSE_MODE && reuse_flag;
542- }
543-
544- void turn_on_reusing () { reuse_flag = true ; }
545-
546- void turn_off_reusing () { reuse_flag = false ; }
547-
548- private:
549- bool reuse_flag;
550- };
551-
552- static Reuse_t Reuse;
553-
554562inline Snapshot_t::Snapshot_t (Cont_t cont, MCont_t mcont)
555563 : stack(SymStack), frames(SymFrames), cont(cont), mcont(mcont) {
556564#ifdef DEBUG
@@ -564,13 +572,15 @@ class ExploreTree_t {
564572 : root(std::make_unique<NodeBox>(nullptr )), cursor(root.get()) {}
565573
566574 void reset_cursor () {
575+ GENSYM_INFO (" Resetting cursor to root" );
567576 // Reset the cursor to the root of the tree
568577 cursor = root.get ();
569- Reuse.turn_off_reusing ();
570- // if root cursor is a branch node, then we can reuse the snapshot inside it
571- if (auto ite = dynamic_cast <IfElseNode *>(cursor->node .get ())) {
572- Reuse.turn_on_reusing ();
573- }
578+ }
579+
580+ void set_cursor (NodeBox *new_cursor) {
581+ GENSYM_INFO (" Setting cursor to a new node" );
582+ cursor = new_cursor;
583+ assert (dynamic_cast <SnapshotNode *>(cursor->node .get ()) != nullptr );
574584 }
575585
576586 std::monostate fillFinishedNode () { return cursor->fillFinishedNode (); }
@@ -656,18 +666,23 @@ static ExploreTree_t ExploreTree;
656666
657667class SymEnv_t {
658668public:
659- Num read (SymVal sym) {
660- auto symbol = dynamic_cast <Symbol *>(sym.symptr .get ());
661- assert (symbol);
662- if (symbol->get_id () >= map.size ()) {
663- map.resize (symbol->get_id () + 1 );
669+ Num read (const Symbol &symbol) {
670+ if (symbol.get_id () >= map.size ()) {
671+ map.resize (symbol.get_id () + 1 );
664672 }
665673#if DEBUG
666- std::cout << " Read symbol: " << symbol-> get_id ()
674+ std::cout << " Read symbol: " << symbol. get_id ()
667675 << " from symbolic environment" << std::endl;
668676 std::cout << " Current symbolic environment: " << to_string () << std::endl;
669677#endif
670- return map[symbol->get_id ()];
678+
679+ return map[symbol.get_id ()];
680+ }
681+
682+ Num read (SymVal sym) {
683+ auto symbol = dynamic_cast <Symbol *>(sym.symptr .get ());
684+ assert (symbol);
685+ return read (*symbol);
671686 }
672687
673688 void update (std::vector<Num> new_env) { map = std::move (new_env); }
@@ -684,10 +699,92 @@ class SymEnv_t {
684699 return result;
685700 }
686701
702+ size_t size () const { return map.size (); }
703+
687704private:
688705 std::vector<Num> map; // The symbolic environment, a vector of Num
689706};
690707
691708static SymEnv_t SymEnv;
692709
710+ // TODO: reduce the re-computation of the same symbolic expression, it's better
711+ // if it can be done by the smt solver
712+ static Num eval_sym_expr (const SymVal &sym, SymEnv_t &sym_env) {
713+ if (auto concrete = dynamic_cast <SymConcrete *>(sym.symptr .get ())) {
714+ return concrete->value ;
715+ } else if (auto operation = dynamic_cast <SymBinary *>(sym.symptr .get ())) {
716+ // If it's a operation, we need to evaluate it
717+ auto lhs = eval_sym_expr (operation->lhs , sym_env);
718+ auto rhs = eval_sym_expr (operation->rhs , sym_env);
719+ switch (operation->op ) {
720+ case ADD:
721+ return lhs + rhs;
722+ case SUB:
723+ return lhs - rhs;
724+ case MUL:
725+ return lhs * rhs;
726+ case DIV:
727+ return lhs / rhs;
728+ case LT:
729+ return lhs < rhs;
730+ case LEQ:
731+ return lhs <= rhs;
732+ case GT:
733+ return lhs > rhs;
734+ case GEQ:
735+ return lhs >= rhs;
736+ default :
737+ throw std::runtime_error (" Operation not supported: " +
738+ std::to_string (operation->op ));
739+ }
740+ } else if (auto symbol = dynamic_cast <Symbol *>(sym.symptr .get ())) {
741+ auto sym_id = symbol->get_id ();
742+ GENSYM_INFO (" Reading symbol: " + std::to_string (sym_id));
743+ return sym_env.read (sym);
744+ }
745+ throw std::runtime_error (" Not supported symbolic expression" );
746+ }
747+
748+ static void resume_conc_stack (const SymStack_t &sym_stack, Stack_t &stack,
749+ SymEnv_t &sym_env) {
750+ stack.resize (sym_stack.size ());
751+ for (size_t i = 0 ; i < sym_stack.size (); ++i) {
752+ auto sym = sym_stack[i];
753+ auto conc = eval_sym_expr (sym, sym_env);
754+ stack.set_from_front (i, conc);
755+ }
756+ }
757+
758+ static void resume_conc_frames (const SymFrames_t &sym_frame, Frames_t &frames,
759+ SymEnv_t &sym_env) {
760+ frames.resize (sym_frame.size ());
761+ for (size_t i = 0 ; i < sym_frame.size (); ++i) {
762+ auto sym = sym_frame[i];
763+ auto conc = eval_sym_expr (sym, sym_env);
764+ frames.set_from_front (i, conc);
765+ }
766+ }
767+
768+ static void resume_conc_states (const SymStack_t &sym_stack,
769+ const SymFrames_t &sym_frame, Stack_t &stack,
770+ Frames_t &frames, SymEnv_t &sym_env) {
771+ resume_conc_stack (sym_stack, stack, sym_env);
772+ resume_conc_frames (sym_frame, frames, sym_env);
773+ }
774+
775+ inline std::monostate Snapshot_t::resume_execution (SymEnv_t &sym_env,
776+ NodeBox *node) const {
777+ // Reset explore tree's cursor
778+ ExploreTree.set_cursor (node);
779+
780+ // Restore the symbolic state from the snapshot
781+ GENSYM_INFO (" Reusing symbolic state from snapshot" );
782+ SymStack = stack;
783+ SymFrames = frames;
784+ // Restore the concrete states from the symbolic states
785+ resume_conc_states (stack, frames, Stack, Frames, sym_env);
786+ // Resume execution from the continuation
787+ return cont (mcont);
788+ }
789+
693790#endif // WASM_SYMBOLIC_RT_HPP
0 commit comments