@@ -1961,109 +1961,7 @@ codet java_bytecode_convert_methodt::convert_instructions(
19611961 c.operands ()=op;
19621962 }
19631963
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);
20671965
20681966 // Finally if this is the beginning of a catch block (already determined
20691967 // before the big bytecode switch), insert the exception 'landing pad'
@@ -2300,6 +2198,117 @@ codet java_bytecode_convert_methodt::convert_instructions(
23002198 return code;
23012199}
23022200
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+
23032312codet java_bytecode_convert_methodt::convert_monitorenter (
23042313 const source_locationt &location,
23052314 const exprt::operandst &op) const
0 commit comments