[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);