Merge pull request #278 from chriseth/hi_lo_offsets

Parse hi and lo data reference offsets.
This commit is contained in:
chriseth
2023-05-16 12:24:19 +02:00
committed by GitHub
5 changed files with 47 additions and 20 deletions

View File

@@ -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(
@@ -216,14 +221,16 @@ fn insert_data_positions(
fn replace_data_reference(constant: &mut Constant, data_positions: &BTreeMap<String, u32>) {
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
@@ -601,8 +608,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}");
}
}
}

View File

@@ -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)
}
}
}

View File

@@ -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}"))

View File

@@ -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),
}
}

View File

@@ -85,8 +85,14 @@ OffsetRegister: Argument = {
Constant: Constant = {
ConstantExpression => Constant::Number(<>),
"%hi(" <Symbol> ")" => Constant::HiDataRef(<>),
"%lo(" <Symbol> ")" => Constant::LoDataRef(<>),
"%hi(" <arg:HiLowArgument> ")" => Constant::HiDataRef(arg.0, arg.1),
"%lo(" <arg:HiLowArgument> ")" => Constant::LoDataRef(arg.0, arg.1),
}
HiLowArgument: (String, i64) = {
<Symbol> => (<>, 0),
<Symbol> "+" <ConstantExpression> => (<>),
<n: Symbol> "-" <o: ConstantExpression> => (n, -o),
}
ConstantExpression: i64 = {