mirror of
https://github.com/mii443/wasmer.git
synced 2025-12-09 14:18:20 +00:00
Create new InvertibleCompilationNamer and use it to name generated functions.
Fixes build of rustc_binary2.wasm with --llvm.
This commit is contained in:
@@ -2,13 +2,16 @@ use crate::config::LLVM;
|
||||
use crate::trampoline::FuncTrampoline;
|
||||
use crate::translator::FuncTranslator;
|
||||
use rayon::prelude::{IntoParallelRefIterator, ParallelIterator};
|
||||
use wasm_common::entity::{EntityRef, PrimaryMap, SecondaryMap};
|
||||
use wasm_common::LocalFunctionIndex;
|
||||
use wasm_common::entity::{EntityRef, PrimaryMap};
|
||||
use wasm_common::{FunctionIndex, LocalFunctionIndex, SignatureIndex};
|
||||
use wasmer_compiler::{
|
||||
Compilation, CompileError, CompileModuleInfo, Compiler, CustomSection, CustomSectionProtection,
|
||||
Dwarf, FunctionBodyData, ModuleTranslationState, RelocationTarget, SectionBody, SectionIndex,
|
||||
Target,
|
||||
};
|
||||
use wasmer_object::CompilationNamer;
|
||||
|
||||
use std::collections::HashMap;
|
||||
|
||||
//use std::sync::{Arc, Mutex};
|
||||
|
||||
@@ -32,6 +35,118 @@ impl LLVMCompiler {
|
||||
}
|
||||
}
|
||||
|
||||
struct ShortNames {}
|
||||
|
||||
impl InvertibleCompilationNamer for ShortNames {
|
||||
/// Gets the function name given a local function index
|
||||
fn get_function_name(&mut self, index: &LocalFunctionIndex) -> String {
|
||||
format!("f{}", index.index())
|
||||
}
|
||||
|
||||
/// Gets the section name given a section index
|
||||
fn get_section_name(&mut self, index: &SectionIndex) -> String {
|
||||
format!("s{}", index.index())
|
||||
}
|
||||
|
||||
/// Gets the function call trampoline name given a signature index
|
||||
fn get_function_call_trampoline_name(&mut self, index: &SignatureIndex) -> String {
|
||||
format!("t{}", index.index())
|
||||
}
|
||||
|
||||
/// Gets the dynamic function trampoline name given a function index
|
||||
fn get_dynamic_function_trampoline_name(&mut self, index: &FunctionIndex) -> String {
|
||||
format!("d{}", index.index())
|
||||
}
|
||||
|
||||
fn get_symbol_from_name(&self, name: &str) -> Option<Symbol> {
|
||||
if name.len() < 2 {
|
||||
return None;
|
||||
}
|
||||
let (ty, idx) = name.split_at(1);
|
||||
let idx = match idx.parse::<u32>() {
|
||||
Ok(v) => v,
|
||||
Err(_) => return None,
|
||||
};
|
||||
match ty.chars().nth(0).unwrap() {
|
||||
'f' => Some(Symbol::LocalFunction(LocalFunctionIndex::from_u32(idx))),
|
||||
's' => Some(Symbol::Section(SectionIndex::from_u32(idx))),
|
||||
't' => Some(Symbol::FunctionCallTrampoline(SignatureIndex::from_u32(
|
||||
idx,
|
||||
))),
|
||||
'd' => Some(Symbol::DynamicFunctionTrampoline(FunctionIndex::from_u32(
|
||||
idx,
|
||||
))),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Symbols we may have produced names for.
|
||||
#[derive(Clone, Debug, PartialEq, Eq)]
|
||||
pub enum Symbol {
|
||||
LocalFunction(LocalFunctionIndex),
|
||||
Section(SectionIndex),
|
||||
FunctionCallTrampoline(SignatureIndex),
|
||||
DynamicFunctionTrampoline(FunctionIndex),
|
||||
}
|
||||
|
||||
pub trait InvertibleCompilationNamer {
|
||||
/// Gets the function name given a local function index.
|
||||
fn get_function_name(&mut self, index: &LocalFunctionIndex) -> String;
|
||||
|
||||
/// Gets the section name given a section index.
|
||||
fn get_section_name(&mut self, index: &SectionIndex) -> String;
|
||||
|
||||
/// Gets the function call trampoline name given a signature index.
|
||||
fn get_function_call_trampoline_name(&mut self, index: &SignatureIndex) -> String;
|
||||
|
||||
/// Gets the dynamic function trampoline name given a function index.
|
||||
fn get_dynamic_function_trampoline_name(&mut self, index: &FunctionIndex) -> String;
|
||||
|
||||
/// Gets the type of symbol from a given name.
|
||||
fn get_symbol_from_name(&self, name: &str) -> Option<Symbol>;
|
||||
}
|
||||
|
||||
pub struct CachingInvertibleCompilationNamer<'a> {
|
||||
cache: HashMap<String, Symbol>,
|
||||
namer: &'a dyn CompilationNamer,
|
||||
}
|
||||
|
||||
impl<'a> InvertibleCompilationNamer for CachingInvertibleCompilationNamer<'a> {
|
||||
fn get_function_name(&mut self, index: &LocalFunctionIndex) -> String {
|
||||
let value = self.namer.get_function_name(index);
|
||||
self.cache
|
||||
.insert(value.clone(), Symbol::LocalFunction(*index));
|
||||
value
|
||||
}
|
||||
|
||||
fn get_section_name(&mut self, index: &SectionIndex) -> String {
|
||||
let value = self.namer.get_section_name(index);
|
||||
self.cache.insert(value.clone(), Symbol::Section(*index));
|
||||
value
|
||||
}
|
||||
|
||||
/// Gets the function call trampoline name given a signature index
|
||||
fn get_function_call_trampoline_name(&mut self, index: &SignatureIndex) -> String {
|
||||
let value = self.namer.get_function_call_trampoline_name(index);
|
||||
self.cache
|
||||
.insert(value.clone(), Symbol::FunctionCallTrampoline(*index));
|
||||
value
|
||||
}
|
||||
|
||||
/// Gets the dynamic function trampoline name given a function index
|
||||
fn get_dynamic_function_trampoline_name(&mut self, index: &FunctionIndex) -> String {
|
||||
let value = self.namer.get_dynamic_function_trampoline_name(index);
|
||||
self.cache
|
||||
.insert(value.clone(), Symbol::DynamicFunctionTrampoline(*index));
|
||||
value
|
||||
}
|
||||
|
||||
fn get_symbol_from_name(&self, name: &str) -> Option<Symbol> {
|
||||
self.cache.get(name).cloned()
|
||||
}
|
||||
}
|
||||
|
||||
impl Compiler for LLVMCompiler {
|
||||
/// Compile the module using LLVM, producing a compilation result with
|
||||
/// associated relocations.
|
||||
@@ -43,20 +158,12 @@ impl Compiler for LLVMCompiler {
|
||||
function_body_inputs: PrimaryMap<LocalFunctionIndex, FunctionBodyData<'data>>,
|
||||
) -> Result<Compilation, CompileError> {
|
||||
//let data = Arc::new(Mutex::new(0));
|
||||
let mut function_names = SecondaryMap::new();
|
||||
let memory_styles = &compile_info.memory_styles;
|
||||
let table_styles = &compile_info.table_styles;
|
||||
let module = &compile_info.module;
|
||||
|
||||
// TODO: merge constants in sections.
|
||||
|
||||
for (func_index, _) in &module.functions {
|
||||
function_names[func_index] = module
|
||||
.function_names
|
||||
.get(&func_index)
|
||||
.cloned()
|
||||
.unwrap_or_else(|| format!("fn{}", func_index.index()));
|
||||
}
|
||||
let mut module_custom_sections = PrimaryMap::new();
|
||||
let mut frame_section_bytes = vec![];
|
||||
let mut frame_section_relocations = vec![];
|
||||
@@ -71,7 +178,7 @@ impl Compiler for LLVMCompiler {
|
||||
},
|
||||
|func_translator, (i, input)| {
|
||||
// TODO: remove (to serialize)
|
||||
//let mut data = data.lock().unwrap();
|
||||
//let _data = data.lock().unwrap();
|
||||
func_translator.translate(
|
||||
&module,
|
||||
module_translation,
|
||||
@@ -80,7 +187,7 @@ impl Compiler for LLVMCompiler {
|
||||
self.config(),
|
||||
memory_styles,
|
||||
&table_styles,
|
||||
&function_names,
|
||||
&mut ShortNames {},
|
||||
)
|
||||
},
|
||||
)
|
||||
|
||||
@@ -24,7 +24,7 @@ use smallvec::SmallVec;
|
||||
|
||||
use crate::config::{CompiledFunctionKind, LLVM};
|
||||
use crate::object_file::{load_object_file, CompiledFunction};
|
||||
use wasm_common::entity::{PrimaryMap, SecondaryMap};
|
||||
use wasm_common::entity::PrimaryMap;
|
||||
use wasm_common::{
|
||||
FunctionIndex, FunctionType, GlobalIndex, LocalFunctionIndex, MemoryIndex, SignatureIndex,
|
||||
TableIndex, Type,
|
||||
@@ -74,12 +74,12 @@ impl FuncTranslator {
|
||||
config: &LLVM,
|
||||
memory_styles: &PrimaryMap<MemoryIndex, MemoryStyle>,
|
||||
_table_styles: &PrimaryMap<TableIndex, TableStyle>,
|
||||
function_names: &SecondaryMap<FunctionIndex, String>,
|
||||
namer: &mut dyn crate::compiler::InvertibleCompilationNamer,
|
||||
) -> Result<CompiledFunction, CompileError> {
|
||||
// The function type, used for the callbacks.
|
||||
let function = CompiledFunctionKind::Local(*local_func_index);
|
||||
let func_index = wasm_module.func_index(*local_func_index);
|
||||
let function_name = &function_names[func_index];
|
||||
let function_name = namer.get_function_name(local_func_index);
|
||||
let module_name = match wasm_module.name.as_ref() {
|
||||
None => format!("<anonymous module> function {}", function_name),
|
||||
Some(module_name) => format!("module {} function {}", module_name, function_name),
|
||||
@@ -99,9 +99,10 @@ impl FuncTranslator {
|
||||
let (func_type, func_attrs) = abi::func_type_to_llvm(&self.ctx, &intrinsics, wasm_fn_type)?;
|
||||
|
||||
let func = module.add_function(&function_name, func_type, Some(Linkage::External));
|
||||
for (attr, attr_loc) in func_attrs {
|
||||
func.add_attribute(attr_loc, attr);
|
||||
for (attr, attr_loc) in &func_attrs {
|
||||
func.add_attribute(*attr_loc, *attr);
|
||||
}
|
||||
|
||||
// TODO: mark vmctx align 16
|
||||
// TODO: figure out how many bytes long vmctx is, and mark it dereferenceable. (no need to mark it nonnull once we do this.)
|
||||
// TODO: mark vmctx nofree
|
||||
@@ -203,8 +204,14 @@ impl FuncTranslator {
|
||||
module: &module,
|
||||
module_translation,
|
||||
wasm_module,
|
||||
function_names,
|
||||
namer,
|
||||
};
|
||||
fcg.ctx.add_func(
|
||||
func_index,
|
||||
func.as_global_value().as_pointer_value(),
|
||||
fcg.ctx.basic(),
|
||||
&func_attrs,
|
||||
);
|
||||
|
||||
while fcg.state.has_control_frames() {
|
||||
let pos = reader.current_position() as u32;
|
||||
@@ -275,17 +282,15 @@ impl FuncTranslator {
|
||||
".wasmer_function",
|
||||
RelocationTarget::LocalFunc(*local_func_index),
|
||||
|name: &String| {
|
||||
if let Some((index, _)) = function_names
|
||||
.iter()
|
||||
.find(|(_, function_name)| **function_name == *name)
|
||||
{
|
||||
let local_index = wasm_module
|
||||
.local_func_index(index)
|
||||
.expect("relocation to non-local function");
|
||||
Ok(Some(RelocationTarget::LocalFunc(local_index)))
|
||||
} else {
|
||||
Ok(None)
|
||||
}
|
||||
Ok(
|
||||
if let Some(crate::compiler::Symbol::LocalFunction(local_func_index)) =
|
||||
namer.get_symbol_from_name(name)
|
||||
{
|
||||
Some(RelocationTarget::LocalFunc(local_func_index))
|
||||
} else {
|
||||
None
|
||||
},
|
||||
)
|
||||
},
|
||||
)
|
||||
}
|
||||
@@ -1277,7 +1282,7 @@ pub struct LLVMFunctionCodeGenerator<'ctx, 'a> {
|
||||
module: &'a Module<'ctx>,
|
||||
module_translation: &'a ModuleTranslationState,
|
||||
wasm_module: &'a ModuleInfo,
|
||||
function_names: &'a SecondaryMap<FunctionIndex, String>,
|
||||
namer: &'a mut dyn crate::compiler::InvertibleCompilationNamer,
|
||||
}
|
||||
|
||||
impl<'ctx, 'a> LLVMFunctionCodeGenerator<'ctx, 'a> {
|
||||
@@ -2045,20 +2050,26 @@ impl<'ctx, 'a> LLVMFunctionCodeGenerator<'ctx, 'a> {
|
||||
let func_index = FunctionIndex::from_u32(function_index);
|
||||
let sigindex = &self.wasm_module.functions[func_index];
|
||||
let func_type = &self.wasm_module.signatures[*sigindex];
|
||||
let function_name = &self.function_names[func_index];
|
||||
|
||||
let FunctionCache {
|
||||
func,
|
||||
vmctx: callee_vmctx,
|
||||
attrs,
|
||||
} = self.ctx.func(
|
||||
func_index,
|
||||
self.intrinsics,
|
||||
self.module,
|
||||
self.context,
|
||||
function_name,
|
||||
func_type,
|
||||
)?;
|
||||
} = if let Some(local_func_index) = self.wasm_module.local_func_index(func_index) {
|
||||
let function_name = self.namer.get_function_name(&local_func_index);
|
||||
self.ctx.local_func(
|
||||
local_func_index,
|
||||
func_index,
|
||||
self.intrinsics,
|
||||
self.module,
|
||||
self.context,
|
||||
func_type,
|
||||
&function_name,
|
||||
)?
|
||||
} else {
|
||||
self.ctx
|
||||
.func(func_index, self.intrinsics, self.context, func_type)?
|
||||
};
|
||||
let func = *func;
|
||||
let callee_vmctx = *callee_vmctx;
|
||||
let attrs = attrs.clone();
|
||||
|
||||
@@ -22,8 +22,8 @@ use inkwell::{
|
||||
use std::collections::{hash_map::Entry, HashMap};
|
||||
use wasm_common::entity::{EntityRef, PrimaryMap};
|
||||
use wasm_common::{
|
||||
FunctionIndex, FunctionType as FuncType, GlobalIndex, MemoryIndex, Mutability, SignatureIndex,
|
||||
TableIndex, Type,
|
||||
FunctionIndex, FunctionType as FuncType, GlobalIndex, LocalFunctionIndex, MemoryIndex,
|
||||
Mutability, SignatureIndex, TableIndex, Type,
|
||||
};
|
||||
use wasmer_compiler::CompileError;
|
||||
use wasmer_vm::ModuleInfo as WasmerCompilerModule;
|
||||
@@ -903,13 +903,61 @@ impl<'ctx, 'a> CtxType<'ctx, 'a> {
|
||||
})
|
||||
}
|
||||
|
||||
pub fn func(
|
||||
pub fn add_func(
|
||||
&mut self,
|
||||
function_index: FunctionIndex,
|
||||
func: PointerValue<'ctx>,
|
||||
vmctx: BasicValueEnum<'ctx>,
|
||||
attrs: &[(Attribute, AttributeLoc)],
|
||||
) {
|
||||
match self.cached_functions.entry(function_index) {
|
||||
Entry::Occupied(_) => unreachable!("duplicate function"),
|
||||
Entry::Vacant(entry) => {
|
||||
entry.insert(FunctionCache {
|
||||
func,
|
||||
vmctx,
|
||||
attrs: attrs.to_vec(),
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn local_func(
|
||||
&mut self,
|
||||
_local_function_index: LocalFunctionIndex,
|
||||
function_index: FunctionIndex,
|
||||
intrinsics: &Intrinsics<'ctx>,
|
||||
module: &Module<'ctx>,
|
||||
context: &'ctx Context,
|
||||
func_type: &FuncType,
|
||||
function_name: &str,
|
||||
) -> Result<&FunctionCache<'ctx>, CompileError> {
|
||||
let (cached_functions, ctx_ptr_value) = (&mut self.cached_functions, &self.ctx_ptr_value);
|
||||
Ok(match cached_functions.entry(function_index) {
|
||||
Entry::Occupied(entry) => entry.into_mut(),
|
||||
Entry::Vacant(entry) => {
|
||||
debug_assert!(module.get_function(function_name).is_none());
|
||||
let (llvm_func_type, llvm_func_attrs) =
|
||||
abi::func_type_to_llvm(context, intrinsics, func_type)?;
|
||||
let func =
|
||||
module.add_function(function_name, llvm_func_type, Some(Linkage::External));
|
||||
for (attr, attr_loc) in &llvm_func_attrs {
|
||||
func.add_attribute(*attr_loc, *attr);
|
||||
}
|
||||
entry.insert(FunctionCache {
|
||||
func: func.as_global_value().as_pointer_value(),
|
||||
vmctx: ctx_ptr_value.as_basic_value_enum(),
|
||||
attrs: llvm_func_attrs,
|
||||
})
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
pub fn func(
|
||||
&mut self,
|
||||
function_index: FunctionIndex,
|
||||
intrinsics: &Intrinsics<'ctx>,
|
||||
context: &'ctx Context,
|
||||
func_type: &FuncType,
|
||||
) -> Result<&FunctionCache<'ctx>, CompileError> {
|
||||
let (cached_functions, wasm_module, ctx_ptr_value, cache_builder, offsets) = (
|
||||
@@ -924,63 +972,43 @@ impl<'ctx, 'a> CtxType<'ctx, 'a> {
|
||||
Entry::Vacant(entry) => {
|
||||
let (llvm_func_type, llvm_func_attrs) =
|
||||
abi::func_type_to_llvm(context, intrinsics, func_type)?;
|
||||
if wasm_module.local_func_index(function_index).is_some() {
|
||||
// TODO: assuming names are unique, we don't need the
|
||||
// get_function call.
|
||||
let func = module.get_function(function_name).unwrap_or_else(|| {
|
||||
let func = module.add_function(
|
||||
function_name,
|
||||
llvm_func_type,
|
||||
Some(Linkage::External),
|
||||
);
|
||||
for (attr, attr_loc) in &llvm_func_attrs {
|
||||
func.add_attribute(*attr_loc, *attr);
|
||||
}
|
||||
func
|
||||
});
|
||||
entry.insert(FunctionCache {
|
||||
func: func.as_global_value().as_pointer_value(),
|
||||
vmctx: ctx_ptr_value.as_basic_value_enum(),
|
||||
attrs: llvm_func_attrs,
|
||||
})
|
||||
} else {
|
||||
let offset = offsets.vmctx_vmfunction_import(function_index);
|
||||
let offset = intrinsics.i32_ty.const_int(offset.into(), false);
|
||||
let vmfunction_import_ptr =
|
||||
unsafe { cache_builder.build_gep(*ctx_ptr_value, &[offset], "") };
|
||||
let vmfunction_import_ptr = cache_builder
|
||||
.build_bitcast(
|
||||
vmfunction_import_ptr,
|
||||
intrinsics.vmfunction_import_ptr_ty,
|
||||
"",
|
||||
)
|
||||
.into_pointer_value();
|
||||
debug_assert!(wasm_module.local_func_index(function_index).is_none());
|
||||
let offset = offsets.vmctx_vmfunction_import(function_index);
|
||||
let offset = intrinsics.i32_ty.const_int(offset.into(), false);
|
||||
let vmfunction_import_ptr =
|
||||
unsafe { cache_builder.build_gep(*ctx_ptr_value, &[offset], "") };
|
||||
let vmfunction_import_ptr = cache_builder
|
||||
.build_bitcast(
|
||||
vmfunction_import_ptr,
|
||||
intrinsics.vmfunction_import_ptr_ty,
|
||||
"",
|
||||
)
|
||||
.into_pointer_value();
|
||||
|
||||
let body_ptr_ptr = cache_builder
|
||||
.build_struct_gep(
|
||||
vmfunction_import_ptr,
|
||||
intrinsics.vmfunction_import_body_element,
|
||||
"",
|
||||
)
|
||||
.unwrap();
|
||||
let body_ptr = cache_builder.build_load(body_ptr_ptr, "");
|
||||
let body_ptr = cache_builder
|
||||
.build_bitcast(body_ptr, llvm_func_type.ptr_type(AddressSpace::Generic), "")
|
||||
.into_pointer_value();
|
||||
let vmctx_ptr_ptr = cache_builder
|
||||
.build_struct_gep(
|
||||
vmfunction_import_ptr,
|
||||
intrinsics.vmfunction_import_vmctx_element,
|
||||
"",
|
||||
)
|
||||
.unwrap();
|
||||
let vmctx_ptr = cache_builder.build_load(vmctx_ptr_ptr, "");
|
||||
entry.insert(FunctionCache {
|
||||
func: body_ptr,
|
||||
vmctx: vmctx_ptr,
|
||||
attrs: llvm_func_attrs,
|
||||
})
|
||||
}
|
||||
let body_ptr_ptr = cache_builder
|
||||
.build_struct_gep(
|
||||
vmfunction_import_ptr,
|
||||
intrinsics.vmfunction_import_body_element,
|
||||
"",
|
||||
)
|
||||
.unwrap();
|
||||
let body_ptr = cache_builder.build_load(body_ptr_ptr, "");
|
||||
let body_ptr = cache_builder
|
||||
.build_bitcast(body_ptr, llvm_func_type.ptr_type(AddressSpace::Generic), "")
|
||||
.into_pointer_value();
|
||||
let vmctx_ptr_ptr = cache_builder
|
||||
.build_struct_gep(
|
||||
vmfunction_import_ptr,
|
||||
intrinsics.vmfunction_import_vmctx_element,
|
||||
"",
|
||||
)
|
||||
.unwrap();
|
||||
let vmctx_ptr = cache_builder.build_load(vmctx_ptr_ptr, "");
|
||||
entry.insert(FunctionCache {
|
||||
func: body_ptr,
|
||||
vmctx: vmctx_ptr,
|
||||
attrs: llvm_func_attrs,
|
||||
})
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user