@@ -2,116 +2,11 @@ use std::fs;
2
2
use std:: path:: Path ;
3
3
use std:: str;
4
4
5
- use rustc_data_structures:: fx:: FxHashMap ;
6
5
use serialize:: leb128;
7
6
8
7
// https://webassembly.github.io/spec/core/binary/modules.html#binary-importsec
9
- const WASM_IMPORT_SECTION_ID : u8 = 2 ;
10
8
const WASM_CUSTOM_SECTION_ID : u8 = 0 ;
11
9
12
- const WASM_EXTERNAL_KIND_FUNCTION : u8 = 0 ;
13
- const WASM_EXTERNAL_KIND_TABLE : u8 = 1 ;
14
- const WASM_EXTERNAL_KIND_MEMORY : u8 = 2 ;
15
- const WASM_EXTERNAL_KIND_GLOBAL : u8 = 3 ;
16
-
17
- /// Rewrite the module imports are listed from in a wasm module given the field
18
- /// name to module name mapping in `import_map`.
19
- ///
20
- /// LLVM 6 which we're using right now doesn't have the ability to configure the
21
- /// module a wasm symbol is import from. Rather all imported symbols come from
22
- /// the bland `"env"` module unconditionally. Furthermore we'd *also* need
23
- /// support in LLD for preserving these import modules, which it unfortunately
24
- /// currently does not.
25
- ///
26
- /// This function is intended as a hack for now where we manually rewrite the
27
- /// wasm output by LLVM to have the correct import modules listed. The
28
- /// `#[link(wasm_import_module = "...")]` attribute in Rust translates to the
29
- /// module that each symbol is imported from, so here we manually go through the
30
- /// wasm file, decode it, rewrite imports, and then rewrite the wasm module.
31
- ///
32
- /// Support for this was added to LLVM in
33
- /// https://github.com/llvm-mirror/llvm/commit/0f32e1365, although support still
34
- /// needs to be added, tracked at https://bugs.llvm.org/show_bug.cgi?id=37168
35
- pub fn rewrite_imports ( path : & Path , import_map : & FxHashMap < String , String > ) {
36
- if import_map. is_empty ( ) {
37
- return
38
- }
39
-
40
- let wasm = fs:: read ( path) . expect ( "failed to read wasm output" ) ;
41
- let mut ret = WasmEncoder :: new ( ) ;
42
- ret. data . extend ( & wasm[ ..8 ] ) ;
43
-
44
- // skip the 8 byte wasm/version header
45
- for ( id, raw) in WasmSections ( WasmDecoder :: new ( & wasm[ 8 ..] ) ) {
46
- ret. byte ( id) ;
47
- if id == WASM_IMPORT_SECTION_ID {
48
- info ! ( "rewriting import section" ) ;
49
- let data = rewrite_import_section (
50
- & mut WasmDecoder :: new ( raw) ,
51
- import_map,
52
- ) ;
53
- ret. bytes ( & data) ;
54
- } else {
55
- info ! ( "carry forward section {}, {} bytes long" , id, raw. len( ) ) ;
56
- ret. bytes ( raw) ;
57
- }
58
- }
59
-
60
- fs:: write ( path, & ret. data ) . expect ( "failed to write wasm output" ) ;
61
-
62
- fn rewrite_import_section (
63
- wasm : & mut WasmDecoder < ' _ > ,
64
- import_map : & FxHashMap < String , String > ,
65
- )
66
- -> Vec < u8 >
67
- {
68
- let mut dst = WasmEncoder :: new ( ) ;
69
- let n = wasm. u32 ( ) ;
70
- dst. u32 ( n) ;
71
- info ! ( "rewriting {} imports" , n) ;
72
- for _ in 0 ..n {
73
- rewrite_import_entry ( wasm, & mut dst, import_map) ;
74
- }
75
- return dst. data
76
- }
77
-
78
- fn rewrite_import_entry ( wasm : & mut WasmDecoder < ' _ > ,
79
- dst : & mut WasmEncoder ,
80
- import_map : & FxHashMap < String , String > ) {
81
- // More info about the binary format here is available at:
82
- // https://webassembly.github.io/spec/core/binary/modules.html#import-section
83
- //
84
- // Note that you can also find the whole point of existence of this
85
- // function here, where we map the `module` name to a different one if
86
- // we've got one listed.
87
- let module = wasm. str ( ) ;
88
- let field = wasm. str ( ) ;
89
- let new_module = if module == "env" {
90
- import_map. get ( field) . map ( |s| & * * s) . unwrap_or ( module)
91
- } else {
92
- module
93
- } ;
94
- info ! ( "import rewrite ({} => {}) / {}" , module, new_module, field) ;
95
- dst. str ( new_module) ;
96
- dst. str ( field) ;
97
- let kind = wasm. byte ( ) ;
98
- dst. byte ( kind) ;
99
- match kind {
100
- WASM_EXTERNAL_KIND_FUNCTION => dst. u32 ( wasm. u32 ( ) ) ,
101
- WASM_EXTERNAL_KIND_TABLE => {
102
- dst. byte ( wasm. byte ( ) ) ; // element_type
103
- dst. limits ( wasm. limits ( ) ) ;
104
- }
105
- WASM_EXTERNAL_KIND_MEMORY => dst. limits ( wasm. limits ( ) ) ,
106
- WASM_EXTERNAL_KIND_GLOBAL => {
107
- dst. byte ( wasm. byte ( ) ) ; // content_type
108
- dst. bool ( wasm. bool ( ) ) ; // mutable
109
- }
110
- b => panic ! ( "unknown kind: {}" , b) ,
111
- }
112
- }
113
- }
114
-
115
10
/// Adds or augment the existing `producers` section to encode information about
116
11
/// the Rust compiler used to produce the wasm file.
117
12
pub fn add_producer_section (
@@ -266,15 +161,6 @@ impl<'a> WasmDecoder<'a> {
266
161
let len = self . u32 ( ) ;
267
162
str:: from_utf8 ( self . skip ( len as usize ) ) . unwrap ( )
268
163
}
269
-
270
- fn bool ( & mut self ) -> bool {
271
- self . byte ( ) == 1
272
- }
273
-
274
- fn limits ( & mut self ) -> ( u32 , Option < u32 > ) {
275
- let has_max = self . bool ( ) ;
276
- ( self . u32 ( ) , if has_max { Some ( self . u32 ( ) ) } else { None } )
277
- }
278
164
}
279
165
280
166
struct WasmEncoder {
@@ -302,16 +188,4 @@ impl WasmEncoder {
302
188
fn str ( & mut self , val : & str ) {
303
189
self . bytes ( val. as_bytes ( ) )
304
190
}
305
-
306
- fn bool ( & mut self , b : bool ) {
307
- self . byte ( b as u8 ) ;
308
- }
309
-
310
- fn limits ( & mut self , limits : ( u32 , Option < u32 > ) ) {
311
- self . bool ( limits. 1 . is_some ( ) ) ;
312
- self . u32 ( limits. 0 ) ;
313
- if let Some ( c) = limits. 1 {
314
- self . u32 ( c) ;
315
- }
316
- }
317
191
}
0 commit comments