@@ -4,7 +4,7 @@ use rustc::ty::layout::LayoutOf;
44use syntax:: codemap:: Span ;
55use rustc_target:: spec:: abi:: Abi ;
66
7- use rustc:: mir:: interpret:: { EvalResult , Scalar , Value } ;
7+ use rustc:: mir:: interpret:: { EvalResult , Value } ;
88use super :: { EvalContext , Place , Machine , ValTy } ;
99
1010use rustc_data_structures:: indexed_vec:: Idx ;
@@ -338,65 +338,39 @@ impl<'a, 'mir, 'tcx, M: Machine<'mir, 'tcx>> EvalContext<'a, 'mir, 'tcx, M> {
338338
339339 // unpack and write all other args
340340 let layout = self . layout_of ( args[ 1 ] . ty ) ?;
341- if let ty:: TyTuple ( ..) = args[ 1 ] . ty . sty {
341+ if let ty:: TyTuple ( _) = args[ 1 ] . ty . sty {
342+ if layout. is_zst ( ) {
343+ // Nothing to do, no need to unpack zsts
344+ return Ok ( ( ) ) ;
345+ }
342346 if self . frame ( ) . mir . args_iter ( ) . count ( ) == layout. fields . count ( ) + 1 {
343- match args[ 1 ] . value {
344- Value :: ByRef ( ptr, align) => {
345- for ( i, arg_local) in arg_locals. enumerate ( ) {
346- let field = layout. field ( & self , i) ?;
347- let offset = layout. fields . offset ( i) ;
348- let arg = Value :: ByRef ( ptr. ptr_offset ( offset, & self ) ?,
349- align. min ( field. align ) ) ;
350- let dest =
351- self . eval_place ( & mir:: Place :: Local ( arg_local) ) ?;
352- trace ! (
353- "writing arg {:?} to {:?} (type: {})" ,
354- arg,
355- dest,
356- field. ty
357- ) ;
358- let valty = ValTy {
359- value : arg,
360- ty : field. ty ,
361- } ;
362- self . write_value ( valty, dest) ?;
363- }
364- }
365- Value :: Scalar ( Scalar :: Bits { defined : 0 , .. } ) => { }
366- other => {
367- trace ! ( "{:#?}, {:#?}" , other, layout) ;
368- let mut layout = layout;
369- ' outer: loop {
370- for i in 0 ..layout. fields . count ( ) {
371- let field = layout. field ( & self , i) ?;
372- if layout. fields . offset ( i) . bytes ( ) == 0 && layout. size == field. size {
373- layout = field;
374- continue ' outer;
375- }
376- }
377- break ;
378- }
379- {
380- let mut write_next = |value| {
381- let dest = self . eval_place ( & mir:: Place :: Local (
382- arg_locals. next ( ) . unwrap ( ) ,
383- ) ) ?;
384- let valty = ValTy {
385- value : Value :: Scalar ( value) ,
386- ty : layout. ty ,
387- } ;
388- self . write_value ( valty, dest)
389- } ;
390- match other {
391- Value :: Scalar ( value) | Value :: ScalarPair ( value, _) => write_next ( value) ?,
392- _ => unreachable ! ( ) ,
393- }
394- if let Value :: ScalarPair ( _, value) = other {
395- write_next ( value) ?;
396- }
397- }
398- assert ! ( arg_locals. next( ) . is_none( ) ) ;
347+ for ( i, arg_local) in arg_locals. enumerate ( ) {
348+ let field = layout. field ( & self , i) ?;
349+ if field. is_zst ( ) {
350+ continue ;
399351 }
352+ let offset = layout. fields . offset ( i) ;
353+ let value = match args[ 1 ] . value {
354+ Value :: ByRef ( ptr, align) => Value :: ByRef (
355+ ptr. ptr_offset ( offset, & self ) ?,
356+ align. min ( field. align ) ,
357+ ) ,
358+ other if field. size == layout. size => {
359+ // this is the case where the field covers the entire type
360+ assert_eq ! ( offset. bytes( ) , 0 ) ;
361+ other
362+ } ,
363+ Value :: ScalarPair ( a, _) if offset. bytes ( ) == 0 => Value :: Scalar ( a) ,
364+ Value :: ScalarPair ( _, b) => Value :: Scalar ( b) ,
365+ Value :: Scalar ( _) => bug ! ( "Scalar does not cover entire type" ) ,
366+ } ;
367+ let dest =
368+ self . eval_place ( & mir:: Place :: Local ( arg_local) ) ?;
369+ let valty = ValTy {
370+ value,
371+ ty : field. ty ,
372+ } ;
373+ self . write_value ( valty, dest) ?;
400374 }
401375 } else {
402376 trace ! ( "manual impl of rust-call ABI" ) ;
0 commit comments