@@ -12,6 +12,7 @@ Date: December 2016
1212// / Remove exception handling
1313
1414#include " remove_exceptions.h"
15+ #include " remove_instanceof.h"
1516
1617#ifdef DEBUG
1718#include < iostream>
@@ -43,8 +44,9 @@ Date: December 2016
4344// / (in instruction->code.exception_list()) and a corresponding GOTO program
4445// / target for each (in instruction->targets).
4546// / Thrown instructions are currently always matched to tags using
46- // / java_instanceof, so a language frontend wanting to use this class
47- // / must use exceptions with a Java-compatible structure.
47+ // / java_instanceof, optionally lowered to a check on the @class_identifier
48+ // / field, so a language frontend wanting to use this class must use
49+ // / exceptions with a Java-compatible structure.
4850// /
4951// / CATCH with a code_pop_catcht operand terminates a try-block begun by
5052// / a code_push_catcht. At present the try block consists of the instructions
@@ -72,9 +74,6 @@ Date: December 2016
7274// / instructions copy back to an ordinary local variable (or other expression)
7375// / and set \#exception_value back to null, indicating the exception has been
7476// / caught and normal control flow resumed.
75- // /
76- // / Note that remove_exceptions introduces java_instanceof comparisons at
77- // / present, so a remove_instanceof may be necessary after it completes.
7877class remove_exceptionst
7978{
8079 typedef std::vector<std::pair<
@@ -84,55 +83,62 @@ class remove_exceptionst
8483public:
8584 explicit remove_exceptionst (
8685 symbol_tablet &_symbol_table,
87- std::map<irep_idt, std::set<irep_idt>> &_exceptions_map):
88- symbol_table(_symbol_table),
89- exceptions_map(_exceptions_map)
86+ std::map<irep_idt, std::set<irep_idt>> &_exceptions_map,
87+ bool remove_added_instanceof)
88+ : symbol_table(_symbol_table),
89+ exceptions_map(_exceptions_map),
90+ remove_added_instanceof(remove_added_instanceof)
9091 {
9192 }
9293
93- void operator ()(
94- goto_functionst &goto_functions);
94+ void operator ()(goto_functionst &goto_functions);
9595
9696protected:
9797 symbol_tablet &symbol_table;
9898 std::map<irep_idt, std::set<irep_idt>> &exceptions_map;
99+ bool remove_added_instanceof;
99100
100101 void add_exceptional_returns (
101- const goto_functionst::function_mapt::iterator &);
102+ const irep_idt &function_id,
103+ goto_programt &goto_program);
102104
103105 void instrument_exception_handler (
104- const goto_functionst::function_mapt::iterator &,
106+ const irep_idt &function_id,
107+ goto_programt &goto_program,
105108 const goto_programt::targett &);
106109
107110 void add_exception_dispatch_sequence (
108- const goto_functionst::function_mapt::iterator &,
111+ const irep_idt &function_id,
112+ goto_programt &goto_program,
109113 const goto_programt::targett &instr_it,
110114 const stack_catcht &stack_catch,
111115 const std::vector<exprt> &locals);
112116
113117 void instrument_throw (
114- const goto_functionst::function_mapt::iterator &,
118+ const irep_idt &function_id,
119+ goto_programt &goto_program,
115120 const goto_programt::targett &,
116121 const stack_catcht &,
117122 const std::vector<exprt> &);
118123
119124 void instrument_function_call (
120- const goto_functionst::function_mapt::iterator &,
125+ const irep_idt &function_id,
126+ goto_programt &goto_program,
121127 const goto_programt::targett &,
122128 const stack_catcht &,
123129 const std::vector<exprt> &);
124130
125131 void instrument_exceptions (
126- const goto_functionst::function_mapt::iterator &);
132+ const irep_idt &function_id,
133+ goto_programt &goto_program);
127134};
128135
129136// / adds exceptional return variables for every function that may escape
130137// / exceptions
131138void remove_exceptionst::add_exceptional_returns (
132- const goto_functionst::function_mapt::iterator &func_it)
139+ const irep_idt &function_id,
140+ goto_programt &goto_program)
133141{
134- const irep_idt &function_id=func_it->first ;
135- goto_programt &goto_program=func_it->second .body ;
136142
137143 auto maybe_symbol=symbol_table.lookup (function_id);
138144 INVARIANT (maybe_symbol, " functions should be recorded in the symbol table" );
@@ -236,17 +242,17 @@ void remove_exceptionst::add_exceptional_returns(
236242// / Translates an exception landing-pad into instructions that copy the
237243// / in-flight exception pointer to a nominated expression, then clear the
238244// / in-flight exception (i.e. null the pointer), hence marking it caught.
239- // / \param func_it: iterator pointing to the function containing this
240- // / landingpad instruction
241- // / \param instr_it [in, out]: iterator pointing to the landingpad instruction.
245+ // / \param function_id: name of the function containing this landingpad
246+ // / instruction
247+ // / \param goto_program: body of the function containing this landingpad
248+ // / instruction
249+ // / \param instr_it: iterator pointing to the landingpad instruction.
242250// / Will be overwritten.
243251void remove_exceptionst::instrument_exception_handler (
244- const goto_functionst::function_mapt::iterator &func_it,
252+ const irep_idt &function_id,
253+ goto_programt &goto_program,
245254 const goto_programt::targett &instr_it)
246255{
247- const irep_idt &function_id=func_it->first ;
248- goto_programt &goto_program=func_it->second .body ;
249-
250256 PRECONDITION (instr_it->type ==CATCH);
251257
252258 // retrieve the exception variable
@@ -285,20 +291,19 @@ void remove_exceptionst::instrument_exception_handler(
285291// / if (exception instanceof ExnA) then goto handlerA
286292// / else if (exception instanceof ExnB) then goto handlerB
287293// / else goto universal_handler or (dead locals; function exit)
288- // / \param func_it: iterator pointing to function instr_it belongs to
294+ // / \param function_id: name of the function to which instr_it belongs
295+ // / \param goto_program: body of the function to which instr_it belongs
289296// / \param instr_it: throw or call instruction that may be an
290297// / exception source
291298// / \param stack_catch: exception handlers currently registered
292299// / \param locals: local variables to kill on a function-exit edge
293300void remove_exceptionst::add_exception_dispatch_sequence (
294- const goto_functionst::function_mapt::iterator &func_it,
301+ const irep_idt &function_id,
302+ goto_programt &goto_program,
295303 const goto_programt::targett &instr_it,
296304 const remove_exceptionst::stack_catcht &stack_catch,
297305 const std::vector<exprt> &locals)
298306{
299- const irep_idt &function_id=func_it->first ;
300- goto_programt &goto_program=func_it->second .body ;
301-
302307 // Unless we have a universal exception handler, jump to end of function
303308 // if not caught:
304309 goto_programt::targett default_target=goto_program.get_end_function ();
@@ -343,6 +348,9 @@ void remove_exceptionst::add_exception_dispatch_sequence(
343348
344349 binary_predicate_exprt check (exc_thrown, ID_java_instanceof, expr);
345350 t_exc->guard =check;
351+
352+ if (remove_added_instanceof)
353+ remove_instanceof (t_exc, goto_program, symbol_table);
346354 }
347355 }
348356 }
@@ -360,10 +368,11 @@ void remove_exceptionst::add_exception_dispatch_sequence(
360368 }
361369}
362370
363- // / instruments each throw with conditional GOTOS to the corresponding
371+ // / instruments each throw with conditional GOTOS to the corresponding
364372// / exception handlers
365373void remove_exceptionst::instrument_throw (
366- const goto_functionst::function_mapt::iterator &func_it,
374+ const irep_idt &function_id,
375+ goto_programt &goto_program,
367376 const goto_programt::targett &instr_it,
368377 const remove_exceptionst::stack_catcht &stack_catch,
369378 const std::vector<exprt> &locals)
@@ -383,11 +392,11 @@ void remove_exceptionst::instrument_throw(
383392 return ;
384393
385394 add_exception_dispatch_sequence (
386- func_it , instr_it, stack_catch, locals);
395+ function_id, goto_program , instr_it, stack_catch, locals);
387396
388397 // find the symbol where the thrown exception should be stored:
389- const symbolt &exc_symbol=
390- symbol_table.lookup_ref (id2string (func_it-> first )+ EXC_SUFFIX);
398+ const symbolt &exc_symbol =
399+ symbol_table.lookup_ref (id2string (function_id) + EXC_SUFFIX);
391400 symbol_exprt exc_thrown=exc_symbol.symbol_expr ();
392401
393402 // add the assignment with the appropriate cast
@@ -401,16 +410,14 @@ void remove_exceptionst::instrument_throw(
401410// / instruments each function call that may escape exceptions with conditional
402411// / GOTOS to the corresponding exception handlers
403412void remove_exceptionst::instrument_function_call (
404- const goto_functionst::function_mapt::iterator &func_it,
413+ const irep_idt &function_id,
414+ goto_programt &goto_program,
405415 const goto_programt::targett &instr_it,
406416 const stack_catcht &stack_catch,
407417 const std::vector<exprt> &locals)
408418{
409419 PRECONDITION (instr_it->type ==FUNCTION_CALL);
410420
411- goto_programt &goto_program=func_it->second .body ;
412- const irep_idt &function_id=func_it->first ;
413-
414421 // save the address of the next instruction
415422 goto_programt::targett next_it=instr_it;
416423 next_it++;
@@ -430,7 +437,7 @@ void remove_exceptionst::instrument_function_call(
430437 if (callee_inflight_exception && local_inflight_exception)
431438 {
432439 add_exception_dispatch_sequence (
433- func_it , instr_it, stack_catch, locals);
440+ function_id, goto_program , instr_it, stack_catch, locals);
434441
435442 const symbol_exprt callee_inflight_exception_expr=
436443 callee_inflight_exception->symbol_expr ();
@@ -463,12 +470,12 @@ void remove_exceptionst::instrument_function_call(
463470// / handlers. Additionally, it re-computes the live-range of local variables in
464471// / order to add DEAD instructions.
465472void remove_exceptionst::instrument_exceptions (
466- const goto_functionst::function_mapt::iterator &func_it)
473+ const irep_idt &function_id,
474+ goto_programt &goto_program)
467475{
468476 stack_catcht stack_catch; // stack of try-catch blocks
469477 std::vector<std::vector<exprt>> stack_locals; // stack of local vars
470478 std::vector<exprt> locals;
471- goto_programt &goto_program=func_it->second .body ;
472479
473480 if (goto_program.empty ())
474481 return ;
@@ -486,7 +493,7 @@ void remove_exceptionst::instrument_exceptions(
486493 // Is it an exception landing pad (start of a catch block)?
487494 if (statement==ID_exception_landingpad)
488495 {
489- instrument_exception_handler (func_it , instr_it);
496+ instrument_exception_handler (function_id, goto_program , instr_it);
490497 }
491498 // Is it a catch handler pop?
492499 else if (statement==ID_pop_catch)
@@ -551,39 +558,43 @@ void remove_exceptionst::instrument_exceptions(
551558 }
552559 else if (instr_it->type ==THROW)
553560 {
554- instrument_throw (func_it, instr_it, stack_catch, locals);
561+ instrument_throw (
562+ function_id, goto_program, instr_it, stack_catch, locals);
555563 }
556564 else if (instr_it->type ==FUNCTION_CALL)
557565 {
558- instrument_function_call (func_it, instr_it, stack_catch, locals);
566+ instrument_function_call (
567+ function_id, goto_program, instr_it, stack_catch, locals);
559568 }
560569 }
561570}
562571
563572void remove_exceptionst::operator ()(goto_functionst &goto_functions)
564573{
565574 Forall_goto_functions (it, goto_functions)
566- add_exceptional_returns (it);
575+ add_exceptional_returns (it-> first , it-> second . body );
567576 Forall_goto_functions (it, goto_functions)
568- instrument_exceptions (it);
577+ instrument_exceptions (it-> first , it-> second . body );
569578}
570579
571580// / removes throws/CATCH-POP/CATCH-PUSH
572581void remove_exceptions (
573582 symbol_tablet &symbol_table,
574- goto_functionst &goto_functions)
583+ goto_functionst &goto_functions,
584+ remove_exceptions_typest type)
575585{
576586 const namespacet ns (symbol_table);
577587 std::map<irep_idt, std::set<irep_idt>> exceptions_map;
578588 uncaught_exceptions (goto_functions, ns, exceptions_map);
579- remove_exceptionst remove_exceptions (symbol_table, exceptions_map);
589+ remove_exceptionst remove_exceptions (
590+ symbol_table,
591+ exceptions_map,
592+ type == remove_exceptions_typest::REMOVE_ADDED_INSTANCEOF);
580593 remove_exceptions (goto_functions);
581594}
582595
583596// / removes throws/CATCH-POP/CATCH-PUSH
584- void remove_exceptions (goto_modelt &goto_model)
597+ void remove_exceptions (goto_modelt &goto_model, remove_exceptions_typest type )
585598{
586- remove_exceptions (
587- goto_model.symbol_table ,
588- goto_model.goto_functions );
599+ remove_exceptions (goto_model.symbol_table , goto_model.goto_functions , type);
589600}
0 commit comments