From 847c8045fd121c17ddd39d71cada2c0ae175a86f Mon Sep 17 00:00:00 2001 From: Jakob Stoklund Olesen Date: Wed, 5 Apr 2017 09:12:12 -0700 Subject: [PATCH] Add a CodeOffset type and CodeSink::offset() method. We need to keep track of code offsets in order to compute accurate branch displacements. --- lib/cretonne/src/binemit/mod.rs | 9 +++++++++ src/filetest/binemit.rs | 29 ++++++++++++++++++++++++----- 2 files changed, 33 insertions(+), 5 deletions(-) diff --git a/lib/cretonne/src/binemit/mod.rs b/lib/cretonne/src/binemit/mod.rs index ccad476f44..9721586033 100644 --- a/lib/cretonne/src/binemit/mod.rs +++ b/lib/cretonne/src/binemit/mod.rs @@ -5,6 +5,12 @@ use ir::{Ebb, FuncRef, JumpTable, Function, Inst}; +/// Offset in bytes from the beginning of the function. +/// +/// Cretonne can be used as a cross compiler, so we don't want to use a type like `usize` which +/// depends on the *host* platform, not the *target* platform. +pub type CodeOffset = u32; + /// Relocation kinds depend on the current ISA. pub struct Reloc(pub u16); @@ -13,6 +19,9 @@ pub struct Reloc(pub u16); /// A `CodeSink` will receive all of the machine code for a function. It also accepts relocations /// which are locations in the code section that need to be fixed up when linking. pub trait CodeSink { + /// Get the current position. + fn offset(&self) -> CodeOffset; + /// Add 1 byte to the code section. fn put1(&mut self, u8); diff --git a/src/filetest/binemit.rs b/src/filetest/binemit.rs index 3c9fc333e6..50949811ec 100644 --- a/src/filetest/binemit.rs +++ b/src/filetest/binemit.rs @@ -8,6 +8,7 @@ use std::fmt::Write; use cretonne::binemit; use cretonne::ir; use cretonne::ir::entities::AnyEntity; +use cretonne::isa::TargetIsa; use cton_reader::TestCommand; use filetest::subtest::{SubTest, Context, Result}; use utils::match_directive; @@ -26,24 +27,46 @@ pub fn subtest(parsed: &TestCommand) -> Result> { // Code sink that generates text. struct TextSink { rnames: &'static [&'static str], + offset: binemit::CodeOffset, text: String, } +impl TextSink { + /// Create a new empty TextSink. + pub fn new(isa: &TargetIsa) -> TextSink { + TextSink { + rnames: isa.reloc_names(), + offset: 0, + text: String::new(), + } + } +} + + + impl binemit::CodeSink for TextSink { + fn offset(&self) -> binemit::CodeOffset { + self.offset + } + fn put1(&mut self, x: u8) { write!(self.text, "{:02x} ", x).unwrap(); + self.offset += 1; } fn put2(&mut self, x: u16) { write!(self.text, "{:04x} ", x).unwrap(); + self.offset += 2; } fn put4(&mut self, x: u32) { write!(self.text, "{:08x} ", x).unwrap(); + self.offset += 4; } fn put8(&mut self, x: u64) { write!(self.text, "{:016x} ", x).unwrap(); + self.offset += 8; } fn reloc_ebb(&mut self, reloc: binemit::Reloc, ebb: ir::Ebb) { @@ -77,11 +100,7 @@ impl SubTest for TestBinEmit { // TODO: Run a verifier pass over the code first to detect any bad encodings or missing/bad // value locations. The current error reporting is just crashing... let mut func = func.into_owned(); - - let mut sink = TextSink { - rnames: isa.reloc_names(), - text: String::new(), - }; + let mut sink = TextSink::new(isa); for comment in &context.details.comments { if let Some(want) = match_directive(comment.text, "bin:") {