@@ -2,7 +2,7 @@ use rustc::ty::{self, Ty, TypeFoldable, UpvarSubsts, Instance};
22use rustc:: ty:: layout:: { TyLayout , HasTyCtxt , FnTypeExt } ;
33use rustc:: mir:: { self , Body } ;
44use rustc:: session:: config:: DebugInfo ;
5- use rustc_target:: abi:: call:: { FnType , PassMode , IgnoreMode } ;
5+ use rustc_target:: abi:: call:: { FnType , PassMode } ;
66use rustc_target:: abi:: { Variants , VariantIdx } ;
77use crate :: base;
88use crate :: debuginfo:: { self , VariableAccess , VariableKind , FunctionDebugContext } ;
@@ -441,15 +441,6 @@ fn arg_local_refs<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>(
441441 None
442442 } ;
443443
444- // Store the index of the last argument. This is used to
445- // call va_start on the va_list instead of attempting
446- // to store_fn_arg.
447- let last_arg_idx = if fx. fn_ty . args . is_empty ( ) {
448- None
449- } else {
450- Some ( fx. fn_ty . args . len ( ) - 1 )
451- } ;
452-
453444 mir. args_iter ( ) . enumerate ( ) . map ( |( arg_index, local) | {
454445 let arg_decl = & mir. local_decls [ local] ;
455446
@@ -503,6 +494,33 @@ fn arg_local_refs<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>(
503494 return LocalRef :: Place ( place) ;
504495 }
505496
497+ if fx. fn_ty . c_variadic && arg_index == fx. fn_ty . args . len ( ) {
498+ let arg_ty = fx. monomorphize ( & arg_decl. ty ) ;
499+
500+ let va_list = PlaceRef :: alloca ( bx, bx. layout_of ( arg_ty) ) ;
501+ bx. set_var_name ( va_list. llval , name) ;
502+ bx. va_start ( va_list. llval ) ;
503+ // FIXME(eddyb) remove `va_list_ref`.
504+ * va_list_ref = Some ( va_list) ;
505+
506+ arg_scope. map ( |scope| {
507+ let variable_access = VariableAccess :: DirectVariable {
508+ alloca : va_list. llval
509+ } ;
510+ bx. declare_local (
511+ & fx. debug_context ,
512+ arg_decl. name . unwrap_or ( kw:: Invalid ) ,
513+ va_list. layout . ty ,
514+ scope,
515+ variable_access,
516+ VariableKind :: ArgumentVariable ( arg_index + 1 ) ,
517+ DUMMY_SP
518+ ) ;
519+ } ) ;
520+
521+ return LocalRef :: Place ( va_list) ;
522+ }
523+
506524 let arg = & fx. fn_ty . args [ idx] ;
507525 idx += 1 ;
508526 if arg. pad . is_some ( ) {
@@ -515,10 +533,9 @@ fn arg_local_refs<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>(
515533 // of putting everything in allocas just so we can use llvm.dbg.declare.
516534 let local = |op| LocalRef :: Operand ( Some ( op) ) ;
517535 match arg. mode {
518- PassMode :: Ignore ( IgnoreMode :: Zst ) => {
536+ PassMode :: Ignore => {
519537 return local ( OperandRef :: new_zst ( bx, arg. layout ) ) ;
520538 }
521- PassMode :: Ignore ( IgnoreMode :: CVarArgs ) => { }
522539 PassMode :: Direct ( _) => {
523540 let llarg = bx. get_param ( llarg_idx) ;
524541 bx. set_var_name ( llarg, & name) ;
@@ -568,22 +585,7 @@ fn arg_local_refs<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>(
568585 } else {
569586 let tmp = PlaceRef :: alloca ( bx, arg. layout ) ;
570587 bx. set_var_name ( tmp. llval , name) ;
571- if fx. fn_ty . c_variadic && last_arg_idx. map ( |idx| arg_index == idx) . unwrap_or ( false ) {
572- let va_list_did = match tcx. lang_items ( ) . va_list ( ) {
573- Some ( did) => did,
574- None => bug ! ( "`va_list` lang item required for C-variadic functions" ) ,
575- } ;
576- match arg_decl. ty . kind {
577- ty:: Adt ( def, _) if def. did == va_list_did => {
578- // Call `va_start` on the spoofed `VaListImpl`.
579- bx. va_start ( tmp. llval ) ;
580- * va_list_ref = Some ( tmp) ;
581- } ,
582- _ => bug ! ( "last argument of variadic function is not a `va_list`" )
583- }
584- } else {
585- bx. store_fn_arg ( arg, & mut llarg_idx, tmp) ;
586- }
588+ bx. store_fn_arg ( arg, & mut llarg_idx, tmp) ;
587589 tmp
588590 } ;
589591 let upvar_debuginfo = & mir. __upvar_debuginfo_codegen_only_do_not_use ;
0 commit comments