@@ -18,7 +18,7 @@ use std::borrow::Cow;
1818use std:: env;
1919
2020use rustc:: ty:: { self , TyCtxt , query:: TyCtxtAt } ;
21- use rustc:: ty:: layout:: { TyLayout , LayoutOf , Size } ;
21+ use rustc:: ty:: layout:: { TyLayout , LayoutOf , Size , Align } ;
2222use rustc:: hir:: { self , def_id:: DefId } ;
2323use rustc:: mir;
2424
@@ -123,24 +123,56 @@ pub fn create_ecx<'a, 'mir: 'a, 'tcx: 'mir>(
123123 let dest = ecx. eval_place ( & mir:: Place :: Local ( args. next ( ) . unwrap ( ) ) ) ?;
124124 let argc = Scalar :: from_int ( 1 , dest. layout . size ) ;
125125 ecx. write_scalar ( argc, dest) ?;
126- let argc_place = ecx. allocate ( dest. layout , MiriMemoryKind :: Env . into ( ) ) ?;
127- ecx. write_scalar ( argc, argc_place. into ( ) ) ?;
128- ecx. machine . argc = Some ( argc_place. ptr . to_ptr ( ) ?) ;
126+ // Store argc for macOS _NSGetArgc
127+ {
128+ let argc_place = ecx. allocate ( dest. layout , MiriMemoryKind :: Env . into ( ) ) ?;
129+ ecx. write_scalar ( argc, argc_place. into ( ) ) ?;
130+ ecx. machine . argc = Some ( argc_place. ptr . to_ptr ( ) ?) ;
131+ }
129132
130133 // FIXME: extract main source file path
131134 // Third argument (argv): &[b"foo"]
135+ const CMD : & str = "running-in-miri" ;
132136 let dest = ecx. eval_place ( & mir:: Place :: Local ( args. next ( ) . unwrap ( ) ) ) ?;
133- let foo = ecx. memory_mut ( ) . allocate_static_bytes ( b"foo\0 " ) . with_default_tag ( ) ;
134- let foo_ty = ecx. tcx . mk_imm_ptr ( ecx. tcx . types . u8 ) ;
135- let foo_layout = ecx. layout_of ( foo_ty) ?;
136- let foo_place = ecx. allocate ( foo_layout, MiriMemoryKind :: Env . into ( ) ) ?;
137- ecx. write_scalar ( Scalar :: Ptr ( foo) , foo_place. into ( ) ) ?;
138- ecx. memory_mut ( ) . mark_immutable ( foo_place. to_ptr ( ) ?. alloc_id ) ?;
139- let argv = foo_place. ptr ;
140- ecx. write_scalar ( argv, dest) ?;
141- let argv_place = ecx. allocate ( dest. layout , MiriMemoryKind :: Env . into ( ) ) ?;
142- ecx. write_scalar ( argv, argv_place. into ( ) ) ?;
143- ecx. machine . argv = Some ( argv_place. ptr . to_ptr ( ) ?) ;
137+ let cmd = ecx. memory_mut ( ) . allocate_static_bytes ( CMD . as_bytes ( ) ) . with_default_tag ( ) ;
138+ let raw_str_layout = ecx. layout_of ( ecx. tcx . mk_imm_ptr ( ecx. tcx . types . u8 ) ) ?;
139+ let cmd_place = ecx. allocate ( raw_str_layout, MiriMemoryKind :: Env . into ( ) ) ?;
140+ ecx. write_scalar ( Scalar :: Ptr ( cmd) , cmd_place. into ( ) ) ?;
141+ ecx. memory_mut ( ) . mark_immutable ( cmd_place. to_ptr ( ) ?. alloc_id ) ?;
142+ // Store argv for macOS _NSGetArgv
143+ {
144+ let argv = cmd_place. ptr ;
145+ ecx. write_scalar ( argv, dest) ?;
146+ let argv_place = ecx. allocate ( dest. layout , MiriMemoryKind :: Env . into ( ) ) ?;
147+ ecx. write_scalar ( argv, argv_place. into ( ) ) ?;
148+ ecx. machine . argv = Some ( argv_place. ptr . to_ptr ( ) ?) ;
149+ }
150+ // Store cmdline as UTF-16 for Windows GetCommandLineW
151+ {
152+ let tcx = & { ecx. tcx . tcx } ;
153+ let cmd_utf16: Vec < u16 > = CMD . encode_utf16 ( )
154+ . chain ( Some ( 0 ) ) // add 0-terminator
155+ . collect ( ) ;
156+ let cmd_ptr = ecx. memory_mut ( ) . allocate (
157+ Size :: from_bytes ( cmd_utf16. len ( ) as u64 * 2 ) ,
158+ Align :: from_bytes ( 2 ) . unwrap ( ) ,
159+ MiriMemoryKind :: Env . into ( ) ,
160+ ) ?. with_default_tag ( ) ;
161+ ecx. machine . cmd_line = Some ( cmd_ptr) ;
162+ // store the UTF-16 string
163+ let char_size = Size :: from_bytes ( 2 ) ;
164+ let cmd_alloc = ecx. memory_mut ( ) . get_mut ( cmd_ptr. alloc_id ) ?;
165+ let mut cur_ptr = cmd_ptr;
166+ for & c in cmd_utf16. iter ( ) {
167+ cmd_alloc. write_scalar (
168+ tcx,
169+ cur_ptr,
170+ Scalar :: from_uint ( c, char_size) . into ( ) ,
171+ char_size,
172+ ) ?;
173+ cur_ptr = cur_ptr. offset ( char_size, tcx) ?;
174+ }
175+ }
144176
145177 assert ! ( args. next( ) . is_none( ) , "start lang item has more arguments than expected" ) ;
146178
@@ -263,8 +295,13 @@ pub struct Evaluator<'tcx> {
263295
264296 /// Program arguments (`Option` because we can only initialize them after creating the ecx).
265297 /// These are *pointers* to argc/argv because macOS.
298+ /// We also need the full cmdline as one string because Window.
266299 pub ( crate ) argc : Option < Pointer < Borrow > > ,
267300 pub ( crate ) argv : Option < Pointer < Borrow > > ,
301+ pub ( crate ) cmd_line : Option < Pointer < Borrow > > ,
302+
303+ /// Last OS error
304+ pub ( crate ) last_error : u32 ,
268305
269306 /// TLS state
270307 pub ( crate ) tls : TlsData < ' tcx > ,
@@ -282,6 +319,8 @@ impl<'tcx> Evaluator<'tcx> {
282319 env_vars : HashMap :: default ( ) ,
283320 argc : None ,
284321 argv : None ,
322+ cmd_line : None ,
323+ last_error : 0 ,
285324 tls : TlsData :: default ( ) ,
286325 validate,
287326 stacked_borrows : stacked_borrows:: State :: default ( ) ,
0 commit comments