Auto merge of #62555 - Centril:rollup-ti46adx, r=Centril

Rollup of 5 pull requests

Successful merges:

 - #61853 (Emit warning when trying to use PGO in conjunction with unwinding on …)
 - #62278 (Add Iterator::partition_in_place() and is_partitioned())
 - #62283 (Target::arch can take more than listed options)
 - #62393 (Fix pretty-printing of `$crate` (take 4))
 - #62474 (Prepare for LLVM 9 update)

Failed merges:

r? @ghost
This commit is contained in:
bors 2019-07-10 05:21:43 +00:00
commit 0324a2b309
60 changed files with 551 additions and 180 deletions

View file

@ -1472,6 +1472,11 @@ pub trait Iterator {
/// `partition()` returns a pair, all of the elements for which it returned /// `partition()` returns a pair, all of the elements for which it returned
/// `true`, and all of the elements for which it returned `false`. /// `true`, and all of the elements for which it returned `false`.
/// ///
/// See also [`is_partitioned()`] and [`partition_in_place()`].
///
/// [`is_partitioned()`]: #method.is_partitioned
/// [`partition_in_place()`]: #method.partition_in_place
///
/// # Examples /// # Examples
/// ///
/// Basic usage: /// Basic usage:
@ -1506,6 +1511,101 @@ pub trait Iterator {
(left, right) (left, right)
} }
/// Reorder the elements of this iterator *in-place* according to the given predicate,
/// such that all those that return `true` precede all those that return `false`.
/// Returns the number of `true` elements found.
///
/// The relative order of partitioned items is not maintained.
///
/// See also [`is_partitioned()`] and [`partition()`].
///
/// [`is_partitioned()`]: #method.is_partitioned
/// [`partition()`]: #method.partition
///
/// # Examples
///
/// ```
/// #![feature(iter_partition_in_place)]
///
/// let mut a = [1, 2, 3, 4, 5, 6, 7];
///
/// // Partition in-place between evens and odds
/// let i = a.iter_mut().partition_in_place(|&n| n % 2 == 0);
///
/// assert_eq!(i, 3);
/// assert!(a[..i].iter().all(|&n| n % 2 == 0)); // evens
/// assert!(a[i..].iter().all(|&n| n % 2 == 1)); // odds
/// ```
#[unstable(feature = "iter_partition_in_place", reason = "new API", issue = "62543")]
fn partition_in_place<'a, T: 'a, P>(mut self, ref mut predicate: P) -> usize
where
Self: Sized + DoubleEndedIterator<Item = &'a mut T>,
P: FnMut(&T) -> bool,
{
// FIXME: should we worry about the count overflowing? The only way to have more than
// `usize::MAX` mutable references is with ZSTs, which aren't useful to partition...
// These closure "factory" functions exist to avoid genericity in `Self`.
#[inline]
fn is_false<'a, T>(
predicate: &'a mut impl FnMut(&T) -> bool,
true_count: &'a mut usize,
) -> impl FnMut(&&mut T) -> bool + 'a {
move |x| {
let p = predicate(&**x);
*true_count += p as usize;
!p
}
}
#[inline]
fn is_true<T>(
predicate: &mut impl FnMut(&T) -> bool
) -> impl FnMut(&&mut T) -> bool + '_ {
move |x| predicate(&**x)
}
// Repeatedly find the first `false` and swap it with the last `true`.
let mut true_count = 0;
while let Some(head) = self.find(is_false(predicate, &mut true_count)) {
if let Some(tail) = self.rfind(is_true(predicate)) {
crate::mem::swap(head, tail);
true_count += 1;
} else {
break;
}
}
true_count
}
/// Checks if the elements of this iterator are partitioned according to the given predicate,
/// such that all those that return `true` precede all those that return `false`.
///
/// See also [`partition()`] and [`partition_in_place()`].
///
/// [`partition()`]: #method.partition
/// [`partition_in_place()`]: #method.partition_in_place
///
/// # Examples
///
/// ```
/// #![feature(iter_is_partitioned)]
///
/// assert!("Iterator".chars().is_partitioned(char::is_uppercase));
/// assert!(!"IntoIterator".chars().is_partitioned(char::is_uppercase));
/// ```
#[unstable(feature = "iter_is_partitioned", reason = "new API", issue = "62544")]
fn is_partitioned<P>(mut self, mut predicate: P) -> bool
where
Self: Sized,
P: FnMut(Self::Item) -> bool,
{
// Either all items test `true`, or the first clause stops at `false`
// and we check that there are no more `true` items after that.
self.all(&mut predicate) || !self.any(predicate)
}
/// An iterator method that applies a function as long as it returns /// An iterator method that applies a function as long as it returns
/// successfully, producing a single, final value. /// successfully, producing a single, final value.
/// ///

View file

@ -2460,3 +2460,39 @@ fn test_is_sorted() {
assert!(!["c", "bb", "aaa"].iter().is_sorted()); assert!(!["c", "bb", "aaa"].iter().is_sorted());
assert!(["c", "bb", "aaa"].iter().is_sorted_by_key(|s| s.len())); assert!(["c", "bb", "aaa"].iter().is_sorted_by_key(|s| s.len()));
} }
#[test]
fn test_partition() {
fn check(xs: &mut [i32], ref p: impl Fn(&i32) -> bool, expected: usize) {
let i = xs.iter_mut().partition_in_place(p);
assert_eq!(expected, i);
assert!(xs[..i].iter().all(p));
assert!(!xs[i..].iter().any(p));
assert!(xs.iter().is_partitioned(p));
if i == 0 || i == xs.len() {
assert!(xs.iter().rev().is_partitioned(p));
} else {
assert!(!xs.iter().rev().is_partitioned(p));
}
}
check(&mut [], |_| true, 0);
check(&mut [], |_| false, 0);
check(&mut [0], |_| true, 1);
check(&mut [0], |_| false, 0);
check(&mut [-1, 1], |&x| x > 0, 1);
check(&mut [-1, 1], |&x| x < 0, 1);
let ref mut xs = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9];
check(xs, |_| true, 10);
check(xs, |_| false, 0);
check(xs, |&x| x % 2 == 0, 5); // evens
check(xs, |&x| x % 2 == 1, 5); // odds
check(xs, |&x| x % 3 == 0, 4); // multiple of 3
check(xs, |&x| x % 4 == 0, 3); // multiple of 4
check(xs, |&x| x % 5 == 0, 2); // multiple of 5
check(xs, |&x| x < 3, 3); // small
check(xs, |&x| x > 6, 3); // large
}

View file

@ -31,6 +31,8 @@
#![feature(slice_partition_dedup)] #![feature(slice_partition_dedup)]
#![feature(int_error_matching)] #![feature(int_error_matching)]
#![feature(const_fn)] #![feature(const_fn)]
#![feature(iter_partition_in_place)]
#![feature(iter_is_partitioned)]
#![warn(rust_2018_idioms)] #![warn(rust_2018_idioms)]
extern crate test; extern crate test;

View file

@ -1303,13 +1303,13 @@ fn validate_commandline_args_with_session_available(sess: &Session) {
} }
// PGO does not work reliably with panic=unwind on Windows. Let's make it // PGO does not work reliably with panic=unwind on Windows. Let's make it
// an error to combine the two for now. It always runs into an assertions // a warning to combine the two for now. It always runs into an assertions
// if LLVM is built with assertions, but without assertions it sometimes // if LLVM is built with assertions, but without assertions it sometimes
// does not crash and will probably generate a corrupted binary. // does not crash and will probably generate a corrupted binary.
if sess.opts.cg.profile_generate.enabled() && if sess.opts.cg.profile_generate.enabled() &&
sess.target.target.options.is_like_msvc && sess.target.target.options.is_like_msvc &&
sess.panic_strategy() == PanicStrategy::Unwind { sess.panic_strategy() == PanicStrategy::Unwind {
sess.err("Profile-guided optimization does not yet work in conjunction \ sess.warn("Profile-guided optimization does not yet work in conjunction \
with `-Cpanic=unwind` on Windows when targeting MSVC. \ with `-Cpanic=unwind` on Windows when targeting MSVC. \
See https://github.com/rust-lang/rust/issues/61002 for details."); See https://github.com/rust-lang/rust/issues/61002 for details.");
} }

View file

@ -34,17 +34,17 @@ trait ArgAttributeExt {
impl ArgAttributeExt for ArgAttribute { impl ArgAttributeExt for ArgAttribute {
fn for_each_kind<F>(&self, mut f: F) where F: FnMut(llvm::Attribute) { fn for_each_kind<F>(&self, mut f: F) where F: FnMut(llvm::Attribute) {
for_each_kind!(self, f, for_each_kind!(self, f,
ByVal, NoAlias, NoCapture, NonNull, ReadOnly, SExt, StructRet, ZExt, InReg) NoAlias, NoCapture, NonNull, ReadOnly, SExt, StructRet, ZExt, InReg)
} }
} }
pub trait ArgAttributesExt { pub trait ArgAttributesExt {
fn apply_llfn(&self, idx: AttributePlace, llfn: &Value); fn apply_llfn(&self, idx: AttributePlace, llfn: &Value, ty: Option<&Type>);
fn apply_callsite(&self, idx: AttributePlace, callsite: &Value); fn apply_callsite(&self, idx: AttributePlace, callsite: &Value, ty: Option<&Type>);
} }
impl ArgAttributesExt for ArgAttributes { impl ArgAttributesExt for ArgAttributes {
fn apply_llfn(&self, idx: AttributePlace, llfn: &Value) { fn apply_llfn(&self, idx: AttributePlace, llfn: &Value, ty: Option<&Type>) {
let mut regular = self.regular; let mut regular = self.regular;
unsafe { unsafe {
let deref = self.pointee_size.bytes(); let deref = self.pointee_size.bytes();
@ -65,11 +65,14 @@ impl ArgAttributesExt for ArgAttributes {
idx.as_uint(), idx.as_uint(),
align.bytes() as u32); align.bytes() as u32);
} }
if regular.contains(ArgAttribute::ByVal) {
llvm::LLVMRustAddByValAttr(llfn, idx.as_uint(), ty.unwrap());
}
regular.for_each_kind(|attr| attr.apply_llfn(idx, llfn)); regular.for_each_kind(|attr| attr.apply_llfn(idx, llfn));
} }
} }
fn apply_callsite(&self, idx: AttributePlace, callsite: &Value) { fn apply_callsite(&self, idx: AttributePlace, callsite: &Value, ty: Option<&Type>) {
let mut regular = self.regular; let mut regular = self.regular;
unsafe { unsafe {
let deref = self.pointee_size.bytes(); let deref = self.pointee_size.bytes();
@ -90,6 +93,9 @@ impl ArgAttributesExt for ArgAttributes {
idx.as_uint(), idx.as_uint(),
align.bytes() as u32); align.bytes() as u32);
} }
if regular.contains(ArgAttribute::ByVal) {
llvm::LLVMRustAddByValCallSiteAttr(callsite, idx.as_uint(), ty.unwrap());
}
regular.for_each_kind(|attr| attr.apply_callsite(idx, callsite)); regular.for_each_kind(|attr| attr.apply_callsite(idx, callsite));
} }
} }
@ -298,7 +304,7 @@ pub trait FnTypeLlvmExt<'tcx> {
fn llvm_type(&self, cx: &CodegenCx<'ll, 'tcx>) -> &'ll Type; fn llvm_type(&self, cx: &CodegenCx<'ll, 'tcx>) -> &'ll Type;
fn ptr_to_llvm_type(&self, cx: &CodegenCx<'ll, 'tcx>) -> &'ll Type; fn ptr_to_llvm_type(&self, cx: &CodegenCx<'ll, 'tcx>) -> &'ll Type;
fn llvm_cconv(&self) -> llvm::CallConv; fn llvm_cconv(&self) -> llvm::CallConv;
fn apply_attrs_llfn(&self, llfn: &'ll Value); fn apply_attrs_llfn(&self, cx: &CodegenCx<'ll, 'tcx>, llfn: &'ll Value);
fn apply_attrs_callsite(&self, bx: &mut Builder<'a, 'll, 'tcx>, callsite: &'ll Value); fn apply_attrs_callsite(&self, bx: &mut Builder<'a, 'll, 'tcx>, callsite: &'ll Value);
} }
@ -384,51 +390,51 @@ impl<'tcx> FnTypeLlvmExt<'tcx> for FnType<'tcx, Ty<'tcx>> {
} }
} }
fn apply_attrs_llfn(&self, llfn: &'ll Value) { fn apply_attrs_llfn(&self, cx: &CodegenCx<'ll, 'tcx>, llfn: &'ll Value) {
let mut i = 0; let mut i = 0;
let mut apply = |attrs: &ArgAttributes| { let mut apply = |attrs: &ArgAttributes, ty: Option<&Type>| {
attrs.apply_llfn(llvm::AttributePlace::Argument(i), llfn); attrs.apply_llfn(llvm::AttributePlace::Argument(i), llfn, ty);
i += 1; i += 1;
}; };
match self.ret.mode { match self.ret.mode {
PassMode::Direct(ref attrs) => { PassMode::Direct(ref attrs) => {
attrs.apply_llfn(llvm::AttributePlace::ReturnValue, llfn); attrs.apply_llfn(llvm::AttributePlace::ReturnValue, llfn, None);
} }
PassMode::Indirect(ref attrs, _) => apply(attrs), PassMode::Indirect(ref attrs, _) => apply(attrs, Some(self.ret.layout.llvm_type(cx))),
_ => {} _ => {}
} }
for arg in &self.args { for arg in &self.args {
if arg.pad.is_some() { if arg.pad.is_some() {
apply(&ArgAttributes::new()); apply(&ArgAttributes::new(), None);
} }
match arg.mode { match arg.mode {
PassMode::Ignore(_) => {} PassMode::Ignore(_) => {}
PassMode::Direct(ref attrs) | PassMode::Direct(ref attrs) |
PassMode::Indirect(ref attrs, None) => apply(attrs), PassMode::Indirect(ref attrs, None) => apply(attrs, Some(arg.layout.llvm_type(cx))),
PassMode::Indirect(ref attrs, Some(ref extra_attrs)) => { PassMode::Indirect(ref attrs, Some(ref extra_attrs)) => {
apply(attrs); apply(attrs, None);
apply(extra_attrs); apply(extra_attrs, None);
} }
PassMode::Pair(ref a, ref b) => { PassMode::Pair(ref a, ref b) => {
apply(a); apply(a, None);
apply(b); apply(b, None);
} }
PassMode::Cast(_) => apply(&ArgAttributes::new()), PassMode::Cast(_) => apply(&ArgAttributes::new(), None),
} }
} }
} }
fn apply_attrs_callsite(&self, bx: &mut Builder<'a, 'll, 'tcx>, callsite: &'ll Value) { fn apply_attrs_callsite(&self, bx: &mut Builder<'a, 'll, 'tcx>, callsite: &'ll Value) {
let mut i = 0; let mut i = 0;
let mut apply = |attrs: &ArgAttributes| { let mut apply = |attrs: &ArgAttributes, ty: Option<&Type>| {
attrs.apply_callsite(llvm::AttributePlace::Argument(i), callsite); attrs.apply_callsite(llvm::AttributePlace::Argument(i), callsite, ty);
i += 1; i += 1;
}; };
match self.ret.mode { match self.ret.mode {
PassMode::Direct(ref attrs) => { PassMode::Direct(ref attrs) => {
attrs.apply_callsite(llvm::AttributePlace::ReturnValue, callsite); attrs.apply_callsite(llvm::AttributePlace::ReturnValue, callsite, None);
} }
PassMode::Indirect(ref attrs, _) => apply(attrs), PassMode::Indirect(ref attrs, _) => apply(attrs, Some(self.ret.layout.llvm_type(bx))),
_ => {} _ => {}
} }
if let layout::Abi::Scalar(ref scalar) = self.ret.layout.abi { if let layout::Abi::Scalar(ref scalar) = self.ret.layout.abi {
@ -446,21 +452,21 @@ impl<'tcx> FnTypeLlvmExt<'tcx> for FnType<'tcx, Ty<'tcx>> {
} }
for arg in &self.args { for arg in &self.args {
if arg.pad.is_some() { if arg.pad.is_some() {
apply(&ArgAttributes::new()); apply(&ArgAttributes::new(), None);
} }
match arg.mode { match arg.mode {
PassMode::Ignore(_) => {} PassMode::Ignore(_) => {}
PassMode::Direct(ref attrs) | PassMode::Direct(ref attrs) |
PassMode::Indirect(ref attrs, None) => apply(attrs), PassMode::Indirect(ref attrs, None) => apply(attrs, Some(arg.layout.llvm_type(bx))),
PassMode::Indirect(ref attrs, Some(ref extra_attrs)) => { PassMode::Indirect(ref attrs, Some(ref extra_attrs)) => {
apply(attrs); apply(attrs, None);
apply(extra_attrs); apply(extra_attrs, None);
} }
PassMode::Pair(ref a, ref b) => { PassMode::Pair(ref a, ref b) => {
apply(a); apply(a, None);
apply(b); apply(b, None);
} }
PassMode::Cast(_) => apply(&ArgAttributes::new()), PassMode::Cast(_) => apply(&ArgAttributes::new(), None),
} }
} }

View file

@ -119,6 +119,29 @@ pub fn set_probestack(cx: &CodegenCx<'ll, '_>, llfn: &'ll Value) {
const_cstr!("probe-stack"), const_cstr!("__rust_probestack")); const_cstr!("probe-stack"), const_cstr!("__rust_probestack"));
} }
fn translate_obsolete_target_features(feature: &str) -> &str {
const LLVM9_FEATURE_CHANGES: &[(&str, &str)] = &[
("+fp-only-sp", "-fp64"),
("-fp-only-sp", "+fp64"),
("+d16", "-d32"),
("-d16", "+d32"),
];
if llvm_util::get_major_version() >= 9 {
for &(old, new) in LLVM9_FEATURE_CHANGES {
if feature == old {
return new;
}
}
} else {
for &(old, new) in LLVM9_FEATURE_CHANGES {
if feature == new {
return old;
}
}
}
feature
}
pub fn llvm_target_features(sess: &Session) -> impl Iterator<Item = &str> { pub fn llvm_target_features(sess: &Session) -> impl Iterator<Item = &str> {
const RUSTC_SPECIFIC_FEATURES: &[&str] = &[ const RUSTC_SPECIFIC_FEATURES: &[&str] = &[
"crt-static", "crt-static",
@ -129,6 +152,7 @@ pub fn llvm_target_features(sess: &Session) -> impl Iterator<Item = &str> {
sess.target.target.options.features.split(',') sess.target.target.options.features.split(',')
.chain(cmdline) .chain(cmdline)
.filter(|l| !l.is_empty()) .filter(|l| !l.is_empty())
.map(translate_obsolete_target_features)
} }
pub fn apply_target_cpu_attr(cx: &CodegenCx<'ll, '_>, llfn: &'ll Value) { pub fn apply_target_cpu_attr(cx: &CodegenCx<'ll, '_>, llfn: &'ll Value) {

View file

@ -249,6 +249,10 @@ impl ConstMethods<'tcx> for CodegenCx<'ll, 'tcx> {
self.const_uint(self.type_i8(), i as u64) self.const_uint(self.type_i8(), i as u64)
} }
fn const_real(&self, t: &'ll Type, val: f64) -> &'ll Value {
unsafe { llvm::LLVMConstReal(t, val) }
}
fn const_struct( fn const_struct(
&self, &self,
elts: &[&'ll Value], elts: &[&'ll Value],

View file

@ -1,5 +1,6 @@
use crate::attributes; use crate::attributes;
use crate::llvm; use crate::llvm;
use crate::llvm_util;
use crate::debuginfo; use crate::debuginfo;
use crate::value::Value; use crate::value::Value;
use rustc::dep_graph::DepGraphSafe; use rustc::dep_graph::DepGraphSafe;
@ -140,6 +141,11 @@ pub fn is_pie_binary(sess: &Session) -> bool {
!is_any_library(sess) && get_reloc_model(sess) == llvm::RelocMode::PIC !is_any_library(sess) && get_reloc_model(sess) == llvm::RelocMode::PIC
} }
fn strip_function_ptr_alignment(data_layout: String) -> String {
// FIXME: Make this more general.
data_layout.replace("-Fi8-", "-")
}
pub unsafe fn create_module( pub unsafe fn create_module(
tcx: TyCtxt<'_>, tcx: TyCtxt<'_>,
llcx: &'ll llvm::Context, llcx: &'ll llvm::Context,
@ -149,14 +155,19 @@ pub unsafe fn create_module(
let mod_name = SmallCStr::new(mod_name); let mod_name = SmallCStr::new(mod_name);
let llmod = llvm::LLVMModuleCreateWithNameInContext(mod_name.as_ptr(), llcx); let llmod = llvm::LLVMModuleCreateWithNameInContext(mod_name.as_ptr(), llcx);
let mut target_data_layout = sess.target.target.data_layout.clone();
if llvm_util::get_major_version() < 9 {
target_data_layout = strip_function_ptr_alignment(target_data_layout);
}
// Ensure the data-layout values hardcoded remain the defaults. // Ensure the data-layout values hardcoded remain the defaults.
if sess.target.target.options.is_builtin { if sess.target.target.options.is_builtin {
let tm = crate::back::write::create_informational_target_machine(&tcx.sess, false); let tm = crate::back::write::create_informational_target_machine(&tcx.sess, false);
llvm::LLVMRustSetDataLayoutFromTargetMachine(llmod, tm); llvm::LLVMRustSetDataLayoutFromTargetMachine(llmod, tm);
llvm::LLVMRustDisposeTargetMachine(tm); llvm::LLVMRustDisposeTargetMachine(tm);
let data_layout = llvm::LLVMGetDataLayout(llmod); let llvm_data_layout = llvm::LLVMGetDataLayout(llmod);
let data_layout = str::from_utf8(CStr::from_ptr(data_layout).to_bytes()) let llvm_data_layout = str::from_utf8(CStr::from_ptr(llvm_data_layout).to_bytes())
.ok().expect("got a non-UTF8 data-layout from LLVM"); .ok().expect("got a non-UTF8 data-layout from LLVM");
// Unfortunately LLVM target specs change over time, and right now we // Unfortunately LLVM target specs change over time, and right now we
@ -177,16 +188,16 @@ pub unsafe fn create_module(
let cfg_llvm_root = option_env!("CFG_LLVM_ROOT").unwrap_or(""); let cfg_llvm_root = option_env!("CFG_LLVM_ROOT").unwrap_or("");
let custom_llvm_used = cfg_llvm_root.trim() != ""; let custom_llvm_used = cfg_llvm_root.trim() != "";
if !custom_llvm_used && sess.target.target.data_layout != data_layout { if !custom_llvm_used && target_data_layout != llvm_data_layout {
bug!("data-layout for builtin `{}` target, `{}`, \ bug!("data-layout for builtin `{}` target, `{}`, \
differs from LLVM default, `{}`", differs from LLVM default, `{}`",
sess.target.target.llvm_target, sess.target.target.llvm_target,
sess.target.target.data_layout, target_data_layout,
data_layout); llvm_data_layout);
} }
} }
let data_layout = SmallCStr::new(&sess.target.target.data_layout); let data_layout = SmallCStr::new(&target_data_layout);
llvm::LLVMSetDataLayout(llmod, data_layout.as_ptr()); llvm::LLVMSetDataLayout(llmod, data_layout.as_ptr());
let llvm_target = SmallCStr::new(&sess.target.target.llvm_target); let llvm_target = SmallCStr::new(&sess.target.target.llvm_target);

View file

@ -107,7 +107,7 @@ impl DeclareMethods<'tcx> for CodegenCx<'ll, 'tcx> {
llvm::Attribute::NoReturn.apply_llfn(Function, llfn); llvm::Attribute::NoReturn.apply_llfn(Function, llfn);
} }
fty.apply_attrs_llfn(llfn); fty.apply_attrs_llfn(self, llfn);
llfn llfn
} }

View file

@ -1663,9 +1663,10 @@ fn generic_simd_intrinsic(
acc acc
} else { } else {
// unordered arithmetic reductions do not: // unordered arithmetic reductions do not:
let identity_acc = if $name.contains("mul") { 1.0 } else { 0.0 };
match f.bit_width() { match f.bit_width() {
32 => bx.const_undef(bx.type_f32()), 32 => bx.const_real(bx.type_f32(), identity_acc),
64 => bx.const_undef(bx.type_f64()), 64 => bx.const_real(bx.type_f64(), identity_acc),
v => { v => {
return_error!(r#" return_error!(r#"
unsupported {} from `{}` with element `{}` of size `{}` to `{}`"#, unsupported {} from `{}` with element `{}` of size `{}` to `{}`"#,

View file

@ -715,6 +715,7 @@ extern "C" {
// Operations on scalar constants // Operations on scalar constants
pub fn LLVMConstInt(IntTy: &Type, N: c_ulonglong, SignExtend: Bool) -> &Value; pub fn LLVMConstInt(IntTy: &Type, N: c_ulonglong, SignExtend: Bool) -> &Value;
pub fn LLVMConstIntOfArbitraryPrecision(IntTy: &Type, Wn: c_uint, Ws: *const u64) -> &Value; pub fn LLVMConstIntOfArbitraryPrecision(IntTy: &Type, Wn: c_uint, Ws: *const u64) -> &Value;
pub fn LLVMConstReal(RealTy: &Type, N: f64) -> &Value;
pub fn LLVMConstIntGetZExtValue(ConstantVal: &Value) -> c_ulonglong; pub fn LLVMConstIntGetZExtValue(ConstantVal: &Value) -> c_ulonglong;
pub fn LLVMRustConstInt128Get(ConstantVal: &Value, SExt: bool, pub fn LLVMRustConstInt128Get(ConstantVal: &Value, SExt: bool,
high: &mut u64, low: &mut u64) -> bool; high: &mut u64, low: &mut u64) -> bool;
@ -794,6 +795,7 @@ extern "C" {
pub fn LLVMRustAddAlignmentAttr(Fn: &Value, index: c_uint, bytes: u32); pub fn LLVMRustAddAlignmentAttr(Fn: &Value, index: c_uint, bytes: u32);
pub fn LLVMRustAddDereferenceableAttr(Fn: &Value, index: c_uint, bytes: u64); pub fn LLVMRustAddDereferenceableAttr(Fn: &Value, index: c_uint, bytes: u64);
pub fn LLVMRustAddDereferenceableOrNullAttr(Fn: &Value, index: c_uint, bytes: u64); pub fn LLVMRustAddDereferenceableOrNullAttr(Fn: &Value, index: c_uint, bytes: u64);
pub fn LLVMRustAddByValAttr(Fn: &Value, index: c_uint, ty: &Type);
pub fn LLVMRustAddFunctionAttribute(Fn: &Value, index: c_uint, attr: Attribute); pub fn LLVMRustAddFunctionAttribute(Fn: &Value, index: c_uint, attr: Attribute);
pub fn LLVMRustAddFunctionAttrStringValue(Fn: &Value, pub fn LLVMRustAddFunctionAttrStringValue(Fn: &Value,
index: c_uint, index: c_uint,
@ -824,6 +826,7 @@ extern "C" {
pub fn LLVMRustAddDereferenceableOrNullCallSiteAttr(Instr: &Value, pub fn LLVMRustAddDereferenceableOrNullCallSiteAttr(Instr: &Value,
index: c_uint, index: c_uint,
bytes: u64); bytes: u64);
pub fn LLVMRustAddByValCallSiteAttr(Instr: &Value, index: c_uint, ty: &Type);
// Operations on load/store instructions (only) // Operations on load/store instructions (only)
pub fn LLVMSetVolatile(MemoryAccessInst: &Value, volatile: Bool); pub fn LLVMSetVolatile(MemoryAccessInst: &Value, volatile: Bool);

View file

@ -17,6 +17,7 @@ pub trait ConstMethods<'tcx>: BackendTypes {
fn const_u64(&self, i: u64) -> Self::Value; fn const_u64(&self, i: u64) -> Self::Value;
fn const_usize(&self, i: u64) -> Self::Value; fn const_usize(&self, i: u64) -> Self::Value;
fn const_u8(&self, i: u8) -> Self::Value; fn const_u8(&self, i: u8) -> Self::Value;
fn const_real(&self, t: Self::Type, val: f64) -> Self::Value;
fn const_struct(&self, elts: &[Self::Value], packed: bool) -> Self::Value; fn const_struct(&self, elts: &[Self::Value], packed: bool) -> Self::Value;

View file

@ -758,7 +758,10 @@ impl<'a> Resolver<'a> {
} }
pub fn macro_def_scope(&mut self, expansion: Mark) -> Module<'a> { pub fn macro_def_scope(&mut self, expansion: Mark) -> Module<'a> {
let def_id = self.macro_defs[&expansion]; let def_id = match self.macro_defs.get(&expansion) {
Some(def_id) => *def_id,
None => return self.graph_root,
};
if let Some(id) = self.definitions.as_local_node_id(def_id) { if let Some(id) = self.definitions.as_local_node_id(def_id) {
self.local_macro_def_scopes[&id] self.local_macro_def_scopes[&id]
} else if def_id.krate == CrateNum::BuiltinMacros { } else if def_id.krate == CrateNum::BuiltinMacros {

View file

@ -17,12 +17,11 @@ use syntax::errors::DiagnosticBuilder;
use syntax::ext::base::{self, Determinacy}; use syntax::ext::base::{self, Determinacy};
use syntax::ext::base::{MacroKind, SyntaxExtension}; use syntax::ext::base::{MacroKind, SyntaxExtension};
use syntax::ext::expand::{AstFragment, Invocation, InvocationKind}; use syntax::ext::expand::{AstFragment, Invocation, InvocationKind};
use syntax::ext::hygiene::Mark; use syntax::ext::hygiene::{self, Mark};
use syntax::ext::tt::macro_rules; use syntax::ext::tt::macro_rules;
use syntax::feature_gate::{feature_err, emit_feature_err, is_builtin_attr_name}; use syntax::feature_gate::{feature_err, emit_feature_err, is_builtin_attr_name};
use syntax::feature_gate::{AttributeGate, GateIssue, Stability, BUILTIN_ATTRIBUTES}; use syntax::feature_gate::{AttributeGate, GateIssue, Stability, BUILTIN_ATTRIBUTES};
use syntax::symbol::{Symbol, kw, sym}; use syntax::symbol::{Symbol, kw, sym};
use syntax::visit::Visitor;
use syntax::util::lev_distance::find_best_match_for_name; use syntax::util::lev_distance::find_best_match_for_name;
use syntax_pos::{Span, DUMMY_SP}; use syntax_pos::{Span, DUMMY_SP};
use errors::Applicability; use errors::Applicability;
@ -146,24 +145,14 @@ impl<'a> base::Resolver for Resolver<'a> {
mark mark
} }
fn resolve_dollar_crates(&mut self, fragment: &AstFragment) { fn resolve_dollar_crates(&mut self) {
struct ResolveDollarCrates<'a, 'b> { hygiene::update_dollar_crate_names(|ctxt| {
resolver: &'a mut Resolver<'b> let ident = Ident::new(kw::DollarCrate, DUMMY_SP.with_ctxt(ctxt));
} match self.resolve_crate_root(ident).kind {
impl<'a> Visitor<'a> for ResolveDollarCrates<'a, '_> {
fn visit_ident(&mut self, ident: Ident) {
if ident.name == kw::DollarCrate {
let name = match self.resolver.resolve_crate_root(ident).kind {
ModuleKind::Def(.., name) if name != kw::Invalid => name, ModuleKind::Def(.., name) if name != kw::Invalid => name,
_ => kw::Crate, _ => kw::Crate,
};
ident.span.ctxt().set_dollar_crate_name(name);
} }
} });
fn visit_mac(&mut self, _: &ast::Mac) {}
}
fragment.visit_with(&mut ResolveDollarCrates { resolver: self });
} }
fn visit_ast_fragment_with_placeholders(&mut self, mark: Mark, fragment: &AstFragment, fn visit_ast_fragment_with_placeholders(&mut self, mark: Mark, fragment: &AstFragment,

View file

@ -11,7 +11,7 @@ pub fn target() -> TargetResult {
target_endian: "little".to_string(), target_endian: "little".to_string(),
target_pointer_width: "32".to_string(), target_pointer_width: "32".to_string(),
target_c_int_width: "32".to_string(), target_c_int_width: "32".to_string(),
data_layout: "e-m:e-p:32:32-i64:64-v128:64:128-a:0:32-n32-S64".to_string(), data_layout: "e-m:e-p:32:32-Fi8-i64:64-v128:64:128-a:0:32-n32-S64".to_string(),
arch: "arm".to_string(), arch: "arm".to_string(),
target_os: "android".to_string(), target_os: "android".to_string(),
target_env: String::new(), target_env: String::new(),

View file

@ -8,7 +8,7 @@ pub fn target() -> TargetResult {
target_endian: "little".to_string(), target_endian: "little".to_string(),
target_pointer_width: "32".to_string(), target_pointer_width: "32".to_string(),
target_c_int_width: "32".to_string(), target_c_int_width: "32".to_string(),
data_layout: "e-m:e-p:32:32-i64:64-v128:64:128-a:0:32-n32-S64".to_string(), data_layout: "e-m:e-p:32:32-Fi8-i64:64-v128:64:128-a:0:32-n32-S64".to_string(),
arch: "arm".to_string(), arch: "arm".to_string(),
target_os: "linux".to_string(), target_os: "linux".to_string(),
target_env: "gnu".to_string(), target_env: "gnu".to_string(),

View file

@ -8,7 +8,7 @@ pub fn target() -> TargetResult {
target_endian: "little".to_string(), target_endian: "little".to_string(),
target_pointer_width: "32".to_string(), target_pointer_width: "32".to_string(),
target_c_int_width: "32".to_string(), target_c_int_width: "32".to_string(),
data_layout: "e-m:e-p:32:32-i64:64-v128:64:128-a:0:32-n32-S64".to_string(), data_layout: "e-m:e-p:32:32-Fi8-i64:64-v128:64:128-a:0:32-n32-S64".to_string(),
arch: "arm".to_string(), arch: "arm".to_string(),
target_os: "linux".to_string(), target_os: "linux".to_string(),
target_env: "gnu".to_string(), target_env: "gnu".to_string(),

View file

@ -15,7 +15,7 @@ pub fn target() -> TargetResult {
target_endian: "little".to_string(), target_endian: "little".to_string(),
target_pointer_width: "32".to_string(), target_pointer_width: "32".to_string(),
target_c_int_width: "32".to_string(), target_c_int_width: "32".to_string(),
data_layout: "e-m:e-p:32:32-i64:64-v128:64:128-a:0:32-n32-S64".to_string(), data_layout: "e-m:e-p:32:32-Fi8-i64:64-v128:64:128-a:0:32-n32-S64".to_string(),
arch: "arm".to_string(), arch: "arm".to_string(),
target_os: "linux".to_string(), target_os: "linux".to_string(),
target_env: "musl".to_string(), target_env: "musl".to_string(),

View file

@ -15,7 +15,7 @@ pub fn target() -> TargetResult {
target_endian: "little".to_string(), target_endian: "little".to_string(),
target_pointer_width: "32".to_string(), target_pointer_width: "32".to_string(),
target_c_int_width: "32".to_string(), target_c_int_width: "32".to_string(),
data_layout: "e-m:e-p:32:32-i64:64-v128:64:128-a:0:32-n32-S64".to_string(), data_layout: "e-m:e-p:32:32-Fi8-i64:64-v128:64:128-a:0:32-n32-S64".to_string(),
arch: "arm".to_string(), arch: "arm".to_string(),
target_os: "linux".to_string(), target_os: "linux".to_string(),
target_env: "musl".to_string(), target_env: "musl".to_string(),

View file

@ -9,7 +9,7 @@ pub fn target() -> TargetResult {
target_endian: "big".to_string(), target_endian: "big".to_string(),
target_pointer_width: "32".to_string(), target_pointer_width: "32".to_string(),
target_c_int_width: "32".to_string(), target_c_int_width: "32".to_string(),
data_layout: "E-m:e-p:32:32-i64:64-v128:64:128-a:0:32-n32-S64".to_string(), data_layout: "E-m:e-p:32:32-Fi8-i64:64-v128:64:128-a:0:32-n32-S64".to_string(),
arch: "arm".to_string(), arch: "arm".to_string(),
target_os: "none".to_string(), target_os: "none".to_string(),
target_env: "".to_string(), target_env: "".to_string(),

View file

@ -9,7 +9,7 @@ pub fn target() -> TargetResult {
target_endian: "big".to_string(), target_endian: "big".to_string(),
target_pointer_width: "32".to_string(), target_pointer_width: "32".to_string(),
target_c_int_width: "32".to_string(), target_c_int_width: "32".to_string(),
data_layout: "E-m:e-p:32:32-i64:64-v128:64:128-a:0:32-n32-S64".to_string(), data_layout: "E-m:e-p:32:32-Fi8-i64:64-v128:64:128-a:0:32-n32-S64".to_string(),
arch: "arm".to_string(), arch: "arm".to_string(),
target_os: "none".to_string(), target_os: "none".to_string(),
target_env: String::new(), target_env: String::new(),
@ -21,7 +21,7 @@ pub fn target() -> TargetResult {
linker: Some("rust-lld".to_owned()), linker: Some("rust-lld".to_owned()),
relocation_model: "static".to_string(), relocation_model: "static".to_string(),
panic_strategy: PanicStrategy::Abort, panic_strategy: PanicStrategy::Abort,
features: "+vfp3,+d16,+fp-only-sp".to_string(), features: "+vfp3,-d32,-fp16".to_string(),
max_atomic_width: Some(32), max_atomic_width: Some(32),
abi_blacklist: super::arm_base::abi_blacklist(), abi_blacklist: super::arm_base::abi_blacklist(),
emit_debug_gdb_scripts: false, emit_debug_gdb_scripts: false,

View file

@ -7,7 +7,7 @@ pub fn target() -> TargetResult {
target_endian: "little".to_string(), target_endian: "little".to_string(),
target_pointer_width: "32".to_string(), target_pointer_width: "32".to_string(),
target_c_int_width: "32".to_string(), target_c_int_width: "32".to_string(),
data_layout: "e-m:e-p:32:32-i64:64-v128:64:128-a:0:32-n32-S64".to_string(), data_layout: "e-m:e-p:32:32-Fi8-i64:64-v128:64:128-a:0:32-n32-S64".to_string(),
arch: "arm".to_string(), arch: "arm".to_string(),
target_os: "linux".to_string(), target_os: "linux".to_string(),
target_env: "gnu".to_string(), target_env: "gnu".to_string(),

View file

@ -7,7 +7,7 @@ pub fn target() -> TargetResult {
target_endian: "little".to_string(), target_endian: "little".to_string(),
target_pointer_width: "32".to_string(), target_pointer_width: "32".to_string(),
target_c_int_width: "32".to_string(), target_c_int_width: "32".to_string(),
data_layout: "e-m:e-p:32:32-i64:64-v128:64:128-a:0:32-n32-S64".to_string(), data_layout: "e-m:e-p:32:32-Fi8-i64:64-v128:64:128-a:0:32-n32-S64".to_string(),
arch: "arm".to_string(), arch: "arm".to_string(),
target_os: "linux".to_string(), target_os: "linux".to_string(),
target_env: "gnu".to_string(), target_env: "gnu".to_string(),

View file

@ -10,7 +10,7 @@ pub fn target() -> TargetResult {
target_endian: "little".to_string(), target_endian: "little".to_string(),
target_pointer_width: "32".to_string(), target_pointer_width: "32".to_string(),
target_c_int_width: "32".to_string(), target_c_int_width: "32".to_string(),
data_layout: "e-m:e-p:32:32-i64:64-v128:64:128-a:0:32-n32-S64".to_string(), data_layout: "e-m:e-p:32:32-Fi8-i64:64-v128:64:128-a:0:32-n32-S64".to_string(),
arch: "arm".to_string(), arch: "arm".to_string(),
target_os: "linux".to_string(), target_os: "linux".to_string(),
target_env: "musl".to_string(), target_env: "musl".to_string(),

View file

@ -7,7 +7,7 @@ pub fn target() -> TargetResult {
target_endian: "little".to_string(), target_endian: "little".to_string(),
target_pointer_width: "32".to_string(), target_pointer_width: "32".to_string(),
target_c_int_width: "32".to_string(), target_c_int_width: "32".to_string(),
data_layout: "e-m:e-p:32:32-i64:64-v128:64:128-a:0:32-n32-S64".to_string(), data_layout: "e-m:e-p:32:32-Fi8-i64:64-v128:64:128-a:0:32-n32-S64".to_string(),
arch: "arm".to_string(), arch: "arm".to_string(),
target_os: "freebsd".to_string(), target_os: "freebsd".to_string(),
target_env: "gnueabihf".to_string(), target_env: "gnueabihf".to_string(),

View file

@ -8,7 +8,7 @@ pub fn target() -> TargetResult {
target_endian: "little".to_string(), target_endian: "little".to_string(),
target_pointer_width: "32".to_string(), target_pointer_width: "32".to_string(),
target_c_int_width: "32".to_string(), target_c_int_width: "32".to_string(),
data_layout: "e-m:e-p:32:32-i64:64-v128:64:128-a:0:32-n32-S64".to_string(), data_layout: "e-m:e-p:32:32-Fi8-i64:64-v128:64:128-a:0:32-n32-S64".to_string(),
arch: "arm".to_string(), arch: "arm".to_string(),
target_os: "netbsd".to_string(), target_os: "netbsd".to_string(),
target_env: "eabihf".to_string(), target_env: "eabihf".to_string(),

View file

@ -8,7 +8,7 @@ pub fn target() -> TargetResult {
target_endian: "little".to_string(), target_endian: "little".to_string(),
target_pointer_width: "32".to_string(), target_pointer_width: "32".to_string(),
target_c_int_width: "32".to_string(), target_c_int_width: "32".to_string(),
data_layout: "e-m:o-p:32:32-f64:32:64-v64:32:64-v128:32:128-a:0:32-n32-S32".to_string(), data_layout: "e-m:o-p:32:32-Fi8-f64:32:64-v64:32:64-v128:32:128-a:0:32-n32-S32".to_string(),
arch: "arm".to_string(), arch: "arm".to_string(),
target_os: "ios".to_string(), target_os: "ios".to_string(),
target_env: String::new(), target_env: String::new(),

View file

@ -10,7 +10,7 @@ use crate::spec::{LinkerFlavor, Target, TargetOptions, TargetResult};
pub fn target() -> TargetResult { pub fn target() -> TargetResult {
let mut base = super::android_base::opts(); let mut base = super::android_base::opts();
base.features = "+v7,+thumb-mode,+thumb2,+vfp3,+d16,-neon".to_string(); base.features = "+v7,+thumb-mode,+thumb2,+vfp3,-d32,-neon".to_string();
base.max_atomic_width = Some(64); base.max_atomic_width = Some(64);
base.pre_link_args base.pre_link_args
.get_mut(&LinkerFlavor::Gcc).unwrap().push("-march=armv7-a".to_string()); .get_mut(&LinkerFlavor::Gcc).unwrap().push("-march=armv7-a".to_string());
@ -20,7 +20,7 @@ pub fn target() -> TargetResult {
target_endian: "little".to_string(), target_endian: "little".to_string(),
target_pointer_width: "32".to_string(), target_pointer_width: "32".to_string(),
target_c_int_width: "32".to_string(), target_c_int_width: "32".to_string(),
data_layout: "e-m:e-p:32:32-i64:64-v128:64:128-a:0:32-n32-S64".to_string(), data_layout: "e-m:e-p:32:32-Fi8-i64:64-v128:64:128-a:0:32-n32-S64".to_string(),
arch: "arm".to_string(), arch: "arm".to_string(),
target_os: "android".to_string(), target_os: "android".to_string(),
target_env: String::new(), target_env: String::new(),

View file

@ -13,7 +13,7 @@ pub fn target() -> TargetResult {
target_endian: "little".to_string(), target_endian: "little".to_string(),
target_pointer_width: "32".to_string(), target_pointer_width: "32".to_string(),
target_c_int_width: "32".to_string(), target_c_int_width: "32".to_string(),
data_layout: "e-m:e-p:32:32-i64:64-v128:64:128-a:0:32-n32-S64".to_string(), data_layout: "e-m:e-p:32:32-Fi8-i64:64-v128:64:128-a:0:32-n32-S64".to_string(),
arch: "arm".to_string(), arch: "arm".to_string(),
target_os: "cloudabi".to_string(), target_os: "cloudabi".to_string(),
target_env: String::new(), target_env: String::new(),

View file

@ -7,7 +7,7 @@ pub fn target() -> TargetResult {
target_endian: "little".to_string(), target_endian: "little".to_string(),
target_pointer_width: "32".to_string(), target_pointer_width: "32".to_string(),
target_c_int_width: "32".to_string(), target_c_int_width: "32".to_string(),
data_layout: "e-m:e-p:32:32-i64:64-v128:64:128-a:0:32-n32-S64".to_string(), data_layout: "e-m:e-p:32:32-Fi8-i64:64-v128:64:128-a:0:32-n32-S64".to_string(),
arch: "arm".to_string(), arch: "arm".to_string(),
target_os: "freebsd".to_string(), target_os: "freebsd".to_string(),
target_env: "gnueabihf".to_string(), target_env: "gnueabihf".to_string(),
@ -15,7 +15,7 @@ pub fn target() -> TargetResult {
linker_flavor: LinkerFlavor::Gcc, linker_flavor: LinkerFlavor::Gcc,
options: TargetOptions { options: TargetOptions {
features: "+v7,+vfp3,+d16,+thumb2,-neon".to_string(), features: "+v7,+vfp3,-d32,+thumb2,-neon".to_string(),
max_atomic_width: Some(64), max_atomic_width: Some(64),
abi_blacklist: super::arm_base::abi_blacklist(), abi_blacklist: super::arm_base::abi_blacklist(),
target_mcount: "\u{1}__gnu_mcount_nc".to_string(), target_mcount: "\u{1}__gnu_mcount_nc".to_string(),

View file

@ -10,7 +10,7 @@ pub fn target() -> TargetResult {
target_endian: "little".to_string(), target_endian: "little".to_string(),
target_pointer_width: "32".to_string(), target_pointer_width: "32".to_string(),
target_c_int_width: "32".to_string(), target_c_int_width: "32".to_string(),
data_layout: "e-m:e-p:32:32-i64:64-v128:64:128-a:0:32-n32-S64".to_string(), data_layout: "e-m:e-p:32:32-Fi8-i64:64-v128:64:128-a:0:32-n32-S64".to_string(),
arch: "arm".to_string(), arch: "arm".to_string(),
target_os: "linux".to_string(), target_os: "linux".to_string(),
target_env: "gnu".to_string(), target_env: "gnu".to_string(),
@ -19,7 +19,7 @@ pub fn target() -> TargetResult {
options: TargetOptions { options: TargetOptions {
// Info about features at https://wiki.debian.org/ArmHardFloatPort // Info about features at https://wiki.debian.org/ArmHardFloatPort
features: "+v7,+vfp3,+d16,+thumb2,-neon".to_string(), features: "+v7,+vfp3,-d32,+thumb2,-neon".to_string(),
cpu: "generic".to_string(), cpu: "generic".to_string(),
max_atomic_width: Some(64), max_atomic_width: Some(64),
abi_blacklist: super::arm_base::abi_blacklist(), abi_blacklist: super::arm_base::abi_blacklist(),

View file

@ -12,7 +12,7 @@ pub fn target() -> TargetResult {
target_endian: "little".to_string(), target_endian: "little".to_string(),
target_pointer_width: "32".to_string(), target_pointer_width: "32".to_string(),
target_c_int_width: "32".to_string(), target_c_int_width: "32".to_string(),
data_layout: "e-m:e-p:32:32-i64:64-v128:64:128-a:0:32-n32-S64".to_string(), data_layout: "e-m:e-p:32:32-Fi8-i64:64-v128:64:128-a:0:32-n32-S64".to_string(),
arch: "arm".to_string(), arch: "arm".to_string(),
target_os: "linux".to_string(), target_os: "linux".to_string(),
target_env: "musl".to_string(), target_env: "musl".to_string(),
@ -22,7 +22,7 @@ pub fn target() -> TargetResult {
// Most of these settings are copied from the armv7_unknown_linux_gnueabihf // Most of these settings are copied from the armv7_unknown_linux_gnueabihf
// target. // target.
options: TargetOptions { options: TargetOptions {
features: "+v7,+vfp3,+d16,+thumb2,-neon".to_string(), features: "+v7,+vfp3,-d32,+thumb2,-neon".to_string(),
cpu: "generic".to_string(), cpu: "generic".to_string(),
max_atomic_width: Some(64), max_atomic_width: Some(64),
abi_blacklist: super::arm_base::abi_blacklist(), abi_blacklist: super::arm_base::abi_blacklist(),

View file

@ -7,7 +7,7 @@ pub fn target() -> TargetResult {
target_endian: "little".to_string(), target_endian: "little".to_string(),
target_pointer_width: "32".to_string(), target_pointer_width: "32".to_string(),
target_c_int_width: "32".to_string(), target_c_int_width: "32".to_string(),
data_layout: "e-m:e-p:32:32-i64:64-v128:64:128-a:0:32-n32-S64".to_string(), data_layout: "e-m:e-p:32:32-Fi8-i64:64-v128:64:128-a:0:32-n32-S64".to_string(),
arch: "arm".to_string(), arch: "arm".to_string(),
target_os: "netbsd".to_string(), target_os: "netbsd".to_string(),
target_env: "eabihf".to_string(), target_env: "eabihf".to_string(),
@ -15,7 +15,7 @@ pub fn target() -> TargetResult {
linker_flavor: LinkerFlavor::Gcc, linker_flavor: LinkerFlavor::Gcc,
options: TargetOptions { options: TargetOptions {
features: "+v7,+vfp3,+d16,+thumb2,-neon".to_string(), features: "+v7,+vfp3,-d32,+thumb2,-neon".to_string(),
cpu: "generic".to_string(), cpu: "generic".to_string(),
max_atomic_width: Some(64), max_atomic_width: Some(64),
abi_blacklist: super::arm_base::abi_blacklist(), abi_blacklist: super::arm_base::abi_blacklist(),

View file

@ -9,7 +9,7 @@ pub fn target() -> TargetResult {
target_endian: "little".to_string(), target_endian: "little".to_string(),
target_pointer_width: "32".to_string(), target_pointer_width: "32".to_string(),
target_c_int_width: "32".to_string(), target_c_int_width: "32".to_string(),
data_layout: "e-m:e-p:32:32-i64:64-v128:64:128-a:0:32-n32-S64".to_string(), data_layout: "e-m:e-p:32:32-Fi8-i64:64-v128:64:128-a:0:32-n32-S64".to_string(),
arch: "arm".to_string(), arch: "arm".to_string(),
target_os: "none".to_string(), target_os: "none".to_string(),
target_env: "".to_string(), target_env: "".to_string(),

View file

@ -9,7 +9,7 @@ pub fn target() -> TargetResult {
target_endian: "little".to_string(), target_endian: "little".to_string(),
target_pointer_width: "32".to_string(), target_pointer_width: "32".to_string(),
target_c_int_width: "32".to_string(), target_c_int_width: "32".to_string(),
data_layout: "e-m:e-p:32:32-i64:64-v128:64:128-a:0:32-n32-S64".to_string(), data_layout: "e-m:e-p:32:32-Fi8-i64:64-v128:64:128-a:0:32-n32-S64".to_string(),
arch: "arm".to_string(), arch: "arm".to_string(),
target_os: "none".to_string(), target_os: "none".to_string(),
target_env: "".to_string(), target_env: "".to_string(),
@ -21,7 +21,7 @@ pub fn target() -> TargetResult {
linker: Some("rust-lld".to_owned()), linker: Some("rust-lld".to_owned()),
relocation_model: "static".to_string(), relocation_model: "static".to_string(),
panic_strategy: PanicStrategy::Abort, panic_strategy: PanicStrategy::Abort,
features: "+vfp3,+d16,+fp-only-sp".to_string(), features: "+vfp3,-d32,-fp16".to_string(),
max_atomic_width: Some(32), max_atomic_width: Some(32),
abi_blacklist: super::arm_base::abi_blacklist(), abi_blacklist: super::arm_base::abi_blacklist(),
emit_debug_gdb_scripts: false, emit_debug_gdb_scripts: false,

View file

@ -8,7 +8,7 @@ pub fn target() -> TargetResult {
target_endian: "little".to_string(), target_endian: "little".to_string(),
target_pointer_width: "32".to_string(), target_pointer_width: "32".to_string(),
target_c_int_width: "32".to_string(), target_c_int_width: "32".to_string(),
data_layout: "e-m:o-p:32:32-f64:32:64-v64:32:64-v128:32:128-a:0:32-n32-S32".to_string(), data_layout: "e-m:o-p:32:32-Fi8-f64:32:64-v64:32:64-v128:32:128-a:0:32-n32-S32".to_string(),
arch: "arm".to_string(), arch: "arm".to_string(),
target_os: "ios".to_string(), target_os: "ios".to_string(),
target_env: String::new(), target_env: String::new(),

View file

@ -497,8 +497,8 @@ pub struct Target {
pub target_env: String, pub target_env: String,
/// Vendor name to use for conditional compilation. /// Vendor name to use for conditional compilation.
pub target_vendor: String, pub target_vendor: String,
/// Architecture to use for ABI considerations. Valid options: "x86", /// Architecture to use for ABI considerations. Valid options include: "x86",
/// "x86_64", "arm", "aarch64", "mips", "powerpc", and "powerpc64". /// "x86_64", "arm", "aarch64", "mips", "powerpc", "powerpc64", and others.
pub arch: String, pub arch: String,
/// [Data layout](http://llvm.org/docs/LangRef.html#data-layout) to pass to LLVM. /// [Data layout](http://llvm.org/docs/LangRef.html#data-layout) to pass to LLVM.
pub data_layout: String, pub data_layout: String,

View file

@ -8,7 +8,7 @@ pub fn target() -> TargetResult {
target_endian: "little".to_string(), target_endian: "little".to_string(),
target_pointer_width: "32".to_string(), target_pointer_width: "32".to_string(),
target_c_int_width: "32".to_string(), target_c_int_width: "32".to_string(),
data_layout: "e-m:e-p:32:32-i64:64-v128:64:128-a:0:32-n32-S64".to_string(), data_layout: "e-m:e-p:32:32-Fi8-i64:64-v128:64:128-a:0:32-n32-S64".to_string(),
arch: "arm".to_string(), arch: "arm".to_string(),
target_os: "none".to_string(), target_os: "none".to_string(),
target_env: String::new(), target_env: String::new(),

View file

@ -22,7 +22,7 @@ pub fn target() -> TargetResult {
target_endian: "little".to_string(), target_endian: "little".to_string(),
target_pointer_width: "32".to_string(), target_pointer_width: "32".to_string(),
target_c_int_width: "32".to_string(), target_c_int_width: "32".to_string(),
data_layout: "e-m:w-p:32:32-i64:64-v128:64:128-a:0:32-n32-S64".to_string(), data_layout: "e-m:w-p:32:32-Fi8-i64:64-v128:64:128-a:0:32-n32-S64".to_string(),
arch: "arm".to_string(), arch: "arm".to_string(),
target_os: "windows".to_string(), target_os: "windows".to_string(),
target_env: "msvc".to_string(), target_env: "msvc".to_string(),

View file

@ -17,7 +17,7 @@ pub fn target() -> TargetResult {
target_endian: "little".to_string(), target_endian: "little".to_string(),
target_pointer_width: "32".to_string(), target_pointer_width: "32".to_string(),
target_c_int_width: "32".to_string(), target_c_int_width: "32".to_string(),
data_layout: "e-m:e-p:32:32-i64:64-v128:64:128-a:0:32-n32-S64".to_string(), data_layout: "e-m:e-p:32:32-Fi8-i64:64-v128:64:128-a:0:32-n32-S64".to_string(),
arch: "arm".to_string(), arch: "arm".to_string(),
target_os: "none".to_string(), target_os: "none".to_string(),
target_env: String::new(), target_env: String::new(),

View file

@ -6,7 +6,7 @@
// Additionally, this target uses the "hard" floating convention (ABI) where floating point values // Additionally, this target uses the "hard" floating convention (ABI) where floating point values
// are passed to/from subroutines via FPU registers (S0, S1, D0, D1, etc.). // are passed to/from subroutines via FPU registers (S0, S1, D0, D1, etc.).
// //
// To opt into double precision hardware support, use the `-C target-feature=-fp-only-sp` flag. // To opt into double precision hardware support, use the `-C target-feature=+fp64` flag.
use crate::spec::{LinkerFlavor, LldFlavor, Target, TargetOptions, TargetResult}; use crate::spec::{LinkerFlavor, LldFlavor, Target, TargetOptions, TargetResult};
@ -16,7 +16,7 @@ pub fn target() -> TargetResult {
target_endian: "little".to_string(), target_endian: "little".to_string(),
target_pointer_width: "32".to_string(), target_pointer_width: "32".to_string(),
target_c_int_width: "32".to_string(), target_c_int_width: "32".to_string(),
data_layout: "e-m:e-p:32:32-i64:64-v128:64:128-a:0:32-n32-S64".to_string(), data_layout: "e-m:e-p:32:32-Fi8-i64:64-v128:64:128-a:0:32-n32-S64".to_string(),
arch: "arm".to_string(), arch: "arm".to_string(),
target_os: "none".to_string(), target_os: "none".to_string(),
target_env: String::new(), target_env: String::new(),
@ -26,14 +26,14 @@ pub fn target() -> TargetResult {
options: TargetOptions { options: TargetOptions {
// `+vfp4` is the lowest common denominator between the Cortex-M4 (vfp4-16) and the // `+vfp4` is the lowest common denominator between the Cortex-M4 (vfp4-16) and the
// Cortex-M7 (vfp5) // Cortex-M7 (vfp5)
// `+d16` both the Cortex-M4 and the Cortex-M7 only have 16 double-precision registers // `-d32` both the Cortex-M4 and the Cortex-M7 only have 16 double-precision registers
// available // available
// `+fp-only-sp` The Cortex-M4 only supports single precision floating point operations // `-fp64` The Cortex-M4 only supports single precision floating point operations
// whereas in the Cortex-M7 double precision is optional // whereas in the Cortex-M7 double precision is optional
// //
// Reference: // Reference:
// ARMv7-M Architecture Reference Manual - A2.5 The optional floating-point extension // ARMv7-M Architecture Reference Manual - A2.5 The optional floating-point extension
features: "+vfp4,+d16,+fp-only-sp".to_string(), features: "+vfp4,-d32,-fp64".to_string(),
max_atomic_width: Some(32), max_atomic_width: Some(32),
.. super::thumb_base::opts() .. super::thumb_base::opts()
} }

View file

@ -8,7 +8,7 @@ pub fn target() -> TargetResult {
target_endian: "little".to_string(), target_endian: "little".to_string(),
target_pointer_width: "32".to_string(), target_pointer_width: "32".to_string(),
target_c_int_width: "32".to_string(), target_c_int_width: "32".to_string(),
data_layout: "e-m:e-p:32:32-i64:64-v128:64:128-a:0:32-n32-S64".to_string(), data_layout: "e-m:e-p:32:32-Fi8-i64:64-v128:64:128-a:0:32-n32-S64".to_string(),
arch: "arm".to_string(), arch: "arm".to_string(),
target_os: "none".to_string(), target_os: "none".to_string(),
target_env: String::new(), target_env: String::new(),

View file

@ -20,7 +20,7 @@ pub fn target() -> TargetResult {
target_endian: "little".to_string(), target_endian: "little".to_string(),
target_pointer_width: "32".to_string(), target_pointer_width: "32".to_string(),
target_c_int_width: "32".to_string(), target_c_int_width: "32".to_string(),
data_layout: "e-m:e-p:32:32-i64:64-v128:64:128-a:0:32-n32-S64".to_string(), data_layout: "e-m:e-p:32:32-Fi8-i64:64-v128:64:128-a:0:32-n32-S64".to_string(),
arch: "arm".to_string(), arch: "arm".to_string(),
target_os: "android".to_string(), target_os: "android".to_string(),
target_env: "".to_string(), target_env: "".to_string(),

View file

@ -13,7 +13,7 @@ pub fn target() -> TargetResult {
target_endian: "little".to_string(), target_endian: "little".to_string(),
target_pointer_width: "32".to_string(), target_pointer_width: "32".to_string(),
target_c_int_width: "32".to_string(), target_c_int_width: "32".to_string(),
data_layout: "e-m:e-p:32:32-i64:64-v128:64:128-a:0:32-n32-S64".to_string(), data_layout: "e-m:e-p:32:32-Fi8-i64:64-v128:64:128-a:0:32-n32-S64".to_string(),
arch: "arm".to_string(), arch: "arm".to_string(),
target_os: "linux".to_string(), target_os: "linux".to_string(),
target_env: "gnu".to_string(), target_env: "gnu".to_string(),

View file

@ -8,7 +8,7 @@ pub fn target() -> TargetResult {
target_endian: "little".to_string(), target_endian: "little".to_string(),
target_pointer_width: "32".to_string(), target_pointer_width: "32".to_string(),
target_c_int_width: "32".to_string(), target_c_int_width: "32".to_string(),
data_layout: "e-m:e-p:32:32-i64:64-v128:64:128-a:0:32-n32-S64".to_string(), data_layout: "e-m:e-p:32:32-Fi8-i64:64-v128:64:128-a:0:32-n32-S64".to_string(),
arch: "arm".to_string(), arch: "arm".to_string(),
target_os: "none".to_string(), target_os: "none".to_string(),
target_env: String::new(), target_env: String::new(),

View file

@ -9,7 +9,7 @@ pub fn target() -> TargetResult {
target_endian: "little".to_string(), target_endian: "little".to_string(),
target_pointer_width: "32".to_string(), target_pointer_width: "32".to_string(),
target_c_int_width: "32".to_string(), target_c_int_width: "32".to_string(),
data_layout: "e-m:e-p:32:32-i64:64-v128:64:128-a:0:32-n32-S64".to_string(), data_layout: "e-m:e-p:32:32-Fi8-i64:64-v128:64:128-a:0:32-n32-S64".to_string(),
arch: "arm".to_string(), arch: "arm".to_string(),
target_os: "none".to_string(), target_os: "none".to_string(),
target_env: String::new(), target_env: String::new(),

View file

@ -9,7 +9,7 @@ pub fn target() -> TargetResult {
target_endian: "little".to_string(), target_endian: "little".to_string(),
target_pointer_width: "32".to_string(), target_pointer_width: "32".to_string(),
target_c_int_width: "32".to_string(), target_c_int_width: "32".to_string(),
data_layout: "e-m:e-p:32:32-i64:64-v128:64:128-a:0:32-n32-S64".to_string(), data_layout: "e-m:e-p:32:32-Fi8-i64:64-v128:64:128-a:0:32-n32-S64".to_string(),
arch: "arm".to_string(), arch: "arm".to_string(),
target_os: "none".to_string(), target_os: "none".to_string(),
target_env: String::new(), target_env: String::new(),
@ -22,7 +22,7 @@ pub fn target() -> TargetResult {
// the FPU uses the FPv5 architecture, single-precision instructions // the FPU uses the FPv5 architecture, single-precision instructions
// and 16 D registers. // and 16 D registers.
// These parameters map to the following LLVM features. // These parameters map to the following LLVM features.
features: "+fp-armv8,+fp-only-sp,+d16".to_string(), features: "+fp-armv8,-fp64,-d32".to_string(),
max_atomic_width: Some(32), max_atomic_width: Some(32),
.. super::thumb_base::opts() .. super::thumb_base::opts()
}, },

View file

@ -701,7 +701,7 @@ pub trait Resolver {
fn get_module_scope(&mut self, id: ast::NodeId) -> Mark; fn get_module_scope(&mut self, id: ast::NodeId) -> Mark;
fn resolve_dollar_crates(&mut self, fragment: &AstFragment); fn resolve_dollar_crates(&mut self);
fn visit_ast_fragment_with_placeholders(&mut self, mark: Mark, fragment: &AstFragment, fn visit_ast_fragment_with_placeholders(&mut self, mark: Mark, fragment: &AstFragment,
derives: &[Mark]); derives: &[Mark]);
fn add_builtin(&mut self, ident: ast::Ident, ext: Lrc<SyntaxExtension>); fn add_builtin(&mut self, ident: ast::Ident, ext: Lrc<SyntaxExtension>);

View file

@ -429,7 +429,7 @@ impl<'a, 'b> MacroExpander<'a, 'b> {
fn collect_invocations(&mut self, mut fragment: AstFragment, derives: &[Mark]) fn collect_invocations(&mut self, mut fragment: AstFragment, derives: &[Mark])
-> (AstFragment, Vec<Invocation>) { -> (AstFragment, Vec<Invocation>) {
// Resolve `$crate`s in the fragment for pretty-printing. // Resolve `$crate`s in the fragment for pretty-printing.
self.cx.resolver.resolve_dollar_crates(&fragment); self.cx.resolver.resolve_dollar_crates();
let invocations = { let invocations = {
let mut collector = InvocationCollector { let mut collector = InvocationCollector {

View file

@ -18,7 +18,7 @@ use crate::tokenstream::{self, TokenStream, TokenTree};
use rustc_target::spec::abi::{self, Abi}; use rustc_target::spec::abi::{self, Abi};
use syntax_pos::{self, BytePos}; use syntax_pos::{self, BytePos};
use syntax_pos::{DUMMY_SP, FileName}; use syntax_pos::{DUMMY_SP, FileName, Span};
use std::borrow::Cow; use std::borrow::Cow;
use std::io::Read; use std::io::Read;
@ -181,7 +181,46 @@ pub fn literal_to_string(lit: token::Lit) -> String {
out out
} }
fn ident_to_string(ident: ast::Ident, is_raw: bool) -> String {
ident_to_string_ext(ident.name, is_raw, Some(ident.span))
}
// AST pretty-printer is used as a fallback for turning AST structures into token streams for
// proc macros. Additionally, proc macros may stringify their input and expect it survive the
// stringification (especially true for proc macro derives written between Rust 1.15 and 1.30).
// So we need to somehow pretty-print `$crate` in a way preserving at least some of its
// hygiene data, most importantly name of the crate it refers to.
// As a result we print `$crate` as `crate` if it refers to the local crate
// and as `::other_crate_name` if it refers to some other crate.
// Note, that this is only done if the ident token is printed from inside of AST pretty-pringing,
// but not otherwise. Pretty-printing is the only way for proc macros to discover token contents,
// so we should not perform this lossy conversion if the top level call to the pretty-printer was
// done for a token stream or a single token.
fn ident_to_string_ext(
name: ast::Name, is_raw: bool, convert_dollar_crate: Option<Span>
) -> String {
if is_raw {
format!("r#{}", name)
} else {
if name == kw::DollarCrate {
if let Some(span) = convert_dollar_crate {
let converted = span.ctxt().dollar_crate_name();
return if converted.is_path_segment_keyword() {
converted.to_string()
} else {
format!("::{}", converted)
}
}
}
name.to_string()
}
}
pub fn token_kind_to_string(tok: &TokenKind) -> String { pub fn token_kind_to_string(tok: &TokenKind) -> String {
token_kind_to_string_ext(tok, None)
}
fn token_kind_to_string_ext(tok: &TokenKind, convert_dollar_crate: Option<Span>) -> String {
match *tok { match *tok {
token::Eq => "=".to_string(), token::Eq => "=".to_string(),
token::Lt => "<".to_string(), token::Lt => "<".to_string(),
@ -227,8 +266,7 @@ pub fn token_kind_to_string(tok: &TokenKind) -> String {
token::Literal(lit) => literal_to_string(lit), token::Literal(lit) => literal_to_string(lit),
/* Name components */ /* Name components */
token::Ident(s, false) => s.to_string(), token::Ident(s, is_raw) => ident_to_string_ext(s, is_raw, convert_dollar_crate),
token::Ident(s, true) => format!("r#{}", s),
token::Lifetime(s) => s.to_string(), token::Lifetime(s) => s.to_string(),
/* Other */ /* Other */
@ -243,7 +281,12 @@ pub fn token_kind_to_string(tok: &TokenKind) -> String {
} }
pub fn token_to_string(token: &Token) -> String { pub fn token_to_string(token: &Token) -> String {
token_kind_to_string(&token.kind) token_to_string_ext(token, false)
}
fn token_to_string_ext(token: &Token, convert_dollar_crate: bool) -> String {
let convert_dollar_crate = if convert_dollar_crate { Some(token.span) } else { None };
token_kind_to_string_ext(&token.kind, convert_dollar_crate)
} }
crate fn nonterminal_to_string(nt: &Nonterminal) -> String { crate fn nonterminal_to_string(nt: &Nonterminal) -> String {
@ -256,9 +299,8 @@ crate fn nonterminal_to_string(nt: &Nonterminal) -> String {
token::NtBlock(ref e) => block_to_string(e), token::NtBlock(ref e) => block_to_string(e),
token::NtStmt(ref e) => stmt_to_string(e), token::NtStmt(ref e) => stmt_to_string(e),
token::NtPat(ref e) => pat_to_string(e), token::NtPat(ref e) => pat_to_string(e),
token::NtIdent(e, false) => ident_to_string(e), token::NtIdent(e, is_raw) => ident_to_string(e, is_raw),
token::NtIdent(e, true) => format!("r#{}", ident_to_string(e)), token::NtLifetime(e) => e.to_string(),
token::NtLifetime(e) => ident_to_string(e),
token::NtLiteral(ref e) => expr_to_string(e), token::NtLiteral(ref e) => expr_to_string(e),
token::NtTT(ref tree) => tt_to_string(tree.clone()), token::NtTT(ref tree) => tt_to_string(tree.clone()),
token::NtImplItem(ref e) => impl_item_to_string(e), token::NtImplItem(ref e) => impl_item_to_string(e),
@ -293,15 +335,15 @@ pub fn lifetime_to_string(lt: &ast::Lifetime) -> String {
} }
pub fn tt_to_string(tt: tokenstream::TokenTree) -> String { pub fn tt_to_string(tt: tokenstream::TokenTree) -> String {
to_string(|s| s.print_tt(tt)) to_string(|s| s.print_tt(tt, false))
} }
pub fn tts_to_string(tts: &[tokenstream::TokenTree]) -> String { pub fn tts_to_string(tts: &[tokenstream::TokenTree]) -> String {
to_string(|s| s.print_tts(tts.iter().cloned().collect())) tokens_to_string(tts.iter().cloned().collect())
} }
pub fn tokens_to_string(tokens: TokenStream) -> String { pub fn tokens_to_string(tokens: TokenStream) -> String {
to_string(|s| s.print_tts(tokens)) to_string(|s| s.print_tts_ext(tokens, false))
} }
pub fn stmt_to_string(stmt: &ast::Stmt) -> String { pub fn stmt_to_string(stmt: &ast::Stmt) -> String {
@ -344,10 +386,6 @@ pub fn path_segment_to_string(p: &ast::PathSegment) -> String {
to_string(|s| s.print_path_segment(p, false)) to_string(|s| s.print_path_segment(p, false))
} }
pub fn ident_to_string(id: ast::Ident) -> String {
to_string(|s| s.print_ident(id))
}
pub fn vis_to_string(v: &ast::Visibility) -> String { pub fn vis_to_string(v: &ast::Visibility) -> String {
to_string(|s| s.print_visibility(v)) to_string(|s| s.print_visibility(v))
} }
@ -629,11 +667,7 @@ pub trait PrintState<'a> {
self.writer().word("::"); self.writer().word("::");
} }
if segment.ident.name != kw::PathRoot { if segment.ident.name != kw::PathRoot {
if segment.ident.name == kw::DollarCrate { self.writer().word(ident_to_string(segment.ident, segment.ident.is_raw_guess()));
self.print_dollar_crate(segment.ident);
} else {
self.writer().word(segment.ident.as_str().to_string());
}
} }
} }
} }
@ -707,10 +741,10 @@ pub trait PrintState<'a> {
/// appropriate macro, transcribe back into the grammar we just parsed from, /// appropriate macro, transcribe back into the grammar we just parsed from,
/// and then pretty-print the resulting AST nodes (so, e.g., we print /// and then pretty-print the resulting AST nodes (so, e.g., we print
/// expression arguments as expressions). It can be done! I think. /// expression arguments as expressions). It can be done! I think.
fn print_tt(&mut self, tt: tokenstream::TokenTree) { fn print_tt(&mut self, tt: tokenstream::TokenTree, convert_dollar_crate: bool) {
match tt { match tt {
TokenTree::Token(ref token) => { TokenTree::Token(ref token) => {
self.writer().word(token_to_string(&token)); self.writer().word(token_to_string_ext(&token, convert_dollar_crate));
match token.kind { match token.kind {
token::DocComment(..) => { token::DocComment(..) => {
self.writer().hardbreak() self.writer().hardbreak()
@ -729,12 +763,16 @@ pub trait PrintState<'a> {
} }
fn print_tts(&mut self, tts: tokenstream::TokenStream) { fn print_tts(&mut self, tts: tokenstream::TokenStream) {
self.print_tts_ext(tts, true)
}
fn print_tts_ext(&mut self, tts: tokenstream::TokenStream, convert_dollar_crate: bool) {
self.ibox(0); self.ibox(0);
for (i, tt) in tts.into_trees().enumerate() { for (i, tt) in tts.into_trees().enumerate() {
if i != 0 { if i != 0 {
self.writer().space(); self.writer().space();
} }
self.print_tt(tt); self.print_tt(tt, convert_dollar_crate);
} }
self.end(); self.end();
} }
@ -744,21 +782,6 @@ pub trait PrintState<'a> {
} }
fn nbsp(&mut self) { self.writer().word(" ") } fn nbsp(&mut self) { self.writer().word(" ") }
// AST pretty-printer is used as a fallback for turning AST structures into token streams for
// proc macros. Additionally, proc macros may stringify their input and expect it survive the
// stringification (especially true for proc macro derives written between Rust 1.15 and 1.30).
// So we need to somehow pretty-print `$crate` in paths in a way preserving at least some of
// its hygiene data, most importantly name of the crate it refers to.
// As a result we print `$crate` as `crate` if it refers to the local crate
// and as `::other_crate_name` if it refers to some other crate.
fn print_dollar_crate(&mut self, ident: ast::Ident) {
let name = ident.span.ctxt().dollar_crate_name();
if !ast::Ident::with_empty_ctxt(name).is_path_segment_keyword() {
self.writer().word("::");
}
self.writer().word(name.as_str().to_string())
}
} }
impl<'a> PrintState<'a> for State<'a> { impl<'a> PrintState<'a> for State<'a> {
@ -2287,11 +2310,7 @@ impl<'a> State<'a> {
} }
crate fn print_ident(&mut self, ident: ast::Ident) { crate fn print_ident(&mut self, ident: ast::Ident) {
if ident.is_raw_guess() { self.s.word(ident_to_string(ident, ident.is_raw_guess()));
self.s.word(format!("r#{}", ident));
} else {
self.s.word(ident.as_str().to_string());
}
self.ann.post(self, AnnNode::Ident(&ident)) self.ann.post(self, AnnNode::Ident(&ident))
} }
@ -2322,11 +2341,7 @@ impl<'a> State<'a> {
segment: &ast::PathSegment, segment: &ast::PathSegment,
colons_before_params: bool) { colons_before_params: bool) {
if segment.ident.name != kw::PathRoot { if segment.ident.name != kw::PathRoot {
if segment.ident.name == kw::DollarCrate {
self.print_dollar_crate(segment.ident);
} else {
self.print_ident(segment.ident); self.print_ident(segment.ident);
}
if let Some(ref args) = segment.args { if let Some(ref args) = segment.args {
self.print_generic_args(args, colons_before_params); self.print_generic_args(args, colons_before_params);
} }

View file

@ -33,7 +33,7 @@ use crate::symbol::{kw, Symbol};
use serialize::{Encodable, Decodable, Encoder, Decoder}; use serialize::{Encodable, Decodable, Encoder, Decoder};
use rustc_data_structures::fx::{FxHashMap, FxHashSet}; use rustc_data_structures::fx::{FxHashMap, FxHashSet};
use rustc_data_structures::sync::Lrc; use rustc_data_structures::sync::Lrc;
use std::{fmt, mem}; use std::fmt;
/// A SyntaxContext represents a chain of macro expansions (represented by marks). /// A SyntaxContext represents a chain of macro expansions (represented by marks).
#[derive(Clone, Copy, PartialEq, Eq, Default, PartialOrd, Ord, Hash)] #[derive(Clone, Copy, PartialEq, Eq, Default, PartialOrd, Ord, Hash)]
@ -387,6 +387,23 @@ pub fn walk_chain(span: Span, to: SyntaxContext) -> Span {
HygieneData::with(|data| data.walk_chain(span, to)) HygieneData::with(|data| data.walk_chain(span, to))
} }
pub fn update_dollar_crate_names(mut get_name: impl FnMut(SyntaxContext) -> Symbol) {
// The new contexts that need updating are at the end of the list and have `$crate` as a name.
let (len, to_update) = HygieneData::with(|data| (
data.syntax_contexts.len(),
data.syntax_contexts.iter().rev()
.take_while(|scdata| scdata.dollar_crate_name == kw::DollarCrate).count()
));
// The callback must be called from outside of the `HygieneData` lock,
// since it will try to acquire it too.
let range_to_update = len - to_update .. len;
let names: Vec<_> =
range_to_update.clone().map(|idx| get_name(SyntaxContext::from_u32(idx as u32))).collect();
HygieneData::with(|data| range_to_update.zip(names.into_iter()).for_each(|(idx, name)| {
data.syntax_contexts[idx].dollar_crate_name = name;
}))
}
impl SyntaxContext { impl SyntaxContext {
#[inline] #[inline]
pub const fn empty() -> Self { pub const fn empty() -> Self {
@ -614,17 +631,6 @@ impl SyntaxContext {
pub fn dollar_crate_name(self) -> Symbol { pub fn dollar_crate_name(self) -> Symbol {
HygieneData::with(|data| data.syntax_contexts[self.0 as usize].dollar_crate_name) HygieneData::with(|data| data.syntax_contexts[self.0 as usize].dollar_crate_name)
} }
pub fn set_dollar_crate_name(self, dollar_crate_name: Symbol) {
HygieneData::with(|data| {
let prev_dollar_crate_name = mem::replace(
&mut data.syntax_contexts[self.0 as usize].dollar_crate_name, dollar_crate_name
);
assert!(dollar_crate_name == prev_dollar_crate_name ||
prev_dollar_crate_name == kw::DollarCrate,
"$crate name is reset for a syntax context");
})
}
} }
impl fmt::Debug for SyntaxContext { impl fmt::Debug for SyntaxContext {

View file

@ -913,7 +913,10 @@ LLVMRustCreateThinLTOData(LLVMRustThinLTOModule *modules,
GlobalValue::LinkageTypes NewLinkage) { GlobalValue::LinkageTypes NewLinkage) {
ResolvedODR[ModuleIdentifier][GUID] = NewLinkage; ResolvedODR[ModuleIdentifier][GUID] = NewLinkage;
}; };
#if LLVM_VERSION_GE(8, 0) #if LLVM_VERSION_GE(9, 0)
thinLTOResolvePrevailingInIndex(Ret->Index, isPrevailing, recordNewLinkage,
Ret->GUIDPreservedSymbols);
#elif LLVM_VERSION_GE(8, 0)
thinLTOResolvePrevailingInIndex(Ret->Index, isPrevailing, recordNewLinkage); thinLTOResolvePrevailingInIndex(Ret->Index, isPrevailing, recordNewLinkage);
#else #else
thinLTOResolveWeakForLinkerInIndex(Ret->Index, isPrevailing, recordNewLinkage); thinLTOResolveWeakForLinkerInIndex(Ret->Index, isPrevailing, recordNewLinkage);

View file

@ -237,6 +237,17 @@ extern "C" void LLVMRustAddDereferenceableOrNullCallSiteAttr(LLVMValueRef Instr,
Call->getContext(), Index, B)); Call->getContext(), Index, B));
} }
extern "C" void LLVMRustAddByValCallSiteAttr(LLVMValueRef Instr, unsigned Index,
LLVMTypeRef Ty) {
CallSite Call = CallSite(unwrap<Instruction>(Instr));
#if LLVM_VERSION_GE(9, 0)
Attribute Attr = Attribute::getWithByValType(Call->getContext(), unwrap(Ty));
#else
Attribute Attr = Attribute::get(Call->getContext(), Attribute::ByVal);
#endif
Call.addAttribute(Index, Attr);
}
extern "C" void LLVMRustAddFunctionAttribute(LLVMValueRef Fn, unsigned Index, extern "C" void LLVMRustAddFunctionAttribute(LLVMValueRef Fn, unsigned Index,
LLVMRustAttribute RustAttr) { LLVMRustAttribute RustAttr) {
Function *A = unwrap<Function>(Fn); Function *A = unwrap<Function>(Fn);
@ -271,6 +282,17 @@ extern "C" void LLVMRustAddDereferenceableOrNullAttr(LLVMValueRef Fn,
A->addAttributes(Index, B); A->addAttributes(Index, B);
} }
extern "C" void LLVMRustAddByValAttr(LLVMValueRef Fn, unsigned Index,
LLVMTypeRef Ty) {
Function *F = unwrap<Function>(Fn);
#if LLVM_VERSION_GE(9, 0)
Attribute Attr = Attribute::getWithByValType(F->getContext(), unwrap(Ty));
#else
Attribute Attr = Attribute::get(F->getContext(), Attribute::ByVal);
#endif
F->addAttribute(Index, Attr);
}
extern "C" void LLVMRustAddFunctionAttrStringValue(LLVMValueRef Fn, extern "C" void LLVMRustAddFunctionAttrStringValue(LLVMValueRef Fn,
unsigned Index, unsigned Index,
const char *Name, const char *Name,

View file

@ -7,7 +7,7 @@
// compile-flags: -g -C no-prepopulate-passes // compile-flags: -g -C no-prepopulate-passes
// CHECK-LABEL: @main // CHECK-LABEL: @main
// CHECK: {{.*}}DISubprogram{{.*}}name: "main",{{.*}}DIFlagMainSubprogram{{.*}} // CHECK: {{.*}}DISubprogram{{.*}}name: "main",{{.*}}DI{{(SP)?}}FlagMainSubprogram{{.*}}
pub fn main() { pub fn main() {
} }

View file

@ -6,7 +6,7 @@
#![feature(start)] #![feature(start)]
// CHECK-LABEL: @main // CHECK-LABEL: @main
// CHECK: {{.*}}DISubprogram{{.*}}name: "start",{{.*}}DIFlagMainSubprogram{{.*}} // CHECK: {{.*}}DISubprogram{{.*}}name: "start",{{.*}}DI{{(SP)?}}FlagMainSubprogram{{.*}}
#[start] #[start]
fn start(_: isize, _: *const *const u8) -> isize { fn start(_: isize, _: *const *const u8) -> isize {

View file

@ -14,3 +14,9 @@ macro_rules! external {
struct D($crate::S); struct D($crate::S);
}; };
} }
#[macro_export]
macro_rules! issue_62325 { () => {
#[print_attr]
struct B(identity!($crate::S));
}}

View file

@ -1,4 +1,4 @@
PRINT-BANG INPUT (DISPLAY): struct M ( $crate :: S ) ; PRINT-BANG INPUT (DISPLAY): struct M ( crate :: S ) ;
PRINT-BANG INPUT (DEBUG): TokenStream [ PRINT-BANG INPUT (DEBUG): TokenStream [
Ident { Ident {
ident: "struct", ident: "struct",
@ -39,7 +39,7 @@ PRINT-BANG INPUT (DEBUG): TokenStream [
}, },
] ]
PRINT-ATTR INPUT (DISPLAY): struct A(crate::S); PRINT-ATTR INPUT (DISPLAY): struct A(crate::S);
PRINT-ATTR RE-COLLECTED (DISPLAY): struct A ( $crate :: S ) ; PRINT-ATTR RE-COLLECTED (DISPLAY): struct A ( crate :: S ) ;
PRINT-ATTR INPUT (DEBUG): TokenStream [ PRINT-ATTR INPUT (DEBUG): TokenStream [
Ident { Ident {
ident: "struct", ident: "struct",

View file

@ -0,0 +1,27 @@
// check-pass
// edition:2018
// aux-build:test-macros.rs
// aux-build:dollar-crate-external.rs
// Anonymize unstable non-dummy spans while still showing dummy spans `0..0`.
// normalize-stdout-test "bytes\([^0]\w*\.\.(\w+)\)" -> "bytes(LO..$1)"
// normalize-stdout-test "bytes\((\w+)\.\.[^0]\w*\)" -> "bytes($1..HI)"
#![feature(proc_macro_hygiene)]
#[macro_use]
extern crate test_macros;
extern crate dollar_crate_external;
type S = u8;
macro_rules! m { () => {
#[print_attr]
struct A(identity!($crate::S));
}}
m!();
dollar_crate_external::issue_62325!();
fn main() {}

View file

@ -0,0 +1,112 @@
PRINT-ATTR INPUT (DISPLAY): struct A(identity!(crate :: S));
PRINT-ATTR RE-COLLECTED (DISPLAY): struct A ( identity ! ( crate :: S ) ) ;
PRINT-ATTR INPUT (DEBUG): TokenStream [
Ident {
ident: "struct",
span: #2 bytes(LO..HI),
},
Ident {
ident: "A",
span: #2 bytes(LO..HI),
},
Group {
delimiter: Parenthesis,
stream: TokenStream [
Ident {
ident: "identity",
span: #2 bytes(LO..HI),
},
Punct {
ch: '!',
spacing: Alone,
span: #2 bytes(LO..HI),
},
Group {
delimiter: Parenthesis,
stream: TokenStream [
Ident {
ident: "$crate",
span: #2 bytes(LO..HI),
},
Punct {
ch: ':',
spacing: Joint,
span: #2 bytes(LO..HI),
},
Punct {
ch: ':',
spacing: Alone,
span: #2 bytes(LO..HI),
},
Ident {
ident: "S",
span: #2 bytes(LO..HI),
},
],
span: #2 bytes(LO..HI),
},
],
span: #2 bytes(LO..HI),
},
Punct {
ch: ';',
spacing: Alone,
span: #2 bytes(LO..HI),
},
]
PRINT-ATTR INPUT (DISPLAY): struct B(identity!(::dollar_crate_external :: S));
PRINT-ATTR RE-COLLECTED (DISPLAY): struct B ( identity ! ( ::dollar_crate_external :: S ) ) ;
PRINT-ATTR INPUT (DEBUG): TokenStream [
Ident {
ident: "struct",
span: #7 bytes(LO..HI),
},
Ident {
ident: "B",
span: #7 bytes(LO..HI),
},
Group {
delimiter: Parenthesis,
stream: TokenStream [
Ident {
ident: "identity",
span: #7 bytes(LO..HI),
},
Punct {
ch: '!',
spacing: Alone,
span: #7 bytes(LO..HI),
},
Group {
delimiter: Parenthesis,
stream: TokenStream [
Ident {
ident: "$crate",
span: #7 bytes(LO..HI),
},
Punct {
ch: ':',
spacing: Joint,
span: #7 bytes(LO..HI),
},
Punct {
ch: ':',
spacing: Alone,
span: #7 bytes(LO..HI),
},
Ident {
ident: "S",
span: #7 bytes(LO..HI),
},
],
span: #7 bytes(LO..HI),
},
],
span: #7 bytes(LO..HI),
},
Punct {
ch: ';',
spacing: Alone,
span: #7 bytes(LO..HI),
},
]

View file

@ -1,4 +1,4 @@
PRINT-BANG INPUT (DISPLAY): struct M ( $crate :: S ) ; PRINT-BANG INPUT (DISPLAY): struct M ( crate :: S ) ;
PRINT-BANG INPUT (DEBUG): TokenStream [ PRINT-BANG INPUT (DEBUG): TokenStream [
Ident { Ident {
ident: "struct", ident: "struct",
@ -39,7 +39,7 @@ PRINT-BANG INPUT (DEBUG): TokenStream [
}, },
] ]
PRINT-ATTR INPUT (DISPLAY): struct A(crate::S); PRINT-ATTR INPUT (DISPLAY): struct A(crate::S);
PRINT-ATTR RE-COLLECTED (DISPLAY): struct A ( $crate :: S ) ; PRINT-ATTR RE-COLLECTED (DISPLAY): struct A ( crate :: S ) ;
PRINT-ATTR INPUT (DEBUG): TokenStream [ PRINT-ATTR INPUT (DEBUG): TokenStream [
Ident { Ident {
ident: "struct", ident: "struct",
@ -80,7 +80,7 @@ PRINT-ATTR INPUT (DEBUG): TokenStream [
}, },
] ]
PRINT-DERIVE INPUT (DISPLAY): struct D(crate::S); PRINT-DERIVE INPUT (DISPLAY): struct D(crate::S);
PRINT-DERIVE RE-COLLECTED (DISPLAY): struct D ( $crate :: S ) ; PRINT-DERIVE RE-COLLECTED (DISPLAY): struct D ( crate :: S ) ;
PRINT-DERIVE INPUT (DEBUG): TokenStream [ PRINT-DERIVE INPUT (DEBUG): TokenStream [
Ident { Ident {
ident: "struct", ident: "struct",
@ -120,7 +120,7 @@ PRINT-DERIVE INPUT (DEBUG): TokenStream [
span: #2 bytes(LO..HI), span: #2 bytes(LO..HI),
}, },
] ]
PRINT-BANG INPUT (DISPLAY): struct M ( $crate :: S ) ; PRINT-BANG INPUT (DISPLAY): struct M ( ::dollar_crate_external :: S ) ;
PRINT-BANG INPUT (DEBUG): TokenStream [ PRINT-BANG INPUT (DEBUG): TokenStream [
Ident { Ident {
ident: "struct", ident: "struct",
@ -161,7 +161,7 @@ PRINT-BANG INPUT (DEBUG): TokenStream [
}, },
] ]
PRINT-ATTR INPUT (DISPLAY): struct A(::dollar_crate_external::S); PRINT-ATTR INPUT (DISPLAY): struct A(::dollar_crate_external::S);
PRINT-ATTR RE-COLLECTED (DISPLAY): struct A ( $crate :: S ) ; PRINT-ATTR RE-COLLECTED (DISPLAY): struct A ( ::dollar_crate_external :: S ) ;
PRINT-ATTR INPUT (DEBUG): TokenStream [ PRINT-ATTR INPUT (DEBUG): TokenStream [
Ident { Ident {
ident: "struct", ident: "struct",
@ -202,7 +202,7 @@ PRINT-ATTR INPUT (DEBUG): TokenStream [
}, },
] ]
PRINT-DERIVE INPUT (DISPLAY): struct D(::dollar_crate_external::S); PRINT-DERIVE INPUT (DISPLAY): struct D(::dollar_crate_external::S);
PRINT-DERIVE RE-COLLECTED (DISPLAY): struct D ( $crate :: S ) ; PRINT-DERIVE RE-COLLECTED (DISPLAY): struct D ( ::dollar_crate_external :: S ) ;
PRINT-DERIVE INPUT (DEBUG): TokenStream [ PRINT-DERIVE INPUT (DEBUG): TokenStream [
Ident { Ident {
ident: "struct", ident: "struct",