void boolbvt::convert_replication(const exprt &expr, bvt &bv) { unsigned width=boolbv_width(expr.type()); if(width==0) return conversion_failed(expr, bv); if(expr.operands().size()!=2) throw "replication takes two operands"; mp_integer times; if(to_integer(expr.op0(), times)) throw "replication takes constant as first parameter"; const unsigned u_times=integer2unsigned(times); const bvt &op=convert_bv(expr.op1()); unsigned offset=0; bv.resize(width); for(unsigned i=0; i<u_times; i++) { if(op.size()+offset>width) throw "replication operand width too big"; for(unsigned i=0; i<op.size(); i++) bv[i+offset]=op[i]; offset+=op.size(); } if(offset!=bv.size()) throw "replication operand width too small"; }
void interpretert::assign( mp_integer address, const std::vector<mp_integer> &rhs) { for(unsigned i=0; i<rhs.size(); i++, ++address) { if(address<memory.size()) { memory_cellt &cell=memory[integer2unsigned(address)]; std::cout << "** assigning " << cell.identifier << "[" << cell.offset << "]:=" << rhs[i] << std::endl; cell.value=rhs[i]; } } }
bvt float_utilst::limit_distance( const bvt &dist, mp_integer limit) { std::size_t nb_bits=integer2unsigned(address_bits(limit)); bvt upper_bits=dist; upper_bits.erase(upper_bits.begin(), upper_bits.begin()+nb_bits); literalt or_upper_bits=prop.lor(upper_bits); bvt lower_bits=dist; lower_bits.resize(nb_bits); bvt result; result.resize(lower_bits.size()); // bitwise or with or_upper_bits for(std::size_t i=0; i<result.size(); i++) result[i]=prop.lor(lower_bits[i], or_upper_bits); return result; }
static unsigned from_ns( const namespacet &ns, const std::string &what) { const irep_idt id=CPROVER_PREFIX "architecture_"+what; const symbolt *symbol; if(ns.lookup(id, symbol)) throw "failed to find "+id2string(id); exprt tmp=symbol->value; simplify(tmp, ns); if(tmp.id()!=ID_constant) throw "symbol table configuration entry `"+id2string(id)+"' is not a constant"; mp_integer int_value; if(to_integer(to_constant_expr(tmp), int_value)) throw "failed to convert symbol table configuration entry `"+id2string(id)+"'"; return integer2unsigned(int_value); }
bvt boolbvt::convert_extractbits(const extractbits_exprt &expr) { std::size_t width=boolbv_width(expr.type()); if(width==0) return conversion_failed(expr); const irep_idt &type_id=expr.type().id(); if(type_id!=ID_signedbv && type_id!=ID_unsignedbv && type_id!=ID_c_enum && type_id!=ID_c_enum_tag && type_id!=ID_bv) return conversion_failed(expr); if(expr.operands().size()!=3) { error().source_location=expr.find_source_location(); error() << "extractbits takes three operands" << eom; throw 0; } mp_integer o1, o2; const bvt &bv0=convert_bv(expr.op0()); // We only do constants for now. // Should implement a shift here. if(to_integer(expr.op1(), o1) || to_integer(expr.op2(), o2)) return conversion_failed(expr); if(o1<0 || o1>=bv0.size()) { error().source_location=expr.find_source_location(); error() << "extractbits: second operand out of range: " << expr.pretty() << eom; } if(o2<0 || o2>=bv0.size()) { error().source_location=expr.find_source_location(); error() << "extractbits: third operand out of range: " << expr.pretty() << eom; throw 0; } if(o2>o1) std::swap(o1, o2); // now o2<=o1 if((o1-o2+1)!=width) { error().source_location=expr.find_source_location(); error() << "extractbits: wrong width (expected " << (o1-o2+1) << " but got " << width << "): " << expr.pretty() << eom; throw 0; } std::size_t offset=integer2unsigned(o2); bvt bv; bv.resize(width); for(std::size_t i=0; i<width; i++) bv[i]=bv0[offset+i]; return bv; }
bvt boolbvt::convert_byte_update(const byte_update_exprt &expr) { if(expr.operands().size()!=3) throw "byte_update takes three operands"; const exprt &op=expr.op0(); const exprt &offset_expr=expr.offset(); const exprt &value=expr.value(); bool little_endian; if(expr.id()==ID_byte_update_little_endian) little_endian=true; else if(expr.id()==ID_byte_update_big_endian) little_endian=false; else assert(false); bvt bv=convert_bv(op); const bvt &value_bv=convert_bv(value); std::size_t update_width=value_bv.size(); std::size_t byte_width=8; if(update_width>bv.size()) update_width=bv.size(); // see if the byte number is constant mp_integer index; if(!to_integer(offset_expr, index)) { // yes! mp_integer offset=index*8; if(offset+update_width>mp_integer(bv.size()) || offset<0) { // out of bounds } else { if(little_endian) { for(std::size_t i=0; i<update_width; i++) bv[integer2size_t(offset+i)]=value_bv[i]; } else { endianness_mapt map_op(op.type(), false, ns); endianness_mapt map_value(value.type(), false, ns); std::size_t offset_i=integer2unsigned(offset); for(std::size_t i=0; i<update_width; i++) { size_t index_op=map_op.map_bit(offset_i+i); size_t index_value=map_value.map_bit(i); assert(index_op<bv.size()); assert(index_value<value_bv.size()); bv[index_op]=value_bv[index_value]; } } } return bv; } // byte_update with variable index for(std::size_t offset=0; offset<bv.size(); offset+=byte_width) { // index condition equal_exprt equality; equality.lhs()=offset_expr; equality.rhs()=from_integer(offset/byte_width, offset_expr.type()); literalt equal=convert(equality); endianness_mapt map_op(op.type(), little_endian, ns); endianness_mapt map_value(value.type(), little_endian, ns); for(std::size_t bit=0; bit<update_width; bit++) if(offset+bit<bv.size()) { std::size_t bv_o=map_op.map_bit(offset+bit); std::size_t value_bv_o=map_value.map_bit(bit); bv[bv_o]=prop.lselect(equal, value_bv[value_bv_o], bv[bv_o]); } } return bv; }
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; }
unsigned interpretert::get_size(const typet &type) const { if(type.id()==ID_struct) { const struct_typet::componentst &components= to_struct_type(type).components(); unsigned sum=0; for(struct_typet::componentst::const_iterator it=components.begin(); it!=components.end(); it++) { const typet &sub_type=it->type(); if(sub_type.id()!=ID_code) sum+=get_size(sub_type); } return sum; } else if(type.id()==ID_union) { const union_typet::componentst &components= to_union_type(type).components(); unsigned max_size=0; for(union_typet::componentst::const_iterator it=components.begin(); it!=components.end(); it++) { const typet &sub_type=it->type(); if(sub_type.id()!=ID_code) max_size=std::max(max_size, get_size(sub_type)); } return max_size; } else if(type.id()==ID_array) { const exprt &size_expr=static_cast<const exprt &>(type.find(ID_size)); unsigned subtype_size=get_size(type.subtype()); mp_integer i; if(!to_integer(size_expr, i)) return subtype_size*integer2unsigned(i); else return subtype_size; } else if(type.id()==ID_symbol) { return get_size(ns.follow(type)); } else return 1; }
void float_utilst::normalization_shift(bvt &fraction, bvt &exponent) { #if 0 // this thing is quadratic! bvt new_fraction=prop.new_variables(fraction.size()); bvt new_exponent=prop.new_variables(exponent.size()); // i is the shift distance for(std::size_t i=0; i<fraction.size(); i++) { bvt equal; // the bits above need to be zero for(std::size_t j=0; j<i; j++) equal.push_back( !fraction[fraction.size()-1-j]); // this one needs to be one equal.push_back(fraction[fraction.size()-1-i]); // iff all of that holds, we shift here! literalt shift=prop.land(equal); // build shifted value bvt shifted_fraction=bv_utils.shift(fraction, bv_utilst::LEFT, i); bv_utils.cond_implies_equal(shift, shifted_fraction, new_fraction); // build new exponent bvt adjustment=bv_utils.build_constant(-i, exponent.size()); bvt added_exponent=bv_utils.add(exponent, adjustment); bv_utils.cond_implies_equal(shift, added_exponent, new_exponent); } // Fraction all zero? It stays zero. // The exponent is undefined in that case. literalt fraction_all_zero=bv_utils.is_zero(fraction); bvt zero_fraction; zero_fraction.resize(fraction.size(), const_literal(false)); bv_utils.cond_implies_equal(fraction_all_zero, zero_fraction, new_fraction); fraction=new_fraction; exponent=new_exponent; #else // n-log-n alignment shifter. // The worst-case shift is the number of fraction // bits minus one, in case the faction is one exactly. assert(!fraction.empty()); unsigned depth=integer2unsigned(address_bits(fraction.size()-1)); if(exponent.size()<depth) exponent=bv_utils.sign_extension(exponent, depth); bvt exponent_delta=bv_utils.zeros(exponent.size()); for(int d=depth-1; d>=0; d--) { std::size_t distance=(1<<d); assert(fraction.size()>distance); // check if first 'distance'-many bits are zeros const bvt prefix=bv_utils.extract_msb(fraction, distance); literalt prefix_is_zero=bv_utils.is_zero(prefix); // If so, shift the zeros out left by 'distance'. // Otherwise, leave as is. const bvt shifted= bv_utils.shift(fraction, bv_utilst::LEFT, distance); fraction= bv_utils.select(prefix_is_zero, shifted, fraction); // add corresponding weight to exponent assert(d<(signed)exponent_delta.size()); exponent_delta[d]=prefix_is_zero; } exponent=bv_utils.sub(exponent, exponent_delta); #endif }
const boolbv_widtht::entryt &boolbv_widtht::get_entry(const typet &type) const { // check cache first std::pair<cachet::iterator, bool> cache_result= cache.insert(std::pair<typet, entryt>(type, entryt())); entryt &entry=cache_result.first->second; if(!cache_result.second) // found! return entry; entry.total_width=0; const irep_idt type_id=type.id(); if(type_id==ID_struct) { const struct_typet::componentst &components= to_struct_type(type).components(); std::size_t offset=0; entry.members.resize(components.size()); for(std::size_t i=0; i<entry.members.size(); i++) { std::size_t sub_width=operator()(components[i].type()); entry.members[i].offset=offset; entry.members[i].width=sub_width; offset+=sub_width; } entry.total_width=offset; } else if(type_id==ID_union) { const union_typet::componentst &components= to_union_type(type).components(); entry.members.resize(components.size()); std::size_t max_width=0; for(std::size_t i=0; i<entry.members.size(); i++) { std::size_t sub_width=operator()(components[i].type()); entry.members[i].width=sub_width; max_width=std::max(max_width, sub_width); } entry.total_width=max_width; } else if(type_id==ID_bool) entry.total_width=1; else if(type_id==ID_c_bool) { entry.total_width=to_c_bool_type(type).get_width(); assert(entry.total_width!=0); } else if(type_id==ID_signedbv) { entry.total_width=to_signedbv_type(type).get_width(); assert(entry.total_width!=0); } else if(type_id==ID_unsignedbv) { entry.total_width=to_unsignedbv_type(type).get_width(); assert(entry.total_width!=0); } else if(type_id==ID_floatbv) { entry.total_width=to_floatbv_type(type).get_width(); assert(entry.total_width!=0); } else if(type_id==ID_fixedbv) { entry.total_width=to_fixedbv_type(type).get_width(); assert(entry.total_width!=0); } else if(type_id==ID_bv) { entry.total_width=to_bv_type(type).get_width(); assert(entry.total_width!=0); } else if(type_id==ID_verilogbv) { // we encode with two bits entry.total_width=type.get_unsigned_int(ID_width)*2; assert(entry.total_width!=0); } else if(type_id==ID_range) { mp_integer from=string2integer(type.get_string(ID_from)), to=string2integer(type.get_string(ID_to)); mp_integer size=to-from+1; if(size>=1) { entry.total_width=integer2unsigned(address_bits(size)); assert(entry.total_width!=0); } } else if(type_id==ID_array) { const array_typet &array_type=to_array_type(type); std::size_t sub_width=operator()(array_type.subtype()); mp_integer array_size; if(to_integer(array_type.size(), array_size)) { // we can still use the theory of arrays for this entry.total_width=0; } else { mp_integer total=array_size*sub_width; if(total>(1<<30)) // realistic limit throw "array too large for flattening"; entry.total_width=integer2unsigned(total); } } else if(type_id==ID_vector) { const vector_typet &vector_type=to_vector_type(type); std::size_t sub_width=operator()(vector_type.subtype()); mp_integer vector_size; if(to_integer(vector_type.size(), vector_size)) { // we can still use the theory of arrays for this entry.total_width=0; } else { mp_integer total=vector_size*sub_width; if(total>(1<<30)) // realistic limit throw "vector too large for flattening"; entry.total_width=integer2unsigned(vector_size*sub_width); } } else if(type_id==ID_complex) { std::size_t sub_width=operator()(type.subtype()); entry.total_width=integer2unsigned(2*sub_width); } else if(type_id==ID_code) { } else if(type_id==ID_enum) { // get number of necessary bits std::size_t size=type.find(ID_elements).get_sub().size(); entry.total_width=integer2unsigned(address_bits(size)); assert(entry.total_width!=0); } else if(type_id==ID_c_enum) { // these have a subtype entry.total_width=type.subtype().get_unsigned_int(ID_width); assert(entry.total_width!=0); } else if(type_id==ID_incomplete_c_enum) { // no width } else if(type_id==ID_pointer || type_id==ID_reference) { entry.total_width=config.ansi_c.pointer_width; } else if(type_id==ID_symbol) entry=get_entry(ns.follow(type)); else if(type_id==ID_struct_tag) entry=get_entry(ns.follow_tag(to_struct_tag_type(type))); else if(type_id==ID_union_tag) entry=get_entry(ns.follow_tag(to_union_tag_type(type))); else if(type_id==ID_c_enum_tag) entry=get_entry(ns.follow_tag(to_c_enum_tag_type(type))); else if(type_id==ID_c_bit_field) { entry.total_width=to_c_bit_field_type(type).get_width(); } return entry; }
propt::resultt qbf_qube_coret::prop_solve() { if(no_clauses()==0) return resultt::P_SATISFIABLE; { messaget::status() << "QuBE: " << no_variables() << " variables, " << no_clauses() << " clauses" << eom; } std::string result_tmp_file="qube.out"; { std::ofstream out(qbf_tmp_file.c_str()); // write it break_lines=false; write_qdimacs_cnf(out); } std::string options=""; // solve it int res=system(( "QuBE "+options+" "+qbf_tmp_file+" > "+result_tmp_file).c_str()); assert(0==res); bool result=false; // read result { std::ifstream in(result_tmp_file.c_str()); bool result_found=false; while(in) { std::string line; std::getline(in, line); if(line!="" && line[line.size()-1]=='\r') line.resize(line.size()-1); if(line[0]=='V') { mp_integer b(line.substr(2).c_str()); if(b<0) assignment[integer2unsigned(b.negate())]=false; else assignment[integer2unsigned(b)]=true; } else if(line=="s cnf 1") { result=true; result_found=true; break; } else if(line=="s cnf 0") { result=false; result_found=true; break; } } if(!result_found) { messaget::error() << "QuBE failed: unknown result" << eom; return resultt::P_ERROR; } } int remove_result=remove(result_tmp_file.c_str()); if(remove_result!=0) { messaget::error() << "Remove failed: " << std::strerror(errno) << eom; return resultt::P_ERROR; } remove_result=remove(qbf_tmp_file.c_str()); if(remove_result!=0) { messaget::error() << "Remove failed: " << std::strerror(errno) << eom; return resultt::P_ERROR; } if(result) { messaget::status() << "QuBE: TRUE" << eom; return resultt::P_SATISFIABLE; } else { messaget::status() << "QuBE: FALSE" << eom; return resultt::P_UNSATISFIABLE; } }
void boolbvt::convert_with_array( const array_typet &type, const exprt &op1, const exprt &op2, const bvt &prev_bv, bvt &next_bv) { if(is_unbounded_array(type)) { // can't do this error().source_location=type.source_location(); error() << "convert_with_array called for unbounded array" << eom; throw 0; } const exprt &array_size=type.size(); mp_integer size; if(to_integer(array_size, size)) { error().source_location=type.source_location(); error() << "convert_with_array expects constant array size" << eom; throw 0; } const bvt &op2_bv=convert_bv(op2); if(size*op2_bv.size()!=prev_bv.size()) { error().source_location=type.source_location(); error() << "convert_with_array: unexpected operand 2 width" << eom; throw 0; } // Is the index a constant? mp_integer op1_value; if(!to_integer(op1, op1_value)) { // Yes, it is! next_bv=prev_bv; if(op1_value>=0 && op1_value<size) // bounds check { std::size_t offset=integer2unsigned(op1_value*op2_bv.size()); for(std::size_t j=0; j<op2_bv.size(); j++) next_bv[offset+j]=op2_bv[j]; } return; } typet counter_type=op1.type(); for(mp_integer i=0; i<size; i=i+1) { exprt counter=from_integer(i, counter_type); literalt eq_lit=convert(equal_exprt(op1, counter)); std::size_t offset=integer2unsigned(i*op2_bv.size()); for(std::size_t j=0; j<op2_bv.size(); j++) next_bv[offset+j]= prop.lselect(eq_lit, op2_bv[j], prev_bv[offset+j]); } }
void add_padding(struct_typet &type, const namespacet &ns) { struct_typet::componentst &components=type.components(); // First do padding for bit-fields to make them // appear on byte boundaries. { unsigned padding_counter=0; unsigned bit_field_bits=0; for(struct_typet::componentst::iterator it=components.begin(); it!=components.end(); it++) { if(it->type().id()==ID_c_bit_field && to_c_bit_field_type(it->type()).get_width()!=0) { // count the bits unsigned width=to_c_bit_field_type(it->type()).get_width(); bit_field_bits+=width; } else if(bit_field_bits!=0) { // not on a byte-boundary? if((bit_field_bits%8)!=0) { unsigned pad=8-bit_field_bits%8; c_bit_field_typet padding_type(unsignedbv_typet(pad), pad); struct_typet::componentt component; component.type()=padding_type; component.set_name("$bit_field_pad"+i2string(padding_counter++)); component.set_is_padding(true); it=components.insert(it, component); it++; // skip over bit_field_bits+=pad; } bit_field_bits=0; } } // Add padding at the end? if((bit_field_bits%8)!=0) { unsigned pad=8-bit_field_bits%8; c_bit_field_typet padding_type(unsignedbv_typet(pad), pad); struct_typet::componentt component; component.type()=padding_type; component.set_name("$bit_field_pad"+i2string(padding_counter++)); component.set_is_padding(true); components.push_back(component); } } // Is the struct packed? if(type.get_bool(ID_C_packed)) return; // done mp_integer offset=0; unsigned padding_counter=0; mp_integer max_alignment=0; unsigned bit_field_bits=0; for(struct_typet::componentst::iterator it=components.begin(); it!=components.end(); it++) { const typet &it_type=it->type(); mp_integer a=1; if(it_type.id()==ID_c_bit_field) { a=alignment(to_c_bit_field_type(it_type).subtype(), ns); // A zero-width bit-field causes alignment to the base-type. if(to_c_bit_field_type(it_type).get_width()==0) { } else { // Otherwise, ANSI-C says that bit-fields do not get padded! // We consider the type for max_alignment, however. if(max_alignment<a) max_alignment=a; unsigned w=to_c_bit_field_type(it_type).get_width(); unsigned bytes; for(bytes=0; w>bit_field_bits; ++bytes, bit_field_bits+=8); bit_field_bits-=w; offset+=bytes; continue; } } else if(it->type().get_bool(ID_C_packed) || ns.follow(it->type()).get_bool(ID_C_packed)) { // the field or type is "packed" } else a=alignment(it_type, ns); // check minimum alignment if(a<config.ansi_c.alignment) a=config.ansi_c.alignment; if(max_alignment<a) max_alignment=a; if(a!=1) { // we may need to align it mp_integer displacement=offset%a; if(displacement!=0) { mp_integer pad=a-displacement; unsignedbv_typet padding_type; padding_type.set_width(integer2unsigned(pad*8)); struct_typet::componentt component; component.type()=padding_type; component.set_name("$pad"+i2string(padding_counter++)); component.set_is_padding(true); it=components.insert(it, component); it++; // skip over offset+=pad; } } mp_integer size=pointer_offset_size(ns, it_type); if(size!=-1) offset+=size; } if(bit_field_bits!=0) { // these are now assumed to be multiples of 8 offset+=bit_field_bits/8; } // any explicit alignment for the struct? if(type.find(ID_C_alignment).is_not_nil()) { const exprt &alignment= static_cast<const exprt &>(type.find(ID_C_alignment)); if(alignment.id()!=ID_default) { exprt tmp=alignment; simplify(tmp, ns); mp_integer tmp_i; if(!to_integer(tmp, tmp_i) && tmp_i>max_alignment) max_alignment=tmp_i; } } // There may be a need for 'end of struct' padding. // We use 'max_alignment'. if(max_alignment>1) { // we may need to align it mp_integer displacement=offset%max_alignment; if(displacement!=0) { mp_integer pad=max_alignment-displacement; unsignedbv_typet padding_type; padding_type.set_width(integer2unsigned(pad*8)); // we insert after any final 'flexible member' struct_typet::componentt component; component.type()=padding_type; component.set_name("$pad"+i2string(padding_counter++)); component.set_is_padding(true); components.push_back(component); } } }
decision_proceduret::resultt smt1_dect::read_result_cvc3(std::istream &in) { std::string line; decision_proceduret::resultt res = D_ERROR; boolean_assignment.clear(); boolean_assignment.resize(no_boolean_variables, false); typedef std::unordered_map<std::string, std::string, string_hash> valuest; valuest values; while(std::getline(in, line)) { if(line=="sat") res = D_SATISFIABLE; else if(line=="unsat") res = D_UNSATISFIABLE; else if(line.find("Current scope level")!=std::string::npos || line.find("Variable Assignment")!=std::string::npos) ; //ignore else { assert(line.substr(0,13)==" :assumption"); std::size_t pos=line.find('('); if(pos!=std::string::npos) { std::string var; std::string val; if(line[pos+1]=='=') { std::string ops = line.substr(pos+3, line.length()-pos-4); std::size_t blank=ops.find(' '); var = ops.substr(0, blank); val = ops.substr(blank+1, ops.length()-blank); if((var.length()>=4 && var.substr(0,4)=="cvc3") || (val.length()>=4 && val.substr(0,4)=="cvc3") || var==val) continue; else if((var.substr(0,9)=="array_of'") || (var.substr(0,2)=="bv" && val.substr(0,2)!="bv")) { std::string t=var; var=val; val=t; } } else if(line.substr(pos+1,3)=="not") { var = line.substr(pos+5, line.length()-pos-6); val = "false"; } else { var = line.substr(pos+1, line.length()-pos-2); assert(var.find(' ')==std::string::npos); val = "true"; } values[var]=val; } } } for(identifier_mapt::iterator it=identifier_map.begin(); it!=identifier_map.end(); it++) { it->second.value.make_nil(); std::string conv_id=convert_identifier(it->first); std::string value=values[conv_id]; if(value=="") continue; if(value.substr(0,2)=="bv") { std::string v=value.substr(2, value.find('[')-2); size_t p = value.find('[')+1; std::string w=value.substr(p, value.find(']')-p); std::string binary=integer2binary(string2integer(v,10), integer2unsigned(string2integer(w,10))); set_value(it->second, "", binary); } else if(value=="false") it->second.value=false_exprt(); else if(value=="true") it->second.value=true_exprt(); else if(value.substr(0,8)=="array_of") { // We assume that array_of has only concrete arguments... irep_idt id(value); array_of_mapt::const_iterator fit=array_of_map.begin(); while(fit!=array_of_map.end() && fit->second!=id) fit++; if(fit!=array_of_map.end()) it->second.value = fit->first; } else set_value(it->second, "", value); } // Booleans for(unsigned v=0; v<no_boolean_variables; v++) { std::string value=values["B"+std::to_string(v)]; if(value=="") continue; boolean_assignment[v]=(value=="true"); } return res; }
bool smt1_dect::string_to_expr_z3( const typet &type, const std::string &value, exprt &e) const { if(value.substr(0,2)=="bv") { std::string v=value.substr(2, value.find('[')-2); size_t p = value.find('[')+1; std::string w=value.substr(p, value.find(']')-p); std::string binary=integer2binary(string2integer(v,10), integer2unsigned(string2integer(w,10))); if(type.id()==ID_struct) { e=binary2struct(to_struct_type(type), binary); } else if(type.id()==ID_union) { e=binary2union(to_union_type(type), binary); } else { constant_exprt c(type); c.set_value(binary); e=c; } return true; } else if(value.substr(0,6)=="(const") // const arrays { std::string av = value.substr(7, value.length()-8); exprt ae; if(!string_to_expr_z3(type.subtype(), av, ae)) return false; array_of_exprt ao; ao.type() = typet(ID_array); ao.type().subtype()=ae.type(); ao.what() = ae; e = ao; return true; } else if(value.substr(0,6)=="(store") { size_t p1=value.rfind(' ')+1; size_t p2=value.rfind(' ', p1-2)+1; assert(p1!=std::string::npos && p2!=std::string::npos); std::string elem = value.substr(p1, value.size()-p1-1); std::string inx = value.substr(p2, p1-p2-1); std::string array = value.substr(7, p2-8); exprt old; if(!string_to_expr_z3(type, array, old)) return false; exprt where; if(!string_to_expr_z3(array_index_type(), inx, where)) return false; exprt new_val; if(!string_to_expr_z3(type.subtype(), elem, new_val)) return false; e = with_exprt(old, where, new_val); return true; } else if(value=="false") { e = false_exprt(); return true; } else if(value=="true") { e = true_exprt(); return true; } else if(value.substr(0,8)=="array_of") { // We assume that array_of has only concrete arguments... irep_idt id(value); array_of_mapt::const_iterator fit=array_of_map.begin(); while(fit!=array_of_map.end() && fit->second!=id) fit++; if(fit==array_of_map.end()) return false; e = fit->first; return true; } else if(type.id()==ID_rational) { constant_exprt result; result.type()=rational_typet(); if(value.substr(0,4)=="val!") result.set_value(value.substr(4)); else result.set_value(value); e = result; return true; } return false; }