member_exprt cegis_operand_id(const symbol_tablet &st, const std::string &func_name, const size_t op) { const dereference_exprt instr(cegis_instr(st, func_name)); const std::string member_name(cegis_operand_base_name(op)); const typet member_type(cegis_operand_type()); return member_exprt(instr, member_name, member_type); }
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 path_symex_statet::expand_structs_and_arrays(const exprt &src) { #ifdef DEBUG std::cout << "expand_structs_and_arrays: " << from_expr(var_map.ns, "", src) << '\n'; #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]=expand_structs_and_arrays(new_src); } 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"; std::size_t size_int=integer2size_t(size); array_exprt result(array_type); result.operands().resize(size_int); // split it up into elements for(std::size_t 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]=expand_structs_and_arrays(new_src); } return result; // done } else { // TODO: variable-sized array } } 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"; std::size_t size_int=integer2size_t(size); vector_exprt result(vector_type); exprt::operandst &operands=result.operands(); operands.resize(size_int); // split it up into elements for(std::size_t 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]=expand_structs_and_arrays(new_src); } return result; // done } return src; }
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; }
member_exprt cegis_opcode(const symbol_tablet &st, const std::string &func_name) { const dereference_exprt instr(cegis_instr(st, func_name)); const typet member_type(cegis_opcode_type()); return member_exprt(instr, CEGIS_PROC_OPCODE_MEMBER_NAME, member_type); }