Skip to content

Commit 3b625fc

Browse files
authored
Merge pull request #2718 from tautschnig/syntactic-eq
Central implementation of syntactic equality of instructions and goto programs
2 parents 51eed48 + 41def9f commit 3b625fc

File tree

5 files changed

+58
-40
lines changed

5 files changed

+58
-40
lines changed

jbmc/src/jdiff/java_syntactic_diff.cpp

Lines changed: 2 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -70,9 +70,7 @@ bool java_syntactic_difft::operator()()
7070
continue;
7171
}
7272

73-
if(
74-
it->second.body.instructions.size() !=
75-
f_it->second.body.instructions.size())
73+
if(!it->second.body.equals(f_it->second.body))
7674
{
7775
modified_functions.insert(it->first);
7876
continue;
@@ -86,22 +84,7 @@ bool java_syntactic_difft::operator()()
8684
i_it2 != f_it->second.body.instructions.end();
8785
++i_it1, ++i_it2)
8886
{
89-
long jump_difference1 = 0;
90-
if(!i_it1->targets.empty())
91-
{
92-
jump_difference1 =
93-
i_it1->get_target()->location_number - i_it1->location_number;
94-
}
95-
long jump_difference2 = 0;
96-
if(!i_it2->targets.empty())
97-
{
98-
jump_difference2 =
99-
i_it2->get_target()->location_number - i_it2->location_number;
100-
}
101-
if(
102-
i_it1->code != i_it2->code || i_it1->function != i_it2->function ||
103-
i_it1->type != i_it2->type || i_it1->guard != i_it2->guard ||
104-
jump_difference1 != jump_difference2)
87+
if(i_it1->function != i_it2->function)
10588
{
10689
modified_functions.insert(it->first);
10790
break;

src/goto-diff/syntactic_diff.cpp

Lines changed: 2 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -69,8 +69,7 @@ bool syntactic_difft::operator()()
6969
continue;
7070
}
7171

72-
if(it->second.body.instructions.size() !=
73-
f_it->second.body.instructions.size())
72+
if(!it->second.body.equals(f_it->second.body))
7473
{
7574
modified_functions.insert(it->first);
7675
continue;
@@ -84,22 +83,7 @@ bool syntactic_difft::operator()()
8483
i_it2!=f_it->second.body.instructions.end();
8584
++i_it1, ++i_it2)
8685
{
87-
long jump_difference1 = 0;
88-
if(!i_it1->targets.empty())
89-
{
90-
jump_difference1 =
91-
i_it1->get_target()->location_number - i_it1->location_number;
92-
}
93-
long jump_difference2 = 0;
94-
if(!i_it2->targets.empty())
95-
{
96-
jump_difference2 =
97-
i_it2->get_target()->location_number - i_it2->location_number;
98-
}
99-
if(
100-
i_it1->code != i_it2->code || i_it1->function != i_it2->function ||
101-
i_it1->type != i_it2->type || i_it1->guard != i_it2->guard ||
102-
jump_difference1 != jump_difference2)
86+
if(i_it1->function != i_it2->function)
10387
{
10488
modified_functions.insert(it->first);
10589
break;

src/goto-diff/unified_diff.cpp

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -392,9 +392,7 @@ bool unified_difft::instructions_equal(
392392
const goto_programt::instructiont &ins1,
393393
const goto_programt::instructiont &ins2)
394394
{
395-
return ins1.code == ins2.code && ins1.function == ins2.function &&
396-
ins1.type == ins2.type && ins1.guard == ins2.guard &&
397-
ins1.targets.size() == ins2.targets.size() &&
395+
return ins1.equals(ins2) && ins1.function == ins2.function &&
398396
(ins1.targets.empty() ||
399397
instructions_equal(*ins1.get_target(), *ins2.get_target()));
400398
}

src/goto-programs/goto_program.cpp

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -634,3 +634,45 @@ void goto_programt::compute_incoming_edges()
634634
}
635635
}
636636

637+
bool goto_programt::instructiont::equals(const instructiont &other) const
638+
{
639+
// clang-format off
640+
return
641+
type == other.type &&
642+
code == other.code &&
643+
guard == other.guard &&
644+
targets.size() == other.targets.size() &&
645+
labels == other.labels;
646+
// clang-format on
647+
}
648+
649+
bool goto_programt::equals(const goto_programt &other) const
650+
{
651+
if(instructions.size() != other.instructions.size())
652+
return false;
653+
654+
goto_programt::const_targett other_it = other.instructions.begin();
655+
for(const auto &ins : instructions)
656+
{
657+
if(!ins.equals(*other_it))
658+
return false;
659+
660+
// the number of targets is the same as instructiont::equals returned "true"
661+
auto other_target_it = other_it->targets.begin();
662+
for(const auto t : ins.targets)
663+
{
664+
if(
665+
t->location_number - ins.location_number !=
666+
(*other_target_it)->location_number - other_it->location_number)
667+
{
668+
return false;
669+
}
670+
671+
++other_target_it;
672+
}
673+
674+
++other_it;
675+
}
676+
677+
return true;
678+
}

src/goto-programs/goto_program.h

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -389,6 +389,12 @@ class goto_programt
389389
instruction_id_builder << type;
390390
return instruction_id_builder.str();
391391
}
392+
393+
/// Syntactic equality: two instructiont are equal if they have the same
394+
/// type, code, guard, number of targets, and labels. All other members can
395+
/// only be evaluated in the context of a goto_programt (see
396+
/// goto_programt::equals).
397+
bool equals(const instructiont &other) const;
392398
};
393399

394400
// Never try to change this to vector-we mutate the list while iterating
@@ -640,6 +646,11 @@ class goto_programt
640646
typedef std::set<irep_idt> decl_identifierst;
641647
/// get the variables in decl statements
642648
void get_decl_identifiers(decl_identifierst &decl_identifiers) const;
649+
650+
/// Syntactic equality: two goto_programt are equal if, and only if, they have
651+
/// the same number of instructions, each pair of instructions compares equal,
652+
/// and relative jumps have the same distance.
653+
bool equals(const goto_programt &other) const;
643654
};
644655

645656
template <typename Target>

0 commit comments

Comments
 (0)