-
Notifications
You must be signed in to change notification settings - Fork 273
/
Copy pathgoto_functions.cpp
149 lines (121 loc) · 3.85 KB
/
goto_functions.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
/*******************************************************************\
Module: Goto Programs with Functions
Author: Daniel Kroening
Date: June 2003
\*******************************************************************/
/// \file
/// Goto Programs with Functions
#include "goto_functions.h"
#include <util/namespace.h>
#include <util/symbol.h>
#include <algorithm>
void goto_functionst::compute_location_numbers()
{
unused_location_number = 0;
for(auto &func : function_map)
{
// Side-effect: bumps unused_location_number.
func.second.body.compute_location_numbers(unused_location_number);
}
}
void goto_functionst::compute_location_numbers(
goto_programt &program)
{
// Renumber just this single function. Use fresh numbers in case it has
// grown since it was last numbered.
program.compute_location_numbers(unused_location_number);
}
void goto_functionst::compute_incoming_edges()
{
for(auto &func : function_map)
{
func.second.body.compute_incoming_edges();
}
}
void goto_functionst::compute_target_numbers()
{
for(auto &func : function_map)
{
func.second.body.compute_target_numbers();
}
}
void goto_functionst::compute_loop_numbers()
{
for(auto &func : function_map)
{
func.second.body.compute_loop_numbers();
}
}
/// returns a vector of the iterators in alphabetical order
std::vector<goto_functionst::function_mapt::const_iterator>
goto_functionst::sorted() const
{
std::vector<function_mapt::const_iterator> result;
result.reserve(function_map.size());
for(auto it = function_map.begin(); it != function_map.end(); it++)
result.push_back(it);
std::sort(
result.begin(),
result.end(),
[](function_mapt::const_iterator a, function_mapt::const_iterator b) {
return id2string(a->first) < id2string(b->first);
});
return result;
}
/// returns a vector of the iterators in alphabetical order
std::vector<goto_functionst::function_mapt::iterator> goto_functionst::sorted()
{
std::vector<function_mapt::iterator> result;
result.reserve(function_map.size());
for(auto it = function_map.begin(); it != function_map.end(); it++)
result.push_back(it);
std::sort(
result.begin(),
result.end(),
[](function_mapt::iterator a, function_mapt::iterator b) {
return id2string(a->first) < id2string(b->first);
});
return result;
}
void goto_functionst::validate(const namespacet &ns, const validation_modet vm)
const
{
for(const auto &entry : function_map)
{
const goto_functiont &goto_function = entry.second;
const auto &function_name = entry.first;
const symbolt &function_symbol = ns.lookup(function_name);
const code_typet::parameterst ¶meters =
to_code_type(function_symbol.type).parameters();
DATA_CHECK(
vm,
goto_function.parameter_identifiers.size() == parameters.size(),
id2string(function_name) + " parameter count inconsistency\n" +
"goto program: " +
std::to_string(goto_function.parameter_identifiers.size()) +
"\nsymbol table: " + std::to_string(parameters.size()));
auto it = goto_function.parameter_identifiers.begin();
for(const auto ¶meter : parameters)
{
DATA_CHECK(
vm,
it->empty() || ns.lookup(*it).type == parameter.type(),
id2string(function_name) + " parameter type inconsistency\n" +
"goto program: " + ns.lookup(*it).type.id_string() +
"\nsymbol table: " + parameter.type().id_string());
++it;
}
goto_function.validate(ns, vm);
// Check that a void function does not contain any RETURN instructions
if(to_code_type(function_symbol.type).return_type().id() == ID_empty)
{
for(const auto &instruction : goto_function.body.instructions)
{
DATA_CHECK(
vm,
!instruction.is_set_return_value(),
"void function should not return a value");
}
}
}
}