cretonne-faerie: add a translation mechanism for LibCalls (#321)

* cretonne-faerie: add a translation mechanism for LibCalls

* cretonne-faerie: docs for libcall_names, rustfmt

* cretonne-faerie: switch libcall naming to use a closure

* travis: debug mypy version

* travis: pin mypy to 0.521

mypy released 0.600 today and even with `--no-strict-optional` flag
passed to it (in lib/codegen/meta/check.sh) it fails to infer the type
of values that did not need type annotations in the past

* faerie-backend: fix swapped nearbyint functions

* cretonne-faerie: move boxing out of FaerieBuilder
This commit is contained in:
Pat Hickey
2018-05-03 06:54:55 -07:00
committed by Dan Gohman
parent 7e1f157692
commit 69468915d5
2 changed files with 50 additions and 6 deletions

View File

@@ -17,7 +17,7 @@ before_install:
- wget https://storage.googleapis.com/wasm-llvm/builds/linux/26619/wasm-toolchain_0.1.26619_amd64.deb - wget https://storage.googleapis.com/wasm-llvm/builds/linux/26619/wasm-toolchain_0.1.26619_amd64.deb
- sudo dpkg -i wasm-toolchain_0.1.26619_amd64.deb - sudo dpkg -i wasm-toolchain_0.1.26619_amd64.deb
install: install:
- pip3 install --user --upgrade mypy flake8 - pip3 install --user --upgrade mypy==0.521 flake8
- travis_wait ./check-rustfmt.sh --install - travis_wait ./check-rustfmt.sh --install
script: ./test-all.sh script: ./test-all.sh
cache: cache:

View File

@@ -30,8 +30,10 @@ pub struct FaerieBuilder {
format: container::Format, format: container::Format,
faerie_target: faerie::Target, faerie_target: faerie::Target,
collect_traps: FaerieTrapCollection, collect_traps: FaerieTrapCollection,
libcall_names: Box<Fn(ir::LibCall) -> String>,
} }
impl FaerieBuilder { impl FaerieBuilder {
/// Create a new `FaerieBuilder` using the given Cretonne target, that /// Create a new `FaerieBuilder` using the given Cretonne target, that
/// can be passed to /// can be passed to
@@ -41,11 +43,17 @@ impl FaerieBuilder {
/// ///
/// `collect_traps` setting determines whether trap information is collected in a /// `collect_traps` setting determines whether trap information is collected in a
/// `FaerieTrapManifest` available in the `FaerieProduct`. /// `FaerieTrapManifest` available in the `FaerieProduct`.
///
/// The `libcall_names` function provides a way to translate `cretonne_codegen`'s `ir::LibCall`
/// enum to symbols. LibCalls are inserted in the IR as part of the legalization for certain
/// floating point instructions, and for stack probes. If you don't know what to use for this
/// argument, use `FaerieBuilder::default_libcall_names()`.
pub fn new( pub fn new(
isa: Box<TargetIsa>, isa: Box<TargetIsa>,
name: String, name: String,
format: container::Format, format: container::Format,
collect_traps: FaerieTrapCollection, collect_traps: FaerieTrapCollection,
libcall_names: Box<Fn(ir::LibCall) -> String>,
) -> Result<Self, ModuleError> { ) -> Result<Self, ModuleError> {
if !isa.flags().is_pic() { if !isa.flags().is_pic() {
return Err(ModuleError::Backend( return Err(ModuleError::Backend(
@@ -59,16 +67,36 @@ impl FaerieBuilder {
format, format,
faerie_target, faerie_target,
collect_traps, collect_traps,
libcall_names,
})
}
/// Default names for `ir::LibCall`s. A function by this name is imported into the object as
/// part of the translation of a `ir::ExternalName::LibCall` variant. Calls to a LibCall should
/// only be inserted into the IR by the `cretonne_codegen` legalizer pass.
pub fn default_libcall_names() -> Box<Fn(ir::LibCall) -> String> {
Box::new(move |libcall| match libcall {
ir::LibCall::Probestack => "__cretonne_probestack".to_owned(),
ir::LibCall::CeilF32 => "ceilf".to_owned(),
ir::LibCall::CeilF64 => "ceil".to_owned(),
ir::LibCall::FloorF32 => "floorf".to_owned(),
ir::LibCall::FloorF64 => "floor".to_owned(),
ir::LibCall::TruncF32 => "truncf".to_owned(),
ir::LibCall::TruncF64 => "trunc".to_owned(),
ir::LibCall::NearestF32 => "nearbyintf".to_owned(),
ir::LibCall::NearestF64 => "nearbyint".to_owned(),
}) })
} }
} }
/// A `FaerieBackend` implements `Backend` and emits ".o" files using the `faerie` library. /// A `FaerieBackend` implements `Backend` and emits ".o" files using the `faerie` library.
pub struct FaerieBackend { pub struct FaerieBackend {
isa: Box<TargetIsa>, isa: Box<TargetIsa>,
artifact: faerie::Artifact, artifact: faerie::Artifact,
format: container::Format, format: container::Format,
trap_manifest: Option<FaerieTrapManifest>, trap_manifest: Option<FaerieTrapManifest>,
libcall_names: Box<Fn(ir::LibCall) -> String>,
} }
pub struct FaerieCompiledFunction {} pub struct FaerieCompiledFunction {}
@@ -100,6 +128,7 @@ impl Backend for FaerieBackend {
FaerieTrapCollection::Enabled => Some(FaerieTrapManifest::new()), FaerieTrapCollection::Enabled => Some(FaerieTrapManifest::new()),
FaerieTrapCollection::Disabled => None, FaerieTrapCollection::Disabled => None,
}, },
libcall_names: builder.libcall_names,
} }
} }
@@ -136,6 +165,7 @@ impl Backend for FaerieBackend {
artifact: &mut self.artifact, artifact: &mut self.artifact,
name, name,
namespace, namespace,
libcall_names: &self.libcall_names,
}; };
if let Some(ref mut trap_manifest) = self.trap_manifest { if let Some(ref mut trap_manifest) = self.trap_manifest {
@@ -334,11 +364,13 @@ fn translate_data_linkage(linkage: Linkage, writable: bool) -> faerie::Decl {
} }
} }
struct FaerieRelocSink<'a> { struct FaerieRelocSink<'a> {
format: container::Format, format: container::Format,
artifact: &'a mut faerie::Artifact, artifact: &'a mut faerie::Artifact,
name: &'a str, name: &'a str,
namespace: &'a ModuleNamespace<'a, FaerieBackend>, namespace: &'a ModuleNamespace<'a, FaerieBackend>,
libcall_names: &'a Box<Fn(ir::LibCall) -> String>,
} }
impl<'a> RelocSink for FaerieRelocSink<'a> { impl<'a> RelocSink for FaerieRelocSink<'a> {
@@ -353,10 +385,22 @@ impl<'a> RelocSink for FaerieRelocSink<'a> {
name: &ir::ExternalName, name: &ir::ExternalName,
addend: Addend, addend: Addend,
) { ) {
let ref_name = if self.namespace.is_function(name) { let ref_name: String = match name {
&self.namespace.get_function_decl(name).name &ir::ExternalName::User { .. } => {
} else { if self.namespace.is_function(name) {
&self.namespace.get_data_decl(name).name self.namespace.get_function_decl(name).name.clone()
} else {
self.namespace.get_data_decl(name).name.clone()
}
}
&ir::ExternalName::LibCall(ref libcall) => {
let sym = (self.libcall_names)(*libcall);
self.artifact
.declare(sym.clone(), faerie::Decl::FunctionImport)
.expect("faerie declaration of libcall");
sym
}
_ => panic!("invalid ExternalName {}", name),
}; };
let addend_i32 = addend as i32; let addend_i32 = addend as i32;
debug_assert!(i64::from(addend_i32) == addend); debug_assert!(i64::from(addend_i32) == addend);
@@ -365,7 +409,7 @@ impl<'a> RelocSink for FaerieRelocSink<'a> {
.link_with( .link_with(
faerie::Link { faerie::Link {
from: self.name, from: self.name,
to: ref_name, to: &ref_name,
at: offset as usize, at: offset as usize,
}, },
faerie::RelocOverride { faerie::RelocOverride {