Skip to content

Commit

Permalink
Add to va_list lang item
Browse files Browse the repository at this point in the history
Add the va_list lang item in order to allow VaList in libcore to be
correctly generated for the target arch by trans.
  • Loading branch information
dlrobertson committed Apr 30, 2018
1 parent 139b207 commit da46325
Show file tree
Hide file tree
Showing 7 changed files with 108 additions and 4 deletions.
1 change: 1 addition & 0 deletions src/libcore/lib.rs
Expand Up @@ -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;
Expand Down
48 changes: 48 additions & 0 deletions 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 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, 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<T: Copy>(&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::<VaList>();
::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
}
}
1 change: 1 addition & 0 deletions src/librustc/middle/lang_items.rs
Expand Up @@ -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;
Expand Down
29 changes: 29 additions & 0 deletions src/librustc/ty/context.rs
Expand Up @@ -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,
Expand Down Expand Up @@ -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<Ty<'tcx>> {
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<T: ?Sized, R> {
Expand Down
19 changes: 18 additions & 1 deletion src/librustc/ty/layout.rs
Expand Up @@ -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::<Vec<_>>();
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<T>.
if Some(def.did) == self.tcx.lang_items().non_zero() {
Expand Down Expand Up @@ -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 {
Expand Down
13 changes: 10 additions & 3 deletions src/librustc_trans/type_of.rs
Expand Up @@ -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
}
}
}
}
}
Expand Down
1 change: 1 addition & 0 deletions src/librustdoc/clean/inline.rs
Expand Up @@ -297,6 +297,7 @@ pub fn build_impls(cx: &DocContext, did: DefId, auto_traits: bool) -> Vec<clean:
lang_items.slice_u8_alloc_impl(),
lang_items.const_ptr_impl(),
lang_items.mut_ptr_impl(),
lang_items.va_list(),
];

for def_id in primitive_impls.iter().filter_map(|&def_id| def_id) {
Expand Down

0 comments on commit da46325

Please sign in to comment.