mirror of
https://github.com/mii443/wasmer.git
synced 2025-08-28 19:29:28 +00:00
Merge branch 'master' into frame-info
# Conflicts: # lib/compiler-llvm/src/compiler.rs # lib/compiler-llvm/src/translator/code.rs
This commit is contained in:
@ -9,14 +9,16 @@ use rayon::prelude::{IntoParallelRefIterator, ParallelIterator};
|
|||||||
use wasm_common::entity::{EntityRef, PrimaryMap, SecondaryMap};
|
use wasm_common::entity::{EntityRef, PrimaryMap, SecondaryMap};
|
||||||
use wasm_common::Features;
|
use wasm_common::Features;
|
||||||
use wasm_common::{FuncIndex, FuncType, LocalFuncIndex, MemoryIndex, TableIndex};
|
use wasm_common::{FuncIndex, FuncType, LocalFuncIndex, MemoryIndex, TableIndex};
|
||||||
use wasmer_compiler::TrapInformation;
|
use wasmer_compiler::{
|
||||||
use wasmer_compiler::{Compilation, CompileError, CompiledFunction, Compiler};
|
Compilation, CompileError, CompiledFunction, Compiler, CompilerConfig, CustomSection,
|
||||||
use wasmer_compiler::{CompilerConfig, ModuleTranslationState, Target};
|
CustomSectionProtection, FunctionBody, FunctionBodyData, ModuleTranslationState, Relocation,
|
||||||
use wasmer_compiler::{FunctionBody, FunctionBodyData};
|
RelocationTarget, SectionIndex, Target, TrapInformation,
|
||||||
|
};
|
||||||
use wasmer_runtime::{MemoryPlan, Module, TablePlan, TrapCode};
|
use wasmer_runtime::{MemoryPlan, Module, TablePlan, TrapCode};
|
||||||
|
|
||||||
use inkwell::targets::{InitializationConfig, Target as InkwellTarget};
|
use inkwell::targets::{InitializationConfig, Target as InkwellTarget};
|
||||||
|
|
||||||
|
use std::collections::HashMap;
|
||||||
use std::sync::{Arc, Mutex}; // TODO: remove
|
use std::sync::{Arc, Mutex}; // TODO: remove
|
||||||
|
|
||||||
/// A compiler that compiles a WebAssembly module with LLVM, translating the Wasm to LLVM IR,
|
/// A compiler that compiles a WebAssembly module with LLVM, translating the Wasm to LLVM IR,
|
||||||
@ -62,7 +64,15 @@ impl Compiler for LLVMCompiler {
|
|||||||
) -> Result<Compilation, CompileError> {
|
) -> Result<Compilation, CompileError> {
|
||||||
//let data = Arc::new(Mutex::new(0));
|
//let data = Arc::new(Mutex::new(0));
|
||||||
let mut func_names = SecondaryMap::new();
|
let mut func_names = SecondaryMap::new();
|
||||||
let custom_sections = PrimaryMap::new();
|
|
||||||
|
// We're going to "link" the sections by simply appending all compatible
|
||||||
|
// sections, then building the new relocations.
|
||||||
|
// TODO: merge constants.
|
||||||
|
let mut used_readonly_section = false;
|
||||||
|
let mut readonly_section = CustomSection {
|
||||||
|
protection: CustomSectionProtection::Read,
|
||||||
|
bytes: Vec::new(),
|
||||||
|
};
|
||||||
|
|
||||||
for (func_index, _) in &module.functions {
|
for (func_index, _) in &module.functions {
|
||||||
func_names[func_index] = module
|
func_names[func_index] = module
|
||||||
@ -71,7 +81,7 @@ impl Compiler for LLVMCompiler {
|
|||||||
.cloned()
|
.cloned()
|
||||||
.unwrap_or_else(|| format!("fn{}", func_index.index()));
|
.unwrap_or_else(|| format!("fn{}", func_index.index()));
|
||||||
}
|
}
|
||||||
let functions = function_body_inputs
|
let mut functions = function_body_inputs
|
||||||
.into_iter()
|
.into_iter()
|
||||||
.collect::<Vec<(LocalFuncIndex, &FunctionBodyData<'_>)>>()
|
.collect::<Vec<(LocalFuncIndex, &FunctionBodyData<'_>)>>()
|
||||||
.par_iter()
|
.par_iter()
|
||||||
@ -90,8 +100,42 @@ impl Compiler for LLVMCompiler {
|
|||||||
})
|
})
|
||||||
.collect::<Result<Vec<_>, CompileError>>()?
|
.collect::<Result<Vec<_>, CompileError>>()?
|
||||||
.into_iter()
|
.into_iter()
|
||||||
|
.map(|(mut function, local_relocations, custom_sections)| {
|
||||||
|
/// We collect the sections data
|
||||||
|
for (local_idx, custom_section) in custom_sections.iter().enumerate() {
|
||||||
|
let local_idx = local_idx as u32;
|
||||||
|
// TODO: these section numbers are potentially wrong, if there's
|
||||||
|
// no Read and only a ReadExecute then ReadExecute is 0.
|
||||||
|
let (ref mut section, section_num) = match &custom_section.protection {
|
||||||
|
CustomSectionProtection::Read => {
|
||||||
|
(&mut readonly_section, SectionIndex::from_u32(0))
|
||||||
|
}
|
||||||
|
};
|
||||||
|
let offset = section.bytes.len() as i64;
|
||||||
|
section.bytes.extend(&custom_section.bytes);
|
||||||
|
// TODO: we're needlessly rescanning the whole list.
|
||||||
|
for local_relocation in &local_relocations {
|
||||||
|
if local_relocation.local_section_index == local_idx {
|
||||||
|
used_readonly_section = true;
|
||||||
|
function.relocations.push(Relocation {
|
||||||
|
kind: local_relocation.kind,
|
||||||
|
reloc_target: RelocationTarget::CustomSection(section_num),
|
||||||
|
offset: local_relocation.offset,
|
||||||
|
addend: local_relocation.addend + offset,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Ok(function)
|
||||||
|
})
|
||||||
|
.collect::<Result<Vec<_>, CompileError>>()?
|
||||||
|
.into_iter()
|
||||||
.collect::<PrimaryMap<LocalFuncIndex, _>>();
|
.collect::<PrimaryMap<LocalFuncIndex, _>>();
|
||||||
|
|
||||||
|
let mut custom_sections = PrimaryMap::new();
|
||||||
|
if used_readonly_section {
|
||||||
|
custom_sections.push(readonly_section);
|
||||||
|
}
|
||||||
Ok(Compilation::new(functions, custom_sections))
|
Ok(Compilation::new(functions, custom_sections))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -37,15 +37,14 @@ use wasm_common::{
|
|||||||
};
|
};
|
||||||
use wasmer_compiler::wasmparser::{self, BinaryReader, MemoryImmediate, Operator};
|
use wasmer_compiler::wasmparser::{self, BinaryReader, MemoryImmediate, Operator};
|
||||||
use wasmer_compiler::{
|
use wasmer_compiler::{
|
||||||
to_wasm_error, wasm_unsupported, CompileError, CompiledFunction, CompiledFunctionFrameInfo,
|
to_wasm_error, wasm_unsupported, Addend, CodeOffset, CompileError, CompiledFunction,
|
||||||
FunctionBody, WasmResult,
|
CompiledFunctionFrameInfo, CompiledFunctionUnwindInfo, CustomSection, CustomSectionProtection,
|
||||||
};
|
FunctionAddressMap, FunctionBody, FunctionBodyData, Relocation, RelocationKind,
|
||||||
use wasmer_compiler::{
|
RelocationTarget, SourceLoc, WasmResult,
|
||||||
CompiledFunctionUnwindInfo, FunctionAddressMap, FunctionBodyData, Relocation, RelocationKind,
|
|
||||||
RelocationTarget, SourceLoc,
|
|
||||||
};
|
};
|
||||||
|
use wasmer_runtime::libcalls::LibCall;
|
||||||
use wasmer_runtime::Module as WasmerCompilerModule;
|
use wasmer_runtime::Module as WasmerCompilerModule;
|
||||||
use wasmer_runtime::{libcalls::LibCall, MemoryPlan, MemoryStyle, TablePlan};
|
use wasmer_runtime::{MemoryPlan, MemoryStyle, TablePlan};
|
||||||
|
|
||||||
// TODO: debugging
|
// TODO: debugging
|
||||||
use std::fs;
|
use std::fs;
|
||||||
@ -83,6 +82,15 @@ fn const_zero<'ctx>(ty: BasicTypeEnum<'ctx>) -> BasicValueEnum<'ctx> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Relocation against a per-function section.
|
||||||
|
#[derive(Debug)]
|
||||||
|
pub struct LocalRelocation {
|
||||||
|
pub kind: RelocationKind,
|
||||||
|
pub local_section_index: u32,
|
||||||
|
pub offset: CodeOffset,
|
||||||
|
pub addend: Addend,
|
||||||
|
}
|
||||||
|
|
||||||
impl FuncTranslator {
|
impl FuncTranslator {
|
||||||
pub fn new() -> Self {
|
pub fn new() -> Self {
|
||||||
Self {
|
Self {
|
||||||
@ -99,7 +107,7 @@ impl FuncTranslator {
|
|||||||
memory_plans: &PrimaryMap<MemoryIndex, MemoryPlan>,
|
memory_plans: &PrimaryMap<MemoryIndex, MemoryPlan>,
|
||||||
table_plans: &PrimaryMap<TableIndex, TablePlan>,
|
table_plans: &PrimaryMap<TableIndex, TablePlan>,
|
||||||
func_names: &SecondaryMap<FuncIndex, String>,
|
func_names: &SecondaryMap<FuncIndex, String>,
|
||||||
) -> Result<CompiledFunction, CompileError> {
|
) -> Result<(CompiledFunction, Vec<LocalRelocation>, Vec<CustomSection>), CompileError> {
|
||||||
let func_index = wasm_module.func_index(*func_index);
|
let func_index = wasm_module.func_index(*func_index);
|
||||||
let func_name = func_names.get(func_index).unwrap();
|
let func_name = func_names.get(func_index).unwrap();
|
||||||
let module_name = match wasm_module.name.as_ref() {
|
let module_name = match wasm_module.name.as_ref() {
|
||||||
@ -300,6 +308,8 @@ impl FuncTranslator {
|
|||||||
|
|
||||||
let mut bytes = vec![];
|
let mut bytes = vec![];
|
||||||
let mut relocations = vec![];
|
let mut relocations = vec![];
|
||||||
|
let mut local_relocations = vec![];
|
||||||
|
let mut required_custom_sections = vec![];
|
||||||
for section in object.get_sections() {
|
for section in object.get_sections() {
|
||||||
match section.get_name().map(std::ffi::CStr::to_bytes) {
|
match section.get_name().map(std::ffi::CStr::to_bytes) {
|
||||||
Some(b"wasmer_function") => {
|
Some(b"wasmer_function") => {
|
||||||
@ -334,26 +344,57 @@ impl FuncTranslator {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if reloc_target.is_none() {
|
if reloc_target.is_some() {
|
||||||
unimplemented!("reference to non-user function {:?}", &target);
|
let reloc_target = reloc_target.unwrap();
|
||||||
}
|
|
||||||
let reloc_target = reloc_target.unwrap();
|
|
||||||
|
|
||||||
let relocation = Relocation {
|
relocations.push(Relocation {
|
||||||
kind,
|
kind,
|
||||||
reloc_target,
|
reloc_target,
|
||||||
offset: rel.get_offset() as u32,
|
offset: rel.get_offset() as u32,
|
||||||
// TODO: it appears the LLVM C API has no way to
|
// TODO: it appears the LLVM C API has no way to
|
||||||
// retrieve the addend.
|
// retrieve the addend.
|
||||||
addend: 0,
|
addend: 0,
|
||||||
};
|
});
|
||||||
relocations.push(relocation);
|
} else {
|
||||||
|
if let Some(ref target) = &target {
|
||||||
|
let local_section_index = required_custom_sections.len() as u32;
|
||||||
|
required_custom_sections.push(target.clone());
|
||||||
|
local_relocations.push(LocalRelocation {
|
||||||
|
kind,
|
||||||
|
local_section_index,
|
||||||
|
offset: rel.get_offset() as u32,
|
||||||
|
// TODO: it appears the LLVM C API has no way to
|
||||||
|
// retrieve the addend.
|
||||||
|
addend: 0,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
_ => {}
|
_ => {}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TODO: verify that we see all of them
|
||||||
|
let mut custom_sections = vec![];
|
||||||
|
custom_sections.resize(
|
||||||
|
required_custom_sections.len(),
|
||||||
|
CustomSection {
|
||||||
|
protection: CustomSectionProtection::Read,
|
||||||
|
bytes: vec![],
|
||||||
|
},
|
||||||
|
);
|
||||||
|
for section in object.get_sections() {
|
||||||
|
if let Some(name) = section.get_name().map(std::ffi::CStr::to_bytes) {
|
||||||
|
if let Some(index) = required_custom_sections
|
||||||
|
.iter()
|
||||||
|
.position(|n| n.as_bytes() == name)
|
||||||
|
{
|
||||||
|
custom_sections[index].bytes.extend(section.get_contents());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
let address_map = FunctionAddressMap {
|
let address_map = FunctionAddressMap {
|
||||||
instructions: vec![],
|
instructions: vec![],
|
||||||
start_srcloc: SourceLoc::default(),
|
start_srcloc: SourceLoc::default(),
|
||||||
@ -362,18 +403,22 @@ impl FuncTranslator {
|
|||||||
body_len: 0, // TODO
|
body_len: 0, // TODO
|
||||||
};
|
};
|
||||||
|
|
||||||
Ok(CompiledFunction {
|
Ok((
|
||||||
body: FunctionBody {
|
CompiledFunction {
|
||||||
body: bytes,
|
body: FunctionBody {
|
||||||
unwind_info: CompiledFunctionUnwindInfo::None,
|
body: bytes,
|
||||||
|
unwind_info: CompiledFunctionUnwindInfo::None,
|
||||||
|
},
|
||||||
|
jt_offsets: SecondaryMap::new(),
|
||||||
|
relocations,
|
||||||
|
frame_info: CompiledFunctionFrameInfo {
|
||||||
|
address_map,
|
||||||
|
traps: vec![],
|
||||||
|
},
|
||||||
},
|
},
|
||||||
jt_offsets: SecondaryMap::new(),
|
local_relocations,
|
||||||
relocations,
|
custom_sections,
|
||||||
frame_info: CompiledFunctionFrameInfo {
|
))
|
||||||
address_map,
|
|
||||||
traps: vec![],
|
|
||||||
},
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -23,8 +23,8 @@ pub enum CustomSectionProtection {
|
|||||||
Read,
|
Read,
|
||||||
// We don't include `ReadWrite` here because it would complicate freeze
|
// We don't include `ReadWrite` here because it would complicate freeze
|
||||||
// and resumption of executing Modules.
|
// and resumption of executing Modules.
|
||||||
/// A compiled section that is also executable.
|
// We also currently don't include `ReadExecute` as we don't have a way
|
||||||
ReadExecute,
|
// to represent relocations for this kind of section.
|
||||||
}
|
}
|
||||||
|
|
||||||
/// A Section for a `Compilation`.
|
/// A Section for a `Compilation`.
|
||||||
|
Reference in New Issue
Block a user