Skip to content

Commit 9bf6d73

Browse files
eira-franshamsunfishcode
authored andcommitted
Integrate Lightbeam (#51)
* Integrate lightbeam
1 parent a1c123c commit 9bf6d73

14 files changed

Lines changed: 351 additions & 85 deletions

File tree

.gitmodules

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,7 @@
11
[submodule "spec_testsuite"]
22
path = spec_testsuite
33
url = https://github.com/WebAssembly/testsuite
4+
[submodule "lightbeam"]
5+
path = lightbeam
6+
url = https://github.com/CraneStation/lightbeam.git
7+
branch = master

Cargo.toml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,3 +44,6 @@ libc = "0.2.50"
4444
errno = "0.2.4"
4545

4646
[workspace]
47+
48+
[features]
49+
lightbeam = ["wasmtime-environ/lightbeam", "wasmtime-jit/lightbeam"]

lightbeam

Submodule lightbeam added at 762cd3f

src/wasm2obj.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,7 @@ use std::str;
4949
use std::str::FromStr;
5050
use target_lexicon::Triple;
5151
use wasmtime_debug::{emit_debugsections, read_debuginfo};
52-
use wasmtime_environ::{cranelift, ModuleEnvironment, Tunables};
52+
use wasmtime_environ::{Compiler, Cranelift, ModuleEnvironment, Tunables};
5353
use wasmtime_obj::emit_module;
5454

5555
const USAGE: &str = "
@@ -159,7 +159,7 @@ fn handle_module(
159159
)
160160
};
161161

162-
let (compilation, relocations, address_transform) = cranelift::compile_module(
162+
let (compilation, relocations, address_transform) = Cranelift::compile_module(
163163
&module,
164164
lazy_function_body_inputs,
165165
&*isa,

wasmtime-environ/Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ edition = "2018"
1515
cranelift-codegen = "0.30.0"
1616
cranelift-entity = "0.30.0"
1717
cranelift-wasm = "0.30.0"
18+
lightbeam = { path = "../lightbeam", optional = true }
1819
cast = { version = "0.2.2", default-features = false }
1920
failure = { version = "0.1.3", default-features = false }
2021
failure_derive = { version = "0.1.3", default-features = false }

wasmtime-environ/src/compilation.rs

Lines changed: 63 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,25 +1,71 @@
11
//! A `Compilation` contains the compiled function bodies for a WebAssembly
22
//! module.
33
4-
use cranelift_codegen::binemit;
5-
use cranelift_codegen::ir;
6-
use cranelift_codegen::CodegenError;
4+
use crate::module;
5+
use crate::module_environ::FunctionBodyData;
6+
use cranelift_codegen::{binemit, ir, isa, CodegenError};
77
use cranelift_entity::PrimaryMap;
88
use cranelift_wasm::{DefinedFuncIndex, FuncIndex, WasmError};
9+
use std::ops::Range;
910
use std::vec::Vec;
1011

12+
type Functions = PrimaryMap<DefinedFuncIndex, Vec<u8>>;
13+
1114
/// The result of compiling a WebAssembly module's functions.
1215
#[derive(Debug)]
1316
pub struct Compilation {
1417
/// Compiled machine code for the function bodies.
15-
pub functions: PrimaryMap<DefinedFuncIndex, Vec<u8>>,
18+
functions: Functions,
1619
}
1720

1821
impl Compilation {
19-
/// Allocates the compilation result with the given function bodies.
20-
pub fn new(functions: PrimaryMap<DefinedFuncIndex, Vec<u8>>) -> Self {
22+
/// Creates a compilation artifact from a contiguous function buffer and a set of ranges
23+
pub fn new(functions: Functions) -> Self {
2124
Self { functions }
2225
}
26+
27+
/// Allocates the compilation result with the given function bodies.
28+
pub fn from_buffer(buffer: Vec<u8>, functions: impl IntoIterator<Item = Range<usize>>) -> Self {
29+
Self::new(
30+
functions
31+
.into_iter()
32+
.map(|range| buffer[range].to_vec())
33+
.collect(),
34+
)
35+
}
36+
37+
/// Gets the bytes of a single function
38+
pub fn get(&self, func: DefinedFuncIndex) -> &[u8] {
39+
&self.functions[func]
40+
}
41+
42+
/// Gets the number of functions defined.
43+
pub fn len(&self) -> usize {
44+
self.functions.len()
45+
}
46+
}
47+
48+
impl<'a> IntoIterator for &'a Compilation {
49+
type IntoIter = Iter<'a>;
50+
type Item = <Self::IntoIter as Iterator>::Item;
51+
52+
fn into_iter(self) -> Self::IntoIter {
53+
Iter {
54+
iterator: self.functions.iter(),
55+
}
56+
}
57+
}
58+
59+
pub struct Iter<'a> {
60+
iterator: <&'a Functions as IntoIterator>::IntoIter,
61+
}
62+
63+
impl<'a> Iterator for Iter<'a> {
64+
type Item = &'a [u8];
65+
66+
fn next(&mut self) -> Option<Self::Item> {
67+
self.iterator.next().map(|(_, b)| &b[..])
68+
}
2369
}
2470

2571
/// A record of a relocation to perform.
@@ -95,3 +141,14 @@ pub struct FunctionAddressTransform {
95141

96142
/// Function AddressTransforms collection.
97143
pub type AddressTransforms = PrimaryMap<DefinedFuncIndex, FunctionAddressTransform>;
144+
145+
/// An implementation of a compiler from parsed WebAssembly module to native code.
146+
pub trait Compiler {
147+
/// Compile a parsed module with the given `TargetIsa`.
148+
fn compile_module<'data, 'module>(
149+
module: &'module module::Module,
150+
function_body_inputs: PrimaryMap<DefinedFuncIndex, FunctionBodyData<'data>>,
151+
isa: &dyn isa::TargetIsa,
152+
generate_debug_info: bool,
153+
) -> Result<(Compilation, Relocations, AddressTransforms), CompileError>;
154+
}

wasmtime-environ/src/cranelift.rs

Lines changed: 67 additions & 61 deletions
Original file line numberDiff line numberDiff line change
@@ -21,9 +21,9 @@ use rayon::prelude::{IntoParallelRefIterator, ParallelIterator};
2121
use std::vec::Vec;
2222

2323
/// Implementation of a relocation sink that just saves all the information for later
24-
struct RelocSink {
24+
pub struct RelocSink {
2525
/// Relocations recorded for the function.
26-
func_relocs: Vec<Relocation>,
26+
pub func_relocs: Vec<Relocation>,
2727
}
2828

2929
impl binemit::RelocSink for RelocSink {
@@ -109,69 +109,75 @@ fn get_address_transform(
109109
result
110110
}
111111

112-
/// Compile the module using Cranelift, producing a compilation result with
113-
/// associated relocations.
114-
pub fn compile_module<'data, 'module>(
115-
module: &'module Module,
116-
function_body_inputs: PrimaryMap<DefinedFuncIndex, FunctionBodyData<'data>>,
117-
isa: &dyn isa::TargetIsa,
118-
generate_debug_info: bool,
119-
) -> Result<(Compilation, Relocations, AddressTransforms), CompileError> {
120-
let mut functions = PrimaryMap::with_capacity(function_body_inputs.len());
121-
let mut relocations = PrimaryMap::with_capacity(function_body_inputs.len());
122-
let mut address_transforms = PrimaryMap::with_capacity(function_body_inputs.len());
112+
/// A compiler that compiles a WebAssembly module with Cranelift, translating the Wasm to Cranelift IR,
113+
/// optimizing it and then translating to assembly.
114+
pub struct Cranelift;
123115

124-
function_body_inputs
125-
.into_iter()
126-
.collect::<Vec<(DefinedFuncIndex, &FunctionBodyData<'data>)>>()
127-
.par_iter()
128-
.map(|(i, input)| {
129-
let func_index = module.func_index(*i);
130-
let mut context = Context::new();
131-
context.func.name = get_func_name(func_index);
132-
context.func.signature = module.signatures[module.functions[func_index]].clone();
116+
impl crate::compilation::Compiler for Cranelift {
117+
/// Compile the module using Cranelift, producing a compilation result with
118+
/// associated relocations.
119+
fn compile_module<'data, 'module>(
120+
module: &'module Module,
121+
function_body_inputs: PrimaryMap<DefinedFuncIndex, FunctionBodyData<'data>>,
122+
isa: &dyn isa::TargetIsa,
123+
generate_debug_info: bool,
124+
) -> Result<(Compilation, Relocations, AddressTransforms), CompileError> {
125+
let mut functions = PrimaryMap::with_capacity(function_body_inputs.len());
126+
let mut relocations = PrimaryMap::with_capacity(function_body_inputs.len());
127+
let mut address_transforms = PrimaryMap::with_capacity(function_body_inputs.len());
133128

134-
let mut trans = FuncTranslator::new();
135-
trans
136-
.translate(
137-
input.data,
138-
input.module_offset,
139-
&mut context.func,
140-
&mut FuncEnvironment::new(isa.frontend_config(), module),
141-
)
142-
.map_err(CompileError::Wasm)?;
129+
function_body_inputs
130+
.into_iter()
131+
.collect::<Vec<(DefinedFuncIndex, &FunctionBodyData<'data>)>>()
132+
.par_iter()
133+
.map(|(i, input)| {
134+
let func_index = module.func_index(*i);
135+
let mut context = Context::new();
136+
context.func.name = get_func_name(func_index);
137+
context.func.signature = module.signatures[module.functions[func_index]].clone();
143138

144-
let mut code_buf: Vec<u8> = Vec::new();
145-
let mut reloc_sink = RelocSink::new();
146-
let mut trap_sink = binemit::NullTrapSink {};
147-
context
148-
.compile_and_emit(isa, &mut code_buf, &mut reloc_sink, &mut trap_sink)
149-
.map_err(CompileError::Codegen)?;
139+
let mut trans = FuncTranslator::new();
140+
trans
141+
.translate(
142+
input.data,
143+
input.module_offset,
144+
&mut context.func,
145+
&mut FuncEnvironment::new(isa.frontend_config(), module),
146+
)
147+
.map_err(CompileError::Wasm)?;
150148

151-
let address_transform = if generate_debug_info {
152-
let body_len = code_buf.len();
153-
let at = get_address_transform(&context, isa);
154-
Some(FunctionAddressTransform {
155-
locations: at,
156-
body_offset: 0,
157-
body_len,
158-
})
159-
} else {
160-
None
161-
};
149+
let mut code_buf: Vec<u8> = Vec::new();
150+
let mut reloc_sink = RelocSink::new();
151+
let mut trap_sink = binemit::NullTrapSink {};
152+
context
153+
.compile_and_emit(isa, &mut code_buf, &mut reloc_sink, &mut trap_sink)
154+
.map_err(CompileError::Codegen)?;
162155

163-
Ok((code_buf, reloc_sink.func_relocs, address_transform))
164-
})
165-
.collect::<Result<Vec<_>, CompileError>>()?
166-
.into_iter()
167-
.for_each(|(function, relocs, address_transform)| {
168-
functions.push(function);
169-
relocations.push(relocs);
170-
if let Some(address_transform) = address_transform {
171-
address_transforms.push(address_transform);
172-
}
173-
});
156+
let address_transform = if generate_debug_info {
157+
let body_len = code_buf.len();
158+
let at = get_address_transform(&context, isa);
159+
Some(FunctionAddressTransform {
160+
locations: at,
161+
body_offset: 0,
162+
body_len,
163+
})
164+
} else {
165+
None
166+
};
167+
168+
Ok((code_buf, reloc_sink.func_relocs, address_transform))
169+
})
170+
.collect::<Result<Vec<_>, CompileError>>()?
171+
.into_iter()
172+
.for_each(|(function, relocs, address_transform)| {
173+
functions.push(function);
174+
relocations.push(relocs);
175+
if let Some(address_transform) = address_transform {
176+
address_transforms.push(address_transform);
177+
}
178+
});
174179

175-
// TODO: Reorganize where we create the Vec for the resolved imports.
176-
Ok((Compilation::new(functions), relocations, address_transforms))
180+
// TODO: Reorganize where we create the Vec for the resolved imports.
181+
Ok((Compilation::new(functions), relocations, address_transforms))
182+
}
177183
}

0 commit comments

Comments
 (0)