void stack_depth( symbol_tablet &symbol_table, goto_functionst &goto_functions, const int depth) { const symbol_exprt sym=add_stack_depth_symbol(symbol_table); const exprt depth_expr(from_integer(depth, sym.type())); Forall_goto_functions(f_it, goto_functions) if(f_it->second.body_available && f_it->first!=CPROVER_PREFIX "initialize" && f_it->first!=ID_main) stack_depth(f_it->second.body, sym, depth, depth_expr); // initialize depth to 0 goto_functionst::function_mapt::iterator i_it=goto_functions.function_map.find(CPROVER_PREFIX "initialize"); assert(i_it!=goto_functions.function_map.end()); goto_programt &init=i_it->second.body; goto_programt::targett first=init.instructions.begin(); goto_programt::targett it=init.insert_before(first); it->make_assignment(); it->code=code_assignt(sym, from_integer(0, sym.type())); it->location=first->location; it->function=first->function; // update counters etc. goto_functions.update(); }
exprt interval_domaint::make_expression(const symbol_exprt &src) const { if(is_int(src.type())) { int_mapt::const_iterator i_it=int_map.find(src.get_identifier()); if(i_it==int_map.end()) return true_exprt(); const integer_intervalt &interval=i_it->second; if(interval.is_top()) return true_exprt(); if(interval.is_bottom()) return false_exprt(); exprt::operandst conjuncts; if(interval.upper_set) { exprt tmp=from_integer(interval.upper, src.type()); conjuncts.push_back(binary_relation_exprt(src, ID_le, tmp)); } if(interval.lower_set) { exprt tmp=from_integer(interval.lower, src.type()); conjuncts.push_back(binary_relation_exprt(tmp, ID_le, src)); } return conjunction(conjuncts); } else if(is_float(src.type())) { float_mapt::const_iterator i_it=float_map.find(src.get_identifier()); if(i_it==float_map.end()) return true_exprt(); const ieee_float_intervalt &interval=i_it->second; if(interval.is_top()) return true_exprt(); if(interval.is_bottom()) return false_exprt(); exprt::operandst conjuncts; if(interval.upper_set) { exprt tmp=interval.upper.to_expr(); conjuncts.push_back(binary_relation_exprt(src, ID_le, tmp)); } if(interval.lower_set) { exprt tmp=interval.lower.to_expr(); conjuncts.push_back(binary_relation_exprt(tmp, ID_le, src)); } return conjunction(conjuncts); } else return true_exprt(); }
void stack_depth( goto_programt &goto_program, const symbol_exprt &symbol, const int i_depth, const exprt &max_depth) { assert(!goto_program.instructions.empty()); goto_programt::targett first=goto_program.instructions.begin(); binary_relation_exprt guard(symbol, ID_le, max_depth); goto_programt::targett assert_ins=goto_program.insert_before(first); assert_ins->make_assertion(guard); assert_ins->location=first->location; assert_ins->function=first->function; assert_ins->location.set_comment("Stack depth exceeds "+i2string(i_depth)); assert_ins->location.set_property("stack-depth"); goto_programt::targett plus_ins=goto_program.insert_before(first); plus_ins->make_assignment(); plus_ins->code=code_assignt(symbol, plus_exprt(symbol, from_integer(1, symbol.type()))); plus_ins->location=first->location; plus_ins->function=first->function; goto_programt::targett last=--goto_program.instructions.end(); assert(last->is_end_function()); goto_programt::instructiont minus_ins; minus_ins.make_assignment(); minus_ins.code=code_assignt(symbol, minus_exprt(symbol, from_integer(1, symbol.type()))); minus_ins.location=last->location; minus_ins.function=last->function; goto_program.insert_before_swap(last, minus_ins); }
void assume_renondet_inputs_valid(jsa_programt &prog) { if (prog.counterexample_locations.empty()) return; const symbol_tablet &st=prog.st; goto_programt &body=get_entry_body(prog.gf); for (const goto_programt::targett &pos : prog.inductive_step_renondets) { const irep_idt &id=get_affected_variable(*pos); const symbol_exprt lhs(st.lookup(id).symbol_expr()); const typet &type=lhs.type(); if (is_jsa_heap(type)) assume_valid_heap(st, body, pos, address_of_exprt(lhs)); } }
void acceleratet::build_state_machine( trace_automatont::sym_mapt::iterator begin, trace_automatont::sym_mapt::iterator end, state_sett &accept_states, symbol_exprt state, symbol_exprt next_state, scratch_programt &state_machine) { std::map<unsigned int, unsigned int> successor_counts; unsigned int max_count=0; unsigned int likely_next=0; // Optimisation: find the most common successor state and initialise // next_state to that value. This reduces the size of the state machine // driver substantially. for(trace_automatont::sym_mapt::iterator p=begin; p!=end; ++p) { trace_automatont::state_pairt state_pair=p->second; unsigned int to=state_pair.second; unsigned int count=0; if(successor_counts.find(to)==successor_counts.end()) { count=1; } else { count=successor_counts[to] + 1; } successor_counts[to]=count; if(count > max_count) { max_count=count; likely_next=to; } } // Optimisation: if there is only one possible successor state, just // jump straight to it instead of driving the whole machine. if(successor_counts.size()==1) { if(accept_states.find(likely_next)!=accept_states.end()) { // It's an accept state. Just assume(false). state_machine.assume(false_exprt()); } else { state_machine.assign(state, from_integer(likely_next, next_state.type())); } return; } state_machine.assign(next_state, from_integer(likely_next, next_state.type())); for(trace_automatont::sym_mapt::iterator p=begin; p!=end; ++p) { trace_automatont::state_pairt state_pair=p->second; unsigned int from=state_pair.first; unsigned int to=state_pair.second; if(to==likely_next) { continue; } // We're encoding the transition // // from -loc-> to // // which we encode by inserting: // // next_state=(state==from) ? to : next_state; // // just before loc. equal_exprt guard(state, from_integer(from, state.type())); if_exprt rhs(guard, from_integer(to, next_state.type()), next_state); state_machine.assign(next_state, rhs); } // Update the state and assume(false) if we've hit an accept state. state_machine.assign(state, next_state); for(state_sett::iterator it=accept_states.begin(); it!=accept_states.end(); ++it) { state_machine.assume( not_exprt(equal_exprt(state, from_integer(*it, state.type())))); } }
void jsil_typecheckt::typecheck_symbol_expr(symbol_exprt &symbol_expr) { irep_idt identifier=symbol_expr.get_identifier(); // if this is a built-in identifier, check if it exists in the // symbol table and retrieve it's type // TODO: add a flag for not needing to prefix internal symbols // that do not start with hash if(has_prefix(id2string(identifier), "#") || identifier=="eval" || identifier=="nan") { symbol_tablet::symbolst::const_iterator s_it= symbol_table.symbols.find(identifier); if(s_it==symbol_table.symbols.end()) throw "unexpected internal symbol: "+id2string(identifier); else { // symbol already exists const symbolt &symbol=s_it->second; // type the expression symbol_expr.type()=symbol.type; } } else { // if this is a variable, we need to check if we already // prefixed it and add to the symbol table if it is not there already irep_idt identifier_base = identifier; if(!has_prefix(id2string(identifier), id2string(proc_name))) { identifier = add_prefix(identifier); symbol_expr.set_identifier(identifier); } symbol_tablet::symbolst::const_iterator s_it= symbol_table.symbols.find(identifier); if(s_it==symbol_table.symbols.end()) { // create new symbol symbolt new_symbol; new_symbol.name=identifier; new_symbol.type=symbol_expr.type(); new_symbol.base_name=identifier_base; new_symbol.mode="jsil"; new_symbol.is_type=false; new_symbol.is_lvalue=new_symbol.type.id()!=ID_code; // mark as already typechecked new_symbol.is_extern=true; if(symbol_table.add(new_symbol)) { error() << "failed to add symbol `" << new_symbol.name << "' in the symbol table" << eom; throw 0; } } else { // symbol already exists assert(!s_it->second.is_type); const symbolt &symbol=s_it->second; // type the expression symbol_expr.type()=symbol.type; } } }
bool is_jsa_const(const symbol_exprt &symbol) { const std::string &id=id2string(symbol.get_identifier()); if (std::string::npos != id.find(JSA_CONSTANT_PREFIX)) return true; return symbol.type().get_bool(ID_C_constant); }
void goto_symext::symex_decl(statet &state, const symbol_exprt &expr) { // We increase the L2 renaming to make these non-deterministic. // We also prevent propagation of old values. ssa_exprt ssa(expr); state.rename(ssa, ns, goto_symex_statet::L1); const irep_idt &l1_identifier=ssa.get_identifier(); // rename type to L2 state.rename(ssa.type(), l1_identifier, ns); ssa.update_type(); // in case of pointers, put something into the value set if(ns.follow(expr.type()).id()==ID_pointer) { exprt failed= get_failed_symbol(expr, ns); exprt rhs; if(failed.is_not_nil()) { address_of_exprt address_of_expr; address_of_expr.object()=failed; address_of_expr.type()=expr.type(); rhs=address_of_expr; } else rhs=exprt(ID_invalid); state.rename(rhs, ns, goto_symex_statet::L1); state.value_set.assign(ssa, rhs, ns, true, false); } // prevent propagation state.propagation.remove(l1_identifier); // L2 renaming // inlining may yield multiple declarations of the same identifier // within the same L1 context if(state.level2.current_names.find(l1_identifier)== state.level2.current_names.end()) state.level2.current_names[l1_identifier]=std::make_pair(ssa, 0); state.level2.increase_counter(l1_identifier); const bool record_events=state.record_events; state.record_events=false; state.rename(ssa, ns); state.record_events=record_events; // we hide the declaration of auxiliary variables // and if the statement itself is hidden bool hidden= ns.lookup(expr.get_identifier()).is_auxiliary || state.top().hidden_function || state.source.pc->source_location.get_hide(); target.decl( state.guard.as_expr(), ssa, state.source, hidden?symex_targett::HIDDEN:symex_targett::STATE); assert(state.dirty); if((*state.dirty)(ssa.get_object_name()) && state.atomic_section_id==0) target.shared_write( state.guard.as_expr(), ssa, state.atomic_section_id, state.source); }