exprt ssa_alias_guard( const exprt &e1, const exprt &e2, const namespacet &ns) { exprt a1=address_canonizer(address_of_exprt(e1), ns); // TODO: We should compare 'base' pointers here because // we have a higher chance that there was no pointer arithmetic // on the base pointer than that the result of the pointer // arithmetic points to a base pointer. // The following hack does that: if(a1.id()==ID_plus) a1=a1.op0(); exprt a2=address_canonizer(address_of_exprt(e2), ns); // in some cases, we can use plain address equality, // as we assume well-aligned-ness mp_integer size1=pointer_offset_size(e1.type(), ns); mp_integer size2=pointer_offset_size(e2.type(), ns); if(size1>=size2) { exprt lhs=a1; exprt rhs=a2; if(ns.follow(rhs.type())!=ns.follow(lhs.type())) rhs=typecast_exprt(rhs, lhs.type()); return equal_exprt(lhs, rhs); } return same_object(a1, a2); }
exprt ssa_alias_guard( const exprt &e1, const exprt &e2, const namespacet &ns) { exprt a1=address_canonizer(address_of_exprt(e1), ns); exprt a2=address_canonizer(address_of_exprt(e2), ns); // in some cases, we can use plain address equality, // as we assume well-aligned-ness mp_integer size1=pointer_offset_size(e1.type(), ns); mp_integer size2=pointer_offset_size(e2.type(), ns); if(size1>=size2) { exprt lhs=a1; exprt rhs=a2; if(ns.follow(rhs.type())!=ns.follow(lhs.type())) rhs=typecast_exprt(rhs, lhs.type()); return equal_exprt(lhs, rhs); } return same_object(a1, a2); }
exprt ssa_alias_value( const exprt &e1, const exprt &e2, const namespacet &ns) { const typet &e1_type=ns.follow(e1.type()); const typet &e2_type=ns.follow(e2.type()); // type matches? if(e1_type==e2_type) return e2; exprt a1=address_canonizer(address_of_exprt(e1), ns); exprt a2=address_canonizer(address_of_exprt(e2), ns); exprt offset1=pointer_offset(a1); // array index possible? if(e2_type.id()==ID_array && e1_type==ns.follow(e2_type.subtype())) { // this assumes well-alignedness mp_integer element_size=pointer_offset_size(e2_type.subtype(), ns); if(element_size==1) return index_exprt(e2, offset1, e1.type()); else if(element_size>1) { exprt index= div_exprt(offset1, from_integer(element_size, offset1.type())); return index_exprt(e2, index, e1.type()); } } byte_extract_exprt byte_extract(byte_extract_id(), e1.type()); byte_extract.op()=e2; byte_extract.offset()=offset1; return byte_extract; }
exprt local_SSAt::read_rhs_rec(const exprt &expr, locationt loc) const { if(expr.id()==ID_side_effect) { throw "unexpected side effect in read_rhs_rec"; } else if(expr.id()==ID_address_of) { address_of_exprt tmp=to_address_of_expr(expr); tmp.object()=read_rhs_address_of_rec(tmp.object(), loc); return address_canonizer(tmp, ns); } else if(expr.id()==ID_dereference) { throw "unexpected dereference in read_rhs_rec"; } else if(expr.id()==ID_index) { const index_exprt &index_expr=to_index_expr(expr); return index_exprt(read_rhs(index_expr.array(), loc), read_rhs(index_expr.index(), loc), expr.type()); } ssa_objectt object(expr, ns); // is it an object identifier? if(!object) { exprt tmp=expr; // copy Forall_operands(it, tmp) *it=read_rhs(*it, loc); return tmp; } // Argument is a struct-typed ssa object? // May need to split up into members. const typet &type=ns.follow(expr.type()); if(type.id()==ID_struct) { // build struct constructor struct_exprt result(expr.type()); const struct_typet &struct_type=to_struct_type(type); const struct_typet::componentst &components=struct_type.components(); result.operands().resize(components.size()); for(struct_typet::componentst::const_iterator it=components.begin(); it!=components.end(); it++) { result.operands()[it-components.begin()]= read_rhs(member_exprt(expr, it->get_name(), it->type()), loc); } return result; } // is this an object we track? if(ssa_objects.objects.find(object)!= ssa_objects.objects.end()) { return read_rhs(object, loc); } else { return name_input(object); } }
exprt address_canonizer( const exprt &address, const namespacet &ns) { assert(ns.follow(address.type()).id()==ID_pointer); if(address.id()==ID_address_of) { const address_of_exprt &address_of_expr= to_address_of_expr(address); const exprt &object=address_of_expr.object(); if(object.id()==ID_dereference) { // &*x ---> x return to_dereference_expr(object).pointer(); } else if(object.id()==ID_member) { // get offset exprt offset=member_offset_expr(to_member_expr(object), ns); // &x.m ---> (&x)+offset address_of_exprt address_of_expr(to_member_expr(object).struct_op()); exprt rec_result=address_canonizer(address_of_expr, ns); // rec. call pointer_typet byte_pointer(unsigned_char_type()); typecast_exprt typecast_expr(rec_result, byte_pointer); plus_exprt sum(typecast_expr, offset); if(sum.type()!=address.type()) sum.make_typecast(address.type()); return sum; } else if(object.id()==ID_index) { // &(x[i]) ---> (&x)+i address_of_exprt address_of_expr(to_index_expr(object).array()); exprt rec_result=address_canonizer(address_of_expr, ns); // rec. call pointer_typet pointer_type; pointer_type.subtype()=object.type(); typecast_exprt typecast_expr(rec_result, pointer_type); plus_exprt sum(typecast_expr, to_index_expr(object).index()); if(sum.type()!=address.type()) sum.make_typecast(address.type()); return sum; } else if(object.id()==ID_symbol && is_iterator(object)) { // address of iterator is dereferenced to a corresponding symbol - // will be bound to real address during analysis symbol_exprt iterator_addr( id2string(to_symbol_expr(object).get_identifier())+"'addr", address.type()); return iterator_addr; } else return address; } else if(address.id()==ID_plus || address.id()==ID_minus) { // one of the operands needs to be a pointer assert(address.operands().size()==2); exprt tmp=address; if(ns.follow(tmp.op0().type()).id()==ID_pointer) { tmp.op0()=address_canonizer(tmp.op0(), ns); return tmp; } else if(ns.follow(tmp.op1().type()).id()==ID_pointer) { tmp.op1()=address_canonizer(tmp.op1(), ns); return tmp; } else return tmp; } else if(address.id()==ID_if) { if_exprt tmp=to_if_expr(address); tmp.true_case()=address_canonizer(tmp.true_case(), ns); tmp.false_case()=address_canonizer(tmp.false_case(), ns); return tmp; } else if(address.id()==ID_typecast) { typecast_exprt tmp=to_typecast_expr(address); // cast from another pointer? if(tmp.op().type().id()==ID_pointer) { tmp.op()=address_canonizer(tmp.op(), ns); return tmp; } return address; } else return address; }