int join(){ int t,t1,t2; t1 = equality(); t = t1; while(look->tag == AND){ t = temp++; move(); t2 = equality(); gen("t%d = t%d && t%d\n",t,t1,t2); t1 = t; } return t; }
NodeInt join(){ int nodeL = equality(); switch (CurrToken) { case AND_OP:{ Token tok = mutch(AND_OP); NodeInt nodeR = equality(); return AddNode(tok, nodeL, 0,nodeR); break; } default: break; } return nodeL; }
int check(int nGood[], int nNum ) { int nFlag; int nCntr1; int nCntr2; int nCnt; int nLen; int nLoop; long nVar1; long nVar2; for(nLen=0;nLen<=nNum;nLen++); nLen--; nFlag=0; for(nCntr1=nLen,nCntr2=nLen-1; nCntr1>=0 && nCntr2 >=0; nCntr1-=1, nCntr2-=2) { nCnt=0; nVar1=0; nVar2=0; for(nLoop=nLen; nLoop >= nCntr1; nLoop--,nCnt++) nVar1=nVar1*10+(long)nGood[nLoop]; for(nLoop=nCntr1-1; nLoop >= nCntr2; nLoop--) nVar2=nVar2*10+(long)nGood[nLoop]; nFlag=equality(nVar1,nVar2,nCnt); if(nFlag>0) return nFlag; } return nFlag; }
rectangle_packer (int _nb_screen, const pair & vscreen_min_size, const pair & vscreen_max_size, const pair_list & screen_sizes, const sequence_pair & layout) : nb_screen (_nb_screen) { init_solver (); // Virtual screen boundaries more_than_const (v_vscreen_size (X), vscreen_min_size.x); less_than_const (v_vscreen_size (X), vscreen_max_size.x); more_than_const (v_vscreen_size (Y), vscreen_min_size.y); less_than_const (v_vscreen_size (Y), vscreen_max_size.y); // Screens inside virtual screen for (int sc = 0; sc < nb_screen; ++sc) { positive_or_zero (v_screen_pos (sc, X)); offseted_less_than_var (v_screen_pos (sc, X), screen_sizes[sc].x, v_vscreen_size (X)); positive_or_zero (v_screen_pos (sc, Y)); offseted_less_than_var (v_screen_pos (sc, Y), screen_sizes[sc].y, v_vscreen_size (Y)); } // Screen ordering constraints for (int sa = 0; sa < nb_screen; ++sa) for (int sb = 0; sb < sa; ++sb) switch (layout.ordering (sa, sb)) { case left: offseted_less_than_var (v_screen_pos (sa, X), screen_sizes[sa].x, v_screen_pos (sb, X)); break; case right: offseted_less_than_var (v_screen_pos (sb, X), screen_sizes[sb].x, v_screen_pos (sa, X)); break; case above: offseted_less_than_var (v_screen_pos (sa, Y), screen_sizes[sa].y, v_screen_pos (sb, Y)); break; case under: offseted_less_than_var (v_screen_pos (sb, Y), screen_sizes[sb].y, v_screen_pos (sa, Y)); break; default: throw std::runtime_error ("rectangle_packer: unordered screens despite sequence pair"); } /* Objective function. sum of : * - constraint gap length * - distance between centers on second axis */ const int constraint_gap_coeff = 1; const int center_distance_coeff = 1; std::vector< int > coeffs (v_nb (), 0); // More practical to gather coeffs coeffs[v_objective ()] = -1; // 0 = -o + sum(...) for (int sa = 0; sa < nb_screen; ++sa) for (int sb = 0; sb < sa; ++sb) switch (layout.ordering (sa, sb)) { case left: coeffs[v_screen_pos (sa, X)] -= constraint_gap_coeff; coeffs[v_screen_pos (sb, X)] += constraint_gap_coeff; // o += sb.x - sa.x coeffs[distance_var (v_screen_pos (sa, Y), screen_sizes[sa].y, v_screen_pos (sb, Y), screen_sizes[sb].y)] += center_distance_coeff; // o += dist (sa.cy, sb.cy) break; case right: coeffs[v_screen_pos (sb, X)] -= constraint_gap_coeff; coeffs[v_screen_pos (sa, X)] += constraint_gap_coeff; // o += sa.x - sb.x coeffs[distance_var (v_screen_pos (sb, Y), screen_sizes[sb].y, v_screen_pos (sa, Y), screen_sizes[sa].y)] += center_distance_coeff; // o += dist (sb.cy, sa.cy) break; case above: coeffs[v_screen_pos (sa, Y)] -= constraint_gap_coeff; coeffs[v_screen_pos (sb, Y)] += constraint_gap_coeff; // o += sb.y - sa.y coeffs[distance_var (v_screen_pos (sa, X), screen_sizes[sa].x, v_screen_pos (sb, X), screen_sizes[sb].x)] += center_distance_coeff; // o += dist (sa.cx, sb.cx) break; case under: coeffs[v_screen_pos (sb, Y)] -= constraint_gap_coeff; coeffs[v_screen_pos (sa, Y)] += constraint_gap_coeff; // o += sa.y - sb.y coeffs[distance_var (v_screen_pos (sb, X), screen_sizes[sb].x, v_screen_pos (sa, X), screen_sizes[sa].x)] += center_distance_coeff; // o += dist (sb.cx, sa.cx) break; default: break; // Error handled before } equality (coeffs); }
void path_searcht::do_show_vcc( statet &state, const namespacet &ns) { // keep statistics number_of_VCCs++; const goto_programt::instructiont &instruction= *state.get_instruction(); mstreamt &out=result(); if(instruction.location.is_not_nil()) out << instruction.location << "\n"; if(instruction.location.get_comment()!="") out << instruction.location.get_comment() << "\n"; unsigned count=1; std::vector<path_symex_step_reft> steps; state.history.build_history(steps); for(std::vector<path_symex_step_reft>::const_iterator s_it=steps.begin(); s_it!=steps.end(); s_it++) { if((*s_it)->guard.is_not_nil()) { std::string string_value=from_expr(ns, "", (*s_it)->guard); out << "{-" << count << "} " << string_value << "\n"; count++; } if((*s_it)->ssa_rhs.is_not_nil()) { equal_exprt equality((*s_it)->ssa_lhs, (*s_it)->ssa_rhs); std::string string_value=from_expr(ns, "", equality); out << "{-" << count << "} " << string_value << "\n"; count++; } } out << "|--------------------------" << "\n"; exprt assertion=state.read(instruction.guard); out << "{" << 1 << "} " << from_expr(ns, "", assertion) << "\n"; if(!assertion.is_true()) number_of_VCCs_after_simplification++; out << eom; }
void local_SSAt::build_cond(locationt loc) { // anything to be built? if(!loc->is_goto() && !loc->is_assume()) return; // produce a symbol for the renamed branching condition equal_exprt equality(cond_symbol(loc), read_rhs(loc->guard, loc)); nodes[loc].equalities.push_back(equality); }
void path_searcht::do_show_vcc(statet &state) { // keep statistics number_of_VCCs++; const goto_programt::instructiont &instruction= *state.get_instruction(); mstreamt &out=result(); if(instruction.source_location.is_not_nil()) out << instruction.source_location << '\n'; if(instruction.source_location.get_comment()!="") out << instruction.source_location.get_comment() << '\n'; unsigned count=1; std::vector<path_symex_step_reft> steps; state.history.build_history(steps); for(const auto &step_ref : steps) { if(step_ref->guard.is_not_nil()) { std::string string_value=from_expr(ns, "", step_ref->guard); out << "{-" << count << "} " << string_value << '\n'; count++; } if(step_ref->ssa_rhs.is_not_nil()) { equal_exprt equality(step_ref->ssa_lhs, step_ref->ssa_rhs); std::string string_value=from_expr(ns, "", equality); out << "{-" << count << "} " << string_value << '\n'; count++; } } out << "|--------------------------" << '\n'; exprt assertion=state.read(instruction.guard); out << "{" << 1 << "} " << from_expr(ns, "", assertion) << '\n'; if(!assertion.is_true()) number_of_VCCs_after_simplification++; out << eom; }
int list_iassoc(Var vtarget, Var vlist, int vindex) { int i; for (i = 1; i <= vlist.v.list[0].v.num; i++) { if (vlist.v.list[i].type == TYPE_LIST && vlist.v.list[i].v.list[0].v.num >= vindex && equality(vlist.v.list[i].v.list[vindex], vtarget, 0)) { return i; } } return 0; }
Var list_assoc(Var vtarget, Var vlist, int vindex) { int i; for (i = 1; i <= vlist.v.list[0].v.num; i++) { if (vlist.v.list[i].type == TYPE_LIST && vlist.v.list[i].v.list[0].v.num >= vindex && equality(vlist.v.list[i].v.list[vindex], vtarget, 0)) { return var_dup(vlist.v.list[i]); } } return new_list(0); }
bodyt termination_baset::get_body( goto_tracet::stepst::const_iterator &loop_begin, const goto_tracet &trace) { bodyt result_body; exprt::operandst op; const goto_trace_stept &assertion=trace.steps.back(); // let's get a loop number as well: assert(assertion.pc->guard.id()=="=>"); std::string c_str = assertion.pc->guard.op0().get_string("identifier"); std::string prefix = termination_prefix+ c_str.substr(c_str.rfind("_")+1) + "::"; // find out what we actually need required_stepst required_steps; find_required_steps(trace, loop_begin, required_steps, prefix); /* We perform a new SSA-conversion. However, since we can only get a single path through the program, there are no joins and thus no phi-functions. We just increment counters. */ std::map<irep_idt, unsigned> ssa_counters; replace_idt replace_id; // get the required body constraints for(goto_tracet::stepst::const_iterator step=loop_begin; step!=--trace.steps.end(); step++) { last_path.push_back(step->pc); // required_stepst::const_iterator fit=required_steps.find(&(*step)); // if(fit==required_steps.end()) continue; switch(step->pc->type) { case ASSIGN: { const code_assignt &code=to_code_assign(step->pc->code); find_symbols_sett w; find_symbols_w(code.lhs(), w); equal_exprt equality(code.lhs(), code.rhs()); replace_id.replace(equality.rhs()); // All the written ones get their SSA-ID updated for(find_symbols_sett::const_iterator it=w.begin(); it!=w.end(); it++) { // Are we writing a pre-variable? if(has_prefix(id2string(*it), prefix)) { assert(code.rhs().id()==ID_symbol); const irep_idt &post_id=code.rhs().get(ID_identifier); const irep_idt &pre_id=code.lhs().get(ID_identifier); result_body.variable_map[post_id]=pre_id; // the RHS gets a #0 id irep_idt new_id=id2string(post_id)+"!0"; replace_id.insert(post_id, new_id); equality.rhs().set(ID_identifier, new_id); } else { const irep_idt &old_id=*it; unsigned cur=++ssa_counters[old_id]; // 0 is never used // gets a new ID irep_idt new_id=id2string(old_id)+"!"+i2string(cur); replace_id.insert(old_id, new_id); } } replace_id.replace(equality.lhs()); op.push_back(equality); break; } case ASSUME: case ASSERT: { if(!step->cond_expr.is_true() && !step->cond_expr.is_nil()) { exprt guard=step->cond_expr; // That's SSA! remove_ssa_ids(guard); // exprt guard=step->pc->guard; find_symbols_sett syms; find_symbols(guard, syms); for(find_symbols_sett::const_iterator it=syms.begin(); it!=syms.end(); it++) { if(ssa_counters.find(*it)==ssa_counters.end()) { irep_idt new_id=id2string(*it)+"!"+i2string(++ssa_counters[*it]); replace_id.insert(*it, new_id); } } replace_id.replace(guard); if(!step->cond_value) guard.negate(); op.push_back(guard); } break; } case GOTO: { if(!step->cond_expr.is_nil()) { // exprt guard=step->pc->guard; exprt guard=step->cond_expr; remove_ssa_ids(guard); find_symbols_sett syms; find_symbols(guard, syms); for(find_symbols_sett::const_iterator it=syms.begin(); it!=syms.end(); it++) { if(ssa_counters.find(*it)==ssa_counters.end()) { ssa_counters[*it]=0; irep_idt new_id=id2string(*it)+"!"+i2string(0); replace_id.insert(*it, new_id); } } replace_id.replace(guard); if(!step->cond_value) guard.negate(); op.push_back(guard); } break; } case DECL: /* nothing */ break; case LOCATION: /* These can show up here? */ break; default: throw std::string("unexpected instruction type."); } } // the final result, which (again) contains SSA variables exprt &body_expr = result_body.body_relation; body_expr = and_exprt(op); if(result_body.variable_map.empty()) { // used to be: // throw "BUG: No variables found; path missing."; // Though: No variable is ever saved, i.e., this loop // must be completely nondeterministic. warning("No pre-variables found; this " "loop is completely non-deterministic."); body_expr=false_exprt(); } // The last SSA-occurrence of a variable is the // output variable and it gets its non-SSA name. replace_idt last_map; for(std::map<irep_idt, unsigned>::const_iterator it=ssa_counters.begin(); it!=ssa_counters.end(); it++) { const irep_idt &id=it->first; unsigned last=it->second; irep_idt last_name=id2string(id)+"!"+i2string(last); last_map.insert(last_name, id); } last_map.replace(body_expr); replace_nondet_sideeffects(body_expr); return result_body; }
void local_SSAt::assign_rec( const exprt &lhs, const exprt &rhs, const exprt &guard, locationt loc) { const typet &type=ns.follow(lhs.type()); if(is_symbol_struct_member(lhs, ns)) { if(type.id()==ID_struct) { // need to split up const struct_typet &struct_type=to_struct_type(type); const struct_typet::componentst &components=struct_type.components(); for(struct_typet::componentst::const_iterator it=components.begin(); it!=components.end(); it++) { member_exprt new_lhs(lhs, it->get_name(), it->type()); member_exprt new_rhs(rhs, it->get_name(), it->type()); assign_rec(new_lhs, new_rhs, guard, loc); } return; } ssa_objectt lhs_object(lhs, ns); const std::set<ssa_objectt> &assigned= assignments.get(loc); if(assigned.find(lhs_object)!=assigned.end()) { exprt ssa_rhs=read_rhs(rhs, loc); const symbol_exprt ssa_symbol=name(lhs_object, OUT, loc); equal_exprt equality(ssa_symbol, ssa_rhs); nodes[loc].equalities.push_back(equality); } } else if(lhs.id()==ID_index) { const index_exprt &index_expr=to_index_expr(lhs); exprt ssa_array=index_expr.array(); exprt new_rhs=with_exprt(ssa_array, index_expr.index(), rhs); assign_rec(index_expr.array(), new_rhs, guard, loc); } else if(lhs.id()==ID_member) { // These are non-flattened struct or union members. const member_exprt &member_expr=to_member_expr(lhs); const exprt &compound=member_expr.struct_op(); const typet &compound_type=ns.follow(compound.type()); if(compound_type.id()==ID_union) { union_exprt new_rhs(member_expr.get_component_name(), rhs, compound.type()); assign_rec(member_expr.struct_op(), new_rhs, guard, loc); } else if(compound_type.id()==ID_struct) { exprt member_name(ID_member_name); member_name.set(ID_component_name, member_expr.get_component_name()); with_exprt new_rhs(compound, member_name, rhs); assign_rec(compound, new_rhs, guard, loc); } } else if(lhs.id()==ID_complex_real) { assert(lhs.operands().size()==1); const exprt &op=lhs.op0(); const complex_typet &complex_type=to_complex_type(op.type()); exprt imag_op=unary_exprt(ID_complex_imag, op, complex_type.subtype()); complex_exprt new_rhs(rhs, imag_op, complex_type); assign_rec(op, new_rhs, guard, loc); } else if(lhs.id()==ID_complex_imag) { assert(lhs.operands().size()==1); const exprt &op=lhs.op0(); const complex_typet &complex_type=to_complex_type(op.type()); exprt real_op=unary_exprt(ID_complex_real, op, complex_type.subtype()); complex_exprt new_rhs(real_op, rhs, complex_type); assign_rec(op, new_rhs, guard, loc); } else if(lhs.id()==ID_if) { const if_exprt &if_expr=to_if_expr(lhs); assign_rec(if_expr.true_case(), rhs, and_exprt(guard, if_expr.cond()), loc); assign_rec(if_expr.false_case(), rhs, and_exprt(guard, not_exprt(if_expr.cond())), loc); } else if(lhs.id()==ID_byte_extract_little_endian || lhs.id()==ID_byte_extract_big_endian) { const byte_extract_exprt &byte_extract_expr=to_byte_extract_expr(lhs); exprt new_lhs=byte_extract_expr.op(); exprt new_rhs=byte_extract_exprt( byte_extract_expr.id(), rhs, byte_extract_expr.offset(), new_lhs.type()); assign_rec(new_lhs, new_rhs, guard, loc); } else throw "UNKNOWN LHS: "+lhs.id_string(); }
void local_SSAt::build_guard(locationt loc) { const guard_mapt::entryt &entry=guard_map[loc]; // anything to be built? if(!entry.has_guard) return; exprt::operandst sources; // the very first 'loc' trivially gets 'true' as source if(loc==goto_function.body.instructions.begin()) sources.push_back(true_exprt()); for(guard_mapt::incomingt::const_iterator i_it=entry.incoming.begin(); i_it!=entry.incoming.end(); i_it++) { const guard_mapt::edget &edge=*i_it; exprt source; // might be backwards branch taken edge if(edge.is_branch_taken() && edge.from->is_backwards_goto()) { // The loop selector indicates whether the path comes from // above (entering the loop) or below (iterating). // By convention, we use the loop select symbol for the location // of the backwards goto. symbol_exprt loop_select= name(guard_symbol(), LOOP_SELECT, edge.from); #if 0 source=false_exprt(); #else // need constraing for edge.cond source=loop_select; #endif } else { // the other cases are basically similar symbol_exprt gs=name(guard_symbol(), OUT, edge.guard_source); exprt cond; if(edge.is_branch_taken() || edge.is_assume() || edge.is_function_call()) cond=cond_symbol(edge.from); else if(edge.is_branch_not_taken()) cond=boolean_negate(cond_symbol(edge.from)); else if(edge.is_successor()) cond=true_exprt(); else assert(false); source=and_exprt(gs, cond); } sources.push_back(source); } // the below produces 'false' if there is no source exprt rhs=disjunction(sources); equal_exprt equality(guard_symbol(loc), rhs); nodes[loc].equalities.push_back(equality); }
void local_SSAt::build_phi_nodes(locationt loc) { const ssa_domaint::phi_nodest &phi_nodes=ssa_analysis[loc].phi_nodes; nodet &node=nodes[loc]; for(objectst::const_iterator o_it=ssa_objects.objects.begin(); o_it!=ssa_objects.objects.end(); o_it++) { // phi-node for this object here? ssa_domaint::phi_nodest::const_iterator p_it= phi_nodes.find(o_it->get_identifier()); if(p_it==phi_nodes.end()) continue; // none // Yes. Get the source -> def map. const std::map<locationt, ssa_domaint::deft> &incoming=p_it->second; exprt rhs=nil_exprt(); // We distinguish forwards- from backwards-edges, // and do forwards-edges first, which gives them // _lower_ priority in the ITE. Inputs are always // forward edges. for(std::map<locationt, ssa_domaint::deft>::const_iterator incoming_it=incoming.begin(); incoming_it!=incoming.end(); incoming_it++) if(incoming_it->second.is_input() || incoming_it->first->location_number < loc->location_number) { // it's a forward edge exprt incoming_value=name(*o_it, incoming_it->second); exprt incoming_guard=edge_guard(incoming_it->first, loc); if(rhs.is_nil()) // first rhs=incoming_value; else rhs=if_exprt(incoming_guard, incoming_value, rhs); } // now do backwards for(std::map<locationt, ssa_domaint::deft>::const_iterator incoming_it=incoming.begin(); incoming_it!=incoming.end(); incoming_it++) if(!incoming_it->second.is_input() && incoming_it->first->location_number >= loc->location_number) { // it's a backwards edge exprt incoming_value=name(*o_it, LOOP_BACK, incoming_it->first); exprt incoming_select=name(guard_symbol(), LOOP_SELECT, incoming_it->first); if(rhs.is_nil()) // first rhs=incoming_value; else rhs=if_exprt(incoming_select, incoming_value, rhs); } symbol_exprt lhs=name(*o_it, PHI, loc); equal_exprt equality(lhs, rhs); node.equalities.push_back(equality); } }
value_set_dereferencet::valuet value_set_dereferencet::build_reference_to( const exprt &what, const modet mode, const exprt &pointer_expr, const guardt &guard) { const typet &dereference_type= ns.follow(pointer_expr.type()).subtype(); if(what.id()==ID_unknown || what.id()==ID_invalid) { invalid_pointer(pointer_expr, guard); return valuet(); } if(what.id()!=ID_object_descriptor) throw "unknown points-to: "+what.id_string(); const object_descriptor_exprt &o=to_object_descriptor_expr(what); const exprt &root_object=o.root_object(); const exprt &object=o.object(); #if 0 std::cout << "O: " << from_expr(ns, "", root_object) << '\n'; #endif valuet result; if(root_object.id()=="NULL-object") { if(options.get_bool_option("pointer-check")) { guardt tmp_guard(guard); if(o.offset().is_zero()) { tmp_guard.add(null_pointer(pointer_expr)); dereference_callback.dereference_failure( "pointer dereference", "NULL pointer", tmp_guard); } else { tmp_guard.add(null_object(pointer_expr)); dereference_callback.dereference_failure( "pointer dereference", "NULL plus offset pointer", tmp_guard); } } } else if(root_object.id()==ID_dynamic_object) { // const dynamic_object_exprt &dynamic_object= // to_dynamic_object_expr(root_object); // the object produced by malloc exprt malloc_object= ns.lookup(CPROVER_PREFIX "malloc_object").symbol_expr(); exprt is_malloc_object=same_object(pointer_expr, malloc_object); // constraint that it actually is a dynamic object exprt dynamic_object_expr(ID_dynamic_object, bool_typet()); dynamic_object_expr.copy_to_operands(pointer_expr); // this is also our guard result.pointer_guard=dynamic_object_expr; // can't remove here, turn into *p result.value=dereference_exprt(pointer_expr, dereference_type); if(options.get_bool_option("pointer-check")) { // if(!dynamic_object.valid().is_true()) { // check if it is still alive guardt tmp_guard(guard); tmp_guard.add(deallocated(pointer_expr, ns)); dereference_callback.dereference_failure( "pointer dereference", "dynamic object deallocated", tmp_guard); } if(options.get_bool_option("bounds-check")) { if(!o.offset().is_zero()) { // check lower bound guardt tmp_guard(guard); tmp_guard.add(is_malloc_object); tmp_guard.add( dynamic_object_lower_bound( pointer_expr, ns, nil_exprt())); dereference_callback.dereference_failure( "pointer dereference", "dynamic object lower bound", tmp_guard); } { // check upper bound // we check SAME_OBJECT(__CPROVER_malloc_object, p) && // POINTER_OFFSET(p)+size>__CPROVER_malloc_size guardt tmp_guard(guard); tmp_guard.add(is_malloc_object); tmp_guard.add( dynamic_object_upper_bound( pointer_expr, dereference_type, ns, size_of_expr(dereference_type, ns))); dereference_callback.dereference_failure( "pointer dereference", "dynamic object upper bound", tmp_guard); } } } } else if(root_object.id()==ID_integer_address) { // This is stuff like *((char *)5). // This is turned into an access to __CPROVER_memory[...]. if(language_mode==ID_java) { result.value=nil_exprt(); return result; } const symbolt &memory_symbol=ns.lookup(CPROVER_PREFIX "memory"); exprt symbol_expr=symbol_exprt(memory_symbol.name, memory_symbol.type); if(base_type_eq( ns.follow(memory_symbol.type).subtype(), dereference_type, ns)) { // Types match already, what a coincidence! // We can use an index expression. exprt index_expr=index_exprt(symbol_expr, pointer_offset(pointer_expr)); index_expr.type()=ns.follow(memory_symbol.type).subtype(); result.value=index_expr; } else if(dereference_type_compare( ns.follow(memory_symbol.type).subtype(), dereference_type)) { exprt index_expr=index_exprt(symbol_expr, pointer_offset(pointer_expr)); index_expr.type()=ns.follow(memory_symbol.type).subtype(); result.value=typecast_exprt(index_expr, dereference_type); } else { // We need to use byte_extract. // Won't do this without a commitment to an endianness. if(config.ansi_c.endianness==configt::ansi_ct::endiannesst::NO_ENDIANNESS) { } else { exprt byte_extract(byte_extract_id(), dereference_type); byte_extract.copy_to_operands( symbol_expr, pointer_offset(pointer_expr)); result.value=byte_extract; } } } else { // something generic -- really has to be a symbol address_of_exprt object_pointer(object); if(o.offset().is_zero()) { equal_exprt equality(pointer_expr, object_pointer); if(ns.follow(equality.lhs().type())!=ns.follow(equality.rhs().type())) equality.lhs().make_typecast(equality.rhs().type()); result.pointer_guard=equality; } else { result.pointer_guard=same_object(pointer_expr, object_pointer); } guardt tmp_guard(guard); tmp_guard.add(result.pointer_guard); valid_check(object, tmp_guard, mode); const typet &object_type=ns.follow(object.type()); const exprt &root_object=o.root_object(); const typet &root_object_type=ns.follow(root_object.type()); exprt root_object_subexpression=root_object; if(dereference_type_compare(object_type, dereference_type) && o.offset().is_zero()) { // The simplest case: types match, and offset is zero! // This is great, we are almost done. result.value=object; if(object_type!=ns.follow(dereference_type)) result.value.make_typecast(dereference_type); } else if(root_object_type.id()==ID_array && dereference_type_compare( root_object_type.subtype(), dereference_type)) { // We have an array with a subtype that matches // the dereferencing type. // We will require well-alignedness! exprt offset; // this should work as the object is essentially the root object if(o.offset().is_constant()) offset=o.offset(); else offset=pointer_offset(pointer_expr); exprt adjusted_offset; // are we doing a byte? mp_integer element_size= dereference_type.id()==ID_empty? pointer_offset_size(char_type(), ns): pointer_offset_size(dereference_type, ns); if(element_size==1) { // no need to adjust offset adjusted_offset=offset; } else if(element_size<=0) { throw "unknown or invalid type size of:\n"+dereference_type.pretty(); } else { exprt element_size_expr= from_integer(element_size, offset.type()); adjusted_offset=binary_exprt( offset, ID_div, element_size_expr, offset.type()); // TODO: need to assert well-alignedness } index_exprt index_expr= index_exprt(root_object, adjusted_offset, root_object_type.subtype()); bounds_check(index_expr, tmp_guard); result.value=index_expr; if(ns.follow(result.value.type())!=ns.follow(dereference_type)) result.value.make_typecast(dereference_type); } else if(get_subexpression_at_offset( root_object_subexpression, o.offset(), dereference_type, ns)) { // Successfully found a member, array index, or combination thereof // that matches the desired type and offset: result.value=root_object_subexpression; } else { // we extract something from the root object result.value=o.root_object(); // this is relative to the root object const exprt offset=pointer_offset(pointer_expr); if(memory_model(result.value, dereference_type, tmp_guard, offset)) { // ok, done } else { if(options.get_bool_option("pointer-check")) { std::string msg="memory model not applicable (got `"; msg+=from_type(ns, "", result.value.type()); msg+="', expected `"; msg+=from_type(ns, "", dereference_type); msg+="')"; dereference_callback.dereference_failure( "pointer dereference", msg, tmp_guard); } return valuet(); // give up, no way that this is ok } } } return result; }
GLboolean _slang_assemble_operation (slang_assemble_ctx *A, slang_operation *op, slang_ref_type ref) { /* set default results */ A->ref = /*(ref == slang_ref_freelance) ? slang_ref_force : */ref; A->swz.num_components = 0; switch (op->type) { case slang_oper_block_no_new_scope: case slang_oper_block_new_scope: { GLuint i; for (i = 0; i < op->num_children; i++) { if (!_slang_assemble_operation (A, &op->children[i], slang_ref_forbid/*slang_ref_freelance*/)) return GL_FALSE; if (!_slang_cleanup_stack (A, &op->children[i])) return GL_FALSE; } } break; case slang_oper_variable_decl: { GLuint i; slang_operation assign; GLboolean result; /* Construct assignment expression placeholder. */ if (!slang_operation_construct (&assign)) return GL_FALSE; assign.type = slang_oper_assign; assign.children = (slang_operation *) slang_alloc_malloc (2 * sizeof (slang_operation)); if (assign.children == NULL) { slang_operation_destruct (&assign); return GL_FALSE; } for (assign.num_children = 0; assign.num_children < 2; assign.num_children++) if (!slang_operation_construct (&assign.children[assign.num_children])) { slang_operation_destruct (&assign); return GL_FALSE; } result = GL_TRUE; for (i = 0; i < op->num_children; i++) { slang_variable *var; var = _slang_locate_variable (op->children[i].locals, op->children[i].a_id, GL_TRUE); if (var == NULL) { result = GL_FALSE; break; } if (var->initializer == NULL) continue; if (!slang_operation_copy (&assign.children[0], &op->children[i]) || !slang_operation_copy (&assign.children[1], var->initializer) || !_slang_assemble_assign (A, &assign, "=", slang_ref_forbid) || !_slang_cleanup_stack (A, &assign)) { result = GL_FALSE; break; } } slang_operation_destruct (&assign); if (!result) return GL_FALSE; } break; case slang_oper_asm: { GLuint i; if (!_slang_assemble_operation (A, &op->children[0], slang_ref_force)) return GL_FALSE; for (i = 1; i < op->num_children; i++) if (!_slang_assemble_operation (A, &op->children[i], slang_ref_forbid)) return GL_FALSE; if (!call_asm_instruction (A, op->a_id)) return GL_FALSE; } break; case slang_oper_break: if (!PLAB (A->file, slang_asm_jump, A->flow.loop_end)) return GL_FALSE; break; case slang_oper_continue: if (!PLAB (A->file, slang_asm_jump, A->flow.loop_start)) return GL_FALSE; break; case slang_oper_discard: if (!PUSH (A->file, slang_asm_discard)) return GL_FALSE; if (!PUSH (A->file, slang_asm_exit)) return GL_FALSE; break; case slang_oper_return: if (A->local.ret_size != 0) { /* push the result's address */ if (!PLAB2 (A->file, slang_asm_local_addr, 0, A->local.ret_size)) return GL_FALSE; if (!_slang_assemble_operation (A, &op->children[0], slang_ref_forbid)) return GL_FALSE; A->swz.num_components = 0; /* assign the operation to the function result (it was reserved on the stack) */ if (!_slang_assemble_assignment (A, op->children)) return GL_FALSE; if (!PLAB (A->file, slang_asm_local_free, 4)) return GL_FALSE; } if (!PLAB (A->file, slang_asm_jump, A->flow.function_end)) return GL_FALSE; break; case slang_oper_expression: if (ref == slang_ref_force) return GL_FALSE; if (!_slang_assemble_operation (A, &op->children[0], ref)) return GL_FALSE; break; case slang_oper_if: if (!_slang_assemble_if (A, op)) return GL_FALSE; break; case slang_oper_while: if (!_slang_assemble_while (A, op)) return GL_FALSE; break; case slang_oper_do: if (!_slang_assemble_do (A, op)) return GL_FALSE; break; case slang_oper_for: if (!_slang_assemble_for (A, op)) return GL_FALSE; break; case slang_oper_void: break; case slang_oper_literal_bool: if (ref == slang_ref_force) return GL_FALSE; if (!PLIT (A->file, slang_asm_bool_push, op->literal)) return GL_FALSE; A->ref = slang_ref_forbid; break; case slang_oper_literal_int: if (ref == slang_ref_force) return GL_FALSE; if (!PLIT (A->file, slang_asm_int_push, op->literal)) return GL_FALSE; A->ref = slang_ref_forbid; break; case slang_oper_literal_float: if (ref == slang_ref_force) return GL_FALSE; if (!PLIT (A->file, slang_asm_float_push, op->literal)) return GL_FALSE; A->ref = slang_ref_forbid; break; case slang_oper_identifier: { slang_variable *var; GLuint size; /* find the variable and calculate its size */ var = _slang_locate_variable (op->locals, op->a_id, GL_TRUE); if (var == NULL) return GL_FALSE; size = 0; if (!sizeof_variable (A, &var->type.specifier, slang_qual_none, var->array_len, &size)) return GL_FALSE; /* prepare stack for dereferencing */ if (ref == slang_ref_forbid) if (!PLAB2 (A->file, slang_asm_local_addr, A->local.addr_tmp, 4)) return GL_FALSE; /* push the variable's address */ if (var->global) { if (!PLAB (A->file, slang_asm_global_addr, var->address)) return GL_FALSE; } else { if (!PLAB2 (A->file, slang_asm_local_addr, var->address, size)) return GL_FALSE; } /* perform the dereference */ if (ref == slang_ref_forbid) { if (!PUSH (A->file, slang_asm_addr_copy)) return GL_FALSE; if (!PLAB (A->file, slang_asm_local_free, 4)) return GL_FALSE; if (!_slang_dereference (A, op)) return GL_FALSE; } } break; case slang_oper_sequence: if (ref == slang_ref_force) return GL_FALSE; if (!_slang_assemble_operation (A, &op->children[0], slang_ref_forbid/*slang_ref_freelance*/)) return GL_FALSE; if (!_slang_cleanup_stack (A, &op->children[0])) return GL_FALSE; if (!_slang_assemble_operation (A, &op->children[1], slang_ref_forbid)) return GL_FALSE; A->ref = slang_ref_forbid; break; case slang_oper_assign: if (!_slang_assemble_assign (A, op, "=", ref)) return GL_FALSE; break; case slang_oper_addassign: if (!_slang_assemble_assign (A, op, "+=", ref)) return GL_FALSE; A->ref = ref; break; case slang_oper_subassign: if (!_slang_assemble_assign (A, op, "-=", ref)) return GL_FALSE; A->ref = ref; break; case slang_oper_mulassign: if (!_slang_assemble_assign (A, op, "*=", ref)) return GL_FALSE; A->ref = ref; break; /*case slang_oper_modassign:*/ /*case slang_oper_lshassign:*/ /*case slang_oper_rshassign:*/ /*case slang_oper_orassign:*/ /*case slang_oper_xorassign:*/ /*case slang_oper_andassign:*/ case slang_oper_divassign: if (!_slang_assemble_assign (A, op, "/=", ref)) return GL_FALSE; A->ref = ref; break; case slang_oper_select: if (!_slang_assemble_select (A, op)) return GL_FALSE; A->ref = slang_ref_forbid; break; case slang_oper_logicalor: if (!_slang_assemble_logicalor (A, op)) return GL_FALSE; A->ref = slang_ref_forbid; break; case slang_oper_logicaland: if (!_slang_assemble_logicaland (A, op)) return GL_FALSE; A->ref = slang_ref_forbid; break; case slang_oper_logicalxor: if (!_slang_assemble_function_call_name (A, "^^", op->children, 2, GL_FALSE)) return GL_FALSE; A->ref = slang_ref_forbid; break; /*case slang_oper_bitor:*/ /*case slang_oper_bitxor:*/ /*case slang_oper_bitand:*/ case slang_oper_less: if (!_slang_assemble_function_call_name (A, "<", op->children, 2, GL_FALSE)) return GL_FALSE; A->ref = slang_ref_forbid; break; case slang_oper_greater: if (!_slang_assemble_function_call_name (A, ">", op->children, 2, GL_FALSE)) return GL_FALSE; A->ref = slang_ref_forbid; break; case slang_oper_lessequal: if (!_slang_assemble_function_call_name (A, "<=", op->children, 2, GL_FALSE)) return GL_FALSE; A->ref = slang_ref_forbid; break; case slang_oper_greaterequal: if (!_slang_assemble_function_call_name (A, ">=", op->children, 2, GL_FALSE)) return GL_FALSE; A->ref = slang_ref_forbid; break; /*case slang_oper_lshift:*/ /*case slang_oper_rshift:*/ case slang_oper_add: if (!_slang_assemble_function_call_name (A, "+", op->children, 2, GL_FALSE)) return GL_FALSE; A->ref = slang_ref_forbid; break; case slang_oper_subtract: if (!_slang_assemble_function_call_name (A, "-", op->children, 2, GL_FALSE)) return GL_FALSE; A->ref = slang_ref_forbid; break; case slang_oper_multiply: if (!_slang_assemble_function_call_name (A, "*", op->children, 2, GL_FALSE)) return GL_FALSE; A->ref = slang_ref_forbid; break; /*case slang_oper_modulus:*/ case slang_oper_divide: if (!_slang_assemble_function_call_name (A, "/", op->children, 2, GL_FALSE)) return GL_FALSE; A->ref = slang_ref_forbid; break; case slang_oper_equal: if (!_slang_assemble_operation (A, &op->children[0], slang_ref_forbid)) return GL_FALSE; if (!_slang_assemble_operation (A, &op->children[1], slang_ref_forbid)) return GL_FALSE; if (!equality (A, op->children, GL_TRUE)) return GL_FALSE; A->ref = slang_ref_forbid; break; case slang_oper_notequal: if (!_slang_assemble_operation (A, &op->children[0], slang_ref_forbid)) return GL_FALSE; if (!_slang_assemble_operation (A, &op->children[1], slang_ref_forbid)) return GL_FALSE; if (!equality (A, op->children, GL_FALSE)) return GL_FALSE; A->ref = slang_ref_forbid; break; case slang_oper_preincrement: if (!_slang_assemble_assign (A, op, "++", ref)) return GL_FALSE; A->ref = ref; break; case slang_oper_predecrement: if (!_slang_assemble_assign (A, op, "--", ref)) return GL_FALSE; A->ref = ref; break; case slang_oper_plus: if (!_slang_dereference (A, op)) return GL_FALSE; A->ref = slang_ref_forbid; break; case slang_oper_minus: if (!_slang_assemble_function_call_name (A, "-", op->children, 1, GL_FALSE)) return GL_FALSE; A->ref = slang_ref_forbid; break; /*case slang_oper_complement:*/ case slang_oper_not: if (!_slang_assemble_function_call_name (A, "!", op->children, 1, GL_FALSE)) return GL_FALSE; A->ref = slang_ref_forbid; break; case slang_oper_subscript: { slang_assembly_typeinfo ti_arr, ti_elem; if (!slang_assembly_typeinfo_construct (&ti_arr)) return GL_FALSE; if (!slang_assembly_typeinfo_construct (&ti_elem)) { slang_assembly_typeinfo_destruct (&ti_arr); return GL_FALSE; } if (!handle_subscript (A, &ti_elem, &ti_arr, op, ref)) { slang_assembly_typeinfo_destruct (&ti_arr); slang_assembly_typeinfo_destruct (&ti_elem); return GL_FALSE; } slang_assembly_typeinfo_destruct (&ti_arr); slang_assembly_typeinfo_destruct (&ti_elem); } break; case slang_oper_call: { slang_function *fun; fun = _slang_locate_function (A->space.funcs, op->a_id, op->children, op->num_children, &A->space, A->atoms); if (fun == NULL) { if (!_slang_assemble_constructor (A, op)) return GL_FALSE; } else { if (!_slang_assemble_function_call (A, fun, op->children, op->num_children, GL_FALSE)) return GL_FALSE; } A->ref = slang_ref_forbid; } break; case slang_oper_field: { slang_assembly_typeinfo ti_after, ti_before; if (!slang_assembly_typeinfo_construct (&ti_after)) return GL_FALSE; if (!slang_assembly_typeinfo_construct (&ti_before)) { slang_assembly_typeinfo_destruct (&ti_after); return GL_FALSE; } if (!handle_field (A, &ti_after, &ti_before, op, ref)) { slang_assembly_typeinfo_destruct (&ti_after); slang_assembly_typeinfo_destruct (&ti_before); return GL_FALSE; } slang_assembly_typeinfo_destruct (&ti_after); slang_assembly_typeinfo_destruct (&ti_before); } break; case slang_oper_postincrement: if (!assemble_function_call_name_dummyint (A, "++", op->children)) return GL_FALSE; A->ref = slang_ref_forbid; break; case slang_oper_postdecrement: if (!assemble_function_call_name_dummyint (A, "--", op->children)) return GL_FALSE; A->ref = slang_ref_forbid; break; default: return GL_FALSE; } return GL_TRUE; }