diff --git a/compiler/src/compiler/analysis/instrumenter.rs b/compiler/src/compiler/analysis/instrumenter.rs index f38972f3..9f559337 100644 --- a/compiler/src/compiler/analysis/instrumenter.rs +++ b/compiler/src/compiler/analysis/instrumenter.rs @@ -2621,7 +2621,9 @@ mod tests { }); entry.set_terminator(Terminator::Return(vec![result])); - InstructionLowering::witness_integer_ops().run(&mut ssa, &AnalysisStore::new()); + InstructionLowering::witness_integer_ops() + .run(&mut ssa, &AnalysisStore::new()) + .unwrap(); let flow = FlowAnalysis::run(&ssa); let type_info = Types::new().run(&ssa, &flow); let costs = CostEstimator::new().run(&ssa, &type_info); @@ -2655,7 +2657,9 @@ mod tests { }); entry.set_terminator(Terminator::Return(vec![result])); - InstructionLowering::witness_integer_ops().run(&mut ssa, &AnalysisStore::new()); + InstructionLowering::witness_integer_ops() + .run(&mut ssa, &AnalysisStore::new()) + .unwrap(); let flow = FlowAnalysis::run(&ssa); let type_info = Types::new().run(&ssa, &flow); let costs = CostEstimator::new().run(&ssa, &type_info); diff --git a/compiler/src/compiler/lowering/tests.rs b/compiler/src/compiler/lowering/tests.rs index 7b8f57a8..47aa050f 100644 --- a/compiler/src/compiler/lowering/tests.rs +++ b/compiler/src/compiler/lowering/tests.rs @@ -210,7 +210,9 @@ fn unit_bodies_and_empty_structs_have_one_typed_result_until_tuple_elision() { let expected = TypeConverter::new().convert_type(&return_type); let mut ssa = lower(vec![function(0, body, return_type)]); assert_return_shape(&ssa, &[expected.clone()]); - PassManager::new(name.into(), false, vec![Box::new(ElideTuples::new())]).run(&mut ssa); + PassManager::new(name.into(), false, vec![Box::new(ElideTuples::new())]) + .run(&mut ssa) + .unwrap(); assert_return_shape(&ssa, &after); } } @@ -349,7 +351,8 @@ fn direct_and_indirect_unit_calls_match_their_signatures() { Box::new(ElideTuples::new()), ], ) - .run(&mut ssa); + .run(&mut ssa) + .unwrap(); assert_return_shape(&ssa, &[]); for (_, function) in ssa.iter_functions() { for (_, block) in function.get_blocks() { diff --git a/compiler/src/compiler/pass_manager.rs b/compiler/src/compiler/pass_manager.rs index a3421d99..3db59212 100644 --- a/compiler/src/compiler/pass_manager.rs +++ b/compiler/src/compiler/pass_manager.rs @@ -8,9 +8,12 @@ use std::{ use crate::{ collections::HashMap, - compiler::ssa::{ - DefaultSSAAnnotator, Instruction, SSA, SSAType, - hlssa::{Constant, OpCode, Type}, + compiler::{ + diagnostic::Diagnostic, + ssa::{ + DefaultSSAAnnotator, Instruction, SSA, SSAType, + hlssa::{Constant, OpCode, Type}, + }, }, }; @@ -179,6 +182,8 @@ impl AnalysisStore { // Pass trait — parametric // --------------------------------------------------------------------------- +pub type PassResult = Result<(), Vec>; + pub trait Pass< Op: Instruction = OpCode, Ty: SSAType = Type, @@ -189,7 +194,7 @@ pub trait Pass< fn needs(&self) -> Vec { vec![] } - fn run(&self, ssa: &mut SSA, store: &AnalysisStore); + fn run(&self, ssa: &mut SSA, store: &AnalysisStore) -> PassResult; fn preserves(&self) -> Vec { vec![] } @@ -260,7 +265,7 @@ impl PassM } #[tracing::instrument(skip_all, name = "PassManager::run", fields(phase = %self.phase_label))] - pub fn run(&mut self, ssa: &mut SSA) { + pub fn run(&mut self, ssa: &mut SSA) -> PassResult { if let Some(debug_output_dir) = &self.debug_output_dir { if debug_output_dir.exists() { fs::remove_dir_all(debug_output_dir).unwrap(); @@ -269,11 +274,14 @@ impl PassM } let passes = std::mem::take(&mut self.passes); - for (i, pass) in passes.iter().enumerate() { - self.run_pass(ssa, pass.as_ref(), i); - } + let outcome = passes + .iter() + .enumerate() + .try_for_each(|(i, pass)| self.run_pass(ssa, pass.as_ref(), i)); self.passes = passes; + outcome?; self.output_final_debug_info(ssa); + Ok(()) } #[tracing::instrument(skip_all, fields(pass = %pass.name()))] @@ -282,7 +290,7 @@ impl PassM ssa: &mut SSA, pass: &dyn Pass, pass_index: usize, - ) { + ) -> PassResult { // Ensure all needed analyses are computed (in dependency order) let ordered = topo_sort(pass.needs(), &self.analyses); for id in ordered { @@ -290,9 +298,10 @@ impl PassM } self.output_debug_info(ssa, pass_index, pass.name()); - pass.run(ssa, &self.analyses); + pass.run(ssa, &self.analyses)?; self.analyses.apply_preserved(&pass.preserves()); self.output_pass_ssa_snapshot(ssa, pass_index, pass.name()); + Ok(()) } /// When `MAVROS_DUMP_PASS_SSA` names a directory, write the SSA text after every pass to diff --git a/compiler/src/compiler/passes/arg_promotion.rs b/compiler/src/compiler/passes/arg_promotion.rs index b5e3daab..ef630505 100644 --- a/compiler/src/compiler/passes/arg_promotion.rs +++ b/compiler/src/compiler/passes/arg_promotion.rs @@ -90,7 +90,7 @@ use crate::{ points_to::{PointerUse, PointsTo, object::AbstractObject}, types::{FunctionTypeInfo, TypeInfo}, }, - pass_manager::{Analysis, AnalysisId, AnalysisStore, Pass}, + pass_manager::{Analysis, AnalysisId, AnalysisStore, Pass, PassResult}, passes::shared::value_replacements::{ReplaceScope, ValueReplacements}, ssa::{ BlockId, FunctionId, SourceLocation, Terminator, ValueId, @@ -120,8 +120,9 @@ impl Pass for ArgPromotion { vec![TypeInfo::id(), PointsTo::id()] } - fn run(&self, ssa: &mut HLSSA, store: &AnalysisStore) { + fn run(&self, ssa: &mut HLSSA, store: &AnalysisStore) -> PassResult { self.do_run(ssa, store.get::(), store.get::()); + Ok(()) } fn preserves(&self) -> Vec { diff --git a/compiler/src/compiler/passes/array_boundary_expansion.rs b/compiler/src/compiler/passes/array_boundary_expansion.rs index 230e85c4..83bfe28a 100644 --- a/compiler/src/compiler/passes/array_boundary_expansion.rs +++ b/compiler/src/compiler/passes/array_boundary_expansion.rs @@ -88,7 +88,7 @@ use crate::{ collections::{HashMap, HashSet}, compiler::{ analysis::{points_to::PointsTo, types::TypeInfo}, - pass_manager::{Analysis, AnalysisId, AnalysisStore, Pass}, + pass_manager::{Analysis, AnalysisId, AnalysisStore, Pass, PassResult}, ssa::{ BlockId, FunctionId, SourceLocation, Terminator, ValueId, hlssa::{ @@ -129,8 +129,9 @@ impl Pass for ArrayBoundaryExpansion { vec![TypeInfo::id(), PointsTo::id()] } - fn run(&self, ssa: &mut HLSSA, store: &AnalysisStore) { + fn run(&self, ssa: &mut HLSSA, store: &AnalysisStore) -> PassResult { self.do_run(ssa, store.get::(), store.get::()); + Ok(()) } fn preserves(&self) -> Vec { diff --git a/compiler/src/compiler/passes/array_sroa.rs b/compiler/src/compiler/passes/array_sroa.rs index 9440fb43..0e5d85b0 100644 --- a/compiler/src/compiler/passes/array_sroa.rs +++ b/compiler/src/compiler/passes/array_sroa.rs @@ -57,7 +57,7 @@ use crate::{ points_to::PointsTo, types::{FunctionTypeInfo, TypeInfo}, }, - pass_manager::{Analysis, AnalysisId, AnalysisStore, Pass}, + pass_manager::{Analysis, AnalysisId, AnalysisStore, Pass, PassResult}, ssa::{ BlockId, FunctionId, Instruction, Terminator, ValueId, hlssa::{Constant, HLSSA, OpCode, Type, TypeExpr}, @@ -85,13 +85,14 @@ impl Pass for ArraySroa { vec![PointsTo::id(), TypeInfo::id(), FlowAnalysis::id()] } - fn run(&self, ssa: &mut HLSSA, store: &AnalysisStore) { + fn run(&self, ssa: &mut HLSSA, store: &AnalysisStore) -> PassResult { self.do_run( ssa, store.get::(), store.get::(), store.get::(), ); + Ok(()) } fn preserves(&self) -> Vec { diff --git a/compiler/src/compiler/passes/assert_constant.rs b/compiler/src/compiler/passes/assert_constant.rs index b9f8dade..3834341b 100644 --- a/compiler/src/compiler/passes/assert_constant.rs +++ b/compiler/src/compiler/passes/assert_constant.rs @@ -14,7 +14,7 @@ use std::{cell::RefCell, collections::BTreeSet, rc::Rc}; use crate::compiler::{ analysis::witness_taint_inference::WitnessTaintInference, - pass_manager::{AnalysisStore, Pass}, + pass_manager::{AnalysisStore, Pass, PassResult}, ssa::{ SourceLocation, hlssa::{CallTarget, HLSSA, OpCode}, @@ -48,7 +48,7 @@ impl Pass for AssertConstantValidation { "assert_constant_validation" } - fn run(&self, ssa: &mut HLSSA, _store: &AnalysisStore) { + fn run(&self, ssa: &mut HLSSA, _store: &AnalysisStore) -> PassResult { let mut failures = BTreeSet::new(); let mut functions_with_markers = Vec::new(); @@ -112,6 +112,7 @@ impl Pass for AssertConstantValidation { } *self.failures.borrow_mut() = Some(failures); + Ok(()) } } @@ -155,7 +156,8 @@ mod tests { Rc::clone(&failures), ))], ) - .run(ssa); + .run(ssa) + .unwrap(); let failures = failures.borrow_mut().take().unwrap(); if failures.is_empty() { Ok(()) @@ -397,6 +399,7 @@ mod tests { failures, ))], ) - .run(&mut ssa); + .run(&mut ssa) + .unwrap(); } } diff --git a/compiler/src/compiler/passes/common_subexpression_elimination.rs b/compiler/src/compiler/passes/common_subexpression_elimination.rs index 730b5ae5..552f7f59 100644 --- a/compiler/src/compiler/passes/common_subexpression_elimination.rs +++ b/compiler/src/compiler/passes/common_subexpression_elimination.rs @@ -11,7 +11,7 @@ use crate::{ compiler::{ Field, analysis::flow_analysis::{CFG, FlowAnalysis}, - pass_manager::{AnalysisId, AnalysisStore, Pass}, + pass_manager::{AnalysisId, AnalysisStore, Pass, PassResult}, passes::shared::{availability::can_replace, value_replacements::ValueReplacements}, ssa::{ BlockId, ProgramPoint, SSAConstantsSnapshot, ValueId, @@ -42,8 +42,9 @@ impl Pass for CSE { vec![FlowAnalysis::id()] } - fn run(&self, ssa: &mut HLSSA, store: &AnalysisStore) { + fn run(&self, ssa: &mut HLSSA, store: &AnalysisStore) -> PassResult { self.do_run(ssa, store.get::()); + Ok(()) } fn preserves(&self) -> Vec { diff --git a/compiler/src/compiler/passes/dead_code_elimination.rs b/compiler/src/compiler/passes/dead_code_elimination.rs index b2beea5c..171dd860 100644 --- a/compiler/src/compiler/passes/dead_code_elimination.rs +++ b/compiler/src/compiler/passes/dead_code_elimination.rs @@ -16,7 +16,7 @@ use crate::{ types::{FunctionTypeInfo, TypeInfo, Types}, value_range_analysis::{ValueRangeAnalysis, ValueRanges}, }, - pass_manager::{AnalysisId, AnalysisStore, Pass}, + pass_manager::{AnalysisId, AnalysisStore, Pass, PassResult}, passes::shared::{ divmod_guard::{ divisor_checked_by_its_lowering, divmod_can_fail, divmod_provably_defined, @@ -183,8 +183,9 @@ impl Pass for DCE { vec![FlowAnalysis::id()] } - fn run(&self, ssa: &mut HLSSA, store: &AnalysisStore) { + fn run(&self, ssa: &mut HLSSA, store: &AnalysisStore) -> PassResult { self.do_run(ssa, store.get::()); + Ok(()) } } diff --git a/compiler/src/compiler/passes/deduplicate_phis.rs b/compiler/src/compiler/passes/deduplicate_phis.rs index 53847ae4..b7ea2982 100644 --- a/compiler/src/compiler/passes/deduplicate_phis.rs +++ b/compiler/src/compiler/passes/deduplicate_phis.rs @@ -3,7 +3,7 @@ use crate::{ collections::HashMap, compiler::{ - pass_manager::{AnalysisId, AnalysisStore, Pass}, + pass_manager::{AnalysisId, AnalysisStore, Pass, PassResult}, ssa::{BlockId, Terminator, ValueId, hlssa::HLSSA}, }, }; @@ -19,8 +19,9 @@ impl Pass for DeduplicatePhis { vec![] } - fn run(&self, ssa: &mut HLSSA, _store: &AnalysisStore) { + fn run(&self, ssa: &mut HLSSA, _store: &AnalysisStore) -> PassResult { self.do_run(ssa); + Ok(()) } } diff --git a/compiler/src/compiler/passes/defunctionalize.rs b/compiler/src/compiler/passes/defunctionalize.rs index a52b26db..76258628 100644 --- a/compiler/src/compiler/passes/defunctionalize.rs +++ b/compiler/src/compiler/passes/defunctionalize.rs @@ -23,7 +23,7 @@ use crate::{ flow_analysis::FlowAnalysis, types::{TypeInfo, Types}, }, - pass_manager::{AnalysisStore, Pass}, + pass_manager::{AnalysisStore, Pass, PassResult}, passes::{ remove_unreachable_blocks::remove_unreachable_blocks, shared::value_replacements::ValueReplacements, @@ -53,8 +53,9 @@ impl Pass for Defunctionalize { "defunctionalize" } - fn run(&self, ssa: &mut HLSSA, _store: &AnalysisStore) { + fn run(&self, ssa: &mut HLSSA, _store: &AnalysisStore) -> PassResult { run_defunctionalize(ssa); + Ok(()) } } diff --git a/compiler/src/compiler/passes/elide_tuples.rs b/compiler/src/compiler/passes/elide_tuples.rs index 8cb92983..1a6bb788 100644 --- a/compiler/src/compiler/passes/elide_tuples.rs +++ b/compiler/src/compiler/passes/elide_tuples.rs @@ -39,7 +39,7 @@ use crate::{ collections::{HashMap, HashSet}, compiler::{ analysis::{flow_analysis::FlowAnalysis, types::TypeInfo}, - pass_manager::{Analysis, AnalysisId, AnalysisStore, Pass}, + pass_manager::{Analysis, AnalysisId, AnalysisStore, Pass, PassResult}, ssa::{ BlockId, FunctionId, Instruction, Located, Terminator, ValueId, hlssa::{HLSSA, OpCode, Type, TypeExpr}, @@ -64,7 +64,7 @@ impl Pass for ElideTuples { vec![TypeInfo::id(), FlowAnalysis::id()] } - fn run(&self, ssa: &mut HLSSA, store: &AnalysisStore) { + fn run(&self, ssa: &mut HLSSA, store: &AnalysisStore) -> PassResult { let old_global_types: Vec = ssa.get_global_types().to_vec(); let mut global_offsets: Vec = Vec::with_capacity(old_global_types.len()); let mut acc = 0usize; @@ -98,6 +98,7 @@ impl Pass for ElideTuples { // Verify the tuple-free invariant on every build: one linear pass, and the // guarantee it enforces is relied on by every subsequent pass. verify_tuple_free(ssa); + Ok(()) } fn preserves(&self) -> Vec { diff --git a/compiler/src/compiler/passes/fix_double_jumps.rs b/compiler/src/compiler/passes/fix_double_jumps.rs index 0f6af24c..d7083633 100644 --- a/compiler/src/compiler/passes/fix_double_jumps.rs +++ b/compiler/src/compiler/passes/fix_double_jumps.rs @@ -7,7 +7,7 @@ use crate::{ collections::HashMap, compiler::{ analysis::flow_analysis::FlowAnalysis, - pass_manager::{AnalysisId, AnalysisStore, Pass}, + pass_manager::{AnalysisId, AnalysisStore, Pass, PassResult}, passes::shared::value_replacements::{ReplaceScope, ValueReplacements}, ssa::{BlockId, Terminator, hlssa::HLSSA}, }, @@ -24,8 +24,9 @@ impl Pass for FixDoubleJumps { vec![FlowAnalysis::id()] } - fn run(&self, ssa: &mut HLSSA, store: &AnalysisStore) { + fn run(&self, ssa: &mut HLSSA, store: &AnalysisStore) -> PassResult { self.do_run(ssa, store.get::()); + Ok(()) } } diff --git a/compiler/src/compiler/passes/instruction_lowering/integer_digits.rs b/compiler/src/compiler/passes/instruction_lowering/integer_digits.rs index 4b465c61..0acc3b41 100644 --- a/compiler/src/compiler/passes/instruction_lowering/integer_digits.rs +++ b/compiler/src/compiler/passes/instruction_lowering/integer_digits.rs @@ -182,7 +182,9 @@ mod tests { .get_entry_mut() .set_terminator(Terminator::Return(vec![result])); - InstructionLowering::operand_shapes().run(&mut ssa, &AnalysisStore::new()); + InstructionLowering::operand_shapes() + .run(&mut ssa, &AnalysisStore::new()) + .unwrap(); let mut widths = Vec::new(); for (_, block) in ssa.get_unique_entrypoint().get_blocks() { diff --git a/compiler/src/compiler/passes/instruction_lowering/mod.rs b/compiler/src/compiler/passes/instruction_lowering/mod.rs index 4b194488..c29f67d9 100644 --- a/compiler/src/compiler/passes/instruction_lowering/mod.rs +++ b/compiler/src/compiler/passes/instruction_lowering/mod.rs @@ -28,7 +28,7 @@ use crate::compiler::{ FunctionValueRanges, Interval, ValueRange, ValueRangeAnalysis, Width, }, }, - pass_manager::{AnalysisId, AnalysisStore, Pass}, + pass_manager::{AnalysisId, AnalysisStore, Pass, PassResult}, ssa::{ BlockId, ValueId, hlssa::{ @@ -411,15 +411,15 @@ impl Pass for InstructionLowering { self.name } - fn run(&self, ssa: &mut HLSSA, _store: &AnalysisStore) { + fn run(&self, ssa: &mut HLSSA, _store: &AnalysisStore) -> PassResult { if !self.fixed_point { self.run_iteration(ssa); - return; + return Ok(()); } for _ in 0..ITERATION_LIMIT { if !self.run_iteration(ssa) { - return; + return Ok(()); } } ice!("instruction lowering did not reach a fixed point"); @@ -500,7 +500,9 @@ mod tests { .get_entry_mut() .set_terminator(Terminator::Return(returned)); - InstructionLowering::witness_integer_ops().run(&mut ssa, &AnalysisStore::new()); + InstructionLowering::witness_integer_ops() + .run(&mut ssa, &AnalysisStore::new()) + .unwrap(); (ssa, op) } diff --git a/compiler/src/compiler/passes/instruction_lowering/pure_decompositions.rs b/compiler/src/compiler/passes/instruction_lowering/pure_decompositions.rs index 1fa207e6..e8775e09 100644 --- a/compiler/src/compiler/passes/instruction_lowering/pure_decompositions.rs +++ b/compiler/src/compiler/passes/instruction_lowering/pure_decompositions.rs @@ -133,7 +133,8 @@ mod tests { }); entry.set_terminator(Terminator::Return(vec![])); InstructionLowering::pure_bit_decompositions() - .run(&mut ssa, &AnalysisStore::new()); + .run(&mut ssa, &AnalysisStore::new()) + .unwrap(); let checks: Vec<_> = ssa .get_unique_entrypoint() .get_entry() @@ -162,7 +163,8 @@ mod tests { // A function parameter is checked only after the radix lowerer has // established that it equals 256. The fit check keeps its guard. InstructionLowering::witness_integer_ops() - .run(&mut ssa, &AnalysisStore::new()); + .run(&mut ssa, &AnalysisStore::new()) + .unwrap(); let checks: Vec<_> = ssa .get_unique_entrypoint() .get_entry() diff --git a/compiler/src/compiler/passes/instruction_lowering/pure_guards.rs b/compiler/src/compiler/passes/instruction_lowering/pure_guards.rs index 48ba9cd6..122c7dc7 100644 --- a/compiler/src/compiler/passes/instruction_lowering/pure_guards.rs +++ b/compiler/src/compiler/passes/instruction_lowering/pure_guards.rs @@ -1020,11 +1020,15 @@ mod tests { }); entry.set_terminator(Terminator::Return(vec![result])); - InstructionLowering::pure_guards().run(&mut ssa, &AnalysisStore::new()); + InstructionLowering::pure_guards() + .run(&mut ssa, &AnalysisStore::new()) + .unwrap(); // The checks use bit windows, lowered one phase later, so lower them here too or a width a // window cannot build would go unseen. - InstructionLowering::witness_integer_ops().run(&mut ssa, &AnalysisStore::new()); + InstructionLowering::witness_integer_ops() + .run(&mut ssa, &AnalysisStore::new()) + .unwrap(); ssa } @@ -1058,7 +1062,9 @@ mod tests { }); entry.set_terminator(Terminator::Return(vec![result])); - InstructionLowering::pure_guards().run(&mut ssa, &AnalysisStore::new()); + InstructionLowering::pure_guards() + .run(&mut ssa, &AnalysisStore::new()) + .unwrap(); ssa.get_unique_entrypoint() .get_blocks() .flat_map(|(_, block)| block.get_instructions()) @@ -1134,7 +1140,9 @@ mod tests { }); entry.set_terminator(Terminator::Return(vec![])); - InstructionLowering::pure_guards().run(&mut ssa, &AnalysisStore::new()); + InstructionLowering::pure_guards() + .run(&mut ssa, &AnalysisStore::new()) + .unwrap(); let ops: Vec = ssa .get_unique_entrypoint() .get_blocks() diff --git a/compiler/src/compiler/passes/instruction_lowering/witness_bitwise.rs b/compiler/src/compiler/passes/instruction_lowering/witness_bitwise.rs index aaa28138..44ba307c 100644 --- a/compiler/src/compiler/passes/instruction_lowering/witness_bitwise.rs +++ b/compiler/src/compiler/passes/instruction_lowering/witness_bitwise.rs @@ -1479,7 +1479,8 @@ mod tests { vec![Box::new(LowerWitnessBitwiseOps::new())], false, ) - .run(&mut ssa, &AnalysisStore::new()); + .run(&mut ssa, &AnalysisStore::new()) + .unwrap(); let answer = ssa .get_unique_entrypoint() diff --git a/compiler/src/compiler/passes/instruction_lowering/witness_field.rs b/compiler/src/compiler/passes/instruction_lowering/witness_field.rs index 19272490..8e853e1e 100644 --- a/compiler/src/compiler/passes/instruction_lowering/witness_field.rs +++ b/compiler/src/compiler/passes/instruction_lowering/witness_field.rs @@ -554,7 +554,9 @@ mod tests { }); entry.set_terminator(Terminator::Return(vec![result])); - InstructionLowering::witness_integer_ops().run(&mut ssa, &AnalysisStore::new()); + InstructionLowering::witness_integer_ops() + .run(&mut ssa, &AnalysisStore::new()) + .unwrap(); (ssa, result) } diff --git a/compiler/src/compiler/passes/lookup_spilling.rs b/compiler/src/compiler/passes/lookup_spilling.rs index 0ee79039..4cb5f1d0 100644 --- a/compiler/src/compiler/passes/lookup_spilling.rs +++ b/compiler/src/compiler/passes/lookup_spilling.rs @@ -9,7 +9,7 @@ use crate::{ lookup_sizing::{Chunk, LookupSizing, TableKind}, types::{FunctionTypeInfo, Types}, }, - pass_manager::{Analysis, AnalysisId, AnalysisStore, Pass}, + pass_manager::{Analysis, AnalysisId, AnalysisStore, Pass, PassResult}, passes::shared::limbs::{narrow_int_bits, widest_injective_int_bits}, ssa::{ FunctionId, SourceLocation, ValueId, @@ -268,7 +268,7 @@ impl Pass for LookupSpilling { vec![LookupSizing::id()] } - fn run(&self, ssa: &mut HLSSA, store: &AnalysisStore) { + fn run(&self, ssa: &mut HLSSA, store: &AnalysisStore) -> PassResult { let sizing = store.get::(); let flow = FlowAnalysis::run(ssa); let types = Types::new().run(ssa, &flow); @@ -336,6 +336,7 @@ impl Pass for LookupSpilling { } }); } + Ok(()) } } diff --git a/compiler/src/compiler/passes/lower_degenerate_array.rs b/compiler/src/compiler/passes/lower_degenerate_array.rs index 9793f709..cbee436f 100644 --- a/compiler/src/compiler/passes/lower_degenerate_array.rs +++ b/compiler/src/compiler/passes/lower_degenerate_array.rs @@ -25,7 +25,7 @@ use crate::compiler::{ flow_analysis::FlowAnalysis, types::{FunctionTypeInfo, TypeInfo}, }, - pass_manager::{Analysis, AnalysisId, AnalysisStore, Pass}, + pass_manager::{Analysis, AnalysisId, AnalysisStore, Pass, PassResult}, ssa::{ BlockId, ValueId, hlssa::{ @@ -48,8 +48,9 @@ impl Pass for LowerDegenerateArray { vec![TypeInfo::id(), FlowAnalysis::id()] } - fn run(&self, ssa: &mut HLSSA, store: &AnalysisStore) { + fn run(&self, ssa: &mut HLSSA, store: &AnalysisStore) -> PassResult { self.do_run(ssa, store.get::(), store.get::()); + Ok(()) } fn preserves(&self) -> Vec { diff --git a/compiler/src/compiler/passes/lower_map_casts.rs b/compiler/src/compiler/passes/lower_map_casts.rs index faa03c7b..86327e7f 100644 --- a/compiler/src/compiler/passes/lower_map_casts.rs +++ b/compiler/src/compiler/passes/lower_map_casts.rs @@ -14,7 +14,7 @@ use crate::compiler::{ analysis::{flow_analysis::FlowAnalysis, types::TypeInfo}, - pass_manager::{Analysis, AnalysisId, AnalysisStore, Pass}, + pass_manager::{Analysis, AnalysisId, AnalysisStore, Pass, PassResult}, ssa::{ BlockId, ValueId, hlssa::{ @@ -35,8 +35,9 @@ impl Pass for LowerMapCasts { vec![TypeInfo::id(), FlowAnalysis::id()] } - fn run(&self, ssa: &mut HLSSA, store: &AnalysisStore) { + fn run(&self, ssa: &mut HLSSA, store: &AnalysisStore) -> PassResult { self.do_run(ssa, store.get::(), store.get::()); + Ok(()) } } diff --git a/compiler/src/compiler/passes/lower_zst_slices.rs b/compiler/src/compiler/passes/lower_zst_slices.rs index 76a328ae..54d82ac2 100644 --- a/compiler/src/compiler/passes/lower_zst_slices.rs +++ b/compiler/src/compiler/passes/lower_zst_slices.rs @@ -40,7 +40,7 @@ use crate::compiler::{ flow_analysis::FlowAnalysis, types::{FunctionTypeInfo, TypeInfo}, }, - pass_manager::{Analysis, AnalysisId, AnalysisStore, Pass}, + pass_manager::{Analysis, AnalysisId, AnalysisStore, Pass, PassResult}, passes::shared::{ seq_bounds::{build_lt_bounds_assert_on_len, build_pop_bounds_assert_on_len, seq_len}, value_replacements::{ReplaceScope, ValueReplacements}, @@ -73,8 +73,9 @@ impl Pass for LowerZstSlices { vec![TypeInfo::id(), FlowAnalysis::id()] } - fn run(&self, ssa: &mut HLSSA, store: &AnalysisStore) { + fn run(&self, ssa: &mut HLSSA, store: &AnalysisStore) -> PassResult { Self::do_run(ssa, store.get::(), store.get::()); + Ok(()) } fn preserves(&self) -> Vec { @@ -439,7 +440,7 @@ mod tests { } fn lower(ssa: &mut HLSSA) { - LowerZstSlices::new().run(ssa, &analyses(ssa)); + LowerZstSlices::new().run(ssa, &analyses(ssa)).unwrap(); } fn program( diff --git a/compiler/src/compiler/passes/mem2reg.rs b/compiler/src/compiler/passes/mem2reg.rs index 982bbd34..2964c6cd 100644 --- a/compiler/src/compiler/passes/mem2reg.rs +++ b/compiler/src/compiler/passes/mem2reg.rs @@ -25,7 +25,7 @@ use crate::{ shared::call_string::Context, types::{FunctionTypeInfo, TypeInfo}, }, - pass_manager::{Analysis, AnalysisId, AnalysisStore, Pass}, + pass_manager::{Analysis, AnalysisId, AnalysisStore, Pass, PassResult}, passes::shared::value_replacements::ValueReplacements, ssa::{ BlockId, FunctionId, Terminator, ValueId, @@ -51,13 +51,14 @@ impl Pass for Mem2Reg { vec![FlowAnalysis::id(), TypeInfo::id(), PointsTo::id()] } - fn run(&self, ssa: &mut HLSSA, store: &AnalysisStore) { + fn run(&self, ssa: &mut HLSSA, store: &AnalysisStore) -> PassResult { self.do_run( ssa, store.get::(), store.get::(), store.get::(), ); + Ok(()) } } diff --git a/compiler/src/compiler/passes/merge_identical_functions.rs b/compiler/src/compiler/passes/merge_identical_functions.rs index 31f066ac..549eabe2 100644 --- a/compiler/src/compiler/passes/merge_identical_functions.rs +++ b/compiler/src/compiler/passes/merge_identical_functions.rs @@ -59,7 +59,7 @@ use crate::{ collections::{HashMap, HashSet}, compiler::{ - pass_manager::{AnalysisStore, Pass}, + pass_manager::{AnalysisStore, Pass, PassResult}, ssa::{ Function, FunctionId, Instruction, Terminator, ValueId, hlssa::{HLSSA, OpCode, Type}, @@ -78,8 +78,9 @@ impl Pass for MergeIdenticalFunctions { "merge_identical_functions" } - fn run(&self, ssa: &mut HLSSA, _store: &AnalysisStore) { + fn run(&self, ssa: &mut HLSSA, _store: &AnalysisStore) -> PassResult { self.do_run(ssa); + Ok(()) } } diff --git a/compiler/src/compiler/passes/normalize_asserts.rs b/compiler/src/compiler/passes/normalize_asserts.rs index 66f89e29..ac19beba 100644 --- a/compiler/src/compiler/passes/normalize_asserts.rs +++ b/compiler/src/compiler/passes/normalize_asserts.rs @@ -12,7 +12,7 @@ use crate::compiler::{ analysis::{flow_analysis::FlowAnalysis, types::TypeInfo}, - pass_manager::{Analysis, AnalysisId, AnalysisStore, Pass}, + pass_manager::{Analysis, AnalysisId, AnalysisStore, Pass, PassResult}, passes::shared::rewrite_asserts::rewrite_asserts, ssa::hlssa::{CmpKind, HLSSA, OpCode}, }; @@ -31,8 +31,9 @@ impl Pass for NormalizeAsserts { vec![TypeInfo::id()] } - fn run(&self, ssa: &mut HLSSA, store: &AnalysisStore) { + fn run(&self, ssa: &mut HLSSA, store: &AnalysisStore) -> PassResult { self.do_run(ssa, store.get::()); + Ok(()) } fn preserves(&self) -> Vec { diff --git a/compiler/src/compiler/passes/partial_redundancy_elimination/mod.rs b/compiler/src/compiler/passes/partial_redundancy_elimination/mod.rs index f1781165..d64ce306 100644 --- a/compiler/src/compiler/passes/partial_redundancy_elimination/mod.rs +++ b/compiler/src/compiler/passes/partial_redundancy_elimination/mod.rs @@ -115,7 +115,7 @@ use crate::compiler::{ click_cooper::ClickCooper, flow_analysis::FlowAnalysis, types::TypeInfo, witness_taint_inference::ApproximateWitnessTaint, }, - pass_manager::{Analysis, AnalysisId, AnalysisStore, Pass}, + pass_manager::{Analysis, AnalysisId, AnalysisStore, Pass, PassResult}, passes::dead_code_elimination::{Config as DceConfig, DCE}, ssa::hlssa::HLSSA, }; @@ -138,7 +138,7 @@ impl Pass for PRE { vec![ClickCooper::id(), TypeInfo::id(), FlowAnalysis::id()] } - fn run(&self, ssa: &mut HLSSA, store: &AnalysisStore) { + fn run(&self, ssa: &mut HLSSA, store: &AnalysisStore) -> PassResult { self.transform( ssa, store.get::(), @@ -149,6 +149,7 @@ impl Pass for PRE { // The rewrite invalidates the store's `FlowAnalysis`; recompute it for the integrated DCE. let flow = FlowAnalysis::run(ssa); DCE::new(self.config.dce).do_run(ssa, &flow); + Ok(()) } } diff --git a/compiler/src/compiler/passes/prepare_entry_point.rs b/compiler/src/compiler/passes/prepare_entry_point.rs index e04c59c0..628089cb 100644 --- a/compiler/src/compiler/passes/prepare_entry_point.rs +++ b/compiler/src/compiler/passes/prepare_entry_point.rs @@ -43,7 +43,7 @@ use std::{cell::RefCell, collections::BTreeSet, rc::Rc}; use crate::{ collections::HashMap, compiler::{ - pass_manager::{AnalysisStore, Pass}, + pass_manager::{AnalysisStore, Pass, PassResult}, passes::{ shared::{limbs::widest_injective_int_bits, unsupported::unsupported_on_this_field}, wide_witness_ints::multi_cell_int_bits, @@ -152,7 +152,7 @@ impl Pass for PrepareEntryPoint { "prepare_entry_point" } - fn run(&self, ssa: &mut HLSSA, _store: &AnalysisStore) { + fn run(&self, ssa: &mut HLSSA, _store: &AnalysisStore) -> PassResult { let layout = Self::wrap_main( ssa, self.main_is_unconstrained, @@ -163,6 +163,7 @@ impl Pass for PrepareEntryPoint { *sink.borrow_mut() = Some(layout); } Self::process_unconstrained_calls(ssa); + Ok(()) } } diff --git a/compiler/src/compiler/passes/purify_witness_slices.rs b/compiler/src/compiler/passes/purify_witness_slices.rs index 781b95d3..b4b83f1b 100644 --- a/compiler/src/compiler/passes/purify_witness_slices.rs +++ b/compiler/src/compiler/passes/purify_witness_slices.rs @@ -23,7 +23,7 @@ use crate::{ witness_info::WitnessShape, witness_taint_inference::ApproximateWitnessTaint, }, - pass_manager::{Analysis, AnalysisId, AnalysisStore, Pass}, + pass_manager::{Analysis, AnalysisId, AnalysisStore, Pass, PassResult}, ssa::{ BlockId, FunctionId, Instruction, SourceLocation, Terminator, ValueId, hlssa::{ @@ -53,7 +53,7 @@ impl Pass for PurifyWitnessSlices { vec![TypeInfo::id(), FlowAnalysis::id()] } - fn run(&self, ssa: &mut HLSSA, store: &AnalysisStore) { + fn run(&self, ssa: &mut HLSSA, store: &AnalysisStore) -> PassResult { ssa.mark_witness_slices_purified(); let flow = store.get::(); let types = store.get::(); @@ -141,6 +141,7 @@ impl Pass for PurifyWitnessSlices { ); ssa.put_function(function_id, function); } + Ok(()) } } @@ -1434,7 +1435,7 @@ mod tests { let mut store = AnalysisStore::new(); store.insert_with_deps::(flow, vec![]); store.insert_with_deps::(types, vec![]); - PurifyWitnessSlices::new().run(ssa, &store); + PurifyWitnessSlices::new().run(ssa, &store).unwrap(); // The rewrite must leave well-typed SSA behind. let flow = FlowAnalysis::run(ssa); let _ = Types::new().run(ssa, &flow); diff --git a/compiler/src/compiler/passes/rc_insertion.rs b/compiler/src/compiler/passes/rc_insertion.rs index f8c56ca1..2eacebed 100644 --- a/compiler/src/compiler/passes/rc_insertion.rs +++ b/compiler/src/compiler/passes/rc_insertion.rs @@ -16,7 +16,7 @@ use crate::{ liveness::{FunctionLiveness, LivenessAnalysis}, types::{FunctionTypeInfo, TypeInfo}, }, - pass_manager::{Analysis, AnalysisId, AnalysisStore, Pass}, + pass_manager::{Analysis, AnalysisId, AnalysisStore, Pass, PassResult}, ssa::{ Instruction, Located, SourceLocation, Terminator, ValueId, hlssa::{CastTarget, HLFunction, HLSSA, OpCode, RefCountOp, Type, TypeExpr}, @@ -36,7 +36,7 @@ impl Pass for RCInsertion { vec![FlowAnalysis::id(), TypeInfo::id()] } - fn run(&self, ssa: &mut HLSSA, store: &AnalysisStore) { + fn run(&self, ssa: &mut HLSSA, store: &AnalysisStore) -> PassResult { let cfg = store.get::(); let liveness = LivenessAnalysis::new().run(ssa, cfg); @@ -47,6 +47,7 @@ impl Pass for RCInsertion { let type_info = store.get::().get_function(*function_id); self.run_function(function, cfg, type_info, &liveness); } + Ok(()) } } diff --git a/compiler/src/compiler/passes/remove_unreachable_blocks.rs b/compiler/src/compiler/passes/remove_unreachable_blocks.rs index 2168a3f3..e361ffae 100644 --- a/compiler/src/compiler/passes/remove_unreachable_blocks.rs +++ b/compiler/src/compiler/passes/remove_unreachable_blocks.rs @@ -4,7 +4,7 @@ use crate::{ collections::HashSet, compiler::{ analysis::flow_analysis::FlowAnalysis, - pass_manager::{AnalysisId, AnalysisStore, Pass}, + pass_manager::{AnalysisId, AnalysisStore, Pass, PassResult}, ssa::{BlockId, hlssa::HLSSA}, }, }; @@ -26,8 +26,9 @@ impl Pass for RemoveUnreachableBlocks { vec![FlowAnalysis::id()] } - fn run(&self, ssa: &mut HLSSA, store: &AnalysisStore) { + fn run(&self, ssa: &mut HLSSA, store: &AnalysisStore) -> PassResult { remove_unreachable_blocks(ssa, store.get::()); + Ok(()) } } diff --git a/compiler/src/compiler/passes/remove_unreachable_functions.rs b/compiler/src/compiler/passes/remove_unreachable_functions.rs index d2a13d8c..fb7ac4eb 100644 --- a/compiler/src/compiler/passes/remove_unreachable_functions.rs +++ b/compiler/src/compiler/passes/remove_unreachable_functions.rs @@ -7,7 +7,7 @@ use crate::{ collections::HashSet, compiler::{ analysis::flow_analysis::FlowAnalysis, - pass_manager::{AnalysisId, AnalysisStore, Pass}, + pass_manager::{AnalysisId, AnalysisStore, Pass, PassResult}, ssa::hlssa::HLSSA, }, }; @@ -29,7 +29,7 @@ impl Pass for RemoveUnreachableFunctions { vec![FlowAnalysis::id()] } - fn run(&self, ssa: &mut HLSSA, store: &AnalysisStore) { + fn run(&self, ssa: &mut HLSSA, store: &AnalysisStore) -> PassResult { let cfg = store.get::(); let call_graph = cfg.get_call_graph(); @@ -46,5 +46,6 @@ impl Pass for RemoveUnreachableFunctions { ssa.delete_function(function_id); } } + Ok(()) } } diff --git a/compiler/src/compiler/passes/return_reachability.rs b/compiler/src/compiler/passes/return_reachability.rs index 2b63620c..69461445 100644 --- a/compiler/src/compiler/passes/return_reachability.rs +++ b/compiler/src/compiler/passes/return_reachability.rs @@ -5,7 +5,7 @@ use std::{cell::RefCell, rc::Rc}; use crate::compiler::{ analysis::{flow_analysis::FlowAnalysis, return_reachability::non_returning_entries}, diagnostic::Diagnostic, - pass_manager::{AnalysisId, AnalysisStore, Pass}, + pass_manager::{AnalysisId, AnalysisStore, Pass, PassResult}, ssa::hlssa::HLSSA, }; @@ -28,7 +28,8 @@ impl Pass for ReturnReachabilityValidation { vec![FlowAnalysis::id()] } - fn run(&self, ssa: &mut HLSSA, store: &AnalysisStore) { + fn run(&self, ssa: &mut HLSSA, store: &AnalysisStore) -> PassResult { *self.failures.borrow_mut() = Some(non_returning_entries(ssa, store.get::())); + Ok(()) } } diff --git a/compiler/src/compiler/passes/simplifier.rs b/compiler/src/compiler/passes/simplifier.rs index e5e479c3..1dd248193 100644 --- a/compiler/src/compiler/passes/simplifier.rs +++ b/compiler/src/compiler/passes/simplifier.rs @@ -9,7 +9,7 @@ use crate::{ types::{FunctionTypeInfo, Types, pool_constant_types}, value_definitions::{FunctionValueDefinitions, ValueDefinition}, }, - pass_manager::{AnalysisId, AnalysisStore, Pass}, + pass_manager::{AnalysisId, AnalysisStore, Pass, PassResult}, passes::shared::{ limbs::widest_injective_int_bits, value_replacements::{ReplaceScope, ValueReplacements}, @@ -38,8 +38,9 @@ impl Pass for Simplifier { vec![FlowAnalysis::id()] } - fn run(&self, ssa: &mut HLSSA, store: &AnalysisStore) { + fn run(&self, ssa: &mut HLSSA, store: &AnalysisStore) -> PassResult { self.do_run(ssa, store.get::()); + Ok(()) } fn preserves(&self) -> Vec { diff --git a/compiler/src/compiler/passes/simplify_asserts.rs b/compiler/src/compiler/passes/simplify_asserts.rs index 44c58a91..13b4b387 100644 --- a/compiler/src/compiler/passes/simplify_asserts.rs +++ b/compiler/src/compiler/passes/simplify_asserts.rs @@ -12,7 +12,7 @@ use crate::{ flow_analysis::FlowAnalysis, types::{FunctionTypeInfo, TypeInfo}, }, - pass_manager::{Analysis, AnalysisId, AnalysisStore, Pass}, + pass_manager::{Analysis, AnalysisId, AnalysisStore, Pass, PassResult}, passes::shared::rewrite_asserts::rewrite_asserts, ssa::{ ValueId, @@ -33,8 +33,9 @@ impl Pass for SimplifyAsserts { fn needs(&self) -> Vec { vec![TypeInfo::id()] } - fn run(&self, ssa: &mut HLSSA, store: &AnalysisStore) { + fn run(&self, ssa: &mut HLSSA, store: &AnalysisStore) -> PassResult { self.do_run(ssa, store.get::()); + Ok(()) } fn preserves(&self) -> Vec { vec![FlowAnalysis::id(), TypeInfo::id()] diff --git a/compiler/src/compiler/passes/sparse_conditional_simplification/mod.rs b/compiler/src/compiler/passes/sparse_conditional_simplification/mod.rs index d2c1568e..630bb0e4 100644 --- a/compiler/src/compiler/passes/sparse_conditional_simplification/mod.rs +++ b/compiler/src/compiler/passes/sparse_conditional_simplification/mod.rs @@ -93,7 +93,7 @@ use crate::{ flow_analysis::FlowAnalysis, types::{FunctionTypeInfo, TypeInfo, Types}, }, - pass_manager::{Analysis, AnalysisId, AnalysisStore, Pass}, + pass_manager::{Analysis, AnalysisId, AnalysisStore, Pass, PassResult}, passes::{ dead_code_elimination::{Config, DCE}, shared::value_replacements::{ReplaceScope, ValueReplacements}, @@ -124,11 +124,12 @@ impl Pass for SCS { vec![ClickCooper::id(), TypeInfo::id()] } - fn run(&self, ssa: &mut HLSSA, store: &AnalysisStore) { + fn run(&self, ssa: &mut HLSSA, store: &AnalysisStore) -> PassResult { propagate_all(ssa, store.get::(), store.get::()); // The rewrite invalidates the store's `FlowAnalysis`; recompute it for the integrated DCE. let flow = FlowAnalysis::run(ssa); DCE::new(self.config).do_run(ssa, &flow); + Ok(()) } } diff --git a/compiler/src/compiler/passes/specializer.rs b/compiler/src/compiler/passes/specializer.rs index b8bf5efe..da54dc49 100644 --- a/compiler/src/compiler/passes/specializer.rs +++ b/compiler/src/compiler/passes/specializer.rs @@ -22,7 +22,7 @@ use crate::{ symbolic_executor::{self, AssertionFailure, SymbolicExecutor}, types::TypeInfo, }, - pass_manager::{Analysis, AnalysisId, AnalysisStore, Pass}, + pass_manager::{Analysis, AnalysisId, AnalysisStore, Pass, PassResult}, ssa::{ BlockId, FunctionId, SourceLocation, ValueId, hlssa::{ @@ -850,7 +850,7 @@ impl Pass for Specializer { vec![Summary::id(), TypeInfo::id()] } - fn run(&self, ssa: &mut HLSSA, store: &AnalysisStore) { + fn run(&self, ssa: &mut HLSSA, store: &AnalysisStore) -> PassResult { let summary = store.get::(); let mut speculative_ids: HashSet = HashSet::default(); let mut accepted_ids: HashSet = HashSet::default(); @@ -873,6 +873,7 @@ impl Pass for Specializer { // unreferenced and are cleaned up by the DCE pass that runs immediately after the // specializer. ssa.retain_functions(|id, _| !speculative_ids.contains(&id) || accepted_ids.contains(&id)); + Ok(()) } } diff --git a/compiler/src/compiler/passes/strip_witness_of.rs b/compiler/src/compiler/passes/strip_witness_of.rs index c6066266..f7972719 100644 --- a/compiler/src/compiler/passes/strip_witness_of.rs +++ b/compiler/src/compiler/passes/strip_witness_of.rs @@ -7,7 +7,7 @@ use crate::compiler::{ analysis::flow_analysis::FlowAnalysis, - pass_manager::{AnalysisId, AnalysisStore, Pass}, + pass_manager::{AnalysisId, AnalysisStore, Pass, PassResult}, passes::shared::value_replacements::ValueReplacements, ssa::hlssa::{HLSSA, OpCode, Type}, util::{ice_non_elided_tuple, ice_unvalidated_assert_constant}, @@ -19,8 +19,9 @@ impl Pass for StripWitnessOf { fn name(&self) -> &'static str { "strip_witness_of" } - fn run(&self, ssa: &mut HLSSA, _store: &AnalysisStore) { + fn run(&self, ssa: &mut HLSSA, _store: &AnalysisStore) -> PassResult { self.do_run(ssa); + Ok(()) } fn preserves(&self) -> Vec { vec![FlowAnalysis::id()] diff --git a/compiler/src/compiler/passes/trivial_phi_elimination.rs b/compiler/src/compiler/passes/trivial_phi_elimination.rs index a8e6e8b9..9e96fdba 100644 --- a/compiler/src/compiler/passes/trivial_phi_elimination.rs +++ b/compiler/src/compiler/passes/trivial_phi_elimination.rs @@ -26,7 +26,7 @@ use crate::{ collections::{HashMap, HashSet}, compiler::{ - pass_manager::{AnalysisId, AnalysisStore, Pass}, + pass_manager::{AnalysisId, AnalysisStore, Pass, PassResult}, passes::shared::value_replacements::{ReplaceScope, ValueReplacements}, ssa::{ BlockId, Terminator, ValueId, @@ -48,8 +48,9 @@ impl Pass for TrivialPhiElimination { vec![] } - fn run(&self, ssa: &mut HLSSA, _store: &AnalysisStore) { + fn run(&self, ssa: &mut HLSSA, _store: &AnalysisStore) -> PassResult { self.do_run(ssa); + Ok(()) } } diff --git a/compiler/src/compiler/passes/wide_witness_ints/mod.rs b/compiler/src/compiler/passes/wide_witness_ints/mod.rs index 0747fb5d..f8bca9ac 100644 --- a/compiler/src/compiler/passes/wide_witness_ints/mod.rs +++ b/compiler/src/compiler/passes/wide_witness_ints/mod.rs @@ -148,7 +148,7 @@ use crate::compiler::{ types::{FunctionTypeInfo, TypeInfo}, value_range_analysis::field_modulus, }, - pass_manager::{Analysis, AnalysisId, AnalysisStore, Pass}, + pass_manager::{Analysis, AnalysisId, AnalysisStore, Pass, PassResult}, passes::shared::{ divmod_guard::nonzero_hint_divisor, limbs::{ @@ -196,7 +196,7 @@ impl Pass for WideWitnessInts { vec![TypeInfo::id(), FlowAnalysis::id()] } - fn run(&self, ssa: &mut HLSSA, store: &AnalysisStore) { + fn run(&self, ssa: &mut HLSSA, store: &AnalysisStore) -> PassResult { let field = ssa.field(); let globals = Globals::split(ssa, field); @@ -254,6 +254,7 @@ impl Pass for WideWitnessInts { } rewrite_function(ssa, fid, &reachable, &value_map, type_info, field, &globals); } + Ok(()) } fn preserves(&self) -> Vec { diff --git a/compiler/src/compiler/passes/wide_witness_ints/tests.rs b/compiler/src/compiler/passes/wide_witness_ints/tests.rs index 63dcaf7f..ab6b8494 100644 --- a/compiler/src/compiler/passes/wide_witness_ints/tests.rs +++ b/compiler/src/compiler/passes/wide_witness_ints/tests.rs @@ -3222,7 +3222,7 @@ fn run_pass(ssa: &mut HLSSA) { let mut store = AnalysisStore::new(); store.insert_with_deps(flow, vec![]); store.insert_with_deps(types, vec![]); - WideWitnessInts::new().run(ssa, &store); + WideWitnessInts::new().run(ssa, &store).unwrap(); } // SPREADS diff --git a/compiler/src/compiler/passes/witness_lowering.rs b/compiler/src/compiler/passes/witness_lowering.rs index 914f88a4..4ff0d249 100644 --- a/compiler/src/compiler/passes/witness_lowering.rs +++ b/compiler/src/compiler/passes/witness_lowering.rs @@ -5,7 +5,7 @@ use crate::{ collections::HashMap, compiler::{ analysis::{flow_analysis::FlowAnalysis, types::TypeInfo}, - pass_manager::{Analysis, AnalysisId, AnalysisStore, Pass}, + pass_manager::{Analysis, AnalysisId, AnalysisStore, Pass, PassResult}, passes::shared::value_replacements::ValueReplacements, ssa::{ BlockId, Terminator, ValueId, @@ -29,8 +29,9 @@ impl Pass for WitnessLowering { vec![TypeInfo::id(), FlowAnalysis::id()] } - fn run(&self, ssa: &mut HLSSA, store: &AnalysisStore) { + fn run(&self, ssa: &mut HLSSA, store: &AnalysisStore) -> PassResult { self.do_run(ssa, store.get::(), store.get::()); + Ok(()) } } diff --git a/compiler/src/compiler/passes/witness_write_to_fresh.rs b/compiler/src/compiler/passes/witness_write_to_fresh.rs index 852ddcf8..e6022048 100644 --- a/compiler/src/compiler/passes/witness_write_to_fresh.rs +++ b/compiler/src/compiler/passes/witness_write_to_fresh.rs @@ -4,7 +4,7 @@ use crate::compiler::{ analysis::{flow_analysis::FlowAnalysis, types::TypeInfo}, - pass_manager::{Analysis, AnalysisId, AnalysisStore, Pass}, + pass_manager::{Analysis, AnalysisId, AnalysisStore, Pass, PassResult}, ssa::hlssa::{HLSSA, OpCode}, util::{ice_non_elided_tuple, ice_unvalidated_assert_constant}, }; @@ -20,8 +20,9 @@ impl Pass for WitnessWriteToFresh { vec![TypeInfo::id()] } - fn run(&self, ssa: &mut HLSSA, store: &AnalysisStore) { + fn run(&self, ssa: &mut HLSSA, store: &AnalysisStore) -> PassResult { self.do_run(ssa, store.get::()); + Ok(()) } fn preserves(&self) -> Vec { diff --git a/compiler/src/compiler/passes/witness_write_to_void.rs b/compiler/src/compiler/passes/witness_write_to_void.rs index 0903eae1..21e0f923 100644 --- a/compiler/src/compiler/passes/witness_write_to_void.rs +++ b/compiler/src/compiler/passes/witness_write_to_void.rs @@ -7,7 +7,7 @@ use crate::compiler::{ analysis::flow_analysis::FlowAnalysis, - pass_manager::{AnalysisId, AnalysisStore, Pass}, + pass_manager::{AnalysisId, AnalysisStore, Pass, PassResult}, passes::shared::value_replacements::ValueReplacements, ssa::hlssa::{HLSSA, OpCode}, }; @@ -18,8 +18,9 @@ impl Pass for WitnessWriteToVoid { fn name(&self) -> &'static str { "witness_write_to_void" } - fn run(&self, ssa: &mut HLSSA, _store: &AnalysisStore) { + fn run(&self, ssa: &mut HLSSA, _store: &AnalysisStore) -> PassResult { self.do_run(ssa); + Ok(()) } fn preserves(&self) -> Vec { vec![FlowAnalysis::id()] diff --git a/compiler/src/driver.rs b/compiler/src/driver.rs index 81685555..b024d1a9 100644 --- a/compiler/src/driver.rs +++ b/compiler/src/driver.rs @@ -144,6 +144,10 @@ pub enum Error { /// assertion failures do not retain their spans. UnsatisfiableProgram(Vec), + /// A pass cannot compile part of the program, such as a width of the configured field is too + /// narrow. + PassFailed(Vec), + /// The program uses a Noir feature Mavros cannot lower, or a value that does not fit the field. LoweringRefused(Vec), @@ -213,6 +217,7 @@ impl std::fmt::Display for Error { } Error::WitnessManifest(message) => write!(f, "witness manifest: {message}"), Error::Toolchain(error) => write!(f, "{error}"), + Error::PassFailed(diagnostics) => write!(f, "{}", diagnostic::render_all(diagnostics)), } } } @@ -440,7 +445,9 @@ impl Driver { ], ); validation.set_debug_output_dir(self.get_debug_output_dir().clone()); - validation.run(&mut ssa); + validation + .run(&mut ssa) + .map_err(|failures| self.pass_failed(failures))?; let failures = failures .borrow_mut() .take() @@ -504,7 +511,9 @@ impl Driver { ); pass_manager.set_debug_output_dir(self.get_debug_output_dir().clone()); - pass_manager.run(&mut ssa); + pass_manager + .run(&mut ssa) + .map_err(|failures| self.pass_failed(failures))?; self.entry_blob_layout = Some( entry_blob_layout .borrow_mut() @@ -515,6 +524,16 @@ impl Driver { Ok(()) } + /// [`Error::PassFailed`] for what a pass reported with compiled sources. + fn pass_failed(&self, failures: Vec) -> Error { + Error::PassFailed( + failures + .into_iter() + .map(|diagnostic| self.attach_compiled_source(diagnostic)) + .collect(), + ) + } + /// Attach the source text the compiler read for `diagnostic`'s file, where there is one, so the /// snippet shows the code that was compiled, even if the file has changed by the time the error /// prints. @@ -625,7 +644,8 @@ impl Driver { Box::new(RemoveUnreachableFunctions::new()), ], ) - .run(&mut ssa); + .run(&mut ssa) + .map_err(|failures| self.pass_failed(failures))?; let flow_analysis = FlowAnalysis::run(&ssa); @@ -649,7 +669,8 @@ impl Driver { Rc::clone(&failures), ))], ) - .run(&mut ssa); + .run(&mut ssa) + .map_err(|failures| self.pass_failed(failures))?; let failures = failures .borrow_mut() .take() @@ -752,7 +773,9 @@ impl Driver { ); pass_manager.set_debug_output_dir(self.get_debug_output_dir().clone()); - pass_manager.run(&mut ssa); + pass_manager + .run(&mut ssa) + .map_err(|failures| self.pass_failed(failures))?; self.witness_spilled_ssa = Some(ssa); Ok(()) } @@ -790,7 +813,9 @@ impl Driver { ], ); r1cs_phase_1.set_debug_output_dir(self.get_debug_output_dir().clone()); - r1cs_phase_1.run(&mut r1cs_ssa); + r1cs_phase_1 + .run(&mut r1cs_ssa) + .map_err(|failures| self.pass_failed(failures))?; let flow_analysis = FlowAnalysis::run(&r1cs_ssa); let type_info = Types::new().run(&r1cs_ssa, &flow_analysis); @@ -986,7 +1011,7 @@ impl Driver { options: CodeGenOptions, mode: WitnessMode, ) -> Result { - self.prepare_program_ssa(); + self.prepare_program_ssa()?; let ssa = self.program_ssa.as_ref().unwrap(); let flow_analysis = FlowAnalysis::run(ssa); @@ -1135,9 +1160,9 @@ impl Driver { /// everything downstream (refcounting, codegen, every artifact) compiles the whole program /// together. #[tracing::instrument(skip_all)] - fn prepare_program_ssa(&mut self) { + fn prepare_program_ssa(&mut self) -> Result<(), Error> { if self.program_ssa.is_some() { - return; + return Ok(()); } let mut ssa = self.witness_spilled_ssa.clone().unwrap(); @@ -1153,7 +1178,9 @@ impl Driver { ], ); witgen_pm.set_debug_output_dir(self.get_debug_output_dir().clone()); - witgen_pm.run(&mut ssa); + witgen_pm + .run(&mut ssa) + .map_err(|failures| self.pass_failed(failures))?; let mut ad_ssa = self.r1cs_ssa.clone().unwrap(); let mut ad_pm = PassManager::new( @@ -1173,7 +1200,9 @@ impl Driver { ], ); ad_pm.set_debug_output_dir(self.get_debug_output_dir().clone()); - ad_pm.run(&mut ad_ssa); + ad_pm + .run(&mut ad_ssa) + .map_err(|failures| self.pass_failed(failures))?; // `SSA::merge` re-interns constants by value, which would silently conflate function // pointers across the two halves; by this point defunctionalization must have removed @@ -1206,7 +1235,9 @@ impl Driver { ], ); tail_pm.set_debug_output_dir(self.get_debug_output_dir().clone()); - tail_pm.run(&mut ssa); + tail_pm + .run(&mut ssa) + .map_err(|failures| self.pass_failed(failures))?; self.write_debug_text( self.get_debug_output_dir().join("program_ssa.txt"), @@ -1214,6 +1245,7 @@ impl Driver { ); self.program_ssa = Some(ssa); + Ok(()) } #[tracing::instrument(skip_all)] @@ -1243,7 +1275,7 @@ impl Driver { )); } - self.prepare_program_ssa(); + self.prepare_program_ssa()?; let ssa = self.program_ssa.as_ref().unwrap(); let flow_analysis = FlowAnalysis::run(ssa);