From 6600ab1216e1a5c3b19e6e1f6988ee283c38b2c6 Mon Sep 17 00:00:00 2001 From: chriseth Date: Mon, 22 May 2023 22:51:02 +0200 Subject: [PATCH] Improved dynamic reference replacement. --- riscv/src/compiler.rs | 41 +++++++++++++++++++++++------------------ 1 file changed, 23 insertions(+), 18 deletions(-) diff --git a/riscv/src/compiler.rs b/riscv/src/compiler.rs index 4178fefd0..64c9756a6 100644 --- a/riscv/src/compiler.rs +++ b/riscv/src/compiler.rs @@ -1,4 +1,4 @@ -use std::collections::BTreeMap; +use std::collections::{BTreeMap, BTreeSet}; use itertools::Itertools; @@ -74,7 +74,6 @@ fn replace_dynamic_label_references( statements: &mut Vec, data_objects: &BTreeMap>, ) { - let mut replacement = vec![]; /* Find patterns of the form lui a0, %hi(LABEL) @@ -85,26 +84,32 @@ fn replace_dynamic_label_references( which is then turned into s10 <=X= load_label(LABEL) + + It gets more complicated by the fact that sometimes, labels + and debugging directives occur between the two statements + matching that pattern... */ - // TODO This is really hacky, should be rustified - let mut i = 0; - while i < statements.len() { - let s1 = &statements[i]; - let s2 = &statements.get(i + 1); - if s2.is_none() { - replacement.push(s1.clone()); - i += 1; - } else if let Some(r) = replace_dynamic_label_reference(s1, s2.unwrap(), data_objects) { - replacement.push(r); - i += 2; - } else { - // TODO avoid clone - replacement.push(s1.clone()); - i += 1; + let instruction_indices = statements + .iter() + .enumerate() + .filter_map(|(i, s)| match s { + Statement::Instruction(_, _) => Some(i), + _ => None, + }) + .collect::>(); + + let mut to_delete = BTreeSet::default(); + for (i1, i2) in instruction_indices.into_iter().tuple_windows() { + if let Some(r) = + replace_dynamic_label_reference(&statements[i1], &statements[i2], data_objects) + { + to_delete.insert(i1); + statements[i2] = r; } } - *statements = replacement; + let mut i = 0; + statements.retain(|_| (!to_delete.contains(&i), i += 1).0); } fn replace_dynamic_label_reference(