2424 ProveRSOpts ,
2525 PruneOpts ,
2626 RunOpts ,
27+ SectionEdgeOpts ,
2728 ShowOpts ,
2829 ViewOpts ,
2930)
@@ -141,6 +142,38 @@ def _kmir_prune(opts: PruneOpts) -> None:
141142 proof .write_proof_data ()
142143
143144
145+ def _kmir_section_edge (opts : SectionEdgeOpts ) -> None :
146+ # Proof dir is checked to be some in arg parsing for instructive errors
147+ assert opts .proof_dir is not None
148+
149+ if not APRProof .proof_data_exists (opts .id , opts .proof_dir ):
150+ raise ValueError (f'Proof id { opts .id } not found in proof dir { opts .proof_dir } ' )
151+
152+ target_path = opts .proof_dir / opts .id
153+
154+ _LOGGER .info (f'Reading proof from disc: { opts .proof_dir } , { opts .id } ' )
155+ apr_proof = APRProof .read_proof_data (opts .proof_dir , opts .id )
156+
157+ smir_info = SMIRInfo .from_file (target_path / 'smir.json' )
158+
159+ kmir = KMIR .from_kompiled_kore (smir_info , symbolic = True , bug_report = opts .bug_report , target_dir = target_path )
160+
161+ source_id , target_id = opts .edge
162+ _LOGGER .info (f'Attempting to add { opts .sections } sections from node { source_id } to node { target_id } ' )
163+
164+ with kmir .kcfg_explore (apr_proof .id ) as kcfg_explore :
165+ node_ids = kcfg_explore .section_edge (
166+ apr_proof .kcfg ,
167+ source_id = int (source_id ),
168+ target_id = int (target_id ),
169+ logs = apr_proof .logs ,
170+ sections = opts .sections ,
171+ )
172+ _LOGGER .info (f'Added nodes on edge { (source_id , target_id )} : { node_ids } ' )
173+
174+ apr_proof .write_proof_data ()
175+
176+
144177def _kmir_info (opts : InfoOpts ) -> None :
145178 smir_info = SMIRInfo .from_file (opts .smir_file )
146179
@@ -171,6 +204,8 @@ def kmir(args: Sequence[str]) -> None:
171204 _kmir_show (opts )
172205 case PruneOpts ():
173206 _kmir_prune (opts )
207+ case SectionEdgeOpts ():
208+ _kmir_section_edge (opts )
174209 case ProveRSOpts ():
175210 _kmir_prove_rs (opts )
176211 case LinkOpts ():
@@ -210,6 +245,84 @@ def _arg_parser() -> ArgumentParser:
210245 '--max-iterations' , metavar = 'ITERATIONS' , type = int , help = 'max number of proof iterations to take'
211246 )
212247 prove_args .add_argument ('--reload' , action = 'store_true' , help = 'Force restarting proof' )
248+ prove_args .add_argument (
249+ '--break-on-calls' , dest = 'break_on_calls' , action = 'store_true' , help = 'Break on all function and intrinsic calls'
250+ )
251+ prove_args .add_argument (
252+ '--break-on-function-calls' ,
253+ dest = 'break_on_function_calls' ,
254+ action = 'store_true' ,
255+ help = 'Break on function calls (not intrinsics)' ,
256+ )
257+ prove_args .add_argument (
258+ '--break-on-intrinsic-calls' ,
259+ dest = 'break_on_intrinsic_calls' ,
260+ action = 'store_true' ,
261+ help = 'Break on intrinsic calls (not other functions)' ,
262+ )
263+ prove_args .add_argument (
264+ '--break-on-thunk' , dest = 'break_on_thunk' , action = 'store_true' , help = 'Break on thunk evaluation'
265+ )
266+ prove_args .add_argument (
267+ '--break-every-statement' ,
268+ dest = 'break_every_statement' ,
269+ action = 'store_true' ,
270+ help = 'Break on every MIR Statement execution' ,
271+ )
272+ prove_args .add_argument (
273+ '--break-on-terminator-goto' ,
274+ dest = 'break_on_terminator_goto' ,
275+ action = 'store_true' ,
276+ help = 'Break on Goto terminator' ,
277+ )
278+ prove_args .add_argument (
279+ '--break-on-terminator-switch-int' ,
280+ dest = 'break_on_terminator_switch_int' ,
281+ action = 'store_true' ,
282+ help = 'Break on SwitchInt terminator' ,
283+ )
284+ prove_args .add_argument (
285+ '--break-on-terminator-return' ,
286+ dest = 'break_on_terminator_return' ,
287+ action = 'store_true' ,
288+ help = 'Break on Return terminator' ,
289+ )
290+ prove_args .add_argument (
291+ '--break-on-terminator-call' ,
292+ dest = 'break_on_terminator_call' ,
293+ action = 'store_true' ,
294+ help = 'Break on Call terminator' ,
295+ )
296+ prove_args .add_argument (
297+ '--break-on-terminator-assert' ,
298+ dest = 'break_on_terminator_assert' ,
299+ action = 'store_true' ,
300+ help = 'Break on Assert terminator' ,
301+ )
302+ prove_args .add_argument (
303+ '--break-on-terminator-drop' ,
304+ dest = 'break_on_terminator_drop' ,
305+ action = 'store_true' ,
306+ help = 'Break on Drop terminator' ,
307+ )
308+ prove_args .add_argument (
309+ '--break-on-terminator-unreachable' ,
310+ dest = 'break_on_terminator_unreachable' ,
311+ action = 'store_true' ,
312+ help = 'Break on Unreachable terminator' ,
313+ )
314+ prove_args .add_argument (
315+ '--break-every-terminator' ,
316+ dest = 'break_every_terminator' ,
317+ action = 'store_true' ,
318+ help = 'Break on every MIR terminator execution' ,
319+ )
320+ prove_args .add_argument (
321+ '--break-every-step' ,
322+ dest = 'break_every_step' ,
323+ action = 'store_true' ,
324+ help = 'Break on every MIR step (statements and terminators)' ,
325+ )
213326
214327 proof_args = ArgumentParser (add_help = False )
215328 proof_args .add_argument ('id' , metavar = 'PROOF_ID' , help = 'The id of the proof to view' )
@@ -287,6 +400,16 @@ def _arg_parser() -> ArgumentParser:
287400 )
288401 prune_parser .add_argument ('node_id' , metavar = 'NODE' , type = int , help = 'The node to prune' )
289402
403+ section_edge_parser = command_parser .add_parser (
404+ 'section-edge' , help = 'Break an edge into sections' , parents = [kcli_args .logging_args , proof_args ]
405+ )
406+ section_edge_parser .add_argument (
407+ 'edge' , type = lambda s : tuple (s .split (',' )), help = 'Edge to section in CFG (format: `source,target`)'
408+ )
409+ section_edge_parser .add_argument (
410+ '--sections' , type = int , default = 2 , help = 'Number of sections to make from edge (>= 2, default: 2)'
411+ )
412+
290413 prove_rs_parser = command_parser .add_parser (
291414 'prove-rs' , help = 'Prove a rust program' , parents = [kcli_args .logging_args , prove_args ]
292415 )
@@ -354,6 +477,11 @@ def _parse_args(ns: Namespace) -> KMirOpts:
354477 case 'prune' :
355478 proof_dir = Path (ns .proof_dir )
356479 return PruneOpts (proof_dir , ns .id , ns .node_id )
480+ case 'section-edge' :
481+ if ns .proof_dir is None :
482+ raise ValueError ('Must pass --proof-dir to section-edge command' )
483+ proof_dir = Path (ns .proof_dir )
484+ return SectionEdgeOpts (proof_dir , ns .id , ns .edge , ns .sections )
357485 case 'prove-rs' :
358486 return ProveRSOpts (
359487 rs_file = Path (ns .rs_file ),
@@ -365,6 +493,20 @@ def _parse_args(ns: Namespace) -> KMirOpts:
365493 save_smir = ns .save_smir ,
366494 smir = ns .smir ,
367495 start_symbol = ns .start_symbol ,
496+ break_on_calls = ns .break_on_calls ,
497+ break_on_function_calls = ns .break_on_function_calls ,
498+ break_on_intrinsic_calls = ns .break_on_intrinsic_calls ,
499+ break_on_thunk = ns .break_on_thunk ,
500+ break_every_statement = ns .break_every_statement ,
501+ break_on_terminator_goto = ns .break_on_terminator_goto ,
502+ break_on_terminator_switch_int = ns .break_on_terminator_switch_int ,
503+ break_on_terminator_return = ns .break_on_terminator_return ,
504+ break_on_terminator_call = ns .break_on_terminator_call ,
505+ break_on_terminator_assert = ns .break_on_terminator_assert ,
506+ break_on_terminator_drop = ns .break_on_terminator_drop ,
507+ break_on_terminator_unreachable = ns .break_on_terminator_unreachable ,
508+ break_every_terminator = ns .break_every_terminator ,
509+ break_every_step = ns .break_every_step ,
368510 )
369511 case 'link' :
370512 return LinkOpts (
0 commit comments