@@ -12,6 +12,7 @@ Date: December 2016
12
12
// / Remove exception handling
13
13
14
14
#include " remove_exceptions.h"
15
+ #include " remove_instanceof.h"
15
16
16
17
#ifdef DEBUG
17
18
#include < iostream>
@@ -43,8 +44,9 @@ Date: December 2016
43
44
// / (in instruction->code.exception_list()) and a corresponding GOTO program
44
45
// / target for each (in instruction->targets).
45
46
// / 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.
48
50
// /
49
51
// / CATCH with a code_pop_catcht operand terminates a try-block begun by
50
52
// / a code_push_catcht. At present the try block consists of the instructions
@@ -72,9 +74,6 @@ Date: December 2016
72
74
// / instructions copy back to an ordinary local variable (or other expression)
73
75
// / and set \#exception_value back to null, indicating the exception has been
74
76
// / 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.
78
77
class remove_exceptionst
79
78
{
80
79
typedef std::vector<std::pair<
@@ -84,55 +83,62 @@ class remove_exceptionst
84
83
public:
85
84
explicit remove_exceptionst (
86
85
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)
90
91
{
91
92
}
92
93
93
- void operator ()(
94
- goto_functionst &goto_functions);
94
+ void operator ()(goto_functionst &goto_functions);
95
95
96
96
protected:
97
97
symbol_tablet &symbol_table;
98
98
std::map<irep_idt, std::set<irep_idt>> &exceptions_map;
99
+ bool remove_added_instanceof;
99
100
100
101
void add_exceptional_returns (
101
- const goto_functionst::function_mapt::iterator &);
102
+ const irep_idt &function_id,
103
+ goto_programt &goto_program);
102
104
103
105
void instrument_exception_handler (
104
- const goto_functionst::function_mapt::iterator &,
106
+ const irep_idt &function_id,
107
+ goto_programt &goto_program,
105
108
const goto_programt::targett &);
106
109
107
110
void add_exception_dispatch_sequence (
108
- const goto_functionst::function_mapt::iterator &,
111
+ const irep_idt &function_id,
112
+ goto_programt &goto_program,
109
113
const goto_programt::targett &instr_it,
110
114
const stack_catcht &stack_catch,
111
115
const std::vector<exprt> &locals);
112
116
113
117
void instrument_throw (
114
- const goto_functionst::function_mapt::iterator &,
118
+ const irep_idt &function_id,
119
+ goto_programt &goto_program,
115
120
const goto_programt::targett &,
116
121
const stack_catcht &,
117
122
const std::vector<exprt> &);
118
123
119
124
void instrument_function_call (
120
- const goto_functionst::function_mapt::iterator &,
125
+ const irep_idt &function_id,
126
+ goto_programt &goto_program,
121
127
const goto_programt::targett &,
122
128
const stack_catcht &,
123
129
const std::vector<exprt> &);
124
130
125
131
void instrument_exceptions (
126
- const goto_functionst::function_mapt::iterator &);
132
+ const irep_idt &function_id,
133
+ goto_programt &goto_program);
127
134
};
128
135
129
136
// / adds exceptional return variables for every function that may escape
130
137
// / exceptions
131
138
void 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)
133
141
{
134
- const irep_idt &function_id=func_it->first ;
135
- goto_programt &goto_program=func_it->second .body ;
136
142
137
143
auto maybe_symbol=symbol_table.lookup (function_id);
138
144
INVARIANT (maybe_symbol, " functions should be recorded in the symbol table" );
@@ -236,17 +242,17 @@ void remove_exceptionst::add_exceptional_returns(
236
242
// / Translates an exception landing-pad into instructions that copy the
237
243
// / in-flight exception pointer to a nominated expression, then clear the
238
244
// / 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.
242
250
// / Will be overwritten.
243
251
void 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,
245
254
const goto_programt::targett &instr_it)
246
255
{
247
- const irep_idt &function_id=func_it->first ;
248
- goto_programt &goto_program=func_it->second .body ;
249
-
250
256
PRECONDITION (instr_it->type ==CATCH);
251
257
252
258
// retrieve the exception variable
@@ -285,20 +291,19 @@ void remove_exceptionst::instrument_exception_handler(
285
291
// / if (exception instanceof ExnA) then goto handlerA
286
292
// / else if (exception instanceof ExnB) then goto handlerB
287
293
// / 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
289
296
// / \param instr_it: throw or call instruction that may be an
290
297
// / exception source
291
298
// / \param stack_catch: exception handlers currently registered
292
299
// / \param locals: local variables to kill on a function-exit edge
293
300
void 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,
295
303
const goto_programt::targett &instr_it,
296
304
const remove_exceptionst::stack_catcht &stack_catch,
297
305
const std::vector<exprt> &locals)
298
306
{
299
- const irep_idt &function_id=func_it->first ;
300
- goto_programt &goto_program=func_it->second .body ;
301
-
302
307
// Unless we have a universal exception handler, jump to end of function
303
308
// if not caught:
304
309
goto_programt::targett default_target=goto_program.get_end_function ();
@@ -343,6 +348,9 @@ void remove_exceptionst::add_exception_dispatch_sequence(
343
348
344
349
binary_predicate_exprt check (exc_thrown, ID_java_instanceof, expr);
345
350
t_exc->guard =check;
351
+
352
+ if (remove_added_instanceof)
353
+ remove_instanceof (t_exc, goto_program, symbol_table);
346
354
}
347
355
}
348
356
}
@@ -360,10 +368,11 @@ void remove_exceptionst::add_exception_dispatch_sequence(
360
368
}
361
369
}
362
370
363
- // / instruments each throw with conditional GOTOS to the corresponding
371
+ // / instruments each throw with conditional GOTOS to the corresponding
364
372
// / exception handlers
365
373
void remove_exceptionst::instrument_throw (
366
- const goto_functionst::function_mapt::iterator &func_it,
374
+ const irep_idt &function_id,
375
+ goto_programt &goto_program,
367
376
const goto_programt::targett &instr_it,
368
377
const remove_exceptionst::stack_catcht &stack_catch,
369
378
const std::vector<exprt> &locals)
@@ -383,11 +392,11 @@ void remove_exceptionst::instrument_throw(
383
392
return ;
384
393
385
394
add_exception_dispatch_sequence (
386
- func_it , instr_it, stack_catch, locals);
395
+ function_id, goto_program , instr_it, stack_catch, locals);
387
396
388
397
// 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);
391
400
symbol_exprt exc_thrown=exc_symbol.symbol_expr ();
392
401
393
402
// add the assignment with the appropriate cast
@@ -401,16 +410,14 @@ void remove_exceptionst::instrument_throw(
401
410
// / instruments each function call that may escape exceptions with conditional
402
411
// / GOTOS to the corresponding exception handlers
403
412
void 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,
405
415
const goto_programt::targett &instr_it,
406
416
const stack_catcht &stack_catch,
407
417
const std::vector<exprt> &locals)
408
418
{
409
419
PRECONDITION (instr_it->type ==FUNCTION_CALL);
410
420
411
- goto_programt &goto_program=func_it->second .body ;
412
- const irep_idt &function_id=func_it->first ;
413
-
414
421
// save the address of the next instruction
415
422
goto_programt::targett next_it=instr_it;
416
423
next_it++;
@@ -430,7 +437,7 @@ void remove_exceptionst::instrument_function_call(
430
437
if (callee_inflight_exception && local_inflight_exception)
431
438
{
432
439
add_exception_dispatch_sequence (
433
- func_it , instr_it, stack_catch, locals);
440
+ function_id, goto_program , instr_it, stack_catch, locals);
434
441
435
442
const symbol_exprt callee_inflight_exception_expr=
436
443
callee_inflight_exception->symbol_expr ();
@@ -463,12 +470,12 @@ void remove_exceptionst::instrument_function_call(
463
470
// / handlers. Additionally, it re-computes the live-range of local variables in
464
471
// / order to add DEAD instructions.
465
472
void remove_exceptionst::instrument_exceptions (
466
- const goto_functionst::function_mapt::iterator &func_it)
473
+ const irep_idt &function_id,
474
+ goto_programt &goto_program)
467
475
{
468
476
stack_catcht stack_catch; // stack of try-catch blocks
469
477
std::vector<std::vector<exprt>> stack_locals; // stack of local vars
470
478
std::vector<exprt> locals;
471
- goto_programt &goto_program=func_it->second .body ;
472
479
473
480
if (goto_program.empty ())
474
481
return ;
@@ -486,7 +493,7 @@ void remove_exceptionst::instrument_exceptions(
486
493
// Is it an exception landing pad (start of a catch block)?
487
494
if (statement==ID_exception_landingpad)
488
495
{
489
- instrument_exception_handler (func_it , instr_it);
496
+ instrument_exception_handler (function_id, goto_program , instr_it);
490
497
}
491
498
// Is it a catch handler pop?
492
499
else if (statement==ID_pop_catch)
@@ -551,39 +558,43 @@ void remove_exceptionst::instrument_exceptions(
551
558
}
552
559
else if (instr_it->type ==THROW)
553
560
{
554
- instrument_throw (func_it, instr_it, stack_catch, locals);
561
+ instrument_throw (
562
+ function_id, goto_program, instr_it, stack_catch, locals);
555
563
}
556
564
else if (instr_it->type ==FUNCTION_CALL)
557
565
{
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);
559
568
}
560
569
}
561
570
}
562
571
563
572
void remove_exceptionst::operator ()(goto_functionst &goto_functions)
564
573
{
565
574
Forall_goto_functions (it, goto_functions)
566
- add_exceptional_returns (it);
575
+ add_exceptional_returns (it-> first , it-> second . body );
567
576
Forall_goto_functions (it, goto_functions)
568
- instrument_exceptions (it);
577
+ instrument_exceptions (it-> first , it-> second . body );
569
578
}
570
579
571
580
// / removes throws/CATCH-POP/CATCH-PUSH
572
581
void remove_exceptions (
573
582
symbol_tablet &symbol_table,
574
- goto_functionst &goto_functions)
583
+ goto_functionst &goto_functions,
584
+ remove_exceptions_typest type)
575
585
{
576
586
const namespacet ns (symbol_table);
577
587
std::map<irep_idt, std::set<irep_idt>> exceptions_map;
578
588
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);
580
593
remove_exceptions (goto_functions);
581
594
}
582
595
583
596
// / 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 )
585
598
{
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);
589
600
}
0 commit comments