Skip to content

Commit

Permalink
wip
Browse files Browse the repository at this point in the history
  • Loading branch information
alexcrichton committed May 28, 2022
1 parent bffce37 commit b0e0f27
Show file tree
Hide file tree
Showing 23 changed files with 1,493 additions and 315 deletions.
1 change: 1 addition & 0 deletions crates/cranelift/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -28,3 +28,4 @@ thiserror = "1.0.4"

[features]
all-arch = ["cranelift-codegen/all-arch"]
component-model = []
43 changes: 32 additions & 11 deletions crates/cranelift/src/compiler.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ use crate::{
CompiledFunction, FunctionAddressMap, Relocation, RelocationTarget,
};
use anyhow::{Context as _, Result};
use cranelift_codegen::ir::{self, ExternalName, InstBuilder, MemFlags};
use cranelift_codegen::ir::{self, ExternalName, InstBuilder, MemFlags, Type, Value};
use cranelift_codegen::isa::TargetIsa;
use cranelift_codegen::print_errors::pretty_error;
use cranelift_codegen::Context;
Expand Down Expand Up @@ -50,7 +50,7 @@ impl Default for CompilerContext {
/// the Wasm to Compiler IR, optimizing it and then translating to assembly.
pub(crate) struct Compiler {
contexts: Mutex<Vec<CompilerContext>>,
isa: Box<dyn TargetIsa>,
pub(crate) isa: Box<dyn TargetIsa>,
linkopts: LinkOptions,
}

Expand Down Expand Up @@ -375,7 +375,9 @@ impl wasmtime_environ::Compiler for Compiler {
obj: &mut Object<'static>,
) -> Result<(Trampoline, Trampoline)> {
let host_to_wasm = self.host_to_wasm_trampoline(ty)?;
let wasm_to_host = self.wasm_to_host_trampoline(ty, host_fn)?;
let wasm_to_host = self.wasm_to_host_trampoline(ty, true, |builder, _, pointer_type| {
builder.ins().iconst(pointer_type, host_fn as i64)
})?;
let module = Module::new();
let mut builder = ObjectBuilder::new(obj, &module, &*self.isa);
let a = builder.trampoline(SignatureIndex::new(0), &host_to_wasm);
Expand Down Expand Up @@ -408,6 +410,11 @@ impl wasmtime_environ::Compiler for Compiler {
.map(|val| (val.name.to_string(), to_flag_value(val)))
.collect()
}

#[cfg(feature = "component-model")]
fn component_compiler(&self) -> &dyn wasmtime_environ::component::ComponentCompiler {
self
}
}

fn to_flag_value(v: &settings::Value) -> FlagValue {
Expand Down Expand Up @@ -508,17 +515,22 @@ impl Compiler {
Ok(func)
}

fn wasm_to_host_trampoline(
pub(crate) fn wasm_to_host_trampoline(
&self,
ty: &WasmFuncType,
host_fn: usize,
give_host_callee_vmcontext: bool,
host_fn: impl FnOnce(&mut FunctionBuilder, Value, Type) -> Value,
) -> Result<CompiledFunction, CompileError> {
let isa = &*self.isa;
let pointer_type = isa.pointer_type();
let wasm_signature = indirect_signature(isa, ty);
// The host signature has an added parameter for the `values_vec` input
// and output.
let mut host_signature = blank_sig(isa, wasmtime_call_conv(isa));
if !give_host_callee_vmcontext {
host_signature.params.pop();
}
// The host signature has an added parameter for the `values_vec`
// input/output as well as the size of the `values_vec`.
host_signature.params.push(ir::AbiParam::new(pointer_type));
host_signature.params.push(ir::AbiParam::new(pointer_type));

// Compute the size of the values vector. The vmctx and caller vmctx are passed separately.
Expand Down Expand Up @@ -548,22 +560,31 @@ impl Compiler {
let values_vec_ptr_val = builder.ins().stack_addr(pointer_type, ss, 0);
let mut mflags = MemFlags::trusted();
mflags.set_endianness(ir::Endianness::Little);
let params_offset = if give_host_callee_vmcontext { 2 } else { 1 };
for i in 0..ty.params().len() {
let val = builder.func.dfg.block_params(block0)[i + 2];
let val = builder.func.dfg.block_params(block0)[i + params_offset];
builder
.ins()
.store(mflags, val, values_vec_ptr_val, (i * value_size) as i32);
}

let block_params = builder.func.dfg.block_params(block0);
let vmctx_ptr_val = block_params[0];
let caller_vmctx_ptr_val = block_params[1];

let callee_args = vec![vmctx_ptr_val, caller_vmctx_ptr_val, values_vec_ptr_val];
let mut callee_args = vec![vmctx_ptr_val];
if give_host_callee_vmcontext {
callee_args.push(block_params[1]);
}
callee_args.push(values_vec_ptr_val);
callee_args.push(
builder
.ins()
.iconst(pointer_type, i64::from(values_vec_len)),
);

let new_sig = builder.import_signature(host_signature);

let callee_value = builder.ins().iconst(pointer_type, host_fn as i64);
let callee_value = host_fn(&mut builder, vmctx_ptr_val, pointer_type);
builder
.ins()
.call_indirect(new_sig, callee_value, &callee_args);
Expand Down
91 changes: 91 additions & 0 deletions crates/cranelift/src/component.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,91 @@
use crate::compiler::Compiler;
use crate::obj::UnwindInfoBuilder;
use crate::CompiledFunction;
use anyhow::Result;
use cranelift_codegen::ir::{InstBuilder, MemFlags};
use object::write::{Object, StandardSegment, Symbol, SymbolSection};
use object::{SectionKind, SymbolFlags, SymbolKind, SymbolScope};
use std::any::Any;
use wasmtime_environ::component::{
Component, ComponentCompiler, ComponentTypes, LoweredIndex, TrampolineInfo, VMComponentOffsets,
};
use wasmtime_environ::{EntityRef, PrimaryMap};

impl ComponentCompiler for Compiler {
fn compile_lowered_trampoline(
&self,
component: &Component,
index: LoweredIndex,
types: &ComponentTypes,
) -> Result<Box<dyn Any + Send>> {
let ty = component.lowerings[index].canonical_abi;
let ty = &types[ty];
let offsets = VMComponentOffsets::new(self.isa.pointer_bytes(), component);
let trampoline: CompiledFunction =
self.wasm_to_host_trampoline(ty, false, |builder, vmctx, pointer_type| {
let offset = offsets.lowering_callee(index);
builder.ins().load(
pointer_type,
MemFlags::trusted(),
vmctx,
i32::try_from(offset).unwrap(),
)
})?;
Ok(Box::new(trampoline))
}

fn emit_obj(
&self,
trampolines: PrimaryMap<LoweredIndex, Box<dyn Any + Send>>,
obj: &mut Object<'static>,
) -> Result<PrimaryMap<LoweredIndex, TrampolineInfo>> {
let trampolines: PrimaryMap<LoweredIndex, CompiledFunction> = trampolines
.into_iter()
.map(|(_, f)| *f.downcast().unwrap())
.collect();
let mut unwind_info = UnwindInfoBuilder::default();
let text_section = obj.add_section(
obj.segment_name(StandardSegment::Text).to_vec(),
b".text".to_vec(),
SectionKind::Text,
);
let mut ret = PrimaryMap::new();
for (idx, trampoline) in trampolines.iter() {
// Currently there's no relocation processing here but it's also
// not used by trampolines at this time.
assert!(trampoline.relocations.is_empty());

let len = trampoline.body.len() as u64;
let off = obj.append_section_data(text_section, &trampoline.body, 1);

// Adding a symbol in normal wasm modules is used to resolve
// relocations, specifically in the dwarf section, but here we
// don't technically need symbols. Add it anyway for now as perhaps
// a debugging convenience one day.
obj.add_symbol(Symbol {
name: format!("wasm_lowered_trampoline{}", idx.index()).into_bytes(),
value: off,
size: len,
kind: SymbolKind::Text,
scope: SymbolScope::Compilation,
weak: false,
section: SymbolSection::Section(text_section),
flags: SymbolFlags::None,
});

if let Some(info) = &trampoline.unwind_info {
unwind_info.push(off, len, info, |data, align| {
obj.append_section_data(text_section, data, align.into())
});
}

let i = ret.push(TrampolineInfo {
start: u32::try_from(off).unwrap(),
length: u32::try_from(len).unwrap(),
});
assert_eq!(i, idx);
}

Ok(ret)
}
}
2 changes: 2 additions & 0 deletions crates/cranelift/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,8 @@ pub use builder::builder;

mod builder;
mod compiler;
#[cfg(feature = "component-model")]
mod component;
mod debug;
mod func_environ;
mod obj;
Expand Down
Loading

0 comments on commit b0e0f27

Please sign in to comment.