void migrate_list_value(Value* value, Migration* migration) { if (!list_value_may_need_migration(value, migration)) return; touch(value); for (int i=0; i < list_length(value); i++) { Value* element = list_get(value, i); migrate_value(element, migration); } // Migrate type if this is a user-type instance. // Future: We could try to reshape the value if the new type has different fields. Type* newType = migrate_type(value->value_type, migration); if (newType != value->value_type) { if (newType == NULL) newType = TYPES.list; else type_incref(newType); type_decref(value->value_type); value->value_type = newType; } }
Type* migrate_type(Type* type, Block* oldBlock, Block* newBlock) { Migration migration; migration.oldBlock = oldBlock; migration.newBlock = newBlock; return migrate_type(type, &migration); }
bool list_value_may_need_migration(Value* value, Migration* migration) { for (int i=0; i < list_length(value); i++) if (value_may_need_migration(value->index(i), migration)) return true; Type* newType = migrate_type(value->value_type, migration); if (newType != value->value_type) return true; return false; }
expr2tc goto_symext::symex_mem( const bool is_malloc, const expr2tc &lhs, const sideeffect2t &code) { if (is_nil_expr(lhs)) return expr2tc(); // ignore // size type2tc type = code.alloctype; expr2tc size = code.size; bool size_is_one = false; if (is_nil_expr(size)) size_is_one=true; else { cur_state->rename(size); mp_integer i; if (is_constant_int2t(size) && to_constant_int2t(size).as_ulong() == 1) size_is_one = true; } if (is_nil_type(type)) type = char_type2(); else if (is_union_type(type)) { // Filter out creation of instantiated unions. They're now all byte arrays. size_is_one = false; type = char_type2(); } unsigned int &dynamic_counter = get_dynamic_counter(); dynamic_counter++; // value symbolt symbol; symbol.base_name = "dynamic_" + i2string(dynamic_counter) + (size_is_one ? "_value" : "_array"); symbol.name = "symex_dynamic::" + id2string(symbol.base_name); symbol.lvalue = true; typet renamedtype = ns.follow(migrate_type_back(type)); if(size_is_one) symbol.type=renamedtype; else { symbol.type=typet(typet::t_array); symbol.type.subtype()=renamedtype; symbol.type.size(migrate_expr_back(size)); } symbol.type.dynamic(true); symbol.mode="C"; new_context.add(symbol); type2tc new_type; migrate_type(symbol.type, new_type); address_of2tc rhs_addrof(get_empty_type(), expr2tc()); if(size_is_one) { rhs_addrof.get()->type = get_pointer_type(pointer_typet(symbol.type)); rhs_addrof.get()->ptr_obj = symbol2tc(new_type, symbol.name); } else { type2tc subtype; migrate_type(symbol.type.subtype(), subtype); expr2tc sym = symbol2tc(new_type, symbol.name); expr2tc idx_val = zero_ulong; expr2tc idx = index2tc(subtype, sym, idx_val); rhs_addrof.get()->type = get_pointer_type(pointer_typet(symbol.type.subtype())); rhs_addrof.get()->ptr_obj = idx; } expr2tc rhs = rhs_addrof; expr2tc ptr_rhs = rhs; if (!options.get_bool_option("force-malloc-success")) { symbol2tc null_sym(rhs->type, "NULL"); sideeffect2tc choice(get_bool_type(), expr2tc(), expr2tc(), std::vector<expr2tc>(), type2tc(), sideeffect2t::nondet); rhs = if2tc(rhs->type, choice, rhs, null_sym); replace_nondet(rhs); ptr_rhs = rhs; } if (rhs->type != lhs->type) rhs = typecast2tc(lhs->type, rhs); cur_state->rename(rhs); expr2tc rhs_copy(rhs); guardt guard; symex_assign_rec(lhs, rhs, guard); pointer_object2tc ptr_obj(pointer_type2(), ptr_rhs); track_new_pointer(ptr_obj, new_type); dynamic_memory.push_back(allocated_obj(rhs_copy, cur_state->guard, !is_malloc)); return rhs_addrof->ptr_obj; }
void goto_inlinet::parameter_assignments( const locationt &location, const code_typet &code_type, const exprt::operandst &arguments, goto_programt &dest) { // iterates over the operands exprt::operandst::const_iterator it1=arguments.begin(); goto_programt::local_variablest local_variables; const code_typet::argumentst &argument_types= code_type.arguments(); // iterates over the types of the arguments for(code_typet::argumentst::const_iterator it2=argument_types.begin(); it2!=argument_types.end(); it2++) { // if you run out of actual arguments there was a mismatch if(it1==arguments.end()) { err_location(location); throw "function call: not enough arguments"; } const exprt &argument=static_cast<const exprt &>(*it2); // this is the type the n-th argument should be const typet &arg_type=ns.follow(argument.type()); const irep_idt &identifier=argument.cmt_identifier(); if(identifier=="") { err_location(location); throw "no identifier for function argument"; } { const symbolt &symbol=ns.lookup(identifier); goto_programt::targett decl=dest.add_instruction(); decl->make_other(); exprt tmp = code_declt(symbol_expr(symbol)); migrate_expr(tmp, decl->code); decl->location=location; decl->function=location.get_function(); decl->local_variables=local_variables; } local_variables.insert(identifier); // nil means "don't assign" if(it1->is_nil()) { } else { // this is the actual parameter exprt actual(*it1); // it should be the same exact type type2tc arg_type_2, actual_type_2; migrate_type(arg_type, arg_type_2); migrate_type(actual.type(), actual_type_2); if (!base_type_eq(arg_type_2, actual_type_2, ns)) { const typet &f_argtype = ns.follow(arg_type); const typet &f_acttype = ns.follow(actual.type()); // we are willing to do some conversion if((f_argtype.id()=="pointer" && f_acttype.id()=="pointer") || (f_argtype.is_array() && f_acttype.id()=="pointer" && f_argtype.subtype()==f_acttype.subtype())) { actual.make_typecast(arg_type); } else if((f_argtype.id()=="signedbv" || f_argtype.id()=="unsignedbv" || f_argtype.is_bool()) && (f_acttype.id()=="signedbv" || f_acttype.id()=="unsignedbv" || f_acttype.is_bool())) { actual.make_typecast(arg_type); } else { err_location(location); str << "function call: argument `" << identifier << "' type mismatch: got " << from_type(ns, identifier, it1->type()) << ", expected " << from_type(ns, identifier, arg_type); throw 0; } } // adds an assignment of the actual parameter to the formal parameter code_assignt assignment(symbol_exprt(identifier, arg_type), actual); assignment.location()=location; dest.add_instruction(ASSIGN); dest.instructions.back().location=location; migrate_expr(assignment, dest.instructions.back().code); dest.instructions.back().local_variables=local_variables; dest.instructions.back().function=location.get_function(); } it1++; } if(it1!=arguments.end()) { // too many arguments -- we just ignore that, no harm done } }