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

@@ -33,6 +33,8 @@ pub enum Reloc {
Abs8,
/// x86 PC-relative 4-byte
X86PCRel4,
/// x86 PC-relative 4-byte offset to trailing rodata
X86PCRelRodata4,
/// x86 call to PC-relative 4-byte
X86CallPCRel4,
/// x86 call to PLT-relative 4-byte
@@ -55,6 +57,7 @@ impl fmt::Display for Reloc {
Reloc::Abs4 => write!(f, "Abs4"),
Reloc::Abs8 => write!(f, "Abs8"),
Reloc::X86PCRel4 => write!(f, "PCRel4"),
Reloc::X86PCRelRodata4 => write!(f, "PCRelRodata4"),
Reloc::X86CallPCRel4 => write!(f, "CallPCRel4"),
Reloc::X86CallPLTRel4 => write!(f, "CallPLTRel4"),
Reloc::X86GOTPCRel4 => write!(f, "GOTPCRel4"),
@@ -63,6 +66,38 @@ impl fmt::Display for Reloc {
}
}
/// Container for information about a vector of compiled code and its supporting read-only data.
///
/// The code starts at offset 0 and is followed optionally by relocatable jump tables and copyable
/// (raw binary) read-only data. Any padding between sections is always part of the section that
/// precedes the boundary between the sections.
#[derive(PartialEq)]
pub struct CodeInfo {
/// Number of bytes of machine code (the code starts at offset 0).
pub code_size: CodeOffset,
/// Number of bytes of jumptables.
pub jumptables_size: CodeOffset,
/// Number of bytes of rodata.
pub rodata_size: CodeOffset,
/// Number of bytes in total.
pub total_size: CodeOffset,
}
impl CodeInfo {
/// Offset of any relocatable jump tables, or equal to rodata if there are no jump tables.
pub fn jumptables(&self) -> CodeOffset {
self.code_size
}
/// Offset of any copyable read-only data, or equal to total_size if there are no rodata.
pub fn rodata(&self) -> CodeOffset {
self.code_size + self.jumptables_size
}
}
/// Abstract interface for adding bytes to the code segment.
///
/// A `CodeSink` will receive all of the machine code for a function. It also accepts relocations
@@ -95,8 +130,14 @@ pub trait CodeSink {
/// Add trap information for the current offset.
fn trap(&mut self, _: TrapCode, _: SourceLoc);
/// Code output is complete, read-only data may follow.
/// Machine code output is complete, jump table data may follow.
fn begin_jumptables(&mut self);
/// Jump table output is complete, raw read-only data may follow.
fn begin_rodata(&mut self);
/// Read-only data output is complete, we're done.
fn end_codegen(&mut self);
}
/// Report a bad encoding error.
@@ -127,7 +168,7 @@ where
}
}
sink.begin_rodata();
sink.begin_jumptables();
// output jump tables
for (jt, jt_data) in func.jump_tables.iter() {
@@ -137,4 +178,9 @@ where
sink.put4(rel_offset as u32)
}
}
sink.begin_rodata();
// TODO: No read-only data (constant pools) at this time.
sink.end_codegen();
}