Skip to content

Commit d3e03ed

Browse files
author
Owen Jones
committed
Address review comments
1 parent a390ae0 commit d3e03ed

File tree

1 file changed

+54
-50
lines changed

1 file changed

+54
-50
lines changed

src/pointer-analysis/local_value_set_analysis.cpp

+54-50
Original file line numberDiff line numberDiff line change
@@ -419,23 +419,23 @@ void local_value_set_analysist::transform_function_stub(
419419
// avoid unnecessary recalculations
420420
const auto &rhs_expr = assignment.second;
421421
if(!pre_call_rhs_value_sets.count(rhs_expr))
422-
{
423-
value_sett::object_mapt &rhs_values = pre_call_rhs_value_sets[rhs_expr];
424-
if(rhs_expr.id() == ID_external_value_set)
425422
{
426-
// The RHS expression is an external value set. Expand this to read from
427-
// local objects that match it too.
428-
const auto &evse = to_external_value_set(rhs_expr);
429-
const std::string &evse_label =
430-
id2string(to_constant_expr(evse.label()).get_value());
423+
value_sett::object_mapt &rhs_values = pre_call_rhs_value_sets[rhs_expr];
424+
if(rhs_expr.id() == ID_external_value_set)
425+
{
426+
// The RHS expression is an external value set. Expand this to read from
427+
// local objects that match it too.
428+
const auto &evse = to_external_value_set(rhs_expr);
429+
const std::string &evse_label =
430+
id2string(to_constant_expr(evse.label()).get_value());
431431

432432
if(has_prefix(evse_label, PER_FIELD_EVS_PREFIX))
433433
{
434434
PRECONDITION(evse.access_path_entries().size() == 1);
435435

436436
// This external value set denotes either all pointers stored in a
437437
// particular field (e.g. TypeA.fieldb), or all arrays (in which case
438-
// declared_on_type() is nil the the field name is "[]")
438+
// declared_on_type() is nil and the field name is "[]")
439439
std::vector<irep_idt> key_list;
440440
const auto &apback = evse.access_path_entries().back();
441441
if(!evse.is_initializer())
@@ -454,33 +454,33 @@ void local_value_set_analysist::transform_function_stub(
454454
local_value_sett::entryt &entry = valuesets.values.at(key);
455455
valuesets.make_union_adjusting_types(
456456
rhs_values, entry.object_map, evse.type(), ns);
457+
}
458+
// Also add the external set itself,
459+
// representing the possibility that the read
460+
// comes from outside *this* function as well:
461+
valuesets.insert(rhs_values, evse);
457462
}
458-
// Also add the external set itself,
459-
// representing the possibility that the read
460-
// comes from outside *this* function as well:
461-
valuesets.insert(rhs_values, evse);
462-
}
463-
else if(has_prefix(evse_label, PRECISE_EVS_PREFIX))
464-
{
465-
// Precise EVS
466-
PRECONDITION(!evse.access_path_entries().empty());
467-
exprt precise_access_path_expr =
468-
get_expr_from_precise_evs(evse, function_symbol, fcall, ns, *this);
463+
else if(has_prefix(evse_label, PRECISE_EVS_PREFIX))
464+
{
465+
// Precise EVS
466+
PRECONDITION(!evse.access_path_entries().empty());
467+
exprt precise_access_path_expr =
468+
get_expr_from_precise_evs(evse, function_symbol, fcall, ns, *this);
469469

470-
valuesets.get_value_set(
471-
precise_access_path_expr, rhs_values, ns, false);
472-
}
473-
else
474-
{
475-
// This should be an external value set of type ROOT_OBJECT. It denotes
476-
// the pointers that may be stored in a particular argument or global
477-
// pre-call.
478-
PRECONDITION(evse.access_path_entries().empty());
479-
exprt root_object_expr = get_expr_from_root_object_evs(
480-
evse, function_symbol, fcall, ns, *this);
481-
482-
valuesets.get_value_set(root_object_expr, rhs_values, ns, false);
483-
}
470+
valuesets.get_value_set(
471+
precise_access_path_expr, rhs_values, ns, false);
472+
}
473+
else
474+
{
475+
// This should be an external value set of type ROOT_OBJECT. It denotes
476+
// the pointers that may be stored in a particular argument or global
477+
// pre-call.
478+
PRECONDITION(evse.access_path_entries().empty());
479+
exprt root_object_expr = get_expr_from_root_object_evs(
480+
evse, function_symbol, fcall, ns, *this);
481+
482+
valuesets.get_value_set(root_object_expr, rhs_values, ns, false);
483+
}
484484
}
485485
else
486486
{
@@ -535,15 +535,14 @@ void local_value_set_analysist::transform_function_stub(
535535
lhs_fieldname.declared_on_type,
536536
lhs_fieldname.structured_lhs);
537537
irep_idt objkey = evse_entry.get_key(ns);
538-
valuesets.values.insert(std::make_pair(objkey, evse_entry));
539-
key_list.emplace_back(objkey);
538+
valuesets.values.emplace(objkey, evse_entry);
539+
key_list.push_back(std::move(objkey));
540540

541541
// Store the write to `weak_updates`:
542542
for(const irep_idt &key : key_list)
543543
{
544-
auto insert_it =
545-
weak_updates.insert(std::make_pair(key, valuesets.values.at(key)));
546-
valuesets.make_union(insert_it.first->second.object_map, rhs_values);
544+
auto result = weak_updates.emplace(key, valuesets.values.at(key));
545+
valuesets.make_union(result.first->second.object_map, rhs_values);
547546
}
548547
}
549548
else if(has_prefix(lhs_fieldname.base_name, PRECISE_EVS_PREFIX))
@@ -570,8 +569,7 @@ void local_value_set_analysist::transform_function_stub(
570569
lhs_fieldname.field_name,
571570
lhs_fieldname.declared_on_type,
572571
lhs_fieldname.structured_lhs);
573-
auto insertit =
574-
weak_updates.insert(std::make_pair(objkey, dynobj_entry_name));
572+
auto insertit = weak_updates.emplace(objkey, dynobj_entry_name);
575573
valuesets.make_union(insertit.first->second.object_map, rhs_values);
576574
}
577575
else
@@ -585,19 +583,22 @@ void local_value_set_analysist::transform_function_stub(
585583
lhs_fieldname.field_name,
586584
lhs_fieldname.declared_on_type,
587585
lhs_fieldname.structured_lhs);
588-
auto insert_it = weak_updates.insert(
589-
std::make_pair(global_entry.get_key(ns), global_entry));
586+
auto result =
587+
weak_updates.emplace(global_entry.get_key(ns), global_entry);
590588

591-
valuesets.make_union(insert_it.first->second.object_map, rhs_values);
589+
valuesets.make_union(result.first->second.object_map, rhs_values);
592590
}
593591
}
594592

595-
// Now apply the updates. We have to be careful that parameters might alias,
596-
// so we have to deal with strong updates in a slightly roundabout way. We
597-
// first write an empty object map to expr which got a strong update. If the
598-
// expr is singular then this will erase the object map. Then we write the
599-
// intended object map with `add_to_sets` false, so the write is weak. Then we
600-
// apply the weak updates.
593+
// Now apply the updates. We can't implement strong updates in the naive way
594+
// because if two parameters alias and both get strong updates then the first
595+
// one will get overwritten by the second one, whereas we want to end up with
596+
// the union of the two (but pre-existing entries in the value set should be
597+
// cleared).
598+
599+
// First go through all expressions that get strong updates and try to do a
600+
// strong write of an empty object map. If a strong write is possible then
601+
// this will clear the value set. Otherwise it will do nothing.
601602
value_sett::object_mapt empty_object_map;
602603
for(auto &strong_update : strong_updates)
603604
{
@@ -606,13 +607,16 @@ void local_value_set_analysist::transform_function_stub(
606607
strong_update.first, empty_object_map, ns, add_to_sets);
607608
}
608609

610+
// Now go through all strong updates doing a weak write of the desired object
611+
// map
609612
for(auto &strong_update : strong_updates)
610613
{
611614
const bool add_to_sets = true;
612615
valuesets.assign_valueset(
613616
strong_update.first, strong_update.second, ns, add_to_sets);
614617
}
615618

619+
// Finally do all weak updates
616620
valuesets.make_union(weak_updates);
617621
}
618622

0 commit comments

Comments
 (0)