@@ -28,14 +28,76 @@ let m = new WebAssembly.Module(buffer);
2828
2929let memory = null ;
3030
31+ function viewstruct ( data , fields ) {
32+ return new Uint32Array ( memory . buffer ) . subarray ( data / 4 , data / 4 + fields ) ;
33+ }
34+
3135function 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 ) ;
3637 return String . fromCharCode . apply ( null , view ) ;
3738}
3839
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+
39101let imports = { } ;
40102imports . env = {
41103 // These are generated by LLVM itself for various intrinsic calls. Hopefully
@@ -48,68 +110,25 @@ imports.env = {
48110 log10 : Math . log10 ,
49111 log10f : Math . log10 ,
50112
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 ;
88123 }
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
108124 }
109- if ( imp . name == 'memory' && imp . kind == 'memory' ) {
110- memory = new WebAssembly . Memory ( { initial : 20 } ) ;
111- imports . env . memory = memory ;
112- }
113- }
125+ } ;
114126
115127let 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