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
/// `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
///
/// Basic usage:
@ -1506,6 +1511,101 @@ pub trait Iterator {
(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
/// 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_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(int_error_matching)]
#![feature(const_fn)]
#![feature(iter_partition_in_place)]
#![feature(iter_is_partitioned)]
#![warn(rust_2018_idioms)]
extern crate test;

View file

@ -1303,15 +1303,15 @@ fn validate_commandline_args_with_session_available(sess: &Session) {
}
// 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
// does not crash and will probably generate a corrupted binary.
if sess.opts.cg.profile_generate.enabled() &&
sess.target.target.options.is_like_msvc &&
sess.panic_strategy() == PanicStrategy::Unwind {
sess.err("Profile-guided optimization does not yet work in conjunction \
with `-Cpanic=unwind` on Windows when targeting MSVC. \
See https://github.com/rust-lang/rust/issues/61002 for details.");
sess.warn("Profile-guided optimization does not yet work in conjunction \
with `-Cpanic=unwind` on Windows when targeting MSVC. \
See https://github.com/rust-lang/rust/issues/61002 for details.");
}
}

View file

@ -34,17 +34,17 @@ trait ArgAttributeExt {
impl ArgAttributeExt for ArgAttribute {
fn for_each_kind<F>(&self, mut f: F) where F: FnMut(llvm::Attribute) {
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 {
fn apply_llfn(&self, idx: AttributePlace, llfn: &Value);
fn apply_callsite(&self, idx: AttributePlace, callsite: &Value);
fn apply_llfn(&self, idx: AttributePlace, llfn: &Value, ty: Option<&Type>);
fn apply_callsite(&self, idx: AttributePlace, callsite: &Value, ty: Option<&Type>);
}
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;
unsafe {
let deref = self.pointee_size.bytes();
@ -65,11 +65,14 @@ impl ArgAttributesExt for ArgAttributes {
idx.as_uint(),
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));
}
}
fn apply_callsite(&self, idx: AttributePlace, callsite: &Value) {
fn apply_callsite(&self, idx: AttributePlace, callsite: &Value, ty: Option<&Type>) {
let mut regular = self.regular;
unsafe {
let deref = self.pointee_size.bytes();
@ -90,6 +93,9 @@ impl ArgAttributesExt for ArgAttributes {
idx.as_uint(),
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));
}
}
@ -298,7 +304,7 @@ pub trait FnTypeLlvmExt<'tcx> {
fn 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 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);
}
@ -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 apply = |attrs: &ArgAttributes| {
attrs.apply_llfn(llvm::AttributePlace::Argument(i), llfn);
let mut apply = |attrs: &ArgAttributes, ty: Option<&Type>| {
attrs.apply_llfn(llvm::AttributePlace::Argument(i), llfn, ty);
i += 1;
};
match self.ret.mode {
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 {
if arg.pad.is_some() {
apply(&ArgAttributes::new());
apply(&ArgAttributes::new(), None);
}
match arg.mode {
PassMode::Ignore(_) => {}
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)) => {
apply(attrs);
apply(extra_attrs);
apply(attrs, None);
apply(extra_attrs, None);
}
PassMode::Pair(ref a, ref b) => {
apply(a);
apply(b);
apply(a, None);
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) {
let mut i = 0;
let mut apply = |attrs: &ArgAttributes| {
attrs.apply_callsite(llvm::AttributePlace::Argument(i), callsite);
let mut apply = |attrs: &ArgAttributes, ty: Option<&Type>| {
attrs.apply_callsite(llvm::AttributePlace::Argument(i), callsite, ty);
i += 1;
};
match self.ret.mode {
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 {
@ -446,21 +452,21 @@ impl<'tcx> FnTypeLlvmExt<'tcx> for FnType<'tcx, Ty<'tcx>> {
}
for arg in &self.args {
if arg.pad.is_some() {
apply(&ArgAttributes::new());
apply(&ArgAttributes::new(), None);
}
match arg.mode {
PassMode::Ignore(_) => {}
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)) => {
apply(attrs);
apply(extra_attrs);
apply(attrs, None);
apply(extra_attrs, None);
}
PassMode::Pair(ref a, ref b) => {
apply(a);
apply(b);
apply(a, None);
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"));
}
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> {
const RUSTC_SPECIFIC_FEATURES: &[&str] = &[
"crt-static",
@ -129,6 +152,7 @@ pub fn llvm_target_features(sess: &Session) -> impl Iterator<Item = &str> {
sess.target.target.options.features.split(',')
.chain(cmdline)
.filter(|l| !l.is_empty())
.map(translate_obsolete_target_features)
}
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)
}
fn const_real(&self, t: &'ll Type, val: f64) -> &'ll Value {
unsafe { llvm::LLVMConstReal(t, val) }
}
fn const_struct(
&self,
elts: &[&'ll Value],

View file

@ -1,5 +1,6 @@
use crate::attributes;
use crate::llvm;
use crate::llvm_util;
use crate::debuginfo;
use crate::value::Value;
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
}
fn strip_function_ptr_alignment(data_layout: String) -> String {
// FIXME: Make this more general.
data_layout.replace("-Fi8-", "-")
}
pub unsafe fn create_module(
tcx: TyCtxt<'_>,
llcx: &'ll llvm::Context,
@ -149,14 +155,19 @@ pub unsafe fn create_module(
let mod_name = SmallCStr::new(mod_name);
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.
if sess.target.target.options.is_builtin {
let tm = crate::back::write::create_informational_target_machine(&tcx.sess, false);
llvm::LLVMRustSetDataLayoutFromTargetMachine(llmod, tm);
llvm::LLVMRustDisposeTargetMachine(tm);
let data_layout = llvm::LLVMGetDataLayout(llmod);
let data_layout = str::from_utf8(CStr::from_ptr(data_layout).to_bytes())
let llvm_data_layout = llvm::LLVMGetDataLayout(llmod);
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");
// 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 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, `{}`, \
differs from LLVM default, `{}`",
sess.target.target.llvm_target,
sess.target.target.data_layout,
data_layout);
target_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());
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);
}
fty.apply_attrs_llfn(llfn);
fty.apply_attrs_llfn(self, llfn);
llfn
}

View file

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

View file

@ -715,6 +715,7 @@ extern "C" {
// Operations on scalar constants
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 LLVMConstReal(RealTy: &Type, N: f64) -> &Value;
pub fn LLVMConstIntGetZExtValue(ConstantVal: &Value) -> c_ulonglong;
pub fn LLVMRustConstInt128Get(ConstantVal: &Value, SExt: 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 LLVMRustAddDereferenceableAttr(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 LLVMRustAddFunctionAttrStringValue(Fn: &Value,
index: c_uint,
@ -824,6 +826,7 @@ extern "C" {
pub fn LLVMRustAddDereferenceableOrNullCallSiteAttr(Instr: &Value,
index: c_uint,
bytes: u64);
pub fn LLVMRustAddByValCallSiteAttr(Instr: &Value, index: c_uint, ty: &Type);
// Operations on load/store instructions (only)
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_usize(&self, i: u64) -> 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;

View file

@ -758,7 +758,10 @@ impl<'a> Resolver<'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) {
self.local_macro_def_scopes[&id]
} 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::{MacroKind, SyntaxExtension};
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::feature_gate::{feature_err, emit_feature_err, is_builtin_attr_name};
use syntax::feature_gate::{AttributeGate, GateIssue, Stability, BUILTIN_ATTRIBUTES};
use syntax::symbol::{Symbol, kw, sym};
use syntax::visit::Visitor;
use syntax::util::lev_distance::find_best_match_for_name;
use syntax_pos::{Span, DUMMY_SP};
use errors::Applicability;
@ -146,24 +145,14 @@ impl<'a> base::Resolver for Resolver<'a> {
mark
}
fn resolve_dollar_crates(&mut self, fragment: &AstFragment) {
struct ResolveDollarCrates<'a, 'b> {
resolver: &'a mut Resolver<'b>
}
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,
_ => kw::Crate,
};
ident.span.ctxt().set_dollar_crate_name(name);
}
fn resolve_dollar_crates(&mut self) {
hygiene::update_dollar_crate_names(|ctxt| {
let ident = Ident::new(kw::DollarCrate, DUMMY_SP.with_ctxt(ctxt));
match self.resolve_crate_root(ident).kind {
ModuleKind::Def(.., name) if name != kw::Invalid => name,
_ => kw::Crate,
}
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,

View file

@ -11,7 +11,7 @@ pub fn target() -> TargetResult {
target_endian: "little".to_string(),
target_pointer_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(),
target_os: "android".to_string(),
target_env: String::new(),

View file

@ -8,7 +8,7 @@ pub fn target() -> TargetResult {
target_endian: "little".to_string(),
target_pointer_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(),
target_os: "linux".to_string(),
target_env: "gnu".to_string(),

View file

@ -8,7 +8,7 @@ pub fn target() -> TargetResult {
target_endian: "little".to_string(),
target_pointer_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(),
target_os: "linux".to_string(),
target_env: "gnu".to_string(),

View file

@ -15,7 +15,7 @@ pub fn target() -> TargetResult {
target_endian: "little".to_string(),
target_pointer_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(),
target_os: "linux".to_string(),
target_env: "musl".to_string(),

View file

@ -15,7 +15,7 @@ pub fn target() -> TargetResult {
target_endian: "little".to_string(),
target_pointer_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(),
target_os: "linux".to_string(),
target_env: "musl".to_string(),

View file

@ -9,7 +9,7 @@ pub fn target() -> TargetResult {
target_endian: "big".to_string(),
target_pointer_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(),
target_os: "none".to_string(),
target_env: "".to_string(),

View file

@ -9,7 +9,7 @@ pub fn target() -> TargetResult {
target_endian: "big".to_string(),
target_pointer_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(),
target_os: "none".to_string(),
target_env: String::new(),
@ -21,7 +21,7 @@ pub fn target() -> TargetResult {
linker: Some("rust-lld".to_owned()),
relocation_model: "static".to_string(),
panic_strategy: PanicStrategy::Abort,
features: "+vfp3,+d16,+fp-only-sp".to_string(),
features: "+vfp3,-d32,-fp16".to_string(),
max_atomic_width: Some(32),
abi_blacklist: super::arm_base::abi_blacklist(),
emit_debug_gdb_scripts: false,

View file

@ -7,7 +7,7 @@ pub fn target() -> TargetResult {
target_endian: "little".to_string(),
target_pointer_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(),
target_os: "linux".to_string(),
target_env: "gnu".to_string(),

View file

@ -7,7 +7,7 @@ pub fn target() -> TargetResult {
target_endian: "little".to_string(),
target_pointer_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(),
target_os: "linux".to_string(),
target_env: "gnu".to_string(),

View file

@ -10,7 +10,7 @@ pub fn target() -> TargetResult {
target_endian: "little".to_string(),
target_pointer_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(),
target_os: "linux".to_string(),
target_env: "musl".to_string(),

View file

@ -7,7 +7,7 @@ pub fn target() -> TargetResult {
target_endian: "little".to_string(),
target_pointer_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(),
target_os: "freebsd".to_string(),
target_env: "gnueabihf".to_string(),

View file

@ -8,7 +8,7 @@ pub fn target() -> TargetResult {
target_endian: "little".to_string(),
target_pointer_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(),
target_os: "netbsd".to_string(),
target_env: "eabihf".to_string(),

View file

@ -8,7 +8,7 @@ pub fn target() -> TargetResult {
target_endian: "little".to_string(),
target_pointer_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(),
target_os: "ios".to_string(),
target_env: String::new(),

View file

@ -10,7 +10,7 @@ use crate::spec::{LinkerFlavor, Target, TargetOptions, TargetResult};
pub fn target() -> TargetResult {
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.pre_link_args
.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_pointer_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(),
target_os: "android".to_string(),
target_env: String::new(),

View file

@ -13,7 +13,7 @@ pub fn target() -> TargetResult {
target_endian: "little".to_string(),
target_pointer_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(),
target_os: "cloudabi".to_string(),
target_env: String::new(),

View file

@ -7,7 +7,7 @@ pub fn target() -> TargetResult {
target_endian: "little".to_string(),
target_pointer_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(),
target_os: "freebsd".to_string(),
target_env: "gnueabihf".to_string(),
@ -15,7 +15,7 @@ pub fn target() -> TargetResult {
linker_flavor: LinkerFlavor::Gcc,
options: TargetOptions {
features: "+v7,+vfp3,+d16,+thumb2,-neon".to_string(),
features: "+v7,+vfp3,-d32,+thumb2,-neon".to_string(),
max_atomic_width: Some(64),
abi_blacklist: super::arm_base::abi_blacklist(),
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_pointer_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(),
target_os: "linux".to_string(),
target_env: "gnu".to_string(),
@ -19,7 +19,7 @@ pub fn target() -> TargetResult {
options: TargetOptions {
// 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(),
max_atomic_width: Some(64),
abi_blacklist: super::arm_base::abi_blacklist(),

View file

@ -12,7 +12,7 @@ pub fn target() -> TargetResult {
target_endian: "little".to_string(),
target_pointer_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(),
target_os: "linux".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
// target.
options: TargetOptions {
features: "+v7,+vfp3,+d16,+thumb2,-neon".to_string(),
features: "+v7,+vfp3,-d32,+thumb2,-neon".to_string(),
cpu: "generic".to_string(),
max_atomic_width: Some(64),
abi_blacklist: super::arm_base::abi_blacklist(),

View file

@ -7,7 +7,7 @@ pub fn target() -> TargetResult {
target_endian: "little".to_string(),
target_pointer_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(),
target_os: "netbsd".to_string(),
target_env: "eabihf".to_string(),
@ -15,7 +15,7 @@ pub fn target() -> TargetResult {
linker_flavor: LinkerFlavor::Gcc,
options: TargetOptions {
features: "+v7,+vfp3,+d16,+thumb2,-neon".to_string(),
features: "+v7,+vfp3,-d32,+thumb2,-neon".to_string(),
cpu: "generic".to_string(),
max_atomic_width: Some(64),
abi_blacklist: super::arm_base::abi_blacklist(),

View file

@ -9,7 +9,7 @@ pub fn target() -> TargetResult {
target_endian: "little".to_string(),
target_pointer_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(),
target_os: "none".to_string(),
target_env: "".to_string(),

View file

@ -9,7 +9,7 @@ pub fn target() -> TargetResult {
target_endian: "little".to_string(),
target_pointer_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(),
target_os: "none".to_string(),
target_env: "".to_string(),
@ -21,7 +21,7 @@ pub fn target() -> TargetResult {
linker: Some("rust-lld".to_owned()),
relocation_model: "static".to_string(),
panic_strategy: PanicStrategy::Abort,
features: "+vfp3,+d16,+fp-only-sp".to_string(),
features: "+vfp3,-d32,-fp16".to_string(),
max_atomic_width: Some(32),
abi_blacklist: super::arm_base::abi_blacklist(),
emit_debug_gdb_scripts: false,

View file

@ -8,7 +8,7 @@ pub fn target() -> TargetResult {
target_endian: "little".to_string(),
target_pointer_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(),
target_os: "ios".to_string(),
target_env: String::new(),

View file

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

View file

@ -8,7 +8,7 @@ pub fn target() -> TargetResult {
target_endian: "little".to_string(),
target_pointer_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(),
target_os: "none".to_string(),
target_env: String::new(),

View file

@ -22,7 +22,7 @@ pub fn target() -> TargetResult {
target_endian: "little".to_string(),
target_pointer_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(),
target_os: "windows".to_string(),
target_env: "msvc".to_string(),

View file

@ -17,7 +17,7 @@ pub fn target() -> TargetResult {
target_endian: "little".to_string(),
target_pointer_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(),
target_os: "none".to_string(),
target_env: String::new(),

View file

@ -6,7 +6,7 @@
// 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.).
//
// 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};
@ -16,7 +16,7 @@ pub fn target() -> TargetResult {
target_endian: "little".to_string(),
target_pointer_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(),
target_os: "none".to_string(),
target_env: String::new(),
@ -26,14 +26,14 @@ pub fn target() -> TargetResult {
options: TargetOptions {
// `+vfp4` is the lowest common denominator between the Cortex-M4 (vfp4-16) and the
// 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
// `+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
//
// Reference:
// 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),
.. super::thumb_base::opts()
}

View file

@ -8,7 +8,7 @@ pub fn target() -> TargetResult {
target_endian: "little".to_string(),
target_pointer_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(),
target_os: "none".to_string(),
target_env: String::new(),

View file

@ -20,7 +20,7 @@ pub fn target() -> TargetResult {
target_endian: "little".to_string(),
target_pointer_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(),
target_os: "android".to_string(),
target_env: "".to_string(),

View file

@ -13,7 +13,7 @@ pub fn target() -> TargetResult {
target_endian: "little".to_string(),
target_pointer_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(),
target_os: "linux".to_string(),
target_env: "gnu".to_string(),

View file

@ -8,7 +8,7 @@ pub fn target() -> TargetResult {
target_endian: "little".to_string(),
target_pointer_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(),
target_os: "none".to_string(),
target_env: String::new(),

View file

@ -9,7 +9,7 @@ pub fn target() -> TargetResult {
target_endian: "little".to_string(),
target_pointer_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(),
target_os: "none".to_string(),
target_env: String::new(),

View file

@ -9,7 +9,7 @@ pub fn target() -> TargetResult {
target_endian: "little".to_string(),
target_pointer_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(),
target_os: "none".to_string(),
target_env: String::new(),
@ -22,7 +22,7 @@ pub fn target() -> TargetResult {
// the FPU uses the FPv5 architecture, single-precision instructions
// and 16 D registers.
// 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),
.. super::thumb_base::opts()
},

View file

@ -701,7 +701,7 @@ pub trait Resolver {
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,
derives: &[Mark]);
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])
-> (AstFragment, Vec<Invocation>) {
// 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 mut collector = InvocationCollector {

View file

@ -18,7 +18,7 @@ use crate::tokenstream::{self, TokenStream, TokenTree};
use rustc_target::spec::abi::{self, Abi};
use syntax_pos::{self, BytePos};
use syntax_pos::{DUMMY_SP, FileName};
use syntax_pos::{DUMMY_SP, FileName, Span};
use std::borrow::Cow;
use std::io::Read;
@ -181,7 +181,46 @@ pub fn literal_to_string(lit: token::Lit) -> String {
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 {
token_kind_to_string_ext(tok, None)
}
fn token_kind_to_string_ext(tok: &TokenKind, convert_dollar_crate: Option<Span>) -> String {
match *tok {
token::Eq => "=".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),
/* Name components */
token::Ident(s, false) => s.to_string(),
token::Ident(s, true) => format!("r#{}", s),
token::Ident(s, is_raw) => ident_to_string_ext(s, is_raw, convert_dollar_crate),
token::Lifetime(s) => s.to_string(),
/* Other */
@ -243,7 +281,12 @@ pub fn token_kind_to_string(tok: &TokenKind) -> 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 {
@ -256,9 +299,8 @@ crate fn nonterminal_to_string(nt: &Nonterminal) -> String {
token::NtBlock(ref e) => block_to_string(e),
token::NtStmt(ref e) => stmt_to_string(e),
token::NtPat(ref e) => pat_to_string(e),
token::NtIdent(e, false) => ident_to_string(e),
token::NtIdent(e, true) => format!("r#{}", ident_to_string(e)),
token::NtLifetime(e) => ident_to_string(e),
token::NtIdent(e, is_raw) => ident_to_string(e, is_raw),
token::NtLifetime(e) => e.to_string(),
token::NtLiteral(ref e) => expr_to_string(e),
token::NtTT(ref tree) => tt_to_string(tree.clone()),
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 {
to_string(|s| s.print_tt(tt))
to_string(|s| s.print_tt(tt, false))
}
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 {
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 {
@ -344,10 +386,6 @@ pub fn path_segment_to_string(p: &ast::PathSegment) -> String {
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 {
to_string(|s| s.print_visibility(v))
}
@ -629,11 +667,7 @@ pub trait PrintState<'a> {
self.writer().word("::");
}
if segment.ident.name != kw::PathRoot {
if segment.ident.name == kw::DollarCrate {
self.print_dollar_crate(segment.ident);
} else {
self.writer().word(segment.ident.as_str().to_string());
}
self.writer().word(ident_to_string(segment.ident, segment.ident.is_raw_guess()));
}
}
}
@ -707,10 +741,10 @@ pub trait PrintState<'a> {
/// appropriate macro, transcribe back into the grammar we just parsed from,
/// and then pretty-print the resulting AST nodes (so, e.g., we print
/// 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 {
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 {
token::DocComment(..) => {
self.writer().hardbreak()
@ -729,12 +763,16 @@ pub trait PrintState<'a> {
}
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);
for (i, tt) in tts.into_trees().enumerate() {
if i != 0 {
self.writer().space();
}
self.print_tt(tt);
self.print_tt(tt, convert_dollar_crate);
}
self.end();
}
@ -744,21 +782,6 @@ pub trait PrintState<'a> {
}
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> {
@ -2287,11 +2310,7 @@ impl<'a> State<'a> {
}
crate fn print_ident(&mut self, ident: ast::Ident) {
if ident.is_raw_guess() {
self.s.word(format!("r#{}", ident));
} else {
self.s.word(ident.as_str().to_string());
}
self.s.word(ident_to_string(ident, ident.is_raw_guess()));
self.ann.post(self, AnnNode::Ident(&ident))
}
@ -2322,11 +2341,7 @@ impl<'a> State<'a> {
segment: &ast::PathSegment,
colons_before_params: bool) {
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 {
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 rustc_data_structures::fx::{FxHashMap, FxHashSet};
use rustc_data_structures::sync::Lrc;
use std::{fmt, mem};
use std::fmt;
/// A SyntaxContext represents a chain of macro expansions (represented by marks).
#[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))
}
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 {
#[inline]
pub const fn empty() -> Self {
@ -614,17 +631,6 @@ impl SyntaxContext {
pub fn dollar_crate_name(self) -> Symbol {
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 {

View file

@ -913,7 +913,10 @@ LLVMRustCreateThinLTOData(LLVMRustThinLTOModule *modules,
GlobalValue::LinkageTypes 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);
#else
thinLTOResolveWeakForLinkerInIndex(Ret->Index, isPrevailing, recordNewLinkage);

View file

@ -237,6 +237,17 @@ extern "C" void LLVMRustAddDereferenceableOrNullCallSiteAttr(LLVMValueRef Instr,
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,
LLVMRustAttribute RustAttr) {
Function *A = unwrap<Function>(Fn);
@ -271,6 +282,17 @@ extern "C" void LLVMRustAddDereferenceableOrNullAttr(LLVMValueRef Fn,
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,
unsigned Index,
const char *Name,

View file

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

View file

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

View file

@ -14,3 +14,9 @@ macro_rules! external {
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 [
Ident {
ident: "struct",
@ -39,7 +39,7 @@ PRINT-BANG INPUT (DEBUG): TokenStream [
},
]
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 [
Ident {
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 [
Ident {
ident: "struct",
@ -39,7 +39,7 @@ PRINT-BANG INPUT (DEBUG): TokenStream [
},
]
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 [
Ident {
ident: "struct",
@ -80,7 +80,7 @@ PRINT-ATTR INPUT (DEBUG): TokenStream [
},
]
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 [
Ident {
ident: "struct",
@ -120,7 +120,7 @@ PRINT-DERIVE INPUT (DEBUG): TokenStream [
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 [
Ident {
ident: "struct",
@ -161,7 +161,7 @@ PRINT-BANG INPUT (DEBUG): TokenStream [
},
]
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 [
Ident {
ident: "struct",
@ -202,7 +202,7 @@ PRINT-ATTR INPUT (DEBUG): TokenStream [
},
]
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 [
Ident {
ident: "struct",