@@ -1961,109 +1961,7 @@ codet java_bytecode_convert_methodt::convert_instructions(
1961
1961
c.operands ()=op;
1962
1962
}
1963
1963
1964
- // next we do the exception handling
1965
- std::vector<irep_idt> exception_ids;
1966
- std::vector<irep_idt> handler_labels;
1967
-
1968
- // for each try-catch add a CATCH-PUSH instruction
1969
- // each CATCH-PUSH records a list of all the handler labels
1970
- // together with a list of all the exception ids
1971
-
1972
- // be aware of different try-catch blocks with the same starting pc
1973
- std::size_t pos=0 ;
1974
- std::size_t end_pc=0 ;
1975
- while (pos<method.exception_table .size ())
1976
- {
1977
- // check if this is the beginning of a try block
1978
- for (; pos<method.exception_table .size (); ++pos)
1979
- {
1980
- // unexplored try-catch?
1981
- if (cur_pc==method.exception_table [pos].start_pc && end_pc==0 )
1982
- {
1983
- end_pc=method.exception_table [pos].end_pc ;
1984
- }
1985
-
1986
- // currently explored try-catch?
1987
- if (cur_pc==method.exception_table [pos].start_pc &&
1988
- method.exception_table [pos].end_pc ==end_pc)
1989
- {
1990
- exception_ids.push_back (
1991
- method.exception_table [pos].catch_type .get_identifier ());
1992
- // record the exception handler in the CATCH-PUSH
1993
- // instruction by generating a label corresponding to
1994
- // the handler's pc
1995
- handler_labels.push_back (
1996
- label (std::to_string (method.exception_table [pos].handler_pc )));
1997
- }
1998
- else
1999
- break ;
2000
- }
2001
-
2002
- // add the actual PUSH-CATCH instruction
2003
- if (!exception_ids.empty ())
2004
- {
2005
- code_push_catcht catch_push;
2006
- INVARIANT (
2007
- exception_ids.size ()==handler_labels.size (),
2008
- " Exception tags and handler labels should be 1-to-1" );
2009
- code_push_catcht::exception_listt &exception_list=
2010
- catch_push.exception_list ();
2011
- for (size_t i=0 ; i<exception_ids.size (); ++i)
2012
- {
2013
- exception_list.push_back (
2014
- code_push_catcht::exception_list_entryt (
2015
- exception_ids[i],
2016
- handler_labels[i]));
2017
- }
2018
-
2019
- code_blockt try_block;
2020
- try_block.move_to_operands (catch_push);
2021
- try_block.move_to_operands (c);
2022
- c=try_block;
2023
- }
2024
- else
2025
- {
2026
- // advance
2027
- ++pos;
2028
- }
2029
-
2030
- // reset
2031
- end_pc=0 ;
2032
- exception_ids.clear ();
2033
- handler_labels.clear ();
2034
- }
2035
-
2036
- // next add the CATCH-POP instructions
2037
- size_t start_pc=0 ;
2038
- // as the first try block may have start_pc 0, we
2039
- // must track it separately
2040
- bool first_handler=false ;
2041
- // check if this is the end of a try block
2042
- for (const auto &exception_row : method.exception_table )
2043
- {
2044
- // add the CATCH-POP before the end of the try block
2045
- if (cur_pc<exception_row.end_pc &&
2046
- !working_set.empty () &&
2047
- *working_set.begin ()==exception_row.end_pc )
2048
- {
2049
- // have we already added a CATCH-POP for the current try-catch?
2050
- // (each row corresponds to a handler)
2051
- if (exception_row.start_pc !=start_pc || !first_handler)
2052
- {
2053
- if (!first_handler)
2054
- first_handler=true ;
2055
- // remember the beginning of the try-catch so that we don't add
2056
- // another CATCH-POP for the same try-catch
2057
- start_pc=exception_row.start_pc ;
2058
- // add CATCH_POP instruction
2059
- code_pop_catcht catch_pop;
2060
- code_blockt end_try_block;
2061
- end_try_block.move_to_operands (c);
2062
- end_try_block.move_to_operands (catch_pop);
2063
- c=end_try_block;
2064
- }
2065
- }
2066
- }
1964
+ c = do_exception_handling (method, working_set, cur_pc, c);
2067
1965
2068
1966
// Finally if this is the beginning of a catch block (already determined
2069
1967
// before the big bytecode switch), insert the exception 'landing pad'
@@ -2300,6 +2198,117 @@ codet java_bytecode_convert_methodt::convert_instructions(
2300
2198
return code;
2301
2199
}
2302
2200
2201
+ codet &java_bytecode_convert_methodt::do_exception_handling (
2202
+ const java_bytecode_convert_methodt::methodt &method,
2203
+ const std::set<unsigned int > &working_set,
2204
+ unsigned int cur_pc,
2205
+ codet &c)
2206
+ {
2207
+ std::vector<irep_idt> exception_ids;
2208
+ std::vector<irep_idt> handler_labels;
2209
+
2210
+ // for each try-catch add a CATCH-PUSH instruction
2211
+ // each CATCH-PUSH records a list of all the handler labels
2212
+ // together with a list of all the exception ids
2213
+
2214
+ // be aware of different try-catch blocks with the same starting pc
2215
+ std::size_t pos = 0 ;
2216
+ std::size_t end_pc = 0 ;
2217
+ while (pos < method.exception_table .size ())
2218
+ {
2219
+ // check if this is the beginning of a try block
2220
+ for (; pos < method.exception_table .size (); ++pos)
2221
+ {
2222
+ // unexplored try-catch?
2223
+ if (cur_pc == method.exception_table [pos].start_pc && end_pc == 0 )
2224
+ {
2225
+ end_pc = method.exception_table [pos].end_pc ;
2226
+ }
2227
+
2228
+ // currently explored try-catch?
2229
+ if (
2230
+ cur_pc == method.exception_table [pos].start_pc &&
2231
+ method.exception_table [pos].end_pc == end_pc)
2232
+ {
2233
+ exception_ids.push_back (
2234
+ method.exception_table [pos].catch_type .get_identifier ());
2235
+ // record the exception handler in the CATCH-PUSH
2236
+ // instruction by generating a label corresponding to
2237
+ // the handler's pc
2238
+ handler_labels.push_back (
2239
+ label (std::to_string (method.exception_table [pos].handler_pc )));
2240
+ }
2241
+ else
2242
+ break ;
2243
+ }
2244
+
2245
+ // add the actual PUSH-CATCH instruction
2246
+ if (!exception_ids.empty ())
2247
+ {
2248
+ code_push_catcht catch_push;
2249
+ INVARIANT (
2250
+ exception_ids.size () == handler_labels.size (),
2251
+ " Exception tags and handler labels should be 1-to-1" );
2252
+ code_push_catcht::exception_listt &exception_list =
2253
+ catch_push.exception_list ();
2254
+ for (size_t i = 0 ; i < exception_ids.size (); ++i)
2255
+ {
2256
+ exception_list.push_back (
2257
+ code_push_catcht::exception_list_entryt (
2258
+ exception_ids[i], handler_labels[i]));
2259
+ }
2260
+
2261
+ code_blockt try_block;
2262
+ try_block.move_to_operands (catch_push);
2263
+ try_block.move_to_operands (c);
2264
+ c = try_block;
2265
+ }
2266
+ else
2267
+ {
2268
+ // advance
2269
+ ++pos;
2270
+ }
2271
+
2272
+ // reset
2273
+ end_pc = 0 ;
2274
+ exception_ids.clear ();
2275
+ handler_labels.clear ();
2276
+ }
2277
+
2278
+ // next add the CATCH-POP instructions
2279
+ size_t start_pc = 0 ;
2280
+ // as the first try block may have start_pc 0, we
2281
+ // must track it separately
2282
+ bool first_handler = false ;
2283
+ // check if this is the end of a try block
2284
+ for (const auto &exception_row : method.exception_table )
2285
+ {
2286
+ // add the CATCH-POP before the end of the try block
2287
+ if (
2288
+ cur_pc < exception_row.end_pc && !working_set.empty () &&
2289
+ *working_set.begin () == exception_row.end_pc )
2290
+ {
2291
+ // have we already added a CATCH-POP for the current try-catch?
2292
+ // (each row corresponds to a handler)
2293
+ if (exception_row.start_pc != start_pc || !first_handler)
2294
+ {
2295
+ if (!first_handler)
2296
+ first_handler = true ;
2297
+ // remember the beginning of the try-catch so that we don't add
2298
+ // another CATCH-POP for the same try-catch
2299
+ start_pc = exception_row.start_pc ;
2300
+ // add CATCH_POP instruction
2301
+ code_pop_catcht catch_pop;
2302
+ code_blockt end_try_block;
2303
+ end_try_block.move_to_operands (c);
2304
+ end_try_block.move_to_operands (catch_pop);
2305
+ c = end_try_block;
2306
+ }
2307
+ }
2308
+ }
2309
+ return c;
2310
+ }
2311
+
2303
2312
codet java_bytecode_convert_methodt::convert_monitorenter (
2304
2313
const source_locationt &location,
2305
2314
const exprt::operandst &op) const
0 commit comments