From 90ca93de5fcb38e65f02f978d724f94a75172ce5 Mon Sep 17 00:00:00 2001 From: chriseth Date: Mon, 15 May 2023 18:19:58 +0200 Subject: [PATCH] Parse hi and lo data reference offsets. --- riscv/src/compiler.rs | 21 ++++++++++++++------- riscv/src/disambiguator.rs | 8 ++++---- riscv/src/parser.rs | 20 ++++++++++++++++---- riscv/src/reachability.rs | 8 +++++--- riscv/src/riscv_asm.lalrpop | 10 ++++++++-- 5 files changed, 47 insertions(+), 20 deletions(-) diff --git a/riscv/src/compiler.rs b/riscv/src/compiler.rs index ecbadc637..d832f91ae 100644 --- a/riscv/src/compiler.rs +++ b/riscv/src/compiler.rs @@ -109,9 +109,14 @@ fn replace_dynamic_label_reference( if instr1.as_str() != "lui" || instr2.as_str() != "addi" { return None; }; - let [Argument::Register(r1), Argument::Constant(Constant::HiDataRef(label1))] = &args1[..] else { return None; }; - let [Argument::Register(r2), Argument::Register(r3), Argument::Constant(Constant::LoDataRef(label2))] = &args2[..] else { return None; }; - if r1 != r3 || label1 != label2 || data_objects.contains_key(label1) { + let [Argument::Register(r1), Argument::Constant(Constant::HiDataRef(label1, offset1))] = &args1[..] else { return None; }; + let [Argument::Register(r2), Argument::Register(r3), Argument::Constant(Constant::LoDataRef(label2, offset2))] = &args2[..] else { return None; }; + if r1 != r3 + || label1 != label2 + || *offset1 != 0 + || *offset2 != 0 + || data_objects.contains_key(label1) + { return None; } Some(Statement::Instruction( @@ -208,14 +213,16 @@ fn insert_data_positions( fn replace_data_reference(constant: &mut Constant, data_positions: &BTreeMap) { match constant { Constant::Number(_) => {} - Constant::HiDataRef(data) => { + Constant::HiDataRef(data, offset) => { if let Some(pos) = data_positions.get(data) { + let pos: u32 = pos + *offset as u32; *constant = Constant::Number((pos >> 12) as i64) } // Otherwise, it references a code label } - Constant::LoDataRef(data) => { + Constant::LoDataRef(data, offset) => { if let Some(pos) = data_positions.get(data) { + let pos: u32 = pos + *offset as u32; *constant = Constant::Number((pos & 0xfff) as i64) } // Otherwise, it references a code label @@ -593,8 +600,8 @@ fn argument_to_number(x: &Argument) -> u32 { fn constant_to_number(c: &Constant) -> u32 { match c { Constant::Number(n) => *n as u32, - Constant::HiDataRef(n) | Constant::LoDataRef(n) => { - panic!("Data reference was not erased during preprocessing: {n}"); + Constant::HiDataRef(n, off) | Constant::LoDataRef(n, off) => { + panic!("Data reference was not erased during preprocessing: {n} + {off}"); } } } diff --git a/riscv/src/disambiguator.rs b/riscv/src/disambiguator.rs index a0be633da..9b7d903e9 100644 --- a/riscv/src/disambiguator.rs +++ b/riscv/src/disambiguator.rs @@ -103,11 +103,11 @@ fn disambiguate_constant_if_needed( ) -> Constant { match c { Constant::Number(_) => c, - Constant::HiDataRef(s) => { - Constant::HiDataRef(disambiguate_symbol_if_needed(s, prefix, globals)) + Constant::HiDataRef(s, offset) => { + Constant::HiDataRef(disambiguate_symbol_if_needed(s, prefix, globals), offset) } - Constant::LoDataRef(s) => { - Constant::LoDataRef(disambiguate_symbol_if_needed(s, prefix, globals)) + Constant::LoDataRef(s, offset) => { + Constant::LoDataRef(disambiguate_symbol_if_needed(s, prefix, globals), offset) } } } diff --git a/riscv/src/parser.rs b/riscv/src/parser.rs index 03a3840af..9d9201ab7 100644 --- a/riscv/src/parser.rs +++ b/riscv/src/parser.rs @@ -39,8 +39,8 @@ impl Register { #[derive(Clone)] pub enum Constant { Number(i64), - HiDataRef(String), - LoDataRef(String), + HiDataRef(String, i64), + LoDataRef(String, i64), } impl Display for Statement { @@ -70,12 +70,24 @@ impl Display for Constant { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { match self { Constant::Number(n) => write!(f, "{n}"), - Constant::HiDataRef(sym) => write!(f, "%hi({sym})"), - Constant::LoDataRef(sym) => write!(f, "%lo({sym})"), + Constant::HiDataRef(sym, offset) => { + write!(f, "%hi({sym}{})", format_hi_lo_offset(*offset)) + } + Constant::LoDataRef(sym, offset) => { + write!(f, "%lo({sym}{})", format_hi_lo_offset(*offset)) + } } } } +fn format_hi_lo_offset(offset: i64) -> String { + match offset { + 0 => String::new(), + 1.. => format!(" + {offset}"), + ..=-1 => format!(" - {}", -offset), + } +} + fn format_arguments(args: &[Argument]) -> String { args.iter() .map(|a| format!("{a}")) diff --git a/riscv/src/reachability.rs b/riscv/src/reachability.rs index 7150de2a0..14d0a7808 100644 --- a/riscv/src/reachability.rs +++ b/riscv/src/reachability.rs @@ -122,7 +122,9 @@ pub fn references_in_statement(statement: &Statement) -> BTreeSet<&str> { Argument::Symbol(s) => Some(s.as_str()), Argument::RegOffset(_, c) | Argument::Constant(c) => match c { Constant::Number(_) => None, - Constant::HiDataRef(s) | Constant::LoDataRef(s) => Some(s.as_str()), + Constant::HiDataRef(s, _offset) | Constant::LoDataRef(s, _offset) => { + Some(s.as_str()) + } }, Argument::Difference(_, _) => todo!(), }) @@ -212,8 +214,8 @@ fn apply_replacement_to_instruction( fn apply_replacement_to_constant(c: Constant, replacements: &BTreeMap<&str, &str>) -> Constant { match c { Constant::Number(_) => c, - Constant::HiDataRef(s) => Constant::HiDataRef(replace(s, replacements)), - Constant::LoDataRef(s) => Constant::LoDataRef(replace(s, replacements)), + Constant::HiDataRef(s, off) => Constant::HiDataRef(replace(s, replacements), off), + Constant::LoDataRef(s, off) => Constant::LoDataRef(replace(s, replacements), off), } } diff --git a/riscv/src/riscv_asm.lalrpop b/riscv/src/riscv_asm.lalrpop index b7c9d5345..cb246a875 100644 --- a/riscv/src/riscv_asm.lalrpop +++ b/riscv/src/riscv_asm.lalrpop @@ -85,8 +85,14 @@ OffsetRegister: Argument = { Constant: Constant = { ConstantExpression => Constant::Number(<>), - "%hi(" ")" => Constant::HiDataRef(<>), - "%lo(" ")" => Constant::LoDataRef(<>), + "%hi(" ")" => Constant::HiDataRef(arg.0, arg.1), + "%lo(" ")" => Constant::LoDataRef(arg.0, arg.1), +} + +HiLowArgument: (String, i64) = { + => (<>, 0), + "+" => (<>), + "-" => (n, -o), } ConstantExpression: i64 = {