Skip to content

Commit a88d181

Browse files
committed
rustc: rely on c_variadic == true instead of CVarArgs in HIR/Ty fn signatures.
1 parent 7683d1c commit a88d181

File tree

30 files changed

+295
-386
lines changed

30 files changed

+295
-386
lines changed

src/librustc/hir/intravisit.rs

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -633,7 +633,6 @@ pub fn walk_ty<'v, V: Visitor<'v>>(visitor: &mut V, typ: &'v Ty) {
633633
TyKind::Typeof(ref expression) => {
634634
visitor.visit_anon_const(expression)
635635
}
636-
TyKind::CVarArgs |
637636
TyKind::Infer | TyKind::Err => {}
638637
}
639638
}

src/librustc/hir/lowering.rs

Lines changed: 21 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1335,8 +1335,8 @@ impl<'a> LoweringContext<'a> {
13351335
}
13361336
}
13371337
}
1338-
TyKind::Mac(_) => bug!("`TyMac` should have been expanded by now"),
1339-
TyKind::CVarArgs => hir::TyKind::CVarArgs,
1338+
TyKind::Mac(_) => bug!("`TyKind::Mac` should have been expanded by now"),
1339+
TyKind::CVarArgs => bug!("`TyKind::CVarArgs` should have been handled elsewhere"),
13401340
};
13411341

13421342
hir::Ty {
@@ -2088,7 +2088,14 @@ impl<'a> LoweringContext<'a> {
20882088
}
20892089

20902090
fn lower_fn_params_to_names(&mut self, decl: &FnDecl) -> hir::HirVec<Ident> {
2091-
decl.inputs
2091+
// Skip the `...` (`CVarArgs`) trailing arguments from the AST,
2092+
// as they are not explicit in HIR/Ty function signatures.
2093+
// (instead, the `c_variadic` flag is set to `true`)
2094+
let mut inputs = &decl.inputs[..];
2095+
if decl.c_variadic() {
2096+
inputs = &inputs[..inputs.len() - 1];
2097+
}
2098+
inputs
20922099
.iter()
20932100
.map(|param| match param.pat.kind {
20942101
PatKind::Ident(_, ident, _) => ident,
@@ -2125,10 +2132,19 @@ impl<'a> LoweringContext<'a> {
21252132
self.anonymous_lifetime_mode
21262133
};
21272134

2135+
let c_variadic = decl.c_variadic();
2136+
21282137
// Remember how many lifetimes were already around so that we can
21292138
// only look at the lifetime parameters introduced by the arguments.
21302139
let inputs = self.with_anonymous_lifetime_mode(lt_mode, |this| {
2131-
decl.inputs
2140+
// Skip the `...` (`CVarArgs`) trailing arguments from the AST,
2141+
// as they are not explicit in HIR/Ty function signatures.
2142+
// (instead, the `c_variadic` flag is set to `true`)
2143+
let mut inputs = &decl.inputs[..];
2144+
if c_variadic {
2145+
inputs = &inputs[..inputs.len() - 1];
2146+
}
2147+
inputs
21322148
.iter()
21332149
.map(|param| {
21342150
if let Some((_, ibty)) = &mut in_band_ty_params {
@@ -2163,7 +2179,7 @@ impl<'a> LoweringContext<'a> {
21632179
P(hir::FnDecl {
21642180
inputs,
21652181
output,
2166-
c_variadic: decl.c_variadic(),
2182+
c_variadic,
21672183
implicit_self: decl.inputs.get(0).map_or(
21682184
hir::ImplicitSelfKind::None,
21692185
|arg| {

src/librustc/hir/mod.rs

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2016,9 +2016,6 @@ pub enum TyKind {
20162016
Infer,
20172017
/// Placeholder for a type that has failed to be defined.
20182018
Err,
2019-
/// Placeholder for C-variadic arguments. We "spoof" the `VaListImpl` created
2020-
/// from the variadic arguments. This type is only valid up to typeck.
2021-
CVarArgs,
20222019
}
20232020

20242021
#[derive(Copy, Clone, RustcEncodable, RustcDecodable, Debug, HashStable)]

src/librustc/hir/print.rs

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -361,9 +361,6 @@ impl<'a> State<'a> {
361361
self.s.word("/*ERROR*/");
362362
self.pclose();
363363
}
364-
hir::TyKind::CVarArgs => {
365-
self.s.word("...");
366-
}
367364
}
368365
self.end()
369366
}

src/librustc/ty/layout.rs

Lines changed: 2 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ use rustc_data_structures::stable_hasher::{HashStable, StableHasher,
2525
pub use rustc_target::abi::*;
2626
use rustc_target::spec::{HasTargetSpec, abi::Abi as SpecAbi};
2727
use rustc_target::abi::call::{
28-
ArgAttribute, ArgAttributes, ArgType, Conv, FnType, IgnoreMode, PassMode, Reg, RegKind
28+
ArgAttribute, ArgAttributes, ArgType, Conv, FnType, PassMode, Reg, RegKind
2929
};
3030

3131
pub trait IntegerExt {
@@ -2722,14 +2722,6 @@ where
27222722
}
27232723
};
27242724

2725-
// Store the index of the last argument. This is useful for working with
2726-
// C-compatible variadic arguments.
2727-
let last_arg_idx = if sig.inputs().is_empty() {
2728-
None
2729-
} else {
2730-
Some(sig.inputs().len() - 1)
2731-
};
2732-
27332725
let arg_of = |ty: Ty<'tcx>, arg_idx: Option<usize>| {
27342726
let is_return = arg_idx.is_none();
27352727
let mut arg = mk_arg_type(ty, arg_idx);
@@ -2739,30 +2731,7 @@ where
27392731
// The same is true for s390x-unknown-linux-gnu
27402732
// and sparc64-unknown-linux-gnu.
27412733
if is_return || rust_abi || (!win_x64_gnu && !linux_s390x && !linux_sparc64) {
2742-
arg.mode = PassMode::Ignore(IgnoreMode::Zst);
2743-
}
2744-
}
2745-
2746-
// If this is a C-variadic function, this is not the return value,
2747-
// and there is one or more fixed arguments; ensure that the `VaListImpl`
2748-
// is ignored as an argument.
2749-
if sig.c_variadic {
2750-
match (last_arg_idx, arg_idx) {
2751-
(Some(last_idx), Some(cur_idx)) if last_idx == cur_idx => {
2752-
let va_list_did = match cx.tcx().lang_items().va_list() {
2753-
Some(did) => did,
2754-
None => bug!("`va_list` lang item required for C-variadic functions"),
2755-
};
2756-
match ty.kind {
2757-
ty::Adt(def, _) if def.did == va_list_did => {
2758-
// This is the "spoofed" `VaListImpl`. Set the arguments mode
2759-
// so that it will be ignored.
2760-
arg.mode = PassMode::Ignore(IgnoreMode::CVarArgs);
2761-
}
2762-
_ => (),
2763-
}
2764-
}
2765-
_ => {}
2734+
arg.mode = PassMode::Ignore;
27662735
}
27672736
}
27682737

src/librustc_codegen_llvm/abi.rs

Lines changed: 5 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -264,7 +264,7 @@ impl ArgTypeExt<'ll, 'tcx> for ArgType<'tcx, Ty<'tcx>> {
264264
val
265265
};
266266
match self.mode {
267-
PassMode::Ignore(_) => {}
267+
PassMode::Ignore => {}
268268
PassMode::Pair(..) => {
269269
OperandValue::Pair(next(), next()).store(bx, dst);
270270
}
@@ -319,9 +319,7 @@ impl<'tcx> FnTypeLlvmExt<'tcx> for FnType<'tcx, Ty<'tcx>> {
319319
);
320320

321321
let llreturn_ty = match self.ret.mode {
322-
PassMode::Ignore(IgnoreMode::Zst) => cx.type_void(),
323-
PassMode::Ignore(IgnoreMode::CVarArgs) =>
324-
bug!("`va_list` should never be a return type"),
322+
PassMode::Ignore => cx.type_void(),
325323
PassMode::Direct(_) | PassMode::Pair(..) => {
326324
self.ret.layout.immediate_llvm_type(cx)
327325
}
@@ -339,7 +337,7 @@ impl<'tcx> FnTypeLlvmExt<'tcx> for FnType<'tcx, Ty<'tcx>> {
339337
}
340338

341339
let llarg_ty = match arg.mode {
342-
PassMode::Ignore(_) => continue,
340+
PassMode::Ignore => continue,
343341
PassMode::Direct(_) => arg.layout.immediate_llvm_type(cx),
344342
PassMode::Pair(..) => {
345343
llargument_tys.push(arg.layout.scalar_pair_element_llvm_type(cx, 0, true));
@@ -408,7 +406,7 @@ impl<'tcx> FnTypeLlvmExt<'tcx> for FnType<'tcx, Ty<'tcx>> {
408406
apply(&ArgAttributes::new(), None);
409407
}
410408
match arg.mode {
411-
PassMode::Ignore(_) => {}
409+
PassMode::Ignore => {}
412410
PassMode::Direct(ref attrs) |
413411
PassMode::Indirect(ref attrs, None) => apply(attrs, Some(arg.layout.llvm_type(cx))),
414412
PassMode::Indirect(ref attrs, Some(ref extra_attrs)) => {
@@ -455,7 +453,7 @@ impl<'tcx> FnTypeLlvmExt<'tcx> for FnType<'tcx, Ty<'tcx>> {
455453
apply(&ArgAttributes::new(), None);
456454
}
457455
match arg.mode {
458-
PassMode::Ignore(_) => {}
456+
PassMode::Ignore => {}
459457
PassMode::Direct(ref attrs) |
460458
PassMode::Indirect(ref attrs, None) => apply(attrs, Some(arg.layout.llvm_type(bx))),
461459
PassMode::Indirect(ref attrs, Some(ref extra_attrs)) => {

src/librustc_codegen_ssa/mir/block.rs

Lines changed: 3 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ use rustc::ty::{self, Ty, TypeFoldable, Instance};
33
use rustc::ty::layout::{self, LayoutOf, HasTyCtxt, FnTypeExt};
44
use rustc::mir::{self, Place, PlaceBase, Static, StaticKind};
55
use rustc::mir::interpret::PanicInfo;
6-
use rustc_target::abi::call::{ArgType, FnType, PassMode, IgnoreMode};
6+
use rustc_target::abi::call::{ArgType, FnType, PassMode};
77
use rustc_target::spec::abi::Abi;
88
use crate::base;
99
use crate::MemFlags;
@@ -242,15 +242,11 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
242242
return;
243243
}
244244
let llval = match self.fn_ty.ret.mode {
245-
PassMode::Ignore(IgnoreMode::Zst) | PassMode::Indirect(..) => {
245+
PassMode::Ignore | PassMode::Indirect(..) => {
246246
bx.ret_void();
247247
return;
248248
}
249249

250-
PassMode::Ignore(IgnoreMode::CVarArgs) => {
251-
bug!("C-variadic arguments should never be the return type");
252-
}
253-
254250
PassMode::Direct(_) | PassMode::Pair(..) => {
255251
let op =
256252
self.codegen_consume(&mut bx, &mir::Place::return_place().as_ref());
@@ -502,10 +498,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
502498
return;
503499
}
504500

505-
// The "spoofed" `VaListImpl` added to a C-variadic functions signature
506-
// should not be included in the `extra_args` calculation.
507-
let extra_args_start_idx = sig.inputs().len() - if sig.c_variadic { 1 } else { 0 };
508-
let extra_args = &args[extra_args_start_idx..];
501+
let extra_args = &args[sig.inputs().len()..];
509502
let extra_args = extra_args.iter().map(|op_arg| {
510503
let op_ty = op_arg.ty(self.mir, bx.tcx());
511504
self.monomorphize(&op_ty)
@@ -691,26 +684,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
691684
(&args[..], None)
692685
};
693686

694-
// Useful determining if the current argument is the "spoofed" `VaListImpl`
695-
let last_arg_idx = if sig.inputs().is_empty() {
696-
None
697-
} else {
698-
Some(sig.inputs().len() - 1)
699-
};
700687
'make_args: for (i, arg) in first_args.iter().enumerate() {
701-
// If this is a C-variadic function the function signature contains
702-
// an "spoofed" `VaListImpl`. This argument is ignored, but we need to
703-
// populate it with a dummy operand so that the users real arguments
704-
// are not overwritten.
705-
let i = if sig.c_variadic && last_arg_idx.map(|x| i >= x).unwrap_or(false) {
706-
if i + 1 < fn_ty.args.len() {
707-
i + 1
708-
} else {
709-
break 'make_args
710-
}
711-
} else {
712-
i
713-
};
714688
let mut op = self.codegen_operand(&mut bx, arg);
715689

716690
if let (0, Some(ty::InstanceDef::Virtual(_, idx))) = (i, def) {

src/librustc_codegen_ssa/mir/mod.rs

Lines changed: 30 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ use rustc::ty::{self, Ty, TypeFoldable, UpvarSubsts, Instance};
22
use rustc::ty::layout::{TyLayout, HasTyCtxt, FnTypeExt};
33
use rustc::mir::{self, Body};
44
use rustc::session::config::DebugInfo;
5-
use rustc_target::abi::call::{FnType, PassMode, IgnoreMode};
5+
use rustc_target::abi::call::{FnType, PassMode};
66
use rustc_target::abi::{Variants, VariantIdx};
77
use crate::base;
88
use 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;

src/librustc_lint/types.rs

Lines changed: 1 addition & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -944,15 +944,8 @@ impl<'a, 'tcx> ImproperCTypesVisitor<'a, 'tcx> {
944944
let def_id = self.cx.tcx.hir().local_def_id(id);
945945
let sig = self.cx.tcx.fn_sig(def_id);
946946
let sig = self.cx.tcx.erase_late_bound_regions(&sig);
947-
let inputs = if sig.c_variadic {
948-
// Don't include the spoofed `VaListImpl` in the functions list
949-
// of inputs.
950-
&sig.inputs()[..sig.inputs().len() - 1]
951-
} else {
952-
&sig.inputs()[..]
953-
};
954947

955-
for (input_ty, input_hir) in inputs.iter().zip(&decl.inputs) {
948+
for (input_ty, input_hir) in sig.inputs().iter().zip(&decl.inputs) {
956949
self.check_type_for_ffi_and_report_errors(input_hir.span, input_ty);
957950
}
958951

0 commit comments

Comments
 (0)