void goto_symext::operator()( statet &state, const goto_functionst &goto_functions, const goto_programt &goto_program) { assert(!goto_program.instructions.empty()); state.source=symex_targett::sourcet(goto_program); assert(!state.threads.empty()); assert(!state.call_stack().empty()); state.top().end_of_function=--goto_program.instructions.end(); state.top().calling_location.pc=state.top().end_of_function; state.symex_target=⌖ state.dirty=new dirtyt(goto_functions); assert(state.top().end_of_function->is_end_function()); while(!state.call_stack().empty()) { symex_step(goto_functions, state); // is there another thread to execute? if(state.call_stack().empty() && state.source.thread_nr+1<state.threads.size()) { unsigned t=state.source.thread_nr+1; // std::cout << "********* Now executing thread " << t << std::endl; state.switch_to_thread(t); } } delete state.dirty; state.dirty=0; }
void goto_symext::dereference( exprt &expr, statet &state, const bool write) { // The expression needs to be renamed to level 1 // in order to distinguish addresses of local variables // from different frames. Would be enough to rename // symbols whose address is taken. assert(!state.call_stack().empty()); state.rename(expr, ns, goto_symex_statet::L1); // start the recursion! guardt guard; dereference_rec(expr, state, guard, write); // dereferencing may introduce new symbol_exprt // (like __CPROVER_memory) state.rename(expr, ns, goto_symex_statet::L1); }
void goto_symext::symex_step( const goto_functionst &goto_functions, statet &state) { #if 0 std::cout << "\ninstruction type is " << state.source.pc->type << '\n'; std::cout << "Location: " << state.source.pc->source_location << '\n'; std::cout << "Guard: " << from_expr(ns, "", state.guard.as_expr()) << '\n'; std::cout << "Code: " << from_expr(ns, "", state.source.pc->code) << '\n'; #endif assert(!state.threads.empty()); assert(!state.call_stack().empty()); const goto_programt::instructiont &instruction=*state.source.pc; merge_gotos(state); // depth exceeded? { unsigned max_depth=options.get_unsigned_int_option("depth"); if(max_depth!=0 && state.depth>max_depth) state.guard.add(false_exprt()); state.depth++; } // actually do instruction switch(instruction.type) { case SKIP: if(!state.guard.is_false()) target.location(state.guard.as_expr(), state.source); state.source.pc++; break; case END_FUNCTION: // do even if state.guard.is_false() to clear out frame created // in symex_start_thread symex_end_of_function(state); state.source.pc++; break; case LOCATION: if(!state.guard.is_false()) target.location(state.guard.as_expr(), state.source); state.source.pc++; break; case GOTO: symex_goto(state); break; case ASSUME: if(!state.guard.is_false()) { exprt tmp=instruction.guard; clean_expr(tmp, state, false); state.rename(tmp, ns); symex_assume(state, tmp); } state.source.pc++; break; case ASSERT: if(!state.guard.is_false()) { std::string msg=id2string(state.source.pc->source_location.get_comment()); if(msg=="") msg="assertion"; exprt tmp(instruction.guard); clean_expr(tmp, state, false); vcc(tmp, msg, state); } state.source.pc++; break; case RETURN: if(!state.guard.is_false()) return_assignment(state); state.source.pc++; break; case ASSIGN: if(!state.guard.is_false()) symex_assign_rec(state, to_code_assign(instruction.code)); state.source.pc++; break; case FUNCTION_CALL: if(!state.guard.is_false()) { code_function_callt deref_code= to_code_function_call(instruction.code); if(deref_code.lhs().is_not_nil()) clean_expr(deref_code.lhs(), state, true); clean_expr(deref_code.function(), state, false); Forall_expr(it, deref_code.arguments()) clean_expr(*it, state, false); symex_function_call(goto_functions, state, deref_code); } else state.source.pc++; break; case OTHER: if(!state.guard.is_false()) symex_other(goto_functions, state); state.source.pc++; break; case DECL: if(!state.guard.is_false()) symex_decl(state); state.source.pc++; break; case DEAD: symex_dead(state); state.source.pc++; break; case START_THREAD: symex_start_thread(state); state.source.pc++; break; case END_THREAD: // behaves like assume(0); if(!state.guard.is_false()) state.guard.add(false_exprt()); state.source.pc++; break; case ATOMIC_BEGIN: symex_atomic_begin(state); state.source.pc++; break; case ATOMIC_END: symex_atomic_end(state); state.source.pc++; break; case CATCH: symex_catch(state); state.source.pc++; break; case THROW: symex_throw(state); state.source.pc++; break; case NO_INSTRUCTION_TYPE: throw "symex got NO_INSTRUCTION"; default: throw "symex got unexpected instruction"; } }