Skip to content

Commit 890b8b1

Browse files
committed
Remove exceptions: add per-function entry point
This removes high-level exception-related instructions from a single function, at the cost of some accuracy as we can no longer analyse other functions to determine whether or not they may throw, and therefore always assume they will.
1 parent f6219d4 commit 890b8b1

File tree

2 files changed

+53
-12
lines changed

2 files changed

+53
-12
lines changed

src/goto-programs/remove_exceptions.cpp

+47-12
Original file line numberDiff line numberDiff line change
@@ -79,23 +79,25 @@ class remove_exceptionst
7979
typedef std::vector<std::pair<
8080
irep_idt, goto_programt::targett>> catch_handlerst;
8181
typedef std::vector<catch_handlerst> stack_catcht;
82+
typedef std::function<bool(const irep_idt &)> function_may_throwt;
8283

8384
public:
8485
explicit remove_exceptionst(
85-
symbol_tablet &_symbol_table,
86-
std::map<irep_idt, std::set<irep_idt>> &_exceptions_map,
86+
symbol_table_baset &_symbol_table,
87+
function_may_throwt _function_may_throw,
8788
bool remove_added_instanceof)
8889
: symbol_table(_symbol_table),
89-
exceptions_map(_exceptions_map),
90+
function_may_throw(_function_may_throw),
9091
remove_added_instanceof(remove_added_instanceof)
9192
{
9293
}
9394

9495
void operator()(goto_functionst &goto_functions);
96+
void operator()(goto_programt &goto_program);
9597

9698
protected:
97-
symbol_tablet &symbol_table;
98-
std::map<irep_idt, std::set<irep_idt>> &exceptions_map;
99+
symbol_table_baset &symbol_table;
100+
function_may_throwt function_may_throw;
99101
bool remove_added_instanceof;
100102

101103
symbol_exprt get_inflight_exception_global();
@@ -177,8 +179,7 @@ bool remove_exceptionst::function_or_callees_may_throw(
177179
"identifier expected to be a symbol");
178180
const irep_idt &function_name=
179181
to_symbol_expr(function_expr).get_identifier();
180-
bool callee_may_throw = !exceptions_map[function_name].empty();
181-
if(callee_may_throw)
182+
if(function_may_throw(function_name))
182183
return true;
183184
}
184185
}
@@ -424,9 +425,7 @@ void remove_exceptionst::instrument_function_call(
424425
const irep_idt &callee_id=
425426
to_symbol_expr(function_call.function()).get_identifier();
426427

427-
bool callee_may_throw = !exceptions_map[callee_id].empty();
428-
429-
if(callee_may_throw)
428+
if(function_may_throw(callee_id))
430429
{
431430
add_exception_dispatch_sequence(
432431
goto_program, instr_it, stack_catch, locals);
@@ -557,22 +556,58 @@ void remove_exceptionst::operator()(goto_functionst &goto_functions)
557556
instrument_exceptions(it->second.body);
558557
}
559558

559+
void remove_exceptionst::operator()(goto_programt &goto_program)
560+
{
561+
instrument_exceptions(goto_program);
562+
}
563+
560564
/// removes throws/CATCH-POP/CATCH-PUSH
561565
void remove_exceptions(
562-
symbol_tablet &symbol_table,
566+
symbol_table_baset &symbol_table,
563567
goto_functionst &goto_functions,
564568
remove_exceptions_typest type)
565569
{
566570
const namespacet ns(symbol_table);
567571
std::map<irep_idt, std::set<irep_idt>> exceptions_map;
568572
uncaught_exceptions(goto_functions, ns, exceptions_map);
573+
// NOLINTNEXTLINE
574+
auto function_may_throw = [&exceptions_map](const irep_idt &id) {
575+
return !exceptions_map[id].empty();
576+
};
569577
remove_exceptionst remove_exceptions(
570578
symbol_table,
571-
exceptions_map,
579+
function_may_throw,
572580
type == remove_exceptions_typest::REMOVE_ADDED_INSTANCEOF);
573581
remove_exceptions(goto_functions);
574582
}
575583

584+
/// removes throws/CATCH-POP/CATCH-PUSH from a single GOTO program, replacing
585+
/// them with explicit exception propagation.
586+
/// Note this is somewhat less accurate than the whole-goto-model version,
587+
/// because we can't inspect other functions to determine whether they throw
588+
/// or not, and therefore must assume they do and always introduce post-call
589+
/// exception dispatch.
590+
/// \param goto_program: program to remove exceptions from
591+
/// \param symbol_table: global symbol table. The `@inflight_exception` global
592+
/// may be added if not already present. It will not be initialised; that is
593+
/// the caller's responsibility.
594+
/// \param type: specifies whether instanceof operations generated by this pass
595+
/// should be lowered to class-identifier comparisons (using
596+
/// remove_instanceof).
597+
void remove_exceptions(
598+
goto_programt &goto_program,
599+
symbol_table_baset &symbol_table,
600+
remove_exceptions_typest type)
601+
{
602+
auto any_function_may_throw = [](const irep_idt &id) { return true; };
603+
604+
remove_exceptionst remove_exceptions(
605+
symbol_table,
606+
any_function_may_throw,
607+
type == remove_exceptions_typest::REMOVE_ADDED_INSTANCEOF);
608+
remove_exceptions(goto_program);
609+
}
610+
576611
/// removes throws/CATCH-POP/CATCH-PUSH
577612
void remove_exceptions(goto_modelt &goto_model, remove_exceptions_typest type)
578613
{

src/goto-programs/remove_exceptions.h

+6
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,12 @@ enum class remove_exceptions_typest
2929
DONT_REMOVE_INSTANCEOF,
3030
};
3131

32+
void remove_exceptions(
33+
goto_programt &goto_program,
34+
symbol_table_baset &symbol_table,
35+
remove_exceptions_typest type =
36+
remove_exceptions_typest::DONT_REMOVE_INSTANCEOF);
37+
3238
void remove_exceptions(
3339
goto_modelt &goto_model,
3440
remove_exceptions_typest type =

0 commit comments

Comments
 (0)