Skip to content

Commit 5d534eb

Browse files
committed
Clean up CATCH instruction code
The three types of CATCH instruction (push-handler, pop-handler and handler-landingpad) are now represented by distinct codet subclasses, and the codet and GOTO representations have been made uniform (the goto-convert step is a simple copy with instruction type CATCH). The Java version of push-catch gives <type-tag, label> pairs and then later populates GOTO targets for them, while the C++ version, being block-structured by nature, omits the labels and directly populates the GOTO instruction targets.
1 parent d15c67d commit 5d534eb

11 files changed

+220
-247
lines changed

src/goto-programs/goto_convert.cpp

Lines changed: 18 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -58,31 +58,24 @@ static void finish_catch_push_targets(goto_programt &dest)
5858
// in the second pass set the targets
5959
Forall_goto_program_instructions(it, dest)
6060
{
61-
if(it->is_catch())
61+
if(it->is_catch() && it->code.get_statement()==ID_push_catch)
6262
{
63-
bool handler_added=true;
64-
irept exceptions=it->code.find(ID_exception_list);
63+
// Populate `targets` with a GOTO instruction target per
64+
// exception handler if it isn't already populated.
65+
// (Java handlers, for example, need this finish step; C++
66+
// handlers will already be populated by now)
6567

66-
if(exceptions.is_nil() &&
67-
it->code.has_operands())
68-
exceptions=it->code.op0().find(ID_exception_list);
69-
70-
const irept::subt &exception_list=exceptions.get_sub();
71-
72-
if(!exception_list.empty())
68+
if(it->targets.empty())
7369
{
74-
// in this case we have a CATCH_PUSH
75-
irept handlers=it->code.find(ID_label);
76-
if(handlers.is_nil() &&
77-
it->code.has_operands())
78-
handlers=it->code.op0().find(ID_label);
79-
const irept::subt &handler_list=handlers.get_sub();
80-
81-
// some handlers may not have been converted (if there was no
82-
// exception to be caught); in such a situation we abort
70+
bool handler_added=true;
71+
const code_push_catcht::exception_listt &handler_list=
72+
to_code_push_catch(it->code).exception_list();
73+
8374
for(const auto &handler : handler_list)
8475
{
85-
if(label_targets.find(handler.id())==label_targets.end())
76+
// some handlers may not have been converted (if there was no
77+
// exception to be caught); in such a situation we abort
78+
if(label_targets.find(handler.get_label())==label_targets.end())
8679
{
8780
handler_added=false;
8881
break;
@@ -93,14 +86,7 @@ static void finish_catch_push_targets(goto_programt &dest)
9386
continue;
9487

9588
for(const auto &handler : handler_list)
96-
{
97-
std::map<irep_idt,
98-
goto_programt::targett>::const_iterator handler_it=
99-
label_targets.find(handler.id());
100-
assert(handler_it!=label_targets.end());
101-
// set the target
102-
it->targets.push_back(handler_it->second);
103-
}
89+
it->targets.push_back(label_targets.at(handler.get_label()));
10490
}
10591
}
10692
}
@@ -566,6 +552,10 @@ void goto_convertt::convert(
566552
forall_operands(it, code)
567553
convert(to_code(*it), dest);
568554
}
555+
else if(statement==ID_push_catch ||
556+
statement==ID_pop_catch ||
557+
statement==ID_exception_landingpad)
558+
copy(code, CATCH, dest);
569559
else
570560
copy(code, OTHER, dest);
571561

src/goto-programs/goto_convert_class.h

Lines changed: 0 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -97,12 +97,6 @@ class goto_convertt:public messaget
9797
side_effect_exprt &expr,
9898
goto_programt &dest,
9999
bool result_is_used);
100-
void remove_push_catch(
101-
side_effect_exprt &expr,
102-
goto_programt &dest);
103-
void remove_exception_landingpad(
104-
side_effect_exprt &expr,
105-
goto_programt &dest);
106100
void remove_assignment(
107101
side_effect_exprt &expr,
108102
goto_programt &dest,
@@ -246,10 +240,6 @@ class goto_convertt:public messaget
246240
void convert_msc_try_except(const codet &code, goto_programt &dest);
247241
void convert_msc_leave(const codet &code, goto_programt &dest);
248242
void convert_try_catch(const codet &code, goto_programt &dest);
249-
void convert_java_try_catch(const codet &code, goto_programt &dest);
250-
void convert_java_exception_landingpad(
251-
const codet &code,
252-
goto_programt &dest);
253243
void convert_CPROVER_try_catch(const codet &code, goto_programt &dest);
254244
void convert_CPROVER_try_finally(const codet &code, goto_programt &dest);
255245
void convert_CPROVER_throw(const codet &code, goto_programt &dest);

src/goto-programs/goto_convert_exceptions.cpp

Lines changed: 9 additions & 68 deletions
Original file line numberDiff line numberDiff line change
@@ -93,69 +93,6 @@ void goto_convertt::convert_msc_leave(
9393
t->source_location=code.source_location();
9494
}
9595

96-
void goto_convertt::convert_java_try_catch(
97-
const codet &code,
98-
goto_programt &dest)
99-
{
100-
assert(!code.operands().empty());
101-
102-
// add the CATCH instruction to 'dest'
103-
goto_programt::targett catch_instruction=dest.add_instruction();
104-
catch_instruction->make_catch();
105-
catch_instruction->code.set_statement(ID_catch);
106-
catch_instruction->source_location=code.source_location();
107-
catch_instruction->function=code.source_location().get_function();
108-
109-
// the CATCH instruction is annotated with a list of exception IDs
110-
const irept exceptions=code.op0().find(ID_exception_list);
111-
if(exceptions.is_not_nil())
112-
{
113-
irept::subt exceptions_sub=exceptions.get_sub();
114-
irept::subt &exception_list=
115-
catch_instruction->code.add(ID_exception_list).get_sub();
116-
exception_list.resize(exceptions_sub.size());
117-
for(size_t i=0; i<exceptions_sub.size(); ++i)
118-
exception_list[i].id(exceptions_sub[i].id());
119-
}
120-
121-
// the CATCH instruction is also annotated with a list of handle labels
122-
const irept handlers=code.op0().find(ID_label);
123-
if(handlers.is_not_nil())
124-
{
125-
irept::subt handlers_sub=handlers.get_sub();
126-
irept::subt &handlers_list=
127-
catch_instruction->code.add(ID_label).get_sub();
128-
handlers_list.resize(handlers_sub.size());
129-
for(size_t i=0; i<handlers_sub.size(); ++i)
130-
handlers_list[i].id(handlers_sub[i].id());
131-
}
132-
133-
// add a SKIP target for the end of everything
134-
goto_programt end;
135-
goto_programt::targett end_target=end.add_instruction();
136-
end_target->make_skip();
137-
end_target->source_location=code.source_location();
138-
end_target->function=code.source_location().get_function();
139-
140-
// add the end-target
141-
dest.destructive_append(end);
142-
}
143-
144-
/// Lower a side_effect_exprt describing an exception
145-
/// landing-pad (catch site) into GOTO code
146-
/// \param code: code to convert
147-
/// (must be a code_expressiont(side_effect_expr_landingpadt))
148-
/// \param [out] dest: code appended to this GOTO program
149-
void goto_convertt::convert_java_exception_landingpad(
150-
const codet &code,
151-
goto_programt &dest)
152-
{
153-
PRECONDITION(code.get_statement()==ID_expression);
154-
PRECONDITION(
155-
to_side_effect_expr(code.op0()).get_statement()==ID_exception_landingpad);
156-
copy(code, CATCH, dest);
157-
}
158-
15996
void goto_convertt::convert_try_catch(
16097
const codet &code,
16198
goto_programt &dest)
@@ -165,13 +102,14 @@ void goto_convertt::convert_try_catch(
165102
// add the CATCH-push instruction to 'dest'
166103
goto_programt::targett catch_push_instruction=dest.add_instruction();
167104
catch_push_instruction->make_catch();
168-
catch_push_instruction->code.set_statement(ID_catch);
169105
catch_push_instruction->source_location=code.source_location();
170106

107+
code_push_catcht push_catch_code;
108+
171109
// the CATCH-push instruction is annotated with a list of IDs,
172110
// one per target
173-
irept::subt &exception_list=
174-
catch_push_instruction->code.add(ID_exception_list).get_sub();
111+
code_push_catcht::exception_listt &exception_list=
112+
push_catch_code.exception_list();
175113

176114
// add a SKIP target for the end of everything
177115
goto_programt end;
@@ -184,7 +122,7 @@ void goto_convertt::convert_try_catch(
184122
// add the CATCH-pop to the end of the 'try' block
185123
goto_programt::targett catch_pop_instruction=dest.add_instruction();
186124
catch_pop_instruction->make_catch();
187-
catch_pop_instruction->code.set_statement(ID_catch);
125+
catch_pop_instruction->code=code_pop_catcht();
188126

189127
// add a goto to the end of the 'try' block
190128
dest.add_instruction()->make_goto(end_target);
@@ -194,7 +132,8 @@ void goto_convertt::convert_try_catch(
194132
const codet &block=to_code(code.operands()[i]);
195133

196134
// grab the ID and add to CATCH instruction
197-
exception_list.push_back(irept(block.get(ID_exception_id)));
135+
exception_list.push_back(
136+
code_push_catcht::exception_list_entryt(block.get(ID_exception_id)));
198137

199138
goto_programt tmp;
200139
convert(block, tmp);
@@ -205,6 +144,8 @@ void goto_convertt::convert_try_catch(
205144
dest.add_instruction()->make_goto(end_target);
206145
}
207146

147+
catch_push_instruction->code=push_catch_code;
148+
208149
// add the end-target
209150
dest.destructive_append(end);
210151
}

src/goto-programs/goto_convert_side_effect.cpp

Lines changed: 0 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -636,34 +636,6 @@ void goto_convertt::remove_statement_expression(
636636
static_cast<exprt &>(expr)=tmp_symbol_expr;
637637
}
638638

639-
void goto_convertt::remove_push_catch(
640-
side_effect_exprt &expr,
641-
goto_programt &dest)
642-
{
643-
// we only get here for ID_push_catch, which is only used for Java
644-
convert_java_try_catch(code_expressiont(expr), dest);
645-
646-
// the result can't be used, these are void
647-
expr.make_nil();
648-
}
649-
650-
/// Lower a side_effect_exprt describing an exception
651-
/// landing-pad (catch site) into GOTO code
652-
/// \param expr: expression to convert
653-
/// \param [out] dest: code appended to this GOTO program
654-
void goto_convertt::remove_exception_landingpad(
655-
side_effect_exprt &expr,
656-
goto_programt &dest)
657-
{
658-
PRECONDITION(expr.get_statement()==ID_exception_landingpad);
659-
660-
// Similar to the above, only currently used in Java.
661-
convert_java_exception_landingpad(code_expressiont(expr), dest);
662-
663-
// the result can't be used, these are void
664-
expr.make_nil();
665-
}
666-
667639
void goto_convertt::remove_side_effect(
668640
side_effect_exprt &expr,
669641
goto_programt &dest,
@@ -724,10 +696,6 @@ void goto_convertt::remove_side_effect(
724696
// the result can't be used, these are void
725697
expr.make_nil();
726698
}
727-
else if(statement==ID_push_catch)
728-
remove_push_catch(expr, dest);
729-
else if(statement==ID_exception_landingpad)
730-
remove_exception_landingpad(expr, dest);
731699
else
732700
{
733701
error().source_location=expr.find_source_location();

src/goto-programs/goto_program.cpp

Lines changed: 26 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -158,41 +158,42 @@ std::ostream &goto_programt::output_instruction(
158158

159159
case CATCH:
160160
{
161-
if(instruction.code.get_statement()==ID_expression &&
162-
instruction.code.op0().id()==ID_side_effect)
161+
if(instruction.code.get_statement()==ID_exception_landingpad)
163162
{
164-
const auto &landingpad=
165-
to_side_effect_expr_landingpad(instruction.code.op0());
163+
const auto &landingpad=to_code_landingpad(instruction.code);
166164
out << "EXCEPTION LANDING PAD ("
167165
<< from_type(ns, identifier, landingpad.catch_expr().type())
168166
<< ' '
169167
<< from_expr(ns, identifier, landingpad.catch_expr())
170168
<< ")";
171169
}
172-
else if(instruction.code.get_statement()==ID_catch)
170+
else if(instruction.code.get_statement()==ID_push_catch)
173171
{
174-
if(!instruction.targets.empty())
172+
out << "CATCH-PUSH ";
173+
174+
unsigned i=0;
175+
const irept::subt &exception_list=
176+
instruction.code.find(ID_exception_list).get_sub();
177+
assert(instruction.targets.size()==exception_list.size());
178+
for(instructiont::targetst::const_iterator
179+
gt_it=instruction.targets.begin();
180+
gt_it!=instruction.targets.end();
181+
gt_it++,
182+
i++)
175183
{
176-
out << "CATCH-PUSH ";
177-
178-
unsigned i=0;
179-
const irept::subt &exception_list=
180-
instruction.code.find(ID_exception_list).get_sub();
181-
assert(instruction.targets.size()==exception_list.size());
182-
for(instructiont::targetst::const_iterator
183-
gt_it=instruction.targets.begin();
184-
gt_it!=instruction.targets.end();
185-
gt_it++,
186-
i++)
187-
{
188-
if(gt_it!=instruction.targets.begin())
189-
out << ", ";
190-
out << exception_list[i].id() << "->"
191-
<< (*gt_it)->target_number;
192-
}
184+
if(gt_it!=instruction.targets.begin())
185+
out << ", ";
186+
out << exception_list[i].id() << "->"
187+
<< (*gt_it)->target_number;
193188
}
194-
else
195-
out << "CATCH-POP";
189+
}
190+
else if(instruction.code.get_statement()==ID_pop_catch)
191+
{
192+
out << "CATCH-POP";
193+
}
194+
else
195+
{
196+
out << "! unexpected CATCH opcode " << instruction.code.get_statement();
196197
}
197198

198199
out << '\n';

0 commit comments

Comments
 (0)