bvt boolbvt::convert_array(const exprt &expr) { std::size_t width=boolbv_width(expr.type()); if(width==0) return conversion_failed(expr); if(expr.type().id()==ID_array) { assert(expr.has_operands()); const exprt::operandst &operands=expr.operands(); assert(!operands.empty()); std::size_t op_width=width/operands.size(); bvt bv; bv.reserve(width); forall_expr(it, operands) { const bvt &tmp=convert_bv(*it); if(tmp.size()!=op_width) throw "convert_array: unexpected operand width"; forall_literals(it2, tmp) bv.push_back(*it2); } return bv; }
bool contains_if(exprt &dest, const namespacet &ns) { if(dest.id()==ID_if) return true; if(dest.has_operands()) Forall_operands(it, dest) if (contains_if(*it, ns)) return true; return false; }
exprt original(const exprt &src) { if(src.id()==ID_symbol) { const std::string &identifier=id2string(to_symbol_expr(src).get_identifier()); std::size_t pos=identifier.rfind('#'); if(pos==std::string::npos) return src; return symbol_exprt(identifier.substr(0,pos), src.type()); } if(src.has_operands()) { exprt tmp=src; Forall_operands(it, tmp) { exprt tmp2=original(*it); *it=tmp2; }
exprt path_symex_statet::instantiate_rec( const exprt &src, bool propagate) { #ifdef DEBUG std::cout << "instantiate_rec: " << from_expr(var_map.ns, "", src) << '\n'; #endif // check whether this is a symbol(.member|[index])* if(is_symbol_member_index(src)) { exprt tmp_symbol_member_index= read_symbol_member_index(src, propagate); assert(tmp_symbol_member_index.is_not_nil()); return tmp_symbol_member_index; // yes! } if(src.id()==ID_address_of) { assert(src.operands().size()==1); exprt tmp=src; tmp.op0()=instantiate_rec_address(tmp.op0(), propagate); return tmp; } else if(src.id()==ID_side_effect) { // could be done separately const irep_idt &statement=to_side_effect_expr(src).get_statement(); if(statement==ID_nondet) { irep_idt id="symex::nondet"+std::to_string(var_map.nondet_count); var_map.nondet_count++; return symbol_exprt(id, src.type()); } else throw "instantiate_rec: unexpected side effect "+id2string(statement); } else if(src.id()==ID_dereference) { // dereferencet has run already, so we should only be left with // integer addresses. Will transform into __CPROVER_memory[] // eventually. } else if(src.id()==ID_member) { const typet &compound_type= var_map.ns.follow(to_member_expr(src).struct_op().type()); if(compound_type.id()==ID_struct) { // do nothing } else if(compound_type.id()==ID_union) { // should already have been rewritten to byte_extract throw "unexpected union member"; } else { throw "member expects struct or union type"+src.pretty(); } } else if(src.id()==ID_byte_extract_little_endian || src.id()==ID_byte_extract_big_endian) { } else if(src.id()==ID_symbol) { // must be SSA already, or code assert(src.type().id()==ID_code || src.get_bool(ID_C_SSA_symbol)); } if(!src.has_operands()) return src; exprt src2=src; // recursive calls on structure of 'src' Forall_operands(it, src2) { exprt tmp_op=instantiate_rec(*it, propagate); *it=tmp_op; }
exprt path_symex_statet::instantiate_rec( const exprt &src, bool propagate) { #ifdef DEBUG std::cout << "instantiate_rec: " << from_expr(var_map.ns, "", src) << std::endl; #endif const typet &src_type=var_map.ns.follow(src.type()); if(src_type.id()==ID_struct) // src is a struct { const struct_typet &struct_type=to_struct_type(src_type); const struct_typet::componentst &components=struct_type.components(); struct_exprt result(src.type()); result.operands().resize(components.size()); // split it up into components for(unsigned i=0; i<components.size(); i++) { const typet &subtype=components[i].type(); const irep_idt &component_name=components[i].get_name(); exprt new_src; if(src.id()==ID_struct) // struct constructor? { assert(src.operands().size()==components.size()); new_src=src.operands()[i]; } else new_src=member_exprt(src, component_name, subtype); // recursive call result.operands()[i]=instantiate_rec(new_src, propagate); } return result; // done } else if(src_type.id()==ID_array) // src is an array { const array_typet &array_type=to_array_type(src_type); const typet &subtype=array_type.subtype(); if(array_type.size().is_constant()) { mp_integer size; if(to_integer(array_type.size(), size)) throw "failed to convert array size"; unsigned long long size_int=integer2unsigned(size); array_exprt result(array_type); result.operands().resize(size_int); // split it up into elements for(unsigned long long i=0; i<size_int; ++i) { exprt index=from_integer(i, array_type.size().type()); exprt new_src=index_exprt(src, index, subtype); // array constructor? if(src.id()==ID_array) new_src=simplify_expr(new_src, var_map.ns); // recursive call result.operands()[i]=instantiate_rec(new_src, propagate); } return result; // done } else { // TODO } } else if(src_type.id()==ID_vector) // src is a vector { const vector_typet &vector_type=to_vector_type(src_type); const typet &subtype=vector_type.subtype(); if(!vector_type.size().is_constant()) throw "vector with non-constant size"; mp_integer size; if(to_integer(vector_type.size(), size)) throw "failed to convert vector size"; unsigned long long int size_int=integer2unsigned(size); vector_exprt result(vector_type); exprt::operandst &operands=result.operands(); operands.resize(size_int); // split it up into elements for(unsigned long long i=0; i<size_int; ++i) { exprt index=from_integer(i, vector_type.size().type()); exprt new_src=index_exprt(src, index, subtype); // vector constructor? if(src.id()==ID_vector) new_src=simplify_expr(new_src, var_map.ns); // recursive call operands[i]=instantiate_rec(new_src, propagate); } return result; // done } // check whether this is a symbol(.member|[index])* { exprt tmp_symbol_member_index= read_symbol_member_index(src, propagate); if(tmp_symbol_member_index.is_not_nil()) return tmp_symbol_member_index; // yes! } if(src.id()==ID_address_of) { assert(src.operands().size()==1); exprt tmp=src; tmp.op0()=instantiate_rec_address(tmp.op0(), propagate); return tmp; } else if(src.id()==ID_sideeffect) { // could be done separately const irep_idt &statement=to_side_effect_expr(src).get_statement(); if(statement==ID_nondet) { irep_idt id="symex::nondet"+i2string(var_map.nondet_count); var_map.nondet_count++; return symbol_exprt(id, src.type()); } else throw "instantiate_rec: unexpected side effect "+id2string(statement); } else if(src.id()==ID_dereference) { // dereferencet has run already, so we should only be left with // integer addresses. Will transform into __CPROVER_memory[] // eventually. } else if(src.id()==ID_index) { // avoids indefinite recursion above return src; } else if(src.id()==ID_member) { const typet &compound_type= var_map.ns.follow(to_member_expr(src).struct_op().type()); if(compound_type.id()==ID_struct) { // avoids indefinite recursion above return src; } else if(compound_type.id()==ID_union) { member_exprt tmp=to_member_expr(src); tmp.struct_op()=instantiate_rec(tmp.struct_op(), propagate); return tmp; } else { throw "member expects struct or union type"+src.pretty(); } } if(!src.has_operands()) return src; exprt src2=src; // recursive calls on structure of 'src' Forall_operands(it, src2) { exprt tmp_op=instantiate_rec(*it, propagate); *it=tmp_op; }
void simplify_byte_expr(exprt &dest, const namespacet &ns) { /* * byte_update(byte_update(e, i, v, t), i, v', t) * ----------------------- * root * => * byte_update(e, i, v', t) */ if(dest.id()==ID_byte_update_little_endian || dest.id()==ID_byte_update_big_endian) { exprt &root=dest.op0(); exprt &offset=dest.op1(); const typet &type=root.type(); if(root.id()==ID_byte_update_little_endian || root.id()==ID_byte_update_big_endian) { exprt &nested_root=root.op0(); exprt &nested_offset=root.op1(); const typet &nested_type=root.type(); if(offset == nested_offset && type == nested_type) { #ifdef DEBUG std::cout << "simplify_byte_expr " << from_expr(dest) << std::endl; #endif root.swap(nested_root); #ifdef DEBUG std::cout << " ==> " << from_expr(dest) << std::endl; #endif } } } /* * byte_extract(byte_update(e, i, v, t), i, t) * => * v */ else if(dest.id()==ID_byte_extract_little_endian || dest.id()==ID_byte_extract_big_endian) { exprt &root=dest.op0(); exprt &offset=dest.op1(); const typet &type=dest.type(); if(root.id()==ID_byte_update_little_endian || root.id()==ID_byte_update_big_endian) { exprt &nested_offset=root.op1(); exprt &nested_with=root.op2(); const typet &nested_type=root.type(); if(offset == nested_offset && type == nested_type) { #ifdef DEBUG std::cout << "simplify_byte_expr " << from_expr(dest) << std::endl; #endif dest.swap(nested_with); //#ifdef DEBUG std::cout << " ==> " << from_expr(dest) << std::endl; //#endif } } } if(dest.has_operands()) Forall_operands(it, dest) simplify_byte_expr(*it, ns); }
void rw_sett::read_write_rec( const exprt &expr, bool r, bool w, const std::string &suffix, const guardt &guard) { if(expr.id()=="symbol" && !expr.has_operands()) { const symbol_exprt &symbol_expr=to_symbol_expr(expr); const symbolt *symbol; if(!ns.lookup(symbol_expr.get_identifier(), symbol)) { if(!symbol->static_lifetime /*&& expr.type().id()=="pointer"*/) { return; // ignore for now } if(symbol->name=="c::__ESBMC_alloc" || symbol->name=="c::__ESBMC_alloc_size" || symbol->name=="c::stdin" || symbol->name=="c::stdout" || symbol->name=="c::stderr" || symbol->name=="c::sys_nerr") { return; // ignore for now } } irep_idt object=id2string(symbol_expr.get_identifier())+suffix; entryt &entry=entries[object]; entry.object=object; entry.r=entry.r || r; entry.w=entry.w || w; entry.guard = migrate_expr_back(guard.as_expr()); } else if(expr.id()=="member") { assert(expr.operands().size()==1); const std::string &component_name=expr.component_name().as_string(); read_write_rec(expr.op0(), r, w, "."+component_name+suffix, guard); } else if(expr.id()=="index") { // we don't distinguish the array elements for now assert(expr.operands().size()==2); std::string tmp; tmp = integer2string(binary2integer(expr.op1().value().as_string(), true),10); read_write_rec(expr.op0(), r, w, "["+suffix+tmp+"]", guard); read(expr.op1(), guard); } else if(expr.id()=="dereference") { assert(expr.operands().size()==1); read(expr.op0(), guard); exprt tmp(expr.op0()); expr2tc tmp_expr; migrate_expr(tmp, tmp_expr); dereference(target, tmp_expr, ns, value_sets); tmp = migrate_expr_back(tmp_expr); read_write_rec(tmp, r, w, suffix, guard); } else if(expr.is_address_of() || expr.id()=="implicit_address_of") { assert(expr.operands().size()==1); } else if(expr.id()=="if") { assert(expr.operands().size()==3); read(expr.op0(), guard); guardt true_guard(guard); expr2tc tmp_expr; migrate_expr(expr.op0(), tmp_expr); true_guard.add(tmp_expr); read_write_rec(expr.op1(), r, w, suffix, true_guard); guardt false_guard(guard); migrate_expr(gen_not(expr.op0()), tmp_expr); false_guard.add(tmp_expr); read_write_rec(expr.op2(), r, w, suffix, false_guard); } else { forall_operands(it, expr) read_write_rec(*it, r, w, suffix, guard); } }