Record information about sections of emitted code+data.

The result of the emitter is a vector of bytes holding machine code,
jump tables, and (in the future) other read-only data.  Some clients,
notably Firefox's Wasm compiler, needs to separate the machine code
from the data in order to insert more code directly after the code
generated by Cranelift.

To make such separation possible, we record more information about the
emitted bytes: the sizes of each of the sections of code, jump tables,
and read-only data, as well as the locations within the code that
reference (PC-relatively) the jump tables and read-only data.
This commit is contained in:
Lars T Hansen
2019-05-21 15:53:46 +02:00
committed by Lars T Hansen
parent 70f79d23bf
commit 420850adf0
12 changed files with 166 additions and 73 deletions

View File

@@ -5,8 +5,7 @@
use crate::match_directive::match_directive;
use crate::subtest::{Context, SubTest, SubtestResult};
use cranelift_codegen::binemit;
use cranelift_codegen::binemit::{CodeSink, RegDiversions};
use cranelift_codegen::binemit::{self, CodeInfo, CodeSink, RegDiversions};
use cranelift_codegen::dbg::DisplayList;
use cranelift_codegen::ir;
use cranelift_codegen::ir::entities::AnyEntity;
@@ -96,9 +95,12 @@ impl binemit::CodeSink for TextSink {
write!(self.text, "{} ", code).unwrap();
}
fn begin_rodata(&mut self) {
fn begin_jumptables(&mut self) {
self.code_size = self.offset
}
fn begin_rodata(&mut self) {}
fn end_codegen(&mut self) {}
}
impl SubTest for TestBinEmit {
@@ -164,7 +166,7 @@ impl SubTest for TestBinEmit {
}
// Relax branches and compute EBB offsets based on the encodings.
let code_size = binemit::relax_branches(&mut func, isa)
let CodeInfo { total_size, .. } = binemit::relax_branches(&mut func, isa)
.map_err(|e| pretty_error(&func, context.isa, e))?;
// Collect all of the 'bin:' directives on instructions.
@@ -288,7 +290,7 @@ impl SubTest for TestBinEmit {
}
}
sink.begin_rodata();
sink.begin_jumptables();
for (jt, jt_data) in func.jump_tables.iter() {
let jt_offset = func.jt_offsets[jt];
@@ -298,10 +300,15 @@ impl SubTest for TestBinEmit {
}
}
if sink.offset != code_size {
sink.begin_rodata();
// TODO: Read-only (constant pool) data.
sink.end_codegen();
if sink.offset != total_size {
return Err(format!(
"Expected code size {}, got {}",
code_size, sink.offset
total_size, sink.offset
));
}

View File

@@ -4,8 +4,9 @@
use crate::subtest::{run_filecheck, Context, SubTest, SubtestResult};
use cranelift_codegen;
use cranelift_codegen::binemit::{self, CodeInfo};
use cranelift_codegen::ir;
use cranelift_codegen::print_errors::pretty_error;
use cranelift_codegen::{binemit, ir};
use cranelift_reader::TestCommand;
use log::info;
use std::borrow::Cow;
@@ -38,13 +39,13 @@ impl SubTest for TestCompile {
let isa = context.isa.expect("compile needs an ISA");
let mut comp_ctx = cranelift_codegen::Context::for_function(func.into_owned());
let code_size = comp_ctx
let CodeInfo { total_size, .. } = comp_ctx
.compile(isa)
.map_err(|e| pretty_error(&comp_ctx.func, context.isa, e))?;
info!(
"Generated {} bytes of code:\n{}",
code_size,
total_size,
comp_ctx.func.display(isa)
);
@@ -56,10 +57,10 @@ impl SubTest for TestCompile {
&mut sink,
);
if sink.offset != code_size {
if sink.offset != total_size {
return Err(format!(
"Expected code size {}, got {}",
code_size, sink.offset
total_size, sink.offset
));
}
@@ -105,5 +106,7 @@ impl binemit::CodeSink for SizeSink {
}
fn reloc_jt(&mut self, _reloc: binemit::Reloc, _jt: ir::JumpTable) {}
fn trap(&mut self, _code: ir::TrapCode, _srcloc: ir::SourceLoc) {}
fn begin_jumptables(&mut self) {}
fn begin_rodata(&mut self) {}
fn end_codegen(&mut self) {}
}