@@ -28,14 +28,76 @@ let m = new WebAssembly.Module(buffer);
28
28
29
29
let memory = null ;
30
30
31
+ function viewstruct ( data , fields ) {
32
+ return new Uint32Array ( memory . buffer ) . subarray ( data / 4 , data / 4 + fields ) ;
33
+ }
34
+
31
35
function copystr ( a , b ) {
32
- if ( memory === null ) {
33
- return null
34
- }
35
- let view = new Uint8Array ( memory . buffer ) . slice ( a , a + b ) ;
36
+ let view = new Uint8Array ( memory . buffer ) . subarray ( a , a + b ) ;
36
37
return String . fromCharCode . apply ( null , view ) ;
37
38
}
38
39
40
+ function syscall_write ( [ fd , ptr , len ] ) {
41
+ let s = copystr ( ptr , len ) ;
42
+ switch ( fd ) {
43
+ case 1 : process . stdout . write ( s ) ; break ;
44
+ case 2 : process . stderr . write ( s ) ; break ;
45
+ }
46
+ }
47
+
48
+ function syscall_exit ( [ code ] ) {
49
+ process . exit ( code ) ;
50
+ }
51
+
52
+ function syscall_args ( params ) {
53
+ let [ ptr , len ] = params ;
54
+
55
+ // Calculate total required buffer size
56
+ let totalLen = - 1 ;
57
+ for ( let i = 2 ; i < process . argv . length ; ++ i ) {
58
+ totalLen += Buffer . byteLength ( process . argv [ i ] ) + 1 ;
59
+ }
60
+ if ( totalLen < 0 ) { totalLen = 0 ; }
61
+ params [ 2 ] = totalLen ;
62
+
63
+ // If buffer is large enough, copy data
64
+ if ( len >= totalLen ) {
65
+ let view = new Uint8Array ( memory . buffer ) ;
66
+ for ( let i = 2 ; i < process . argv . length ; ++ i ) {
67
+ let value = process . argv [ i ] ;
68
+ Buffer . from ( value ) . copy ( view , ptr ) ;
69
+ ptr += Buffer . byteLength ( process . argv [ i ] ) + 1 ;
70
+ }
71
+ }
72
+ }
73
+
74
+ function syscall_getenv ( params ) {
75
+ let [ keyPtr , keyLen , valuePtr , valueLen ] = params ;
76
+
77
+ let key = copystr ( keyPtr , keyLen ) ;
78
+ let value = process . env [ key ] ;
79
+
80
+ if ( value == null ) {
81
+ params [ 4 ] = 0xFFFFFFFF ;
82
+ } else {
83
+ let view = new Uint8Array ( memory . buffer ) ;
84
+ let totalLen = Buffer . byteLength ( value ) ;
85
+ params [ 4 ] = totalLen ;
86
+ if ( valueLen >= totalLen ) {
87
+ Buffer . from ( value ) . copy ( view , valuePtr ) ;
88
+ }
89
+ }
90
+ }
91
+
92
+ function syscall_time ( params ) {
93
+ let t = Date . now ( ) ;
94
+ let secs = Math . floor ( t / 1000 ) ;
95
+ let millis = t % 1000 ;
96
+ params [ 1 ] = Math . floor ( secs / 0x100000000 ) ;
97
+ params [ 2 ] = secs % 0x100000000 ;
98
+ params [ 3 ] = Math . floor ( millis * 1000000 ) ;
99
+ }
100
+
39
101
let imports = { } ;
40
102
imports . env = {
41
103
// These are generated by LLVM itself for various intrinsic calls. Hopefully
@@ -48,68 +110,25 @@ imports.env = {
48
110
log10 : Math . log10 ,
49
111
log10f : Math . log10 ,
50
112
51
- // These are called in src/libstd/sys/wasm/stdio.rs and are used when
52
- // debugging is enabled.
53
- rust_wasm_write_stdout : function ( a , b ) {
54
- let s = copystr ( a , b ) ;
55
- if ( s !== null ) {
56
- process . stdout . write ( s ) ;
57
- }
58
- } ,
59
- rust_wasm_write_stderr : function ( a , b ) {
60
- let s = copystr ( a , b ) ;
61
- if ( s !== null ) {
62
- process . stderr . write ( s ) ;
63
- }
64
- } ,
65
-
66
- // These are called in src/libstd/sys/wasm/args.rs and are used when
67
- // debugging is enabled.
68
- rust_wasm_args_count : function ( ) {
69
- if ( memory === null )
70
- return 0 ;
71
- return process . argv . length - 2 ;
72
- } ,
73
- rust_wasm_args_arg_size : function ( i ) {
74
- return Buffer . byteLength ( process . argv [ i + 2 ] ) ;
75
- } ,
76
- rust_wasm_args_arg_fill : function ( idx , ptr ) {
77
- let arg = process . argv [ idx + 2 ] ;
78
- let view = new Uint8Array ( memory . buffer ) ;
79
- Buffer . from ( arg ) . copy ( view , ptr ) ;
80
- } ,
81
-
82
- // These are called in src/libstd/sys/wasm/os.rs and are used when
83
- // debugging is enabled.
84
- rust_wasm_getenv_len : function ( a , b ) {
85
- let key = copystr ( a , b ) ;
86
- if ( key === null ) {
87
- return - 1 ;
113
+ rust_wasm_syscall : function ( index , data ) {
114
+ switch ( index ) {
115
+ case 1 : syscall_write ( viewstruct ( data , 3 ) ) ; return true ;
116
+ case 2 : syscall_exit ( viewstruct ( data , 1 ) ) ; return true ;
117
+ case 3 : syscall_args ( viewstruct ( data , 3 ) ) ; return true ;
118
+ case 4 : syscall_getenv ( viewstruct ( data , 5 ) ) ; return true ;
119
+ case 6 : syscall_time ( viewstruct ( data , 4 ) ) ; return true ;
120
+ default :
121
+ console . log ( "Unsupported syscall: " + index ) ;
122
+ return false ;
88
123
}
89
- if ( ! ( key in process . env ) ) {
90
- return - 1 ;
91
- }
92
- return Buffer . byteLength ( process . env [ key ] ) ;
93
- } ,
94
- rust_wasm_getenv_data : function ( a , b , ptr ) {
95
- let key = copystr ( a , b ) ;
96
- let value = process . env [ key ] ;
97
- let view = new Uint8Array ( memory . buffer ) ;
98
- Buffer . from ( value ) . copy ( view , ptr ) ;
99
- } ,
100
- } ;
101
-
102
- let module_imports = WebAssembly . Module . imports ( m ) ;
103
-
104
- for ( var i = 0 ; i < module_imports . length ; i ++ ) {
105
- let imp = module_imports [ i ] ;
106
- if ( imp . module != 'env' ) {
107
- continue
108
124
}
109
- if ( imp . name == 'memory' && imp . kind == 'memory' ) {
110
- memory = new WebAssembly . Memory ( { initial : 20 } ) ;
111
- imports . env . memory = memory ;
112
- }
113
- }
125
+ } ;
114
126
115
127
let instance = new WebAssembly . Instance ( m , imports ) ;
128
+ memory = instance . exports . memory ;
129
+ try {
130
+ instance . exports . main ( ) ;
131
+ } catch ( e ) {
132
+ console . error ( e ) ;
133
+ process . exit ( 101 ) ;
134
+ }
0 commit comments