void java_record_outputs( const symbolt &function, const exprt::operandst &main_arguments, code_blockt &init_code, symbol_tablet &symbol_table) { const code_typet::parameterst ¶meters= to_code_type(function.type).parameters(); exprt::operandst result; result.reserve(parameters.size()+1); bool has_return_value= to_code_type(function.type).return_type()!=empty_typet(); if(has_return_value) { // record return value codet output(ID_output); output.operands().resize(2); const symbolt &return_symbol=symbol_table.lookup("return'"); output.op0()= address_of_exprt( index_exprt( string_constantt(return_symbol.base_name), from_integer(0, index_type()))); output.op1()=return_symbol.symbol_expr(); output.add_source_location()=function.location; init_code.move_to_operands(output); } for(std::size_t param_number=0; param_number<parameters.size(); param_number++) { const symbolt &p_symbol= symbol_table.lookup(parameters[param_number].get_identifier()); if(p_symbol.type.id()==ID_pointer) { // record as an output codet output(ID_output); output.operands().resize(2); output.op0()= address_of_exprt( index_exprt( string_constantt(p_symbol.base_name), from_integer(0, index_type()))); output.op1()=main_arguments[param_number]; output.add_source_location()=function.location; init_code.move_to_operands(output); } } }
T* alloc() { // I need to atomically advance freelisthead to the freelist[head] queue_ref_type oldhead; queue_ref_type newhead; do { oldhead.combined = freelisthead.combined; if (oldhead.q.val == index_type(-1)) return new T; // ran out of pool elements newhead.q.val = freelist[oldhead.q.val]; newhead.q.counter = oldhead.q.counter + 1; } while(!atomic_compare_and_swap(freelisthead.combined, oldhead.combined, newhead.combined)); freelist[oldhead.q.val] = index_type(-1); return &(data[oldhead.q.val]); }
void free(T* p) { // is this from the pool? // if it is below the pointer limits if (__unlikely__(p < lower_ptrlimit || p > upper_ptrlimit)) { delete p; return; } index_type cur = index_type(p - &(data[0])); // prepare for free list insertion // I need to atomically set freelisthead == cur // and freelist[cur] = freelisthead queue_ref_type oldhead; queue_ref_type newhead; do{ oldhead.combined = freelisthead.combined; freelist[cur] = oldhead.q.val; newhead.q.val = cur; newhead.q.counter = oldhead.q.counter + 1; // now try to atomically move freelisthead } while(!atomic_compare_and_swap(freelisthead.combined, oldhead.combined, newhead.combined)); }
enumerator(succinct::bit_vector const& bv, uint64_t offset, uint64_t universe, uint64_t n, global_parameters const& params) { auto sparams = strict_params(params); if (all_ones_sequence::bitsize(params, universe, n) == 0) { m_type = all_ones; } else { m_type = index_type(bv.get_word56(offset) & ((uint64_t(1) << type_bits) - 1)); } switch (m_type) { case elias_fano: m_ef_enumerator = strict_elias_fano::enumerator(bv, offset + type_bits, universe, n, sparams); break; case ranked_bitvector: m_rb_enumerator = compact_ranked_bitvector::enumerator(bv, offset + type_bits, universe, n, sparams); break; case all_ones: m_ao_enumerator = all_ones_sequence::enumerator(bv, offset + type_bits, universe, n, sparams); break; default: throw std::invalid_argument("Unsupported type"); } }
void pool::deallocate(index_type index) { if (!owns(index)) throw allocate_error(allocate_errc::invalid_ptr); *(index_type*)pointer(index) = index_type(head_); head_ = index; nfree_++; }
code_function_callt function_to_call( symbol_tablet &symbol_table, const irep_idt &id, const irep_idt &argument) { // already there? symbol_tablet::symbolst::const_iterator s_it= symbol_table.symbols.find(id); if(s_it==symbol_table.symbols.end()) { // not there pointer_typet p(char_type()); p.subtype().set(ID_C_constant, true); code_typet function_type; function_type.return_type()=empty_typet(); function_type.parameters().push_back( code_typet::parametert(p)); symbolt new_symbol; new_symbol.name=id; new_symbol.base_name=id; new_symbol.type=function_type; symbol_table.move(new_symbol); s_it=symbol_table.symbols.find(id); assert(s_it!=symbol_table.symbols.end()); } // signature is expected to be // (type *) -> ... if(s_it->second.type.id()!=ID_code || to_code_type(s_it->second.type).parameters().size()!=1 || to_code_type(s_it->second.type).parameters()[0].type().id()!=ID_pointer) { std::string error="function `"+id2string(id)+"' has wrong signature"; throw error; } string_constantt function_id_string(argument); code_function_callt call; call.lhs().make_nil(); call.function()= symbol_exprt(s_it->second.name, s_it->second.type); call.arguments().resize(1); call.arguments()[0]= typecast_exprt( address_of_exprt( index_exprt( function_id_string, from_integer(0, index_type()))), to_code_type(s_it->second.type).parameters()[0].type()); return call; }
pool::index_type pool::allocate_index() { index_type i = index_type(head_); if (i == nullidx) return nullidx; head_ = *(index_type*)pointer(i); nfree_--; return i; }
void c_typecastt::implicit_typecast_arithmetic( exprt &expr, c_typet c_type) { typet new_type; const typet &expr_type=ns.follow(expr.type()); switch(c_type) { case PTR: if(expr_type.id()==ID_array) { new_type.id(ID_pointer); new_type.subtype()=expr_type.subtype(); break; } return; case BOOL: new_type=bool_typet(); break; case CHAR: assert(false); // should always be promoted to int case UCHAR: assert(false); // should always be promoted to int case SHORT: assert(false); // should always be promoted to int case USHORT: assert(false); // should always be promoted to int case INT: new_type=int_type(); break; case UINT: new_type=uint_type(); break; case LONG: new_type=long_int_type(); break; case ULONG: new_type=long_uint_type(); break; case LONGLONG: new_type=long_long_int_type(); break; case ULONGLONG: new_type=long_long_uint_type(); break; case SINGLE: new_type=float_type(); break; case DOUBLE: new_type=double_type(); break; case LONGDOUBLE: new_type=long_double_type(); break; case RATIONAL: new_type=rational_typet(); break; case REAL: new_type=real_typet(); break; case INTEGER: new_type=integer_typet(); break; case COMPLEX: return; // do nothing default: return; } if(new_type!=expr_type) { if(new_type.id()==ID_pointer && expr_type.id()==ID_array) { exprt index_expr(ID_index, expr_type.subtype()); index_expr.reserve_operands(2); index_expr.move_to_operands(expr); index_expr.copy_to_operands(gen_zero(index_type())); expr=exprt(ID_address_of, new_type); expr.move_to_operands(index_expr); } else do_typecast(expr, new_type); } }
std::set<symbol_exprt> concurrency_aware_abstractort::targets_of_lvalue(const exprt& lvalue, goto_programt::const_targett program_location) { std::set<symbol_exprt> result; if(lvalue.id() == ID_index) { exprt array_name = lvalue.op0(); if(array_name.id() == ID_symbol) { result.insert(to_symbol_expr(array_name)); } else { return targets_of_lvalue(array_name, program_location); } } else if(lvalue.id() == ID_member) { assert(lvalue.operands().size() == 1); return targets_of_lvalue(lvalue.op0(), program_location); } else if(lvalue.id() == ID_symbol) { result.insert(to_symbol_expr(lvalue)); } else if(lvalue.id() == ID_dereference) { // We would like to add anything the pointer can point to, // but not the pointer itself value_setst::valuest value_set; pointer_info.get_values(program_location, lvalue.op0(), value_set); for(value_setst::valuest::iterator it = value_set.begin(); it != value_set.end(); it++) { if(it->id() != ID_object_descriptor) { // TODO: We may need to deal with this situation more carefully continue; } object_descriptor_exprt& object_descriptor = to_object_descriptor_expr(*it); if(object_descriptor.offset() != from_integer(0, index_type())) { std::cout << "Pointer " << from_expr(lvalue.op0()) << " can point to " << from_expr(*it) << " at line " << program_location->location.get_line() << ", we cannot handle this" << std::endl; exit(1); } if(object_descriptor.object().id() != ID_symbol) { std::cout << "Pointer " << from_expr(lvalue.op0()) << " can point to " << from_expr(*it) << " at line " << program_location->location.get_line() << ", we cannot handle this" << std::endl; exit(1); } result.insert(to_symbol_expr(object_descriptor.object())); } } else { std::cout << "Cannot currently handle lvalue: " << from_expr(lvalue) << std::endl; assert(false); } return result; }
void goto_symext::process_array_expr_rec( exprt &expr, const typet &type) const { if(expr.id()==ID_if) { if_exprt &if_expr=to_if_expr(expr); process_array_expr_rec(if_expr.true_case(), type); process_array_expr_rec(if_expr.false_case(), type); } else if(expr.id()==ID_index) { // strip index index_exprt &index_expr=to_index_expr(expr); exprt tmp=index_expr.array(); expr.swap(tmp); } else if(expr.id()==ID_typecast) { // strip exprt tmp=to_typecast_expr(expr).op0(); expr.swap(tmp); process_array_expr_rec(expr, type); } else if(expr.id()==ID_address_of) { // strip exprt tmp=to_address_of_expr(expr).op0(); expr.swap(tmp); process_array_expr_rec(expr, type); } else if(expr.id()==ID_symbol && expr.get_bool(ID_C_SSA_symbol) && to_ssa_expr(expr).get_original_expr().id()==ID_index) { const ssa_exprt &ssa=to_ssa_expr(expr); const index_exprt &index_expr=to_index_expr(ssa.get_original_expr()); exprt tmp=index_expr.array(); expr.swap(tmp); } else Forall_operands(it, expr) process_array_expr_rec(*it, it->type()); if(!base_type_eq(expr.type(), type, ns)) { byte_extract_exprt be(byte_extract_id()); be.type()=type; be.op()=expr; be.offset()=gen_zero(index_type()); expr.swap(be); } }
exprt dereferencet::dereference_rec( const exprt &address, const exprt &offset, const typet &type) { 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(); return read_object(object, offset, type); } else if(address.id()==ID_typecast) { const typecast_exprt &typecast_expr=to_typecast_expr(address); return dereference_typecast(typecast_expr, offset, type); } else if(address.id()==ID_plus) { // pointer arithmetic if(address.operands().size()<2) throw "plus with less than two operands"; return dereference_plus(address, offset, type); } else if(address.id()==ID_if) { const if_exprt &if_expr=to_if_expr(address); return dereference_if(if_expr, offset, type); } else if(address.id()==ID_constant) { const typet result_type=ns.follow(address.type()).subtype(); // pointer-typed constant if(to_constant_expr(address).get_value()==ID_NULL) // NULL { // we turn this into (type *)0 exprt zero=gen_zero(index_type()); return dereference_rec( typecast_exprt(zero, address.type()), offset, type); } else throw "dereferencet: unexpected pointer constant "+address.pretty(); } else { throw "failed to dereference `"+address.id_string()+"'"; } }
// --------------------------------------------------------------------------- // synthesizeNext // --------------------------------------------------------------------------- //! Synthesize next block of samples of the partials. The synthesizer //! will resize the inner buffer as necessary. Previous contents of the buffer //! are overwritten. //! //! \param sample Number of samples to synthesize. //! \return Nothing. //! \post Internal state of synthesizer changes - it is ready to synthesize //! next block of samples starting at 'previous count of samples' + samples. void RealTimeSynthesizer::synthesizeNext( int samples ) noexcept { //TODO: check processedSamples overflow processedSamples += samples;// for performance reason this is computed at the beginning PartialStruct *partial; // prepare buffer for new data if (buffer->capacity() < samples) buffer->reserve(samples); memset(buffer->data(), 0, samples * sizeof(decltype(buffer->data()))); // process partials being processed int size = partialsBeingProcessed.size(); for (int i = 0; i < size; i++) { partial = partialsBeingProcessed.front(); synthesize( *partial, buffer->data(), samples ); if ( partial->state.lastBreakpointIdx < partial->numBreakpoints - 1) partialsBeingProcessed.push( partial ); partialsBeingProcessed.pop(); } // partials to be processed int partialSize = partials.size(); for (; partialIdx < partialSize; partialIdx++) { partial = &(partials[partialIdx]); // setup partial for synthesis partial->state.currentSamp = index_type( (partial->startTime * m_srateHz) + 0.5 ); // cheap rounding if (partial->state.currentSamp > processedSamples) break; partial->state.lastBreakpointIdx = PartialStruct::NoBreakpointProcessed; partial->state.envelope = partial->breakpoints[0].second; partial->state.breakpointFinished = true; // cache the previous frequency (in Hz) so that it can be used to reset the phase when necessary partial->state.prevFrequency = m_osc.frequencyScaling() * partial->breakpoints[1].second._frequency;// 0 is null breakpoint int sampleCount = processedSamples - partial->state.currentSamp; // how much sample to be processed during this call int sampleDelta = samples - sampleCount; // delta when partial should start synthesize( *partial, buffer->data() + sampleDelta, sampleCount ); if ( partial->state.lastBreakpointIdx < partial->numBreakpoints - 1) partialsBeingProcessed.push(partial); } }
bool value_sett::eval_pointer_offset( exprt &expr, const namespacet &ns) const { bool mod=false; if(expr.id()==ID_pointer_offset) { assert(expr.operands().size()==1); object_mapt reference_set; get_value_set(expr.op0(), reference_set, ns, true); exprt new_expr; mp_integer previous_offset=0; const object_map_dt &object_map=reference_set.read(); for(object_map_dt::const_iterator it=object_map.begin(); it!=object_map.end(); it++) if(!it->second.offset_is_set) return false; else { const exprt &object=object_numbering[it->first]; mp_integer ptr_offset=compute_pointer_offset(object, ns); if(ptr_offset<0) return false; ptr_offset+=it->second.offset; if(mod && ptr_offset!=previous_offset) return false; new_expr=from_integer(ptr_offset, index_type()); previous_offset=ptr_offset; mod=true; } if(mod) expr.swap(new_expr); } else { Forall_operands(it, expr) mod=eval_pointer_offset(*it, ns) || mod; } return mod; }
exprt dereferencet::operator()(const exprt &pointer) { if(pointer.type().id()!=ID_pointer) throw "dereference expected pointer type, but got "+ pointer.type().pretty(); // type of the object const typet &type=pointer.type().subtype(); #ifdef DEBUG std::cout << "DEREF: " << from_expr(ns, "", pointer) << std::endl; #endif return dereference_rec( pointer, gen_zero(index_type()), // offset type); }
void c_typecastt::do_typecast(exprt &expr, const typet &type) { // special case: array -> pointer is actually // something like address_of const typet &expr_type=ns.follow(expr.type()); if(expr_type.id()==ID_array) { index_exprt index; index.array()=expr; index.index()=gen_zero(index_type()); index.type()=expr_type.subtype(); expr=address_of_exprt(index); if(ns.follow(expr.type())!=ns.follow(type)) expr.make_typecast(type); return; } if(expr_type!=type) { // C booleans are special: we compile to ?0:1 if(type.get(ID_C_c_type)==ID_bool) { if(expr_type.id()==ID_bool) // bool -> _Bool { exprt result=if_exprt(expr, gen_one(type), gen_zero(type)); expr.swap(result); } else // * -> _Bool { equal_exprt equal_zero(expr, gen_zero(expr_type)); exprt result=if_exprt(equal_zero, gen_zero(type), gen_one(type)); expr.swap(result); } } else { expr.make_typecast(type); } } }
exprt value_sett::to_expr(object_map_dt::const_iterator it) const { const exprt &object=object_numbering[it->first]; if(object.id()==ID_invalid || object.id()==ID_unknown) return object; object_descriptor_exprt od; od.object()=object; if(it->second.offset_is_set) od.offset()=from_integer(it->second.offset, index_type()); od.type()=od.object().type(); return od; }
void reset_pool(size_t poolsize) { if (poolsize == 0) { data.clear(); freelist.clear(); lower_ptrlimit = NULL; upper_ptrlimit = NULL; } else { data.resize(poolsize); freelist.resize(poolsize); for (index_type i = 0;i < freelist.size(); ++i) { freelist[i] = i + 1; } freelist[freelist.size() - 1] = index_type(-1); lower_ptrlimit = &(data[0]); upper_ptrlimit = &(data[data.size() - 1]); } freelisthead.q.val = 0; freelisthead.q.counter = 0; }
array_exprt string_constantt::to_array_expr() const { const std::string &str=get_string(ID_value); unsigned string_size=str.size()+1; // we add the zero const typet &char_type=type().subtype(); bool char_is_unsigned=char_type.id()==ID_unsignedbv; exprt size=from_integer(string_size, index_type()); array_exprt dest; dest.type()=array_typet(); dest.type().subtype()=char_type; dest.type().set(ID_size, size); dest.operands().resize(string_size); exprt::operandst::iterator it=dest.operands().begin(); for(unsigned i=0; i<string_size; i++, it++) { // Are we at the end? Do implicit zero. int ch=i==string_size-1?0:str[i]; if(char_is_unsigned) ch=(unsigned char)ch; exprt &op=*it; op=from_integer(ch, char_type); if(ch>=32 && ch<=126) { std::string ch_str="'"; if(ch=='\'' || ch=='\\') ch_str+='\\'; ch_str+=(char)ch; ch_str+="'"; op.set(ID_C_cformat, ch_str); } } return dest; }
void c_typecastt::do_typecast(exprt &expr, const typet &dest_type) { // special case: array -> pointer is actually // something like address_of const typet &src_type=ns.follow(expr.type()); if(src_type.id()==ID_array) { index_exprt index; index.array()=expr; index.index()=gen_zero(index_type()); index.type()=src_type.subtype(); expr=address_of_exprt(index); if(ns.follow(expr.type())!=ns.follow(dest_type)) expr.make_typecast(dest_type); return; } if(src_type!=dest_type) { // C booleans are special; we produce the // explicit comparision with zero. // Note that this requires ieee_float_notequal // in case of floating-point numbers. if(dest_type.get(ID_C_c_type)==ID_bool) { expr=is_not_zero(expr, ns); expr.make_typecast(dest_type); } else if(dest_type.id()==ID_bool) { expr=is_not_zero(expr, ns); } else { expr.make_typecast(dest_type); } } }
array_exprt string_constantt::to_array_expr() const { const std::string &str=get_string(ID_value); unsigned string_size=str.size()+1; // zero const typet &char_type=type().subtype(); bool char_is_unsigned=char_type.id()==ID_unsignedbv; exprt size=from_integer(string_size, index_type()); array_exprt dest; dest.type()=array_typet(); dest.type().subtype()=char_type; dest.type().set(ID_size, size); dest.operands().resize(string_size); exprt::operandst::iterator it=dest.operands().begin(); for(unsigned i=0; i<string_size; i++, it++) { int ch=i==string_size-1?0:str[i]; if(char_is_unsigned) ch=(unsigned char)ch; exprt &op=*it; op=from_integer(ch, char_type); if(ch>=32 && ch<=126) { char ch_str[2]; ch_str[0]=ch; ch_str[1]=0; op.set(ID_C_cformat, "'"+std::string(ch_str)+"'"); } } return dest; }
bool ssa_may_alias( const exprt &e1, const exprt &e2, const namespacet &ns) { #ifdef DEBUG std::cout << "MAY ALIAS1 " << from_expr(ns, "", e1) << " " << from_expr(ns, "", e2) << "\n"; #endif // The same? if(e1==e2) return true; // Both symbol? if(e1.id()==ID_symbol && e2.id()==ID_symbol) { return to_symbol_expr(e1).get_identifier()== to_symbol_expr(e2).get_identifier(); } // __CPROVER symbols if(e1.id()==ID_symbol && has_prefix( id2string(to_symbol_expr(e1).get_identifier()), CPROVER_PREFIX)) return false; if(e2.id()==ID_symbol && has_prefix( id2string(to_symbol_expr(e2).get_identifier()), CPROVER_PREFIX)) return false; if(e1.id()==ID_symbol && has_suffix( id2string(to_symbol_expr(e1).get_identifier()), "#return_value")) return false; if(e2.id()==ID_symbol && has_suffix( id2string(to_symbol_expr(e2).get_identifier()), "#return_value")) return false; // Both member? if(e1.id()==ID_member && e2.id()==ID_member) { const member_exprt &m1=to_member_expr(e1); const member_exprt &m2=to_member_expr(e2); // same component? if(m1.get_component_name()!=m2.get_component_name()) return false; return ssa_may_alias(m1.struct_op(), m2.struct_op(), ns); } // Both index? if(e1.id()==ID_index && e2.id()==ID_index) { const index_exprt &i1=to_index_expr(e1); const index_exprt &i2=to_index_expr(e2); return ssa_may_alias(i1.array(), i2.array(), ns); } const typet &t1=ns.follow(e1.type()); const typet &t2=ns.follow(e2.type()); // If one is an array and the other not, consider the elements if(t1.id()==ID_array && t2.id()!=ID_array) if(ssa_may_alias( index_exprt(e1, gen_zero(index_type()), t1.subtype()), e2, ns)) return true; if(t2.id()==ID_array && t2.id()!=ID_array) if(ssa_may_alias( e1, index_exprt(e2, gen_zero(index_type()), t2.subtype()), ns)) return true; // Pointers only alias with other pointers, // which is a restriction. if(t1.id()==ID_pointer) return t2.id()==ID_pointer; if(t2.id()==ID_pointer) return t1.id()==ID_pointer; // Is one a scalar pointer? if(e1.id()==ID_dereference && (t1.id()==ID_signedbv || t1.id()==ID_unsignedbv || t1.id()==ID_floatbv)) return true; if(e2.id()==ID_dereference && (t2.id()==ID_signedbv || t2.id()==ID_unsignedbv || t1.id()==ID_floatbv)) return true; // Is one a pointer? if(e1.id()==ID_dereference || e2.id()==ID_dereference) { // look at the types // same type? if(base_type_eq(t1, t2, ns)) { return true; } // should consider further options, e.g., struct prefixes return false; } return false; // both different objects }
void cvc_convt::convert_address_of_rec(const exprt &expr) { if(expr.id()==ID_symbol || expr.id()==ID_constant || expr.id()==ID_string_constant) { out << "(# object:=" << pointer_logic.add_object(expr) << ", offset:=" << bin_zero(config.ansi_c.pointer_width) << " #)"; } else if(expr.id()==ID_index) { if(expr.operands().size()!=2) throw "index takes two operands"; const exprt &array=expr.op0(); const exprt &index=expr.op1(); if(index.is_zero()) { if(array.type().id()==ID_pointer) convert_expr(array); else if(array.type().id()==ID_array) convert_address_of_rec(array); else assert(false); } else { out << "(LET P: "; out << cvc_pointer_type(); out << " = "; if(array.type().id()==ID_pointer) convert_expr(array); else if(array.type().id()==ID_array) convert_address_of_rec(array); else assert(false); out << " IN P WITH .offset:=BVPLUS(" << config.ansi_c.pointer_width << ", P.offset, "; convert_expr(index); out << "))"; } } else if(expr.id()==ID_member) { if(expr.operands().size()!=1) throw "member takes one operand"; const exprt &struct_op=expr.op0(); out << "(LET P: "; out << cvc_pointer_type(); out << " = "; convert_address_of_rec(struct_op); const irep_idt &component_name= to_member_expr(expr).get_component_name(); mp_integer offset=member_offset( to_struct_type(struct_op.type()), component_name, ns); typet index_type(ID_unsignedbv); index_type.set(ID_width, config.ansi_c.pointer_width); exprt index=from_integer(offset, index_type); out << " IN P WITH .offset:=BVPLUS(" << config.ansi_c.pointer_width << ", P.offset, "; convert_expr(index); out << "))"; } else throw "don't know how to take address of: "+expr.id_string(); }
std::set<symbol_exprt> locations_of_expression_rec(const predicatet& phi, const goto_programt::const_targett program_location, value_set_analysist& pointer_info, const namespacet& ns) { if(phi.id()==ID_address_of) { // Addresses are constant -- don't need to read the symbol whose address we are taking return std::set<symbol_exprt>(); } if(phi.id()==ID_constant) { // No symbols associated with a constant return std::set<symbol_exprt>(); } if(phi.id()==ID_symbol) { std::set<symbol_exprt> result; result.insert(to_symbol_expr(phi)); return result; } if(phi.id()==ID_dereference) { // We would like to add the pointer itself (which for now we require to be a variable) // and anything it can point to std::set<symbol_exprt> result; result = locations_of_expression_rec(phi.op0(), program_location, pointer_info, ns); // if we have *p, we insert the locations of p itself value_setst::valuest value_set; pointer_info.get_values(program_location, phi.op0(), value_set); for(value_setst::valuest::iterator it = value_set.begin(); it != value_set.end(); it++) { if(it->id() != ID_object_descriptor) { // TODO: We may need to deal with this situation more carefully continue; } object_descriptor_exprt& object_descriptor = to_object_descriptor_expr(*it); if(object_descriptor.object().id() == "NULL-object") { // No locations associated with NULL continue; } if(object_descriptor.offset() != from_integer(0, index_type())) { std::cout << "(*) Warning: pointer " << from_expr(ns, "", phi.op0()) << " can point to " << from_expr(ns, "", *it) << " at " << program_location->location << ", this needs further investigation" << std::endl; continue; } if(object_descriptor.object().id() != ID_symbol) { std::cout << "(**) Warning: pointer " << from_expr(ns, "", phi.op0()) << " can point to " << from_expr(ns, "", *it) << " at " << program_location->location << ", this needs further investigation" << std::endl; continue; } result.insert(to_symbol_expr(object_descriptor.object())); } return result; } if(phi.id()=="invalid-pointer" || phi.id()=="pointer_arithmetic" || phi.id()=="pointer_difference") { std::cout << "(***) Warning: cannot yet handle " << from_expr(ns, "", phi) << ", ignoring it" << std::endl; return std::set<symbol_exprt>(); } { /* Default case: iterate through the operands of the expression, adding all locations referenced therein */ std::set<symbol_exprt> result; for(unsigned int i = 0; i < phi.operands().size(); i++) { std::set<symbol_exprt> symbols_i = locations_of_expression_rec(phi.operands()[i], program_location, pointer_info, ns); for(std::set<symbol_exprt>::iterator it = symbols_i.begin(); it != symbols_i.end(); it++) { result.insert(*it); } } return result; } }
void c_typecheck_baset::typecheck_compound_type(struct_union_typet &type) { struct_union_typet::componentst &components=type.components(); // mark bit-fields for(struct_union_typet::componentst::iterator it=components.begin(); it!=components.end(); it++) if(it->type().id()==ID_c_bitfield) { it->set_is_bit_field(true); typet tmp=it->type().subtype(); typecheck_type(tmp); it->set_bit_field_type(tmp); } // check subtypes for(struct_union_typet::componentst::iterator it=components.begin(); it!=components.end(); it++) typecheck_type(it->type()); unsigned anon_member_counter=0; // scan for anonymous members, and name them for(struct_union_typet::componentst::iterator it=components.begin(); it!=components.end(); it++) { if(it->get_name()!=irep_idt()) continue; it->set_name("$anon"+i2string(anon_member_counter++)); it->set_anonymous(true); } // scan for duplicate members { hash_set_cont<irep_idt, irep_id_hash> members; for(struct_union_typet::componentst::iterator it=components.begin(); it!=components.end(); it++) { if(!members.insert(it->get_name()).second) { // we do nothing (as gcc won't complain) } } } // We allow an incomplete (C99) array as _last_ member! // Zero-length is allowed everywhere. if(type.id()==ID_struct) { for(struct_union_typet::componentst::iterator it=components.begin(); it!=components.end(); it++) { typet &type=it->type(); if(type.id()==ID_array && to_array_type(type).is_incomplete()) { // needs to be last member if(it!=--components.end()) { err_location(*it); throw "flexible struct member must be last member"; } // make it zero-length type.id(ID_array); type.set(ID_size, gen_zero(index_type())); } } } // we may add some minimal padding inside structs (not unions) // unless there is an attribute that says that the struct is // 'packed' if(type.id()==ID_struct) add_padding(to_struct_type(type), *this); // finally, check _Static_assert inside the compound for(struct_union_typet::componentst::iterator it=components.begin(); it!=components.end(); ) // no it++ { if(it->id()==ID_code && it->get(ID_statement)==ID_static_assert) { assert(it->operands().size()==2); exprt &assertion=it->op0(); typecheck_expr(assertion); typecheck_expr(it->op1()); assertion.make_typecast(bool_typet()); make_constant(assertion); if(assertion.is_false()) { err_location(*it); throw "failed _Static_assert"; } else if(!assertion.is_true()) { // should warn/complain } it=components.erase(it); } else it++; } }
void c_typecheck_baset::typecheck_compound_body( struct_union_typet &type) { struct_union_typet::componentst &components=type.components(); struct_union_typet::componentst old_components; old_components.swap(components); // We get these as declarations! for(auto &decl : old_components) { // the arguments are member declarations or static assertions assert(decl.id()==ID_declaration); ansi_c_declarationt &declaration= to_ansi_c_declaration(static_cast<exprt &>(decl)); if(declaration.get_is_static_assert()) { struct_union_typet::componentt new_component; new_component.id(ID_static_assert); new_component.add_source_location()=declaration.source_location(); new_component.operands().swap(declaration.operands()); assert(new_component.operands().size()==2); components.push_back(new_component); } else { // do first half of type typecheck_type(declaration.type()); make_already_typechecked(declaration.type()); for(const auto &declarator : declaration.declarators()) { struct_union_typet::componentt new_component; new_component.add_source_location()= declarator.source_location(); new_component.set(ID_name, declarator.get_base_name()); new_component.set(ID_pretty_name, declarator.get_base_name()); new_component.type()=declaration.full_type(declarator); typecheck_type(new_component.type()); if(!is_complete_type(new_component.type()) && (new_component.type().id()!=ID_array || !to_array_type(new_component.type()).is_incomplete())) { error().source_location=new_component.type().source_location(); error() << "incomplete type not permitted here" << eom; throw 0; } components.push_back(new_component); } } } unsigned anon_member_counter=0; // scan for anonymous members, and name them for(auto &member : components) { if(member.get_name()!=irep_idt()) continue; member.set_name("$anon"+std::to_string(anon_member_counter++)); member.set_anonymous(true); } // scan for duplicate members { std::unordered_set<irep_idt, irep_id_hash> members; for(struct_union_typet::componentst::iterator it=components.begin(); it!=components.end(); it++) { if(!members.insert(it->get_name()).second) { error().source_location=it->source_location(); error() << "duplicate member '" << it->get_name() << '\'' << eom; throw 0; } } } // We allow an incomplete (C99) array as _last_ member! // Zero-length is allowed everywhere. if(type.id()==ID_struct || type.id()==ID_union) { for(struct_union_typet::componentst::iterator it=components.begin(); it!=components.end(); it++) { typet &c_type=it->type(); if(c_type.id()==ID_array && to_array_type(c_type).is_incomplete()) { // needs to be last member if(type.id()==ID_struct && it!=--components.end()) { error().source_location=it->source_location(); error() << "flexible struct member must be last member" << eom; throw 0; } // make it zero-length c_type.id(ID_array); c_type.set(ID_size, from_integer(0, index_type())); } } } // We may add some minimal padding inside and at // the end of structs and // as additional member for unions. if(type.id()==ID_struct) add_padding(to_struct_type(type), *this); else if(type.id()==ID_union) add_padding(to_union_type(type), *this); // Now remove zero-width bit-fields, these are just // for adjusting alignment. for(struct_typet::componentst::iterator it=components.begin(); it!=components.end(); ) // blank { if(it->type().id()==ID_c_bit_field && to_c_bit_field_type(it->type()).get_width()==0) it=components.erase(it); else it++; } // finally, check _Static_assert inside the compound for(struct_union_typet::componentst::iterator it=components.begin(); it!=components.end(); ) // no it++ { if(it->id()==ID_static_assert) { assert(it->operands().size()==2); exprt &assertion=it->op0(); typecheck_expr(assertion); typecheck_expr(it->op1()); assertion.make_typecast(bool_typet()); make_constant(assertion); if(assertion.is_false()) { error().source_location=it->source_location(); error() << "failed _Static_assert" << eom; throw 0; } else if(!assertion.is_true()) { // should warn/complain } it=components.erase(it); } else it++; } }
void string_instrumentationt::invalidate_buffer( goto_programt &dest, goto_programt::const_targett target, const exprt &buffer, const typet &buf_type, const mp_integer &limit) { irep_idt cntr_id="string_instrumentation::$counter"; if(symbol_table.symbols.find(cntr_id)==symbol_table.symbols.end()) { symbolt new_symbol; new_symbol.base_name="$counter"; new_symbol.pretty_name=new_symbol.base_name; new_symbol.name=cntr_id; new_symbol.mode=ID_C; new_symbol.type=size_type(); new_symbol.is_state_var=true; new_symbol.is_lvalue=true; new_symbol.is_static_lifetime=true; symbol_table.move(new_symbol); } const symbolt &cntr_sym=ns.lookup(cntr_id); // create a loop that runs over the buffer // and invalidates every element goto_programt::targett init=dest.add_instruction(ASSIGN); init->location=target->location; init->code=code_assignt(cntr_sym.symbol_expr(), gen_zero(cntr_sym.type)); goto_programt::targett check=dest.add_instruction(); check->location=target->location; goto_programt::targett invalidate=dest.add_instruction(ASSIGN); invalidate->location=target->location; goto_programt::targett increment=dest.add_instruction(ASSIGN); increment->location=target->location; exprt plus(ID_plus, unsigned_int_type()); plus.copy_to_operands(cntr_sym.symbol_expr()); plus.copy_to_operands(gen_one(unsigned_int_type())); increment->code=code_assignt(cntr_sym.symbol_expr(), plus); goto_programt::targett back=dest.add_instruction(); back->location=target->location; back->make_goto(check); back->guard=true_exprt(); goto_programt::targett exit=dest.add_instruction(); exit->location=target->location; exit->make_skip(); exprt cnt_bs, bufp; if(buf_type.id()==ID_pointer) bufp = buffer; else { index_exprt index; index.array()=buffer; index.index()=gen_zero(index_type()); index.type()=buf_type.subtype(); bufp = address_of_exprt(index); } exprt deref(ID_dereference, buf_type.subtype()); exprt b_plus_i(ID_plus, bufp.type()); b_plus_i.copy_to_operands(bufp); b_plus_i.copy_to_operands(cntr_sym.symbol_expr()); deref.copy_to_operands(b_plus_i); check->make_goto(exit); if(limit==0) check->guard= binary_relation_exprt(cntr_sym.symbol_expr(), ID_ge, buffer_size(bufp)); else check->guard= binary_relation_exprt(cntr_sym.symbol_expr(), ID_gt, from_integer(limit, unsigned_int_type())); exprt nondet=side_effect_expr_nondett(buf_type.subtype()); invalidate->code=code_assignt(deref, nondet); }
void string_instrumentationt::do_format_string_read( goto_programt &dest, goto_programt::const_targett target, const code_function_callt::argumentst &arguments, unsigned format_string_inx, unsigned argument_start_inx, const std::string &function_name) { const exprt &format_arg = arguments[format_string_inx]; if(format_arg.id()==ID_address_of && format_arg.op0().id()==ID_index && format_arg.op0().op0().id()==ID_string_constant) { format_token_listt token_list; parse_format_string(format_arg.op0().op0(), token_list); unsigned args=0; for(format_token_listt::const_iterator it=token_list.begin(); it!=token_list.end(); it++) { if(it->type==format_tokent::STRING) { const exprt &arg = arguments[argument_start_inx+args]; const typet &arg_type = ns.follow(arg.type()); if(arg.id()!=ID_string_constant) // we don't need to check constants { goto_programt::targett assertion=dest.add_instruction(); assertion->location=target->location; assertion->location.set("property", "string"); std::string comment("zero-termination of string argument of "); comment += function_name; assertion->location.set("comment", comment); exprt temp(arg); if(arg_type.id()!=ID_pointer) { index_exprt index; index.array()=temp; index.index()=gen_zero(index_type()); index.type()=arg_type.subtype(); temp=address_of_exprt(index); } assertion->make_assertion(is_zero_string(temp)); } } if(it->type!=format_tokent::TEXT && it->type!=format_tokent::UNKNOWN) args++; if(find(it->flags.begin(), it->flags.end(), format_tokent::ASTERISK)!= it->flags.end()) args++; // just eat the additional argument } } else // non-const format string { goto_programt::targett format_ass=dest.add_instruction(); format_ass->make_assertion(is_zero_string(arguments[1])); format_ass->location=target->location; format_ass->location.set("property", "string"); std::string comment("zero-termination of format string of "); comment += function_name; format_ass->location.set("comment", comment); for(unsigned i=2; i<arguments.size(); i++) { const exprt &arg = arguments[i]; const typet &arg_type=ns.follow(arguments[i].type()); if(arguments[i].id()!=ID_string_constant && is_string_type(arg_type)) { goto_programt::targett assertion=dest.add_instruction(); assertion->location=target->location; assertion->location.set("property", "string"); std::string comment("zero-termination of string argument of "); comment += function_name; assertion->location.set("comment", comment); exprt temp(arg); if(arg_type.id()!=ID_pointer) { index_exprt index; index.array()=temp; index.index()=gen_zero(index_type()); index.type()=arg_type.subtype(); temp=address_of_exprt(index); } assertion->make_assertion(is_zero_string(temp)); } } } }
pool::index_type pool::index(void* ptr) const { return ptr ? index_type(((uint8_t*)ptr - blocks_) / stride_) : nullidx; }
void string_instrumentationt::do_strerror( goto_programt &dest, goto_programt::targett it, code_function_callt &call) { if(call.lhs().is_nil()) { it->make_skip(); return; } irep_idt identifier_buf="c::__strerror_buffer"; irep_idt identifier_size="c::__strerror_buffer_size"; if(symbol_table.symbols.find(identifier_buf)==symbol_table.symbols.end()) { symbolt new_symbol_size; new_symbol_size.base_name="__strerror_buffer_size"; new_symbol_size.pretty_name=new_symbol_size.base_name; new_symbol_size.name=identifier_size; new_symbol_size.mode=ID_C; new_symbol_size.type=size_type(); new_symbol_size.is_state_var=true; new_symbol_size.is_lvalue=true; new_symbol_size.is_static_lifetime=true; array_typet type; type.subtype()=char_type(); type.size()=new_symbol_size.symbol_expr(); symbolt new_symbol_buf; new_symbol_buf.mode=ID_C; new_symbol_buf.type=type; new_symbol_buf.is_state_var=true; new_symbol_buf.is_lvalue=true; new_symbol_buf.is_static_lifetime=true; new_symbol_buf.base_name="__strerror_buffer"; new_symbol_buf.pretty_name=new_symbol_buf.base_name; new_symbol_buf.name="c::"+id2string(new_symbol_buf.base_name); symbol_table.move(new_symbol_buf); symbol_table.move(new_symbol_size); } const symbolt &symbol_size=ns.lookup(identifier_size); const symbolt &symbol_buf=ns.lookup(identifier_buf); goto_programt tmp; { goto_programt::targett assignment1=tmp.add_instruction(ASSIGN); exprt nondet_size=side_effect_expr_nondett(size_type()); assignment1->code=code_assignt(symbol_size.symbol_expr(), nondet_size); assignment1->location=it->location; goto_programt::targett assumption1=tmp.add_instruction(); assumption1->make_assumption(binary_relation_exprt( symbol_size.symbol_expr(), ID_notequal, gen_zero(symbol_size.type))); assumption1->location=it->location; } // return a pointer to some magic buffer exprt index=exprt(ID_index, char_type()); index.copy_to_operands(symbol_buf.symbol_expr(), gen_zero(index_type())); exprt ptr=exprt(ID_address_of, pointer_typet()); ptr.type().subtype()=char_type(); ptr.copy_to_operands(index); // make that zero-terminated { goto_programt::targett assignment2=tmp.add_instruction(ASSIGN); assignment2->code=code_assignt(is_zero_string(ptr, true), true_exprt()); assignment2->location=it->location; } // assign address { goto_programt::targett assignment3=tmp.add_instruction(ASSIGN); exprt rhs=ptr; make_type(rhs, call.lhs().type()); assignment3->code=code_assignt(call.lhs(), rhs); assignment3->location=it->location; } it->make_skip(); dest.insert_before_swap(it, tmp); }
void goto_convertt::do_java_new_array( const exprt &lhs, const side_effect_exprt &rhs, goto_programt &dest) { if(lhs.is_nil()) throw "do_java_new_array without lhs is yet to be implemented"; source_locationt location=rhs.source_location(); assert(rhs.operands().size()>=1); // one per dimension if(rhs.type().id()!=ID_pointer) throw "do_java_new_array returns pointer"; typet object_type=rhs.type().subtype(); // build size expression exprt object_size=size_of_expr(object_type, ns); if(object_size.is_nil()) throw "do_java_new_array got nil object_size"; // we produce a malloc side-effect, which stays side_effect_exprt malloc_expr(ID_malloc); malloc_expr.copy_to_operands(object_size); malloc_expr.type()=pointer_typet(object_type); goto_programt::targett t_n=dest.add_instruction(ASSIGN); t_n->code=code_assignt(lhs, malloc_expr); t_n->source_location=location; // multi-dimensional? assert(ns.follow(object_type).id()==ID_struct); const struct_typet &struct_type=to_struct_type(ns.follow(object_type)); assert(struct_type.components().size()==3); // if it's an array, we need to set the length field dereference_exprt deref(lhs, object_type); member_exprt length(deref, struct_type.components()[1].get_name(), struct_type.components()[1].type()); goto_programt::targett t_s=dest.add_instruction(ASSIGN); t_s->code=code_assignt(length, rhs.op0()); t_s->source_location=location; // we also need to allocate space for the data member_exprt data(deref, struct_type.components()[2].get_name(), struct_type.components()[2].type()); side_effect_exprt data_cpp_new_expr(ID_cpp_new_array, data.type()); data_cpp_new_expr.set(ID_size, rhs.op0()); goto_programt::targett t_p=dest.add_instruction(ASSIGN); t_p->code=code_assignt(data, data_cpp_new_expr); t_p->source_location=location; // zero-initialize the data exprt zero_element=gen_zero(data.type().subtype()); codet array_set(ID_array_set); array_set.copy_to_operands(data, zero_element); goto_programt::targett t_d=dest.add_instruction(OTHER); t_d->code=array_set; t_d->source_location=location; if(rhs.operands().size()>=2) { // produce // for(int i=0; i<size; i++) tmp[i]=java_new(dim-1); // This will be converted recursively. goto_programt tmp; symbol_exprt tmp_i= new_tmp_symbol(index_type(), "index", tmp, location).symbol_expr(); code_fort for_loop; side_effect_exprt sub_java_new=rhs; sub_java_new.operands().erase(sub_java_new.operands().begin()); side_effect_exprt inc(ID_assign); inc.operands().resize(2); inc.op0()=tmp_i; inc.op1()=plus_exprt(tmp_i, gen_one(tmp_i.type())); dereference_exprt deref_expr(plus_exprt(data, tmp_i), data.type().subtype()); for_loop.init()=code_assignt(tmp_i, gen_zero(tmp_i.type())); for_loop.cond()=binary_relation_exprt(tmp_i, ID_lt, rhs.op0()); for_loop.iter()=inc; for_loop.body()=code_skipt(); for_loop.body()=code_assignt(deref_expr, sub_java_new); convert(for_loop, tmp); dest.destructive_append(tmp); } }