Create new InvertibleCompilationNamer and use it to name generated functions.

Fixes build of rustc_binary2.wasm with --llvm.
This commit is contained in:
Nick Lewycky
2020-08-04 16:33:31 -07:00
parent e08e0a0e41
commit 64448dda40
4 changed files with 245 additions and 98 deletions

View File

@@ -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 {},
)
},
)

View File

@@ -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();

View File

@@ -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,
})
}
})
}