1 //! Defines the `Backend` trait.
2 
3 use crate::DataContext;
4 use crate::DataId;
5 use crate::FuncId;
6 use crate::Linkage;
7 use crate::ModuleNamespace;
8 use crate::ModuleResult;
9 use core::marker;
10 use cranelift_codegen::isa::TargetIsa;
11 use cranelift_codegen::Context;
12 use cranelift_codegen::{binemit, ir};
13 
14 use std::borrow::ToOwned;
15 use std::boxed::Box;
16 use std::string::String;
17 
18 /// A `Backend` implements the functionality needed to support a `Module`.
19 ///
20 /// Three notable implementations of this trait are:
21 ///  - `SimpleJITBackend`, defined in [cranelift-simplejit], which JITs
22 ///    the contents of a `Module` to memory which can be directly executed.
23 ///  - `ObjectBackend`, defined in [cranelift-object], which writes the
24 ///    contents of a `Module` out as a native object file.
25 ///  - `FaerieBackend`, defined in [cranelift-faerie], which writes the
26 ///    contents of a `Module` out as a native object file.
27 ///
28 /// [cranelift-simplejit]: https://docs.rs/cranelift-simplejit/
29 /// [cranelift-object]: https://docs.rs/cranelift-object/
30 /// [cranelift-faerie]: https://docs.rs/cranelift-faerie/
31 pub trait Backend
32 where
33     Self: marker::Sized,
34 {
35     /// A builder for constructing `Backend` instances.
36     type Builder;
37 
38     /// The results of compiling a function.
39     type CompiledFunction;
40 
41     /// The results of "compiling" a data object.
42     type CompiledData;
43 
44     /// The completed output artifact for a function, if this is meaningful for
45     /// the `Backend`.
46     type FinalizedFunction;
47 
48     /// The completed output artifact for a data object, if this is meaningful for
49     /// the `Backend`.
50     type FinalizedData;
51 
52     /// This is an object returned by `Module`'s
53     /// [`finish`](struct.Module.html#method.finish) function,
54     /// if the `Backend` has a purpose for this.
55     type Product;
56 
57     /// Create a new `Backend` instance.
new(_: Self::Builder) -> Self58     fn new(_: Self::Builder) -> Self;
59 
60     /// Return the `TargetIsa` to compile for.
isa(&self) -> &dyn TargetIsa61     fn isa(&self) -> &dyn TargetIsa;
62 
63     /// Declare a function.
declare_function(&mut self, id: FuncId, name: &str, linkage: Linkage)64     fn declare_function(&mut self, id: FuncId, name: &str, linkage: Linkage);
65 
66     /// Declare a data object.
declare_data( &mut self, id: DataId, name: &str, linkage: Linkage, writable: bool, tls: bool, align: Option<u8>, )67     fn declare_data(
68         &mut self,
69         id: DataId,
70         name: &str,
71         linkage: Linkage,
72         writable: bool,
73         tls: bool,
74         align: Option<u8>,
75     );
76 
77     /// Define a function, producing the function body from the given `Context`.
78     ///
79     /// Functions must be declared before being defined.
define_function<TS>( &mut self, id: FuncId, name: &str, ctx: &Context, namespace: &ModuleNamespace<Self>, code_size: u32, trap_sink: &mut TS, ) -> ModuleResult<Self::CompiledFunction> where TS: binemit::TrapSink80     fn define_function<TS>(
81         &mut self,
82         id: FuncId,
83         name: &str,
84         ctx: &Context,
85         namespace: &ModuleNamespace<Self>,
86         code_size: u32,
87         trap_sink: &mut TS,
88     ) -> ModuleResult<Self::CompiledFunction>
89     where
90         TS: binemit::TrapSink;
91 
92     /// Define a function, taking the function body from the given `bytes`.
93     ///
94     /// Functions must be declared before being defined.
define_function_bytes( &mut self, id: FuncId, name: &str, bytes: &[u8], namespace: &ModuleNamespace<Self>, ) -> ModuleResult<Self::CompiledFunction>95     fn define_function_bytes(
96         &mut self,
97         id: FuncId,
98         name: &str,
99         bytes: &[u8],
100         namespace: &ModuleNamespace<Self>,
101     ) -> ModuleResult<Self::CompiledFunction>;
102 
103     /// Define a zero-initialized data object of the given size.
104     ///
105     /// Data objects must be declared before being defined.
define_data( &mut self, id: DataId, name: &str, writable: bool, tls: bool, align: Option<u8>, data_ctx: &DataContext, namespace: &ModuleNamespace<Self>, ) -> ModuleResult<Self::CompiledData>106     fn define_data(
107         &mut self,
108         id: DataId,
109         name: &str,
110         writable: bool,
111         tls: bool,
112         align: Option<u8>,
113         data_ctx: &DataContext,
114         namespace: &ModuleNamespace<Self>,
115     ) -> ModuleResult<Self::CompiledData>;
116 
117     /// Write the address of `what` into the data for `data` at `offset`. `data` must refer to a
118     /// defined data object.
write_data_funcaddr( &mut self, data: &mut Self::CompiledData, offset: usize, what: ir::FuncRef, )119     fn write_data_funcaddr(
120         &mut self,
121         data: &mut Self::CompiledData,
122         offset: usize,
123         what: ir::FuncRef,
124     );
125 
126     /// Write the address of `what` plus `addend` into the data for `data` at `offset`. `data` must
127     /// refer to a defined data object.
write_data_dataaddr( &mut self, data: &mut Self::CompiledData, offset: usize, what: ir::GlobalValue, addend: binemit::Addend, )128     fn write_data_dataaddr(
129         &mut self,
130         data: &mut Self::CompiledData,
131         offset: usize,
132         what: ir::GlobalValue,
133         addend: binemit::Addend,
134     );
135 
136     /// Perform all outstanding relocations on the given function. This requires all `Local`
137     /// and `Export` entities referenced to be defined.
138     ///
139     /// This method is not relevant for `Backend` implementations that do not provide
140     /// `Backend::FinalizedFunction`.
finalize_function( &mut self, id: FuncId, func: &Self::CompiledFunction, namespace: &ModuleNamespace<Self>, ) -> Self::FinalizedFunction141     fn finalize_function(
142         &mut self,
143         id: FuncId,
144         func: &Self::CompiledFunction,
145         namespace: &ModuleNamespace<Self>,
146     ) -> Self::FinalizedFunction;
147 
148     /// Return the finalized artifact from the backend, if relevant.
get_finalized_function(&self, func: &Self::CompiledFunction) -> Self::FinalizedFunction149     fn get_finalized_function(&self, func: &Self::CompiledFunction) -> Self::FinalizedFunction;
150 
151     /// Perform all outstanding relocations on the given data object. This requires all
152     /// `Local` and `Export` entities referenced to be defined.
153     ///
154     /// This method is not relevant for `Backend` implementations that do not provide
155     /// `Backend::FinalizedData`.
finalize_data( &mut self, id: DataId, data: &Self::CompiledData, namespace: &ModuleNamespace<Self>, ) -> Self::FinalizedData156     fn finalize_data(
157         &mut self,
158         id: DataId,
159         data: &Self::CompiledData,
160         namespace: &ModuleNamespace<Self>,
161     ) -> Self::FinalizedData;
162 
163     /// Return the finalized artifact from the backend, if relevant.
get_finalized_data(&self, data: &Self::CompiledData) -> Self::FinalizedData164     fn get_finalized_data(&self, data: &Self::CompiledData) -> Self::FinalizedData;
165 
166     /// "Publish" all finalized functions and data objects to their ultimate destinations.
167     ///
168     /// This method is not relevant for `Backend` implementations that do not provide
169     /// `Backend::FinalizedFunction` or `Backend::FinalizedData`.
publish(&mut self)170     fn publish(&mut self);
171 
172     /// Consume this `Backend` and return a result. Some implementations may
173     /// provide additional functionality through this result.
finish(self, namespace: &ModuleNamespace<Self>) -> Self::Product174     fn finish(self, namespace: &ModuleNamespace<Self>) -> Self::Product;
175 }
176 
177 /// Default names for `ir::LibCall`s. A function by this name is imported into the object as
178 /// part of the translation of a `ir::ExternalName::LibCall` variant.
default_libcall_names() -> Box<dyn Fn(ir::LibCall) -> String>179 pub fn default_libcall_names() -> Box<dyn Fn(ir::LibCall) -> String> {
180     Box::new(move |libcall| match libcall {
181         ir::LibCall::Probestack => "__cranelift_probestack".to_owned(),
182         ir::LibCall::UdivI64 => "__udivdi3".to_owned(),
183         ir::LibCall::SdivI64 => "__divdi3".to_owned(),
184         ir::LibCall::UremI64 => "__umoddi3".to_owned(),
185         ir::LibCall::SremI64 => "__moddi3".to_owned(),
186         ir::LibCall::CeilF32 => "ceilf".to_owned(),
187         ir::LibCall::CeilF64 => "ceil".to_owned(),
188         ir::LibCall::FloorF32 => "floorf".to_owned(),
189         ir::LibCall::FloorF64 => "floor".to_owned(),
190         ir::LibCall::TruncF32 => "truncf".to_owned(),
191         ir::LibCall::TruncF64 => "trunc".to_owned(),
192         ir::LibCall::NearestF32 => "nearbyintf".to_owned(),
193         ir::LibCall::NearestF64 => "nearbyint".to_owned(),
194         ir::LibCall::Memcpy => "memcpy".to_owned(),
195         ir::LibCall::Memset => "memset".to_owned(),
196         ir::LibCall::Memmove => "memmove".to_owned(),
197 
198         ir::LibCall::ElfTlsGetAddr => "__tls_get_addr".to_owned(),
199     })
200 }
201