Skip to content

Commit

Permalink
Add size assertion, Assert terminator, and serialization of the LIR.
Browse files Browse the repository at this point in the history
  • Loading branch information
nbp committed Sep 24, 2017
1 parent b04dd26 commit a8c18b6
Show file tree
Hide file tree
Showing 6 changed files with 431 additions and 94 deletions.
3 changes: 3 additions & 0 deletions lib/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,9 @@ authors = [ "Nicolas B. Pierron <[email protected]>" ]
[dependencies]
dynasm = "0.1"
dynasmrt = "0.1"
serde = "1.0"
serde_derive = "1.0"
bincode = "0.8"

[lib]
name = "holyjit_lib"
Expand Down
10 changes: 10 additions & 0 deletions lib/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,9 +12,19 @@

pub use std::marker::PhantomData;

// dynasm is "currently" used by the compiler as a way to generate code
// without the burden of implementing yet another macro-assembler.
#[macro_use]
extern crate dynasmrt;

// Serde is used for serializing and deserializing the LIR which is stored
// by the plugin in a constant, and deserialized by the JIT compiler in
// order to be manipulated.
#[macro_use]
extern crate serde_derive;
extern crate serde;
extern crate bincode;

pub mod lir;
mod context;
mod compile;
Expand Down
56 changes: 54 additions & 2 deletions lib/src/lir.rs
Original file line number Diff line number Diff line change
@@ -1,19 +1,27 @@
//! Defines the LIR structures and how to represent a graph and its
//! instructions.
use std::fmt;

/// Prototype of the Mir graph of a single function. This representation is
/// not optimized for graph optimizations, but optimized only for the ease
/// of convertion from the MIR and the ease of naive compilation.
#[derive(Serialize, Deserialize, Debug)]
pub struct CompilationUnit {
/// Size of all local variable of the Mir.
pub stack_size: usize,

/// Ordered list of arguments, with their associated registers.
pub args_defs: Vec<RegDef>,

/// List of basic blocks of a given function.
pub blocks: Vec<BasicBlockData>,
}

/// (Prototype) Set of instruction within a block.
pub type BasicBlock = usize;

/// Basic block which contains a list of instructions.
#[derive(Serialize, Deserialize, Debug)]
pub struct BasicBlockData {
/// Ordered list of registers available in this basic block.
//
Expand All @@ -29,13 +37,21 @@ pub struct BasicBlockData {
pub end: Terminator,
}

/// Basic block terminator instruction, which resume the execution in
/// another basic block.
#[derive(Serialize, Deserialize, Debug)]
pub enum Terminator {
/// Exit successfully the current function.
Return,
Return {
value: Option<Reg>,
},

/// Unwind the current function.
Unwind,

/// Trap.
Unreachable,

/// Jump unconditionally to the next basic block.
Goto {
target: BasicBlock,
Expand All @@ -44,6 +60,7 @@ pub enum Terminator {
/// Conditional branches, implemented as a switch case to handle all
/// forms of conditionals.
SwitchInt {
value: Reg,
range: RangeInclusive,
targets: Vec<(Imm, BasicBlock)>,
otherwise: Option<BasicBlock>,
Expand Down Expand Up @@ -78,8 +95,11 @@ pub type RangeInclusive = (Imm, Imm);

/// (Prototype) Minimal set of instructions to support the MIR graph of
/// Rust for the examples directory.
#[derive(Debug)]
#[derive(Serialize, Deserialize, Debug)]
pub enum Inst {
// Initialize the frame pointer.
SetFramePtr(Reg, Sz, Sz),

// Copy the address of a static value in a register.
Static(Reg, Imm),

Expand Down Expand Up @@ -134,3 +154,35 @@ pub enum Inst {
// Note: Live is useless in case of SSA forms.
Live(Reg), Dead(Reg),
}

/// Display a Compilation unit with some hard-coded indentation level.
impl fmt::Display for CompilationUnit {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "CompilationUnit {{\n")?;
write!(f, " stack_size: {:?},\n", self.stack_size)?;
write!(f, " args_defs: {:?},\n", self.args_defs)?;
write!(f, " blocks: [\n")?;
let mut x = 0;
for b in &self.blocks {
write!(f, " [{}] = {},\n", x, b)?;
}
write!(f, " ],\n")?;
write!(f, "}}")
}
}

/// Display a BasicBlockData unit with some hard-coded indentation level.
impl fmt::Display for BasicBlockData {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "BasicBlockData {{\n")?;
write!(f, " input_regs: {:?},\n", self.input_regs)?;
write!(f, " insts: [\n")?;
for ins in &self.insts {
write!(f, " {:?},\n", ins)?;
}
write!(f, " ],\n")?;
write!(f, " end: {:?},\n", self.end)?;
write!(f, " output_regs: {:?},\n", self.output_regs)?;
write!(f, " }}")
}
}
2 changes: 2 additions & 0 deletions plugin/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@ authors = [ "Nicolas B. Pierron <[email protected]>" ]

[dependencies]
holyjit_lib = { path = "../lib" }
serde = "1.0"
bincode = "0.8"

[lib]
name = "holyjit_plugin"
Expand Down
6 changes: 6 additions & 0 deletions plugin/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,13 @@ use rustc::hir::def_id::DefId;
use rustc_plugin::Registry;
use std::rc::Rc;

// Used to express the Mir into the Lir used for the Jit compilation.
extern crate holyjit_lib;

// Used to serialize the lir provided in holyjit_lib.
extern crate serde;
extern crate bincode;

mod trans;

// This plugin works in 3 steps:
Expand Down
Loading

0 comments on commit a8c18b6

Please sign in to comment.