From da463254f95e4f7748e1d436cb32457ed266a813 Mon Sep 17 00:00:00 2001 From: Dan Robertson Date: Sun, 1 Apr 2018 06:13:20 +0000 Subject: [PATCH] Add to va_list lang item Add the va_list lang item in order to allow VaList in libcore to be correctly generated for the target arch by trans. --- src/libcore/lib.rs | 1 + src/libcore/va_list.rs | 48 +++++++++++++++++++++++++++++++ src/librustc/middle/lang_items.rs | 1 + src/librustc/ty/context.rs | 29 +++++++++++++++++++ src/librustc/ty/layout.rs | 19 +++++++++++- src/librustc_trans/type_of.rs | 13 +++++++-- src/librustdoc/clean/inline.rs | 1 + 7 files changed, 108 insertions(+), 4 deletions(-) create mode 100644 src/libcore/va_list.rs diff --git a/src/libcore/lib.rs b/src/libcore/lib.rs index 0e21a3327fddf..a34893dcabd9b 100644 --- a/src/libcore/lib.rs +++ b/src/libcore/lib.rs @@ -189,6 +189,7 @@ pub mod iter; pub mod option; pub mod raw; pub mod result; +pub mod va_list; pub mod slice; pub mod str; diff --git a/src/libcore/va_list.rs b/src/libcore/va_list.rs new file mode 100644 index 0000000000000..f2eceffc67b69 --- /dev/null +++ b/src/libcore/va_list.rs @@ -0,0 +1,48 @@ +// Copyright 2018 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +#![unstable(feature = "c_variadic", + reason = "dlrobertson is still working on this", + issue = "27745")] + +//! Implementation of a `va_list` + +#[cfg(not(stage0))] +#[lang = "va_list"] +/// A wrapper for a `va_list` +//#[derive(Debug)] +#[repr(C)] +#[unstable(feature = "c_variadic", + reason = "dlrobertson is still working on this", + issue = "27745")] +#[derive(Debug)] +pub struct VaList; + +#[cfg(not(stage0))] +#[unstable(feature = "c_variadic", + reason = "This is just a test.", + issue = "27745")] +impl VaList { + /// Advance to the next arg. + pub unsafe fn arg(&mut self) -> T { + let tmp = self as *mut _ as *mut i8; + ::intrinsics::va_arg(tmp) + } + + /// Copy the `va_list` at the current location. + pub unsafe fn copy<'ret, F, T>(&self, f: F) -> T + where F: FnOnce(&mut VaList) -> T, T: 'ret { + let mut ap: VaList = ::mem::uninitialized::(); + ::intrinsics::va_copy(self as *const _ as *const i8, &mut ap as *mut _ as *mut i8); + let ret = f(&mut ap); + ::intrinsics::va_end(&mut ap as *const _ as *mut i8); + ret + } +} diff --git a/src/librustc/middle/lang_items.rs b/src/librustc/middle/lang_items.rs index 95e92e21b09dc..0d1ec24c89c88 100644 --- a/src/librustc/middle/lang_items.rs +++ b/src/librustc/middle/lang_items.rs @@ -273,6 +273,7 @@ language_item_table! { IndexMutTraitLangItem, "index_mut", index_mut_trait; UnsafeCellTypeLangItem, "unsafe_cell", unsafe_cell_type; + VaListTypeLangItem, "va_list", va_list; DerefTraitLangItem, "deref", deref_trait; DerefMutTraitLangItem, "deref_mut", deref_mut_trait; diff --git a/src/librustc/ty/context.rs b/src/librustc/ty/context.rs index c28fcfe88059f..0f36d6d453435 100644 --- a/src/librustc/ty/context.rs +++ b/src/librustc/ty/context.rs @@ -53,6 +53,7 @@ use ty::BindingMode; use ty::CanonicalTy; use util::nodemap::{DefIdSet, ItemLocalMap}; use util::nodemap::{FxHashMap, FxHashSet}; +use rustc_target::spec::VaListKind; use rustc_data_structures::accumulate_vec::AccumulateVec; use rustc_data_structures::stable_hasher::{HashStable, hash_stable_hashmap, StableHasher, StableHasherResult, @@ -2694,6 +2695,34 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { self.object_lifetime_defaults_map(id.owner) .and_then(|map| map.get(&id.local_id).cloned()) } + + pub fn va_list_types(&self) -> Vec> { + match self.sess.target.target.options.va_list_kind { + VaListKind::CharPtr | VaListKind::VoidPtr => { + vec![self.mk_mut_ptr(self.types.i8)] + } + VaListKind::X86_64Abi => { + vec![self.types.i32, + self.types.i32, + self.mk_mut_ptr(self.types.i8), + self.mk_mut_ptr(self.types.i8)] + } + VaListKind::AArch64Abi => { + vec![self.mk_mut_ptr(self.types.i8), + self.mk_mut_ptr(self.types.i8), + self.mk_mut_ptr(self.types.i8), + self.types.i32, + self.types.i32] + } + VaListKind::PowerPcAbi => { + vec![self.types.i8, + self.types.i8, + self.types.i16, + self.mk_mut_ptr(self.types.i8), + self.mk_mut_ptr(self.types.i8)] + } + } + } } pub trait InternAs { diff --git a/src/librustc/ty/layout.rs b/src/librustc/ty/layout.rs index 55137e2891123..657ef884ed297 100644 --- a/src/librustc/ty/layout.rs +++ b/src/librustc/ty/layout.rs @@ -744,7 +744,17 @@ impl<'a, 'tcx> LayoutCx<'tcx, TyCtxt<'a, 'tcx, 'tcx>> { else { StructKind::AlwaysSized } }; - let mut st = univariant_uninterned(&variants[v], &def.repr, kind)?; + let mut st = match tcx.lang_items().va_list() { + Some(did) if did == def.did => { + let variants = tcx.va_list_types().iter() + .map(|x| self.layout_of(x).unwrap()) + .collect::>(); + univariant_uninterned(&variants[..], &def.repr, kind)? + } + _ => { + univariant_uninterned(&variants[v], &def.repr, kind)? + } + }; st.variants = Variants::Single { index: v }; // Exclude 0 from the range of a newtype ABI NonZero. if Some(def.did) == self.tcx.lang_items().non_zero() { @@ -1614,6 +1624,13 @@ impl<'a, 'tcx, C> TyLayoutMethods<'tcx, C> for Ty<'tcx> this.ty.simd_type(tcx) } + ty::TyAdt(def, ..) if Some(def.did) == tcx.lang_items().va_list() => { + match this.variants { + Variants::Single { index } => tcx.va_list_types()[index], + _ => bug!("VaList must be a struct type with a single variant.") + } + } + // ADTs. ty::TyAdt(def, substs) => { match this.variants { diff --git a/src/librustc_trans/type_of.rs b/src/librustc_trans/type_of.rs index 5e6b276495764..afa283e47aaef 100644 --- a/src/librustc_trans/type_of.rs +++ b/src/librustc_trans/type_of.rs @@ -103,9 +103,16 @@ fn uncached_llvm_type<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>, Type::struct_(cx, &llfields, packed) } Some(ref name) => { - let llty = Type::named_struct(cx, name); - *defer = Some((llty, layout)); - llty + match layout.ty.sty { + ty::TyAdt(def, _) if Some(def.did) == cx.tcx.lang_items().va_list() => { + Type::va_list(cx, name) + } + _ => { + let llty = Type::named_struct(cx, name); + *defer = Some((llty, layout)); + llty + } + } } } } diff --git a/src/librustdoc/clean/inline.rs b/src/librustdoc/clean/inline.rs index 23e0c2625eeeb..3993e6428fcae 100644 --- a/src/librustdoc/clean/inline.rs +++ b/src/librustdoc/clean/inline.rs @@ -297,6 +297,7 @@ pub fn build_impls(cx: &DocContext, did: DefId, auto_traits: bool) -> Vec