@@ -5,32 +5,35 @@ use crate::config::Cranelift;
5
5
#[ cfg( feature = "unwind" ) ]
6
6
use crate :: dwarf:: WriterRelocate ;
7
7
use crate :: func_environ:: { get_function_name, FuncEnvironment } ;
8
- use crate :: sink:: { RelocSink , TrapSink } ;
9
8
use crate :: trampoline:: {
10
9
make_trampoline_dynamic_function, make_trampoline_function_call, FunctionBuilderContext ,
11
10
} ;
12
11
use crate :: translator:: {
13
- compiled_function_unwind_info, signature_to_cranelift_ir , transform_jump_table ,
14
- CraneliftUnwindInfo , FuncTranslator ,
12
+ compiled_function_unwind_info, irlibcall_to_libcall , irreloc_to_relocationkind ,
13
+ signature_to_cranelift_ir , CraneliftUnwindInfo , FuncTranslator ,
15
14
} ;
16
- use cranelift_codegen:: ir;
15
+ use cranelift_codegen:: ir:: ExternalName ;
17
16
use cranelift_codegen:: print_errors:: pretty_error;
18
- use cranelift_codegen:: { binemit, Context } ;
17
+ use cranelift_codegen:: { ir, MachReloc } ;
18
+ use cranelift_codegen:: { Context , MachTrap } ;
19
19
#[ cfg( feature = "unwind" ) ]
20
20
use gimli:: write:: { Address , EhFrame , FrameTable } ;
21
21
use loupe:: MemoryUsage ;
22
22
use rayon:: prelude:: { IntoParallelRefIterator , ParallelIterator } ;
23
23
use std:: sync:: Arc ;
24
- use wasmer_compiler:: CompileError ;
25
- use wasmer_compiler:: { CallingConvention , ModuleTranslationState , Target } ;
24
+ use wasmer_compiler:: {
25
+ CallingConvention , ModuleTranslationState , RelocationTarget , Target , TrapInformation ,
26
+ } ;
26
27
use wasmer_compiler:: {
27
28
Compilation , CompileModuleInfo , CompiledFunction , CompiledFunctionFrameInfo ,
28
29
CompiledFunctionUnwindInfo , Compiler , Dwarf , FunctionBinaryReader , FunctionBody ,
29
30
FunctionBodyData , MiddlewareBinaryReader , ModuleMiddleware , ModuleMiddlewareChain ,
30
31
SectionIndex ,
31
32
} ;
33
+ use wasmer_compiler:: { CompileError , Relocation } ;
32
34
use wasmer_types:: entity:: { EntityRef , PrimaryMap } ;
33
- use wasmer_types:: { FunctionIndex , LocalFunctionIndex , SignatureIndex } ;
35
+ use wasmer_types:: { FunctionIndex , LocalFunctionIndex , ModuleInfo , SignatureIndex } ;
36
+ use wasmer_vm:: TrapCode ;
34
37
35
38
/// A compiler that compiles a WebAssembly module with Cranelift, translating the Wasm to Cranelift IR,
36
39
/// optimizing it and then translating to assembly.
@@ -66,7 +69,10 @@ impl Compiler for CraneliftCompiler {
66
69
module_translation_state : & ModuleTranslationState ,
67
70
function_body_inputs : PrimaryMap < LocalFunctionIndex , FunctionBodyData < ' _ > > ,
68
71
) -> Result < Compilation , CompileError > {
69
- let isa = self . config ( ) . isa ( target) ;
72
+ let isa = self
73
+ . config ( )
74
+ . isa ( target)
75
+ . map_err ( |error| CompileError :: Codegen ( error. to_string ( ) ) ) ?;
70
76
let frontend_config = isa. frontend_config ( ) ;
71
77
let memory_styles = & compile_info. memory_styles ;
72
78
let table_styles = & compile_info. table_styles ;
@@ -139,20 +145,24 @@ impl Compiler for CraneliftCompiler {
139
145
) ?;
140
146
141
147
let mut code_buf: Vec < u8 > = Vec :: new ( ) ;
142
- let mut reloc_sink = RelocSink :: new ( & module, func_index) ;
143
- let mut trap_sink = TrapSink :: new ( ) ;
144
- let mut stackmap_sink = binemit:: NullStackMapSink { } ;
145
148
context
146
- . compile_and_emit (
147
- & * isa,
148
- & mut code_buf,
149
- & mut reloc_sink,
150
- & mut trap_sink,
151
- & mut stackmap_sink,
152
- )
153
- . map_err ( |error| {
154
- CompileError :: Codegen ( pretty_error ( & context. func , Some ( & * isa) , error) )
155
- } ) ?;
149
+ . compile_and_emit ( & * isa, & mut code_buf)
150
+ . map_err ( |error| CompileError :: Codegen ( pretty_error ( & context. func , error) ) ) ?;
151
+
152
+ let result = context. mach_compile_result . as_ref ( ) . unwrap ( ) ;
153
+ let func_relocs = result
154
+ . buffer
155
+ . relocs ( )
156
+ . into_iter ( )
157
+ . map ( |r| mach_reloc_to_reloc ( module, r) )
158
+ . collect :: < Vec < _ > > ( ) ;
159
+
160
+ let traps = result
161
+ . buffer
162
+ . traps ( )
163
+ . into_iter ( )
164
+ . map ( mach_trap_to_trap)
165
+ . collect :: < Vec < _ > > ( ) ;
156
166
157
167
let ( unwind_info, fde) = match compiled_function_unwind_info ( & * isa, & context) ? {
158
168
#[ cfg( feature = "unwind" ) ]
@@ -182,23 +192,16 @@ impl Compiler for CraneliftCompiler {
182
192
} ;
183
193
184
194
let range = reader. range ( ) ;
185
- let address_map = get_function_address_map ( & context, range, code_buf. len ( ) , & * isa) ;
186
-
187
- // We transform the Cranelift JumpTable's into compiler JumpTables
188
- let func_jt_offsets = transform_jump_table ( context. func . jt_offsets ) ;
195
+ let address_map = get_function_address_map ( & context, range, code_buf. len ( ) ) ;
189
196
190
197
Ok ( (
191
198
CompiledFunction {
192
199
body : FunctionBody {
193
200
body : code_buf,
194
201
unwind_info,
195
202
} ,
196
- jt_offsets : func_jt_offsets,
197
- relocations : reloc_sink. func_relocs ,
198
- frame_info : CompiledFunctionFrameInfo {
199
- address_map,
200
- traps : trap_sink. traps ,
201
- } ,
203
+ relocations : func_relocs,
204
+ frame_info : CompiledFunctionFrameInfo { address_map, traps } ,
202
205
} ,
203
206
fde,
204
207
) )
@@ -262,3 +265,63 @@ impl Compiler for CraneliftCompiler {
262
265
) )
263
266
}
264
267
}
268
+
269
+ fn mach_reloc_to_reloc ( module : & ModuleInfo , reloc : & MachReloc ) -> Relocation {
270
+ let & MachReloc {
271
+ offset,
272
+ srcloc : _,
273
+ kind,
274
+ ref name,
275
+ addend,
276
+ } = reloc;
277
+ let reloc_target = if let ExternalName :: User { namespace, index } = * name {
278
+ debug_assert_eq ! ( namespace, 0 ) ;
279
+ RelocationTarget :: LocalFunc (
280
+ module
281
+ . local_func_index ( FunctionIndex :: from_u32 ( index) )
282
+ . expect ( "The provided function should be local" ) ,
283
+ )
284
+ } else if let ExternalName :: LibCall ( libcall) = * name {
285
+ RelocationTarget :: LibCall ( irlibcall_to_libcall ( libcall) )
286
+ } else {
287
+ panic ! ( "unrecognized external name" )
288
+ } ;
289
+ Relocation {
290
+ kind : irreloc_to_relocationkind ( kind) ,
291
+ reloc_target,
292
+ offset,
293
+ addend,
294
+ }
295
+ }
296
+
297
+ fn mach_trap_to_trap ( trap : & MachTrap ) -> TrapInformation {
298
+ let & MachTrap {
299
+ offset,
300
+ srcloc : _,
301
+ code,
302
+ } = trap;
303
+ TrapInformation {
304
+ code_offset : offset,
305
+ trap_code : translate_ir_trapcode ( code) ,
306
+ }
307
+ }
308
+
309
+ /// Translates the Cranelift IR TrapCode into generic Trap Code
310
+ fn translate_ir_trapcode ( trap : ir:: TrapCode ) -> TrapCode {
311
+ match trap {
312
+ ir:: TrapCode :: StackOverflow => TrapCode :: StackOverflow ,
313
+ ir:: TrapCode :: HeapOutOfBounds => TrapCode :: HeapAccessOutOfBounds ,
314
+ ir:: TrapCode :: HeapMisaligned => TrapCode :: HeapMisaligned ,
315
+ ir:: TrapCode :: TableOutOfBounds => TrapCode :: TableAccessOutOfBounds ,
316
+ ir:: TrapCode :: IndirectCallToNull => TrapCode :: IndirectCallToNull ,
317
+ ir:: TrapCode :: BadSignature => TrapCode :: BadSignature ,
318
+ ir:: TrapCode :: IntegerOverflow => TrapCode :: IntegerOverflow ,
319
+ ir:: TrapCode :: IntegerDivisionByZero => TrapCode :: IntegerDivisionByZero ,
320
+ ir:: TrapCode :: BadConversionToInteger => TrapCode :: BadConversionToInteger ,
321
+ ir:: TrapCode :: UnreachableCodeReached => TrapCode :: UnreachableCodeReached ,
322
+ ir:: TrapCode :: Interrupt => unimplemented ! ( "Interrupts not supported" ) ,
323
+ ir:: TrapCode :: User ( _user_code) => unimplemented ! ( "User trap code not supported" ) ,
324
+ // ir::TrapCode::Interrupt => TrapCode::Interrupt,
325
+ // ir::TrapCode::User(user_code) => TrapCode::User(user_code),
326
+ }
327
+ }
0 commit comments