@samitouri / QOS-React-2 / commits / 32286b74ac

[rust] enter_ssa uses new diagnostic type

Joe Savona committed Jul 14, 2023 at 15:56 UTC 32286b74acb55ea19fa9946ba868b5ee2ffae207
4 files changed +44 -17
compiler/forget/Cargo.lock
+1
@@ -549,6 +549,7 @@ name = "forget_ssa"
549 version = "0.1.0"
550 dependencies = [
551 "bumpalo",
552 + "forget_diagnostics",
553 "forget_hir",
554 "forget_utils",
555 "indexmap 2.0.0",
compiler/forget/crates/forget_hir/src/instruction.rs
+26
@@ -40,6 +40,32 @@ impl<'a> Instruction<'a> {
40 }
41 }
42
43 + pub fn try_each_identifier_store<F, E>(&mut self, mut f: F) -> Result<(), E>
44 + where
45 + F: FnMut(&mut LValue<'a>) -> Result<(), E>,
46 + {
47 + match &mut self.value {
48 + InstructionValue::DeclareContext(instr) => {
49 + f(&mut instr.lvalue)?;
50 + }
51 + InstructionValue::DeclareLocal(instr) => {
52 + f(&mut instr.lvalue)?;
53 + }
54 + InstructionValue::StoreLocal(instr) => {
55 + f(&mut instr.lvalue)?;
56 + }
57 + InstructionValue::Array(_)
58 + | InstructionValue::Binary(_)
59 + | InstructionValue::LoadContext(_)
60 + | InstructionValue::LoadGlobal(_)
61 + | InstructionValue::LoadLocal(_)
62 + | InstructionValue::Primitive(_)
63 + | InstructionValue::Function(_)
64 + | InstructionValue::Tombstone => {}
65 + }
66 + Ok(())
67 + }
68 +
69 pub fn each_identifier_load<F>(&mut self, mut f: F) -> ()
70 where
71 F: FnMut(&mut IdentifierOperand<'a>) -> (),
compiler/forget/crates/forget_ssa/Cargo.toml
+1
@@ -15,6 +15,7 @@ repository.workspace = true
15 [dependencies]
16 forget_hir = { workspace = true }
17 forget_utils = { workspace = true }
18 +forget_diagnostics = { workspace = true }
19 bumpalo = { workspace = true }
20 indexmap = { workspace = true }
21 miette = { workspace = true }
compiler/forget/crates/forget_ssa/src/enter.rs
+16 -17
@@ -2,18 +2,14 @@ use std::cell::RefCell;
2 use std::rc::Rc;
3
4 use bumpalo::collections::{CollectIn, Vec};
5 +use forget_diagnostics::{invariant, Diagnostic};
6 use forget_hir::{
7 BasicBlock, BlockId, Blocks, Environment, Function, Identifier, IdentifierData, IdentifierId,
8 IdentifierOperand, Instruction, InstructionValue, LValue, MutableRange, Phi,
9 };
10 use indexmap::{IndexMap, IndexSet};
10 -use thiserror::Error;
11
12 -#[derive(Error, Debug)]
13 -#[error("Error constructing SSA form")]
14 -pub struct SSAError;
15 -
16 -pub fn enter_ssa<'a>(env: &Environment<'a>, fun: &mut Function<'a>) -> Result<(), SSAError> {
12 +pub fn enter_ssa<'a>(env: &Environment<'a>, fun: &mut Function<'a>) -> Result<(), Diagnostic> {
13 assert!(fun.context.is_empty());
14 enter_ssa_impl(env, fun, None)
15 }
@@ -22,7 +18,7 @@ pub fn enter_ssa_impl<'a>(
18 env: &Environment<'a>,
19 fun: &mut Function<'a>,
20 context_defs: Option<IndexMap<IdentifierId, Identifier<'a>>>,
25 -) -> Result<(), SSAError> {
21 +) -> Result<(), Diagnostic> {
22 let blocks = &fun.body.blocks;
23 let instructions = &mut fun.body.instructions;
24 let mut builder = Builder::new(env, fun.body.entry, blocks);
@@ -48,11 +44,11 @@ fn visit_instructions<'a, 'e, 'f>(
44 env: &Environment<'a>,
45 builder: &mut Builder<'a, 'e, 'f>,
46 instructions: &mut Vec<'a, Instruction<'a>>,
51 -) -> Result<(), SSAError> {
47 +) -> Result<(), Diagnostic> {
48 builder.each_block(|block, builder| {
49 for instr_ix in &block.instructions {
50 let instr = &mut instructions[usize::from(*instr_ix)];
55 - instr.each_identifier_store(|store| builder.visit_store(store));
51 + instr.try_each_identifier_store(|store| builder.visit_store(store))?;
52 instr.each_identifier_load(|load| builder.visit_load(load));
53
54 if let InstructionValue::Function(fun) = &mut instr.value {
@@ -143,24 +139,27 @@ impl<'a, 'e, 'f> Builder<'a, 'e, 'f> {
139 self.env.next_identifier_id()
140 }
141
146 - fn visit_store(&mut self, lvalue: &mut LValue<'a>) -> () {
142 + fn visit_store(&mut self, lvalue: &mut LValue<'a>) -> Result<(), Diagnostic> {
143 let old_identifier = &lvalue.identifier.identifier;
144 // TODO: use Result (?)
149 - assert!(
150 - !self.unknown.contains(&old_identifier.id),
151 - "EnterSSA: Expected identifier to be defined before being used. Identifier {old_identifier:?} is undefined."
152 - );
145 + invariant(!self.unknown.contains(&old_identifier.id), || {
146 + Diagnostic::invariant(
147 + "EnterSSA: Expected identifier to be defined before being used",
148 + None,
149 + )
150 + })?;
151
152 if self.context.contains(&old_identifier.id) {
153 let new_identifier = self.get_id_at(self.current, old_identifier);
154 lvalue.identifier.identifier = new_identifier;
157 - return;
155 + return Ok(());
156 }
157
158 let new_identifier = self.make_identifier(old_identifier);
159 let state = self.states.get_mut(&self.current).unwrap();
160 state.defs.insert(old_identifier.id, new_identifier.clone());
161 lvalue.identifier.identifier = new_identifier;
162 + Ok(())
163 }
164
165 fn visit_param(&mut self, param: &mut IdentifierOperand<'a>) -> () {
@@ -258,9 +257,9 @@ impl<'a, 'e, 'f> Builder<'a, 'e, 'f> {
257 }
258 }
259
261 - fn each_block<F>(&mut self, mut f: F) -> Result<(), SSAError>
260 + fn each_block<F>(&mut self, mut f: F) -> Result<(), Diagnostic>
261 where
263 - F: FnMut(&BasicBlock<'a>, &mut Self) -> Result<(), SSAError>,
262 + F: FnMut(&BasicBlock<'a>, &mut Self) -> Result<(), Diagnostic>,
263 {
264 let mut visited = IndexSet::new();
265 let block_ids: Vec<_> = self.blocks.keys().cloned().collect_in(self.env.allocator);