@@ -250,7 +250,16 @@ impl FnType {
250250 extra_args
251251 } ;
252252
253- let arg_of = |ty : Ty < ' tcx > | {
253+ let target = & ccx. sess ( ) . target . target ;
254+ let win_x64_gnu = target. target_os == "windows"
255+ && target. arch == "x86_64"
256+ && target. target_env == "gnu" ;
257+ let rust_abi = match abi {
258+ RustIntrinsic | PlatformIntrinsic | Rust | RustCall => true ,
259+ _ => false
260+ } ;
261+
262+ let arg_of = |ty : Ty < ' tcx > , is_return : bool | {
254263 if ty. is_bool ( ) {
255264 let llty = Type :: i1 ( ccx) ;
256265 let mut arg = ArgType :: new ( llty, llty) ;
@@ -260,7 +269,11 @@ impl FnType {
260269 let mut arg = ArgType :: new ( type_of:: type_of ( ccx, ty) ,
261270 type_of:: sizing_type_of ( ccx, ty) ) ;
262271 if llsize_of_real ( ccx, arg. ty ) == 0 {
263- arg. ignore ( ) ;
272+ // For some forsaken reason, x86_64-pc-windows-gnu
273+ // doesn't ignore zero-sized struct arguments.
274+ if is_return || rust_abi || !win_x64_gnu {
275+ arg. ignore ( ) ;
276+ }
264277 }
265278 arg
266279 }
@@ -270,7 +283,7 @@ impl FnType {
270283 ty:: FnConverging ( ret_ty) => ret_ty,
271284 ty:: FnDiverging => ccx. tcx ( ) . mk_nil ( )
272285 } ;
273- let mut ret = arg_of ( ret_ty) ;
286+ let mut ret = arg_of ( ret_ty, true ) ;
274287
275288 if !type_is_fat_ptr ( ccx. tcx ( ) , ret_ty) {
276289 // The `noalias` attribute on the return value is useful to a
@@ -335,7 +348,7 @@ impl FnType {
335348 } ;
336349
337350 for ty in inputs. iter ( ) . chain ( extra_args. iter ( ) ) {
338- let mut arg = arg_of ( ty) ;
351+ let mut arg = arg_of ( ty, false ) ;
339352
340353 if type_is_fat_ptr ( ccx. tcx ( ) , ty) {
341354 let original_tys = arg. original_ty . field_types ( ) ;
0 commit comments