Add a CodeOffset type and CodeSink::offset() method.
We need to keep track of code offsets in order to compute accurate branch displacements.
This commit is contained in:
@@ -5,6 +5,12 @@
|
|||||||
|
|
||||||
use ir::{Ebb, FuncRef, JumpTable, Function, Inst};
|
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.
|
/// Relocation kinds depend on the current ISA.
|
||||||
pub struct Reloc(pub u16);
|
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
|
/// 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.
|
/// which are locations in the code section that need to be fixed up when linking.
|
||||||
pub trait CodeSink {
|
pub trait CodeSink {
|
||||||
|
/// Get the current position.
|
||||||
|
fn offset(&self) -> CodeOffset;
|
||||||
|
|
||||||
/// Add 1 byte to the code section.
|
/// Add 1 byte to the code section.
|
||||||
fn put1(&mut self, u8);
|
fn put1(&mut self, u8);
|
||||||
|
|
||||||
|
|||||||
@@ -8,6 +8,7 @@ use std::fmt::Write;
|
|||||||
use cretonne::binemit;
|
use cretonne::binemit;
|
||||||
use cretonne::ir;
|
use cretonne::ir;
|
||||||
use cretonne::ir::entities::AnyEntity;
|
use cretonne::ir::entities::AnyEntity;
|
||||||
|
use cretonne::isa::TargetIsa;
|
||||||
use cton_reader::TestCommand;
|
use cton_reader::TestCommand;
|
||||||
use filetest::subtest::{SubTest, Context, Result};
|
use filetest::subtest::{SubTest, Context, Result};
|
||||||
use utils::match_directive;
|
use utils::match_directive;
|
||||||
@@ -26,24 +27,46 @@ pub fn subtest(parsed: &TestCommand) -> Result<Box<SubTest>> {
|
|||||||
// Code sink that generates text.
|
// Code sink that generates text.
|
||||||
struct TextSink {
|
struct TextSink {
|
||||||
rnames: &'static [&'static str],
|
rnames: &'static [&'static str],
|
||||||
|
offset: binemit::CodeOffset,
|
||||||
text: String,
|
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 {
|
impl binemit::CodeSink for TextSink {
|
||||||
|
fn offset(&self) -> binemit::CodeOffset {
|
||||||
|
self.offset
|
||||||
|
}
|
||||||
|
|
||||||
fn put1(&mut self, x: u8) {
|
fn put1(&mut self, x: u8) {
|
||||||
write!(self.text, "{:02x} ", x).unwrap();
|
write!(self.text, "{:02x} ", x).unwrap();
|
||||||
|
self.offset += 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
fn put2(&mut self, x: u16) {
|
fn put2(&mut self, x: u16) {
|
||||||
write!(self.text, "{:04x} ", x).unwrap();
|
write!(self.text, "{:04x} ", x).unwrap();
|
||||||
|
self.offset += 2;
|
||||||
}
|
}
|
||||||
|
|
||||||
fn put4(&mut self, x: u32) {
|
fn put4(&mut self, x: u32) {
|
||||||
write!(self.text, "{:08x} ", x).unwrap();
|
write!(self.text, "{:08x} ", x).unwrap();
|
||||||
|
self.offset += 4;
|
||||||
}
|
}
|
||||||
|
|
||||||
fn put8(&mut self, x: u64) {
|
fn put8(&mut self, x: u64) {
|
||||||
write!(self.text, "{:016x} ", x).unwrap();
|
write!(self.text, "{:016x} ", x).unwrap();
|
||||||
|
self.offset += 8;
|
||||||
}
|
}
|
||||||
|
|
||||||
fn reloc_ebb(&mut self, reloc: binemit::Reloc, ebb: ir::Ebb) {
|
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
|
// 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...
|
// value locations. The current error reporting is just crashing...
|
||||||
let mut func = func.into_owned();
|
let mut func = func.into_owned();
|
||||||
|
let mut sink = TextSink::new(isa);
|
||||||
let mut sink = TextSink {
|
|
||||||
rnames: isa.reloc_names(),
|
|
||||||
text: String::new(),
|
|
||||||
};
|
|
||||||
|
|
||||||
for comment in &context.details.comments {
|
for comment in &context.details.comments {
|
||||||
if let Some(want) = match_directive(comment.text, "bin:") {
|
if let Some(want) = match_directive(comment.text, "bin:") {
|
||||||
|
|||||||
Reference in New Issue
Block a user