From 32286b74acb55ea19fa9946ba868b5ee2ffae207 Mon Sep 17 00:00:00 2001 From: Joe Savona Date: Fri, 14 Jul 2023 15:56:53 +0900 Subject: [PATCH] [rust] enter_ssa uses new diagnostic type --- compiler/forget/Cargo.lock | 1 + .../crates/forget_hir/src/instruction.rs | 26 +++++++++++++++ compiler/forget/crates/forget_ssa/Cargo.toml | 1 + .../forget/crates/forget_ssa/src/enter.rs | 33 +++++++++---------- 4 files changed, 44 insertions(+), 17 deletions(-) diff --git a/compiler/forget/Cargo.lock b/compiler/forget/Cargo.lock index c08519d179..7cda77f40d 100644 --- a/compiler/forget/Cargo.lock +++ b/compiler/forget/Cargo.lock @@ -549,6 +549,7 @@ name = "forget_ssa" version = "0.1.0" dependencies = [ "bumpalo", + "forget_diagnostics", "forget_hir", "forget_utils", "indexmap 2.0.0", diff --git a/compiler/forget/crates/forget_hir/src/instruction.rs b/compiler/forget/crates/forget_hir/src/instruction.rs index dc7baa16a6..49e0cb1b75 100644 --- a/compiler/forget/crates/forget_hir/src/instruction.rs +++ b/compiler/forget/crates/forget_hir/src/instruction.rs @@ -40,6 +40,32 @@ impl<'a> Instruction<'a> { } } + pub fn try_each_identifier_store(&mut self, mut f: F) -> Result<(), E> + where + F: FnMut(&mut LValue<'a>) -> Result<(), E>, + { + match &mut self.value { + InstructionValue::DeclareContext(instr) => { + f(&mut instr.lvalue)?; + } + InstructionValue::DeclareLocal(instr) => { + f(&mut instr.lvalue)?; + } + InstructionValue::StoreLocal(instr) => { + f(&mut instr.lvalue)?; + } + InstructionValue::Array(_) + | InstructionValue::Binary(_) + | InstructionValue::LoadContext(_) + | InstructionValue::LoadGlobal(_) + | InstructionValue::LoadLocal(_) + | InstructionValue::Primitive(_) + | InstructionValue::Function(_) + | InstructionValue::Tombstone => {} + } + Ok(()) + } + pub fn each_identifier_load(&mut self, mut f: F) -> () where F: FnMut(&mut IdentifierOperand<'a>) -> (), diff --git a/compiler/forget/crates/forget_ssa/Cargo.toml b/compiler/forget/crates/forget_ssa/Cargo.toml index 855b7c0bfa..e4eb2eab0d 100644 --- a/compiler/forget/crates/forget_ssa/Cargo.toml +++ b/compiler/forget/crates/forget_ssa/Cargo.toml @@ -15,6 +15,7 @@ repository.workspace = true [dependencies] forget_hir = { workspace = true } forget_utils = { workspace = true } +forget_diagnostics = { workspace = true } bumpalo = { workspace = true } indexmap = { workspace = true } miette = { workspace = true } diff --git a/compiler/forget/crates/forget_ssa/src/enter.rs b/compiler/forget/crates/forget_ssa/src/enter.rs index fc8f9f8f6c..0eabc0545f 100644 --- a/compiler/forget/crates/forget_ssa/src/enter.rs +++ b/compiler/forget/crates/forget_ssa/src/enter.rs @@ -2,18 +2,14 @@ use std::cell::RefCell; use std::rc::Rc; use bumpalo::collections::{CollectIn, Vec}; +use forget_diagnostics::{invariant, Diagnostic}; use forget_hir::{ BasicBlock, BlockId, Blocks, Environment, Function, Identifier, IdentifierData, IdentifierId, IdentifierOperand, Instruction, InstructionValue, LValue, MutableRange, Phi, }; use indexmap::{IndexMap, IndexSet}; -use thiserror::Error; -#[derive(Error, Debug)] -#[error("Error constructing SSA form")] -pub struct SSAError; - -pub fn enter_ssa<'a>(env: &Environment<'a>, fun: &mut Function<'a>) -> Result<(), SSAError> { +pub fn enter_ssa<'a>(env: &Environment<'a>, fun: &mut Function<'a>) -> Result<(), Diagnostic> { assert!(fun.context.is_empty()); enter_ssa_impl(env, fun, None) } @@ -22,7 +18,7 @@ pub fn enter_ssa_impl<'a>( env: &Environment<'a>, fun: &mut Function<'a>, context_defs: Option>>, -) -> Result<(), SSAError> { +) -> Result<(), Diagnostic> { let blocks = &fun.body.blocks; let instructions = &mut fun.body.instructions; let mut builder = Builder::new(env, fun.body.entry, blocks); @@ -48,11 +44,11 @@ fn visit_instructions<'a, 'e, 'f>( env: &Environment<'a>, builder: &mut Builder<'a, 'e, 'f>, instructions: &mut Vec<'a, Instruction<'a>>, -) -> Result<(), SSAError> { +) -> Result<(), Diagnostic> { builder.each_block(|block, builder| { for instr_ix in &block.instructions { let instr = &mut instructions[usize::from(*instr_ix)]; - instr.each_identifier_store(|store| builder.visit_store(store)); + instr.try_each_identifier_store(|store| builder.visit_store(store))?; instr.each_identifier_load(|load| builder.visit_load(load)); if let InstructionValue::Function(fun) = &mut instr.value { @@ -143,24 +139,27 @@ impl<'a, 'e, 'f> Builder<'a, 'e, 'f> { self.env.next_identifier_id() } - fn visit_store(&mut self, lvalue: &mut LValue<'a>) -> () { + fn visit_store(&mut self, lvalue: &mut LValue<'a>) -> Result<(), Diagnostic> { let old_identifier = &lvalue.identifier.identifier; // TODO: use Result (?) - assert!( - !self.unknown.contains(&old_identifier.id), - "EnterSSA: Expected identifier to be defined before being used. Identifier {old_identifier:?} is undefined." - ); + invariant(!self.unknown.contains(&old_identifier.id), || { + Diagnostic::invariant( + "EnterSSA: Expected identifier to be defined before being used", + None, + ) + })?; if self.context.contains(&old_identifier.id) { let new_identifier = self.get_id_at(self.current, old_identifier); lvalue.identifier.identifier = new_identifier; - return; + return Ok(()); } let new_identifier = self.make_identifier(old_identifier); let state = self.states.get_mut(&self.current).unwrap(); state.defs.insert(old_identifier.id, new_identifier.clone()); lvalue.identifier.identifier = new_identifier; + Ok(()) } fn visit_param(&mut self, param: &mut IdentifierOperand<'a>) -> () { @@ -258,9 +257,9 @@ impl<'a, 'e, 'f> Builder<'a, 'e, 'f> { } } - fn each_block(&mut self, mut f: F) -> Result<(), SSAError> + fn each_block(&mut self, mut f: F) -> Result<(), Diagnostic> where - F: FnMut(&BasicBlock<'a>, &mut Self) -> Result<(), SSAError>, + F: FnMut(&BasicBlock<'a>, &mut Self) -> Result<(), Diagnostic>, { let mut visited = IndexSet::new(); let block_ids: Vec<_> = self.blocks.keys().cloned().collect_in(self.env.allocator);