du . | sort -nr | head -n100
after_failure:
+ # Requested by travis to debug "shutting down NOW" errors
+ - sudo tail -n 500 /var/log/syslog
- >
echo "#### Build failed; Disk usage after running script:";
df -h;
name = "rustc_codegen_llvm"
version = "0.0.0"
dependencies = [
- "bitflags 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)",
"cc 1.0.18 (registry+https://github.com/rust-lang/crates.io-index)",
- "env_logger 0.5.10 (registry+https://github.com/rust-lang/crates.io-index)",
- "flate2 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)",
- "jobserver 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)",
- "libc 0.2.42 (registry+https://github.com/rust-lang/crates.io-index)",
- "log 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)",
"num_cpus 1.8.0 (registry+https://github.com/rust-lang/crates.io-index)",
- "rustc 0.0.0",
"rustc-demangle 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)",
- "rustc_allocator 0.0.0",
- "rustc_apfloat 0.0.0",
- "rustc_codegen_utils 0.0.0",
- "rustc_data_structures 0.0.0",
- "rustc_errors 0.0.0",
- "rustc_incremental 0.0.0",
"rustc_llvm 0.0.0",
- "rustc_mir 0.0.0",
- "rustc_platform_intrinsics 0.0.0",
- "rustc_target 0.0.0",
- "serialize 0.0.0",
- "syntax 0.0.0",
- "syntax_pos 0.0.0",
- "tempfile 3.0.2 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
let target = self.target;
let backend = self.backend;
+ let out_dir = builder.cargo_out(compiler, Mode::Codegen, target);
+ builder.clear_if_dirty(&out_dir, &librustc_stamp(builder, compiler, target));
+
let mut cargo = builder.cargo(compiler, Mode::Codegen, target, "check");
- let features = builder.rustc_features().to_string();
cargo.arg("--manifest-path").arg(builder.src.join("src/librustc_codegen_llvm/Cargo.toml"));
rustc_cargo_env(builder, &mut cargo);
let _folder = builder.fold_output(|| format!("stage{}-rustc_codegen_llvm", compiler.stage));
run_cargo(builder,
- cargo.arg("--features").arg(features),
+ &mut cargo,
&codegen_backend_stamp(builder, compiler, target, backend),
true);
}
return;
}
+ let out_dir = builder.cargo_out(compiler, Mode::Codegen, target);
+ builder.clear_if_dirty(&out_dir, &librustc_stamp(builder, compiler, target));
+
let mut cargo = builder.cargo(compiler, Mode::Codegen, target, "build");
- let mut features = builder.rustc_features().to_string();
cargo.arg("--manifest-path")
.arg(builder.src.join("src/librustc_codegen_llvm/Cargo.toml"));
rustc_cargo_env(builder, &mut cargo);
- features += &build_codegen_backend(&builder, &mut cargo, &compiler, target, backend);
+ let features = build_codegen_backend(&builder, &mut cargo, &compiler, target, backend);
- let tmp_stamp = builder.cargo_out(compiler, Mode::Codegen, target)
- .join(".tmp.stamp");
+ let tmp_stamp = out_dir.join(".tmp.stamp");
let _folder = builder.fold_output(|| format!("stage{}-rustc_codegen_llvm", compiler.stage));
let files = run_cargo(builder,
let suffix = match mode {
Mode::Std => "-std",
Mode::Test => "-test",
- Mode::Codegen => "-rustc",
Mode::Rustc => "-rustc",
+ Mode::Codegen => "-codegen",
Mode::ToolBootstrap => "-bootstrap-tools",
Mode::ToolStd => "-tools",
Mode::ToolRustc => "-tools",
use core::mem::{self, PinMut};
use core::ops::{CoerceUnsized, Deref, DerefMut, Generator, GeneratorState};
use core::ptr::{self, NonNull, Unique};
-use core::task::{Context, Poll, Executor, SpawnErrorKind, SpawnObjError};
+use core::task::{Context, Poll, Spawn, SpawnErrorKind, SpawnObjError};
use raw_vec::RawVec;
use str::from_boxed_utf8_unchecked;
}
#[unstable(feature = "futures_api", issue = "50547")]
-impl<E> Executor for Box<E>
- where E: Executor + ?Sized
+impl<Sp> Spawn for Box<Sp>
+ where Sp: Spawn + ?Sized
{
- fn spawn_obj(&mut self, task: FutureObj<'static, ()>) -> Result<(), SpawnObjError> {
- (**self).spawn_obj(task)
+ fn spawn_obj(
+ &mut self,
+ future: FutureObj<'static, ()>,
+ ) -> Result<(), SpawnObjError> {
+ (**self).spawn_obj(future)
}
fn status(&self) -> Result<(), SpawnErrorKind> {
/// This length is in bytes, not [`char`]s or graphemes. In other words,
/// it may not be what a human considers the length of the string.
///
- /// [`char`]: primitive.char.html
- ///
/// # Examples
///
/// Basic usage:
/// Value, and may not match your idea of what a 'character' is. Iteration
/// over grapheme clusters may be what you actually want.
///
- /// [`char`]: primitive.char.html
- ///
/// # Examples
///
/// Basic usage:
/// The iterator yields tuples. The position is first, the [`char`] is
/// second.
///
- /// [`char`]: primitive.char.html
- ///
/// # Examples
///
/// Basic usage:
/// The pattern can be a `&str`, [`char`], or a closure that determines if
/// a character matches.
///
- /// [`char`]: primitive.char.html
/// [`None`]: option/enum.Option.html#variant.None
///
/// # Examples
/// The pattern can be a `&str`, [`char`], or a closure that determines if
/// a character matches.
///
- /// [`char`]: primitive.char.html
/// [`None`]: option/enum.Option.html#variant.None
///
/// # Examples
/// If the pattern allows a reverse search but its results might differ
/// from a forward search, the [`rsplit`] method can be used.
///
- /// [`char`]: primitive.char.html
/// [`rsplit`]: #method.rsplit
///
/// # Examples
/// The pattern can be a `&str`, [`char`], or a closure that determines the
/// split.
///
- /// [`char`]: primitive.char.html
- ///
/// # Iterator behavior
///
/// The returned iterator requires that the pattern supports a reverse
/// elements. This is true for, eg, [`char`] but not for `&str`.
///
/// [`DoubleEndedIterator`]: iter/trait.DoubleEndedIterator.html
- /// [`char`]: primitive.char.html
///
/// If the pattern allows a reverse search but its results might differ
/// from a forward search, the [`rsplit_terminator`] method can be used.
/// Additional libraries might provide more complex patterns like
/// regular expressions.
///
- /// [`char`]: primitive.char.html
- ///
/// Equivalent to [`split`], except that the trailing substring is
/// skipped if empty.
///
/// The pattern can be a `&str`, [`char`], or a closure that determines the
/// split.
///
- /// [`char`]: primitive.char.html
- ///
/// # Iterator behavior
///
/// The returned iterator will not be double ended, because it is
/// The pattern can be a `&str`, [`char`], or a closure that
/// determines the split.
///
- /// [`char`]: primitive.char.html
- ///
/// # Iterator behavior
///
/// The returned iterator will not be double ended, because it is not
/// The pattern can be a `&str`, [`char`], or a closure that
/// determines if a character matches.
///
- /// [`char`]: primitive.char.html
- ///
/// # Iterator behavior
///
/// The returned iterator will be a [`DoubleEndedIterator`] if the pattern
/// elements. This is true for, eg, [`char`] but not for `&str`.
///
/// [`DoubleEndedIterator`]: iter/trait.DoubleEndedIterator.html
- /// [`char`]: primitive.char.html
///
/// If the pattern allows a reverse search but its results might differ
/// from a forward search, the [`rmatches`] method can be used.
/// The pattern can be a `&str`, [`char`], or a closure that determines if
/// a character matches.
///
- /// [`char`]: primitive.char.html
- ///
/// # Iterator behavior
///
/// The returned iterator requires that the pattern supports a reverse
/// The pattern can be a `&str`, [`char`], or a closure that determines
/// if a character matches.
///
- /// [`char`]: primitive.char.html
- ///
/// # Iterator behavior
///
/// The returned iterator will be a [`DoubleEndedIterator`] if the pattern
/// The pattern can be a `&str`, [`char`], or a closure that determines if a
/// character matches.
///
- /// [`char`]: primitive.char.html
- ///
/// # Iterator behavior
///
/// The returned iterator requires that the pattern supports a reverse
/// The pattern can be a [`char`] or a closure that determines if a
/// character matches.
///
- /// [`char`]: primitive.char.html
- ///
/// # Examples
///
/// Simple patterns:
/// The pattern can be a `&str`, [`char`], or a closure that determines if
/// a character matches.
///
- /// [`char`]: primitive.char.html
- ///
/// # Text directionality
///
/// A string is a sequence of bytes. 'Left' in this context means the first
/// The pattern can be a `&str`, [`char`], or a closure that
/// determines if a character matches.
///
- /// [`char`]: primitive.char.html
- ///
/// # Text directionality
///
/// A string is a sequence of bytes. 'Right' in this context means the last
issue = "50547")]
use fmt;
-use super::{Executor, Waker, LocalWaker};
+use super::{Spawn, Waker, LocalWaker};
/// Information about the currently-running task.
///
/// when performing a single `poll` step on a task.
pub struct Context<'a> {
local_waker: &'a LocalWaker,
- executor: &'a mut dyn Executor,
+ spawner: &'a mut dyn Spawn,
}
impl<'a> fmt::Debug for Context<'a> {
}
impl<'a> Context<'a> {
- /// Create a new task `Context` with the provided `local_waker`, `waker`, and `executor`.
+ /// Create a new task `Context` with the provided `local_waker`, `waker`,
+ /// and `spawner`.
#[inline]
- pub fn new(local_waker: &'a LocalWaker, executor: &'a mut dyn Executor) -> Context<'a> {
- Context {
- local_waker,
- executor,
- }
+ pub fn new(
+ local_waker: &'a LocalWaker,
+ spawner: &'a mut dyn Spawn,
+ ) -> Context<'a> {
+ Context { local_waker, spawner }
}
/// Get the `LocalWaker` associated with the current task.
unsafe { &*(self.local_waker as *const LocalWaker as *const Waker) }
}
- /// Get the default executor associated with this task.
+ /// Get the spawner associated with this task.
///
/// This method is useful primarily if you want to explicitly handle
/// spawn failures.
#[inline]
- pub fn executor(&mut self) -> &mut dyn Executor {
- self.executor
+ pub fn spawner(&mut self) -> &mut dyn Spawn {
+ self.spawner
}
- /// Produce a context like the current one, but using the given waker instead.
+ /// Produce a context like the current one, but using the given waker
+ /// instead.
///
/// This advanced method is primarily used when building "internal
/// schedulers" within a task, where you want to provide some customized
/// wakeup logic.
#[inline]
- pub fn with_waker<'b>(&'b mut self, local_waker: &'b LocalWaker) -> Context<'b> {
+ pub fn with_waker<'b>(
+ &'b mut self,
+ local_waker: &'b LocalWaker,
+ ) -> Context<'b> {
Context {
local_waker,
- executor: self.executor,
+ spawner: self.spawner,
}
}
- /// Produce a context like the current one, but using the given executor
+ /// Produce a context like the current one, but using the given spawner
/// instead.
///
/// This advanced method is primarily used when building "internal
/// schedulers" within a task.
#[inline]
- pub fn with_executor<'b, E>(&'b mut self, executor: &'b mut E) -> Context<'b>
- where E: Executor
- {
+ pub fn with_spawner<'b, Sp: Spawn>(
+ &'b mut self,
+ spawner: &'b mut Sp,
+ ) -> Context<'b> {
Context {
local_waker: self.local_waker,
- executor,
+ spawner,
}
}
}
+++ /dev/null
-// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
-// option. This file may not be copied, modified, or distributed
-// except according to those terms.
-
-#![unstable(feature = "futures_api",
- reason = "futures in libcore are unstable",
- issue = "50547")]
-
-use fmt;
-use future::{FutureObj, LocalFutureObj};
-
-/// A task executor.
-///
-/// Futures are polled until completion by tasks, a kind of lightweight
-/// "thread". A *task executor* is responsible for the creation of these tasks
-/// and the coordination of their execution on real operating system threads. In
-/// particular, whenever a task signals that it can make further progress via a
-/// wake-up notification, it is the responsibility of the task executor to put
-/// the task into a queue to continue executing it, i.e. polling the future in
-/// it, later.
-pub trait Executor {
- /// Spawns a new task with the given future. The future will be polled until
- /// completion.
- ///
- /// # Errors
- ///
- /// The executor may be unable to spawn tasks, either because it has
- /// been shut down or is resource-constrained.
- fn spawn_obj(
- &mut self,
- future: FutureObj<'static, ()>,
- ) -> Result<(), SpawnObjError>;
-
- /// Determines whether the executor is able to spawn new tasks.
- ///
- /// # Returns
- ///
- /// An `Ok` return means the executor is *likely* (but not guaranteed)
- /// to accept a subsequent spawn attempt. Likewise, an `Err` return
- /// means that `spawn` is likely, but not guaranteed, to yield an error.
- #[inline]
- fn status(&self) -> Result<(), SpawnErrorKind> {
- Ok(())
- }
-}
-
-/// Provides the reason that an executor was unable to spawn.
-pub struct SpawnErrorKind {
- _hidden: (),
-}
-
-impl fmt::Debug for SpawnErrorKind {
- fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
- f.debug_tuple("SpawnErrorKind")
- .field(&"shutdown")
- .finish()
- }
-}
-
-impl SpawnErrorKind {
- /// Spawning is failing because the executor has been shut down.
- pub fn shutdown() -> SpawnErrorKind {
- SpawnErrorKind { _hidden: () }
- }
-
- /// Check whether this error is the `shutdown` error.
- pub fn is_shutdown(&self) -> bool {
- true
- }
-}
-
-/// The result of a failed spawn
-#[derive(Debug)]
-pub struct SpawnObjError {
- /// The kind of error
- pub kind: SpawnErrorKind,
-
- /// The future for which spawning inside a task was attempted
- pub future: FutureObj<'static, ()>,
-}
-
-/// The result of a failed spawn
-#[derive(Debug)]
-pub struct SpawnLocalObjError {
- /// The kind of error
- pub kind: SpawnErrorKind,
-
- /// The future for which spawning inside a task was attempted
- pub future: LocalFutureObj<'static, ()>,
-}
mod context;
pub use self::context::Context;
-mod executor;
-pub use self::executor::{
- Executor, SpawnErrorKind, SpawnObjError, SpawnLocalObjError
-};
+mod spawn;
+pub use self::spawn::{Spawn, SpawnErrorKind, SpawnObjError, SpawnLocalObjError};
mod poll;
pub use self::poll::Poll;
--- /dev/null
+// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+#![unstable(feature = "futures_api",
+ reason = "futures in libcore are unstable",
+ issue = "50547")]
+
+use fmt;
+use future::{FutureObj, LocalFutureObj};
+
+/// Spawns tasks that poll futures to completion onto its associated task
+/// executor.
+///
+/// The term "task" refers to a kind of lightweight "thread". Task executors
+/// are responsible for scheduling the execution of tasks on operating system
+/// threads.
+pub trait Spawn {
+ /// Spawns a new task with the given future. The future will be polled until
+ /// completion.
+ ///
+ /// # Errors
+ ///
+ /// The executor may be unable to spawn tasks, either because it has
+ /// been shut down or is resource-constrained.
+ fn spawn_obj(
+ &mut self,
+ future: FutureObj<'static, ()>,
+ ) -> Result<(), SpawnObjError>;
+
+ /// Determines whether the executor is able to spawn new tasks.
+ ///
+ /// # Returns
+ ///
+ /// An `Ok` return means the executor is *likely* (but not guaranteed)
+ /// to accept a subsequent spawn attempt. Likewise, an `Err` return
+ /// means that `spawn` is likely, but not guaranteed, to yield an error.
+ #[inline]
+ fn status(&self) -> Result<(), SpawnErrorKind> {
+ Ok(())
+ }
+}
+
+/// Provides the reason that an executor was unable to spawn.
+pub struct SpawnErrorKind {
+ _hidden: (),
+}
+
+impl fmt::Debug for SpawnErrorKind {
+ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+ f.debug_tuple("SpawnErrorKind")
+ .field(&"shutdown")
+ .finish()
+ }
+}
+
+impl SpawnErrorKind {
+ /// Spawning is failing because the executor has been shut down.
+ pub fn shutdown() -> SpawnErrorKind {
+ SpawnErrorKind { _hidden: () }
+ }
+
+ /// Check whether this error is the `shutdown` error.
+ pub fn is_shutdown(&self) -> bool {
+ true
+ }
+}
+
+/// The result of a failed spawn
+#[derive(Debug)]
+pub struct SpawnObjError {
+ /// The kind of error
+ pub kind: SpawnErrorKind,
+
+ /// The future for which spawning inside a task was attempted
+ pub future: FutureObj<'static, ()>,
+}
+
+/// The result of a failed spawn
+#[derive(Debug)]
+pub struct SpawnLocalObjError {
+ /// The kind of error
+ pub kind: SpawnErrorKind,
+
+ /// The future for which spawning inside a task was attempted
+ pub future: LocalFutureObj<'static, ()>,
+}
Macro(DefId, MacroKind),
NonMacroAttr, // e.g. `#[inline]` or `#[rustfmt::skip]`
- GlobalAsm(DefId),
-
// Both namespaces
Err,
}
Def::AssociatedTy(id) | Def::TyParam(id) | Def::Struct(id) | Def::StructCtor(id, ..) |
Def::Union(id) | Def::Trait(id) | Def::Method(id) | Def::Const(id) |
Def::AssociatedConst(id) | Def::Macro(id, ..) |
- Def::Existential(id) | Def::AssociatedExistential(id) |
- Def::GlobalAsm(id) | Def::TyForeign(id) => {
+ Def::Existential(id) | Def::AssociatedExistential(id) | Def::TyForeign(id) => {
id
}
Def::Label(..) => "label",
Def::SelfTy(..) => "self type",
Def::Macro(.., macro_kind) => macro_kind.descr(),
- Def::GlobalAsm(..) => "global asm",
Def::ToolMod => "tool module",
Def::NonMacroAttr => "non-macro attribute",
Def::Err => "unresolved item",
ItemKind::Const(..) => Some(Def::Const(def_id())),
ItemKind::Fn(..) => Some(Def::Fn(def_id())),
ItemKind::Mod(..) => Some(Def::Mod(def_id())),
- ItemKind::GlobalAsm(..) => Some(Def::GlobalAsm(def_id())),
ItemKind::Existential(..) => Some(Def::Existential(def_id())),
ItemKind::Ty(..) => Some(Def::TyAlias(def_id())),
ItemKind::Enum(..) => Some(Def::Enum(def_id())),
ItemKind::ExternCrate(_) |
ItemKind::Use(..) |
ItemKind::ForeignMod(..) |
+ ItemKind::GlobalAsm(..) |
ItemKind::Impl(..) => None,
}
}
Upvar(def_id, index, expr_id),
Label(node_id),
Macro(def_id, macro_kind),
- GlobalAsm(def_id),
ToolMod,
NonMacroAttr,
Err
test = false
[dependencies]
-bitflags = "1.0.1"
cc = "1.0.1"
-flate2 = "1.0"
-jobserver = "0.1.5"
-libc = "0.2"
-log = "0.4"
num_cpus = "1.0"
-rustc = { path = "../librustc" }
rustc-demangle = "0.1.4"
-rustc_allocator = { path = "../librustc_allocator" }
-rustc_apfloat = { path = "../librustc_apfloat" }
-rustc_target = { path = "../librustc_target" }
-rustc_data_structures = { path = "../librustc_data_structures" }
-rustc_errors = { path = "../librustc_errors" }
-rustc_incremental = { path = "../librustc_incremental" }
rustc_llvm = { path = "../librustc_llvm" }
-rustc_platform_intrinsics = { path = "../librustc_platform_intrinsics" }
-rustc_codegen_utils = { path = "../librustc_codegen_utils" }
-rustc_mir = { path = "../librustc_mir" }
-serialize = { path = "../libserialize" }
-syntax = { path = "../libsyntax" }
-syntax_pos = { path = "../libsyntax_pos" }
-tempfile = "3.0"
-
-# not actually used but needed to make sure we enable the same feature set as
-# winapi used in librustc
-env_logger = { version = "0.5", default-features = false }
[features]
-# Used to communicate the feature to `rustc_target` in the same manner that the
-# `rustc` driver script communicate this.
-jemalloc = ["rustc_target/jemalloc"]
-
# This is used to convince Cargo to separately cache builds of `rustc_codegen_llvm`
# when this option is enabled or not. That way we can build two, cache two
# artifacts, and have nice speedy rebuilds.
};
if config.verify_llvm_ir { assert!(addpass("verify")); }
+
+ // Some options cause LLVM bitcode to be emitted, which uses ThinLTOBuffers, so we need
+ // to make sure we run LLVM's NameAnonGlobals pass when emitting bitcode; otherwise
+ // we'll get errors in LLVM.
+ let using_thin_buffers = llvm::LLVMRustThinLTOAvailable() && (config.emit_bc
+ || config.obj_is_bitcode || config.emit_bc_compressed || config.embed_bitcode);
+ let mut have_name_anon_globals_pass = false;
if !config.no_prepopulate_passes {
llvm::LLVMRustAddAnalysisPasses(tm, fpm, llmod);
llvm::LLVMRustAddAnalysisPasses(tm, mpm, llmod);
let opt_level = config.opt_level.unwrap_or(llvm::CodeGenOptLevel::None);
let prepare_for_thin_lto = cgcx.lto == Lto::Thin || cgcx.lto == Lto::ThinLocal;
+ have_name_anon_globals_pass = have_name_anon_globals_pass || prepare_for_thin_lto;
+ if using_thin_buffers && !prepare_for_thin_lto {
+ assert!(addpass("name-anon-globals"));
+ have_name_anon_globals_pass = true;
+ }
with_llvm_pmb(llmod, &config, opt_level, prepare_for_thin_lto, &mut |b| {
llvm::LLVMPassManagerBuilderPopulateFunctionPassManager(b, fpm);
llvm::LLVMPassManagerBuilderPopulateModulePassManager(b, mpm);
diag_handler.warn(&format!("unknown pass `{}`, ignoring",
pass));
}
+ if pass == "name-anon-globals" {
+ have_name_anon_globals_pass = true;
+ }
}
for pass in &cgcx.plugin_passes {
`{}` but LLVM does not \
recognize it", pass));
}
+ if pass == "name-anon-globals" {
+ have_name_anon_globals_pass = true;
+ }
+ }
+
+ if using_thin_buffers && !have_name_anon_globals_pass {
+ // As described above, this will probably cause an error in LLVM
+ if config.no_prepopulate_passes {
+ diag_handler.err("The current compilation is going to use thin LTO buffers \
+ without running LLVM's NameAnonGlobals pass. \
+ This will likely cause errors in LLVM. Consider adding \
+ -C passes=name-anon-globals to the compiler command line.");
+ } else {
+ bug!("We are using thin LTO buffers without running the NameAnonGlobals pass. \
+ This will likely cause errors in LLVM and shoud never happen.");
+ }
}
}
cx: &CodegenCx<'ll, '_>,
cv: &'ll Value,
align: Align,
- kind: &str,
+ kind: Option<&str>,
) -> &'ll Value {
unsafe {
- let name = cx.generate_local_symbol_name(kind);
- let gv = declare::define_global(cx, &name[..], val_ty(cv)).unwrap_or_else(||{
- bug!("symbol `{}` is already defined", name);
- });
+ let gv = match kind {
+ Some(kind) if !cx.tcx.sess.fewer_names() => {
+ let name = cx.generate_local_symbol_name(kind);
+ let gv = declare::define_global(cx, &name[..], val_ty(cv)).unwrap_or_else(||{
+ bug!("symbol `{}` is already defined", name);
+ });
+ llvm::LLVMRustSetLinkage(gv, llvm::Linkage::PrivateLinkage);
+ gv
+ },
+ _ => declare::define_private_global(cx, val_ty(cv)),
+ };
llvm::LLVMSetInitializer(gv, cv);
set_global_alignment(cx, gv, align);
- llvm::LLVMRustSetLinkage(gv, llvm::Linkage::PrivateLinkage);
SetUnnamedAddr(gv, true);
gv
}
cx: &CodegenCx<'ll, '_>,
cv: &'ll Value,
align: Align,
- kind: &str,
+ kind: Option<&str>,
) -> &'ll Value {
if let Some(&gv) = cx.const_globals.borrow().get(&cv) {
unsafe {
use std::ffi::CString;
-
/// Declare a global value.
///
/// If there’s a value with the same name already declared, the function will
}
}
+/// Declare a private global
+///
+/// Use this function when you intend to define a global without a name.
+pub fn define_private_global(cx: &CodegenCx<'ll, '_>, ty: &'ll Type) -> &'ll Value {
+ unsafe {
+ llvm::LLVMRustInsertPrivateGlobal(cx.llmod, ty)
+ }
+}
+
/// Declare a Rust function with an intention to define it.
///
/// Use this function when you intend to define a function. This function will
pub fn LLVMAddGlobal(M: &'a Module, Ty: &'a Type, Name: *const c_char) -> &'a Value;
pub fn LLVMGetNamedGlobal(M: &Module, Name: *const c_char) -> Option<&Value>;
pub fn LLVMRustGetOrInsertGlobal(M: &'a Module, Name: *const c_char, T: &'a Type) -> &'a Value;
+ pub fn LLVMRustInsertPrivateGlobal(M: &'a Module, T: &'a Type) -> &'a Value;
pub fn LLVMGetFirstGlobal(M: &Module) -> Option<&Value>;
pub fn LLVMGetNextGlobal(GlobalVar: &Value) -> Option<&Value>;
pub fn LLVMDeleteGlobal(GlobalVar: &Value);
let vtable_const = C_struct(cx, &components, false);
let align = cx.data_layout().pointer_align;
- let vtable = consts::addr_of(cx, vtable_const, align, "vtable");
+ let vtable = consts::addr_of(cx, vtable_const, align, Some("vtable"));
debuginfo::create_vtable_metadata(cx, ty, vtable);
let file_line_col = consts::addr_of(bx.cx,
file_line_col,
align,
- "panic_bounds_check_loc");
+ Some("panic_bounds_check_loc"));
(lang_items::PanicBoundsCheckFnLangItem,
vec![file_line_col, index, len])
}
let msg_file_line_col = consts::addr_of(bx.cx,
msg_file_line_col,
align,
- "panic_loc");
+ Some("panic_loc"));
(lang_items::PanicFnLangItem,
vec![msg_file_line_col])
}
Some(AllocType::Memory(alloc)) => {
let init = const_alloc_to_llvm(cx, alloc);
if alloc.runtime_mutability == Mutability::Mutable {
- consts::addr_of_mut(cx, init, alloc.align, "byte_str")
+ consts::addr_of_mut(cx, init, alloc.align, None)
} else {
- consts::addr_of(cx, init, alloc.align, "byte_str")
+ consts::addr_of(cx, init, alloc.align, None)
}
}
Some(AllocType::Function(fn_instance)) => {
offset: Size,
) -> PlaceRef<'ll, 'tcx> {
let init = const_alloc_to_llvm(bx.cx, alloc);
- let base_addr = consts::addr_of(bx.cx, init, layout.align, "byte_str");
+ let base_addr = consts::addr_of(bx.cx, init, layout.align, None);
let llval = unsafe { LLVMConstInBoundsGEP(
consts::bitcast(base_addr, Type::i8p(bx.cx)),
EntryKind::Trait(_) => Def::Trait(did),
EntryKind::Enum(..) => Def::Enum(did),
EntryKind::MacroDef(_) => Def::Macro(did, MacroKind::Bang),
- EntryKind::GlobalAsm => Def::GlobalAsm(did),
EntryKind::ForeignType => Def::TyForeign(did),
EntryKind::ForeignMod |
+ EntryKind::GlobalAsm |
EntryKind::Impl(_) |
EntryKind::Field |
EntryKind::Generator(_) |
```
This is because cell types do operations that are not thread-safe. Due to this,
-they don't implement Sync and thus can't be placed in statics. In this
-case, `StaticMutex` would work just fine, but it isn't stable yet:
-https://doc.rust-lang.org/nightly/std/sync/struct.StaticMutex.html
+they don't implement Sync and thus can't be placed in statics.
However, if you still wish to use these types, you can achieve this by an unsafe
wrapper:
HirDef::SelfTy(..) |
HirDef::Label(..) |
HirDef::Macro(..) |
- HirDef::GlobalAsm(..) |
HirDef::ToolMod |
HirDef::NonMacroAttr |
HirDef::Err => None,
if let Err(ErrorReported) = compare_synthetic_generics(tcx,
impl_m,
- impl_m_span,
- trait_m,
- trait_item_span) {
+ trait_m) {
return;
}
fn compare_synthetic_generics<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
impl_m: &ty::AssociatedItem,
- _impl_m_span: Span, // FIXME necessary?
- trait_m: &ty::AssociatedItem,
- _trait_item_span: Option<Span>) // FIXME necessary?
+ trait_m: &ty::AssociatedItem)
-> Result<(), ErrorReported> {
// FIXME(chrisvittal) Clean up this function, list of FIXME items:
// 1. Better messages for the span labels
// 2. Explanation as to what is going on
- // 3. Correct the function signature for what we actually use
// If we get here, we already have the same number of generics, so the zip will
// be okay.
let mut error_found = false;
impl<'a, 'tcx> Checker<'a, 'tcx> {
fn check<F>(&self, trait_def_id: Option<DefId>, mut f: F) -> &Self
- where F: FnMut(TyCtxt<'a, 'tcx, 'tcx>, DefId, DefId)
+ where F: FnMut(TyCtxt<'a, 'tcx, 'tcx>, DefId)
{
if Some(self.trait_def_id) == trait_def_id {
for &impl_id in self.tcx.hir.trait_impls(self.trait_def_id) {
let impl_def_id = self.tcx.hir.local_def_id(impl_id);
- f(self.tcx, self.trait_def_id, impl_def_id);
+ f(self.tcx, impl_def_id);
}
}
self
}
}
-fn visit_implementation_of_drop<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
- _drop_did: DefId,
- impl_did: DefId) {
+fn visit_implementation_of_drop<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, impl_did: DefId) {
match tcx.type_of(impl_did).sty {
ty::TyAdt(..) => {}
_ => {
}
}
-fn visit_implementation_of_copy<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
- _copy_did: DefId,
- impl_did: DefId) {
+fn visit_implementation_of_copy<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, impl_did: DefId) {
debug!("visit_implementation_of_copy: impl_did={:?}", impl_did);
let impl_node_id = if let Some(n) = tcx.hir.as_local_node_id(impl_did) {
}
}
-fn visit_implementation_of_coerce_unsized<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
- _: DefId,
- impl_did: DefId) {
+fn visit_implementation_of_coerce_unsized<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, impl_did: DefId) {
debug!("visit_implementation_of_coerce_unsized: impl_did={:?}",
impl_did);
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f,
"<h1 class='fqn'>\
- <span class='in-band'>List of all items</span>\
<span class='out-of-band'>\
<span id='render-detail'>\
<a id=\"toggle-all-docs\" href=\"javascript:void(0)\" title=\"collapse all docs\">\
</a>\
</span>
</span>
+ <span class='in-band'>List of all items</span>\
</h1>")?;
print_entries(f, &self.structs, "Structs", "structs")?;
print_entries(f, &self.enums, "Enums", "enums")?;
fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
debug_assert!(!self.item.is_stripped());
// Write the breadcrumb trail header for the top
- write!(fmt, "<h1 class='fqn'><span class='in-band'>")?;
+ write!(fmt, "<h1 class='fqn'><span class='out-of-band'>")?;
+ if let Some(version) = self.item.stable_since() {
+ write!(fmt, "<span class='since' title='Stable since Rust version {0}'>{0}</span>",
+ version)?;
+ }
+ write!(fmt,
+ "<span id='render-detail'>\
+ <a id=\"toggle-all-docs\" href=\"javascript:void(0)\" \
+ title=\"collapse all docs\">\
+ [<span class='inner'>−</span>]\
+ </a>\
+ </span>")?;
+
+ // Write `src` tag
+ //
+ // When this item is part of a `pub use` in a downstream crate, the
+ // [src] link in the downstream documentation will actually come back to
+ // this page, and this link will be auto-clicked. The `id` attribute is
+ // used to find the link to auto-click.
+ if self.cx.shared.include_sources && !self.item.is_primitive() {
+ if let Some(l) = self.src_href() {
+ write!(fmt, "<a class='srclink' href='{}' title='{}'>[src]</a>",
+ l, "goto source code")?;
+ }
+ }
+
+ write!(fmt, "</span>")?; // out-of-band
+ write!(fmt, "<span class='in-band'>")?;
match self.item.inner {
clean::ModuleItem(ref m) => if m.is_crate {
write!(fmt, "Crate ")?;
write!(fmt, "<a class=\"{}\" href=''>{}</a>",
self.item.type_(), self.item.name.as_ref().unwrap())?;
- write!(fmt, "</span>")?; // in-band
- write!(fmt, "<span class='out-of-band'>")?;
- if let Some(version) = self.item.stable_since() {
- write!(fmt, "<span class='since' title='Stable since Rust version {0}'>{0}</span>",
- version)?;
- }
- write!(fmt,
- "<span id='render-detail'>\
- <a id=\"toggle-all-docs\" href=\"javascript:void(0)\" \
- title=\"collapse all docs\">\
- [<span class='inner'>−</span>]\
- </a>\
- </span>")?;
-
- // Write `src` tag
- //
- // When this item is part of a `pub use` in a downstream crate, the
- // [src] link in the downstream documentation will actually come back to
- // this page, and this link will be auto-clicked. The `id` attribute is
- // used to find the link to auto-click.
- if self.cx.shared.include_sources && !self.item.is_primitive() {
- if let Some(l) = self.src_href() {
- write!(fmt, "<a class='srclink' href='{}' title='{}'>[src]</a>",
- l, "goto source code")?;
- }
- }
-
- write!(fmt, "</span></h1>")?; // out-of-band
+ write!(fmt, "</span></h1>")?; // in-band
match self.item.inner {
clean::ModuleItem(ref m) =>
h1.fqn {
border-bottom: 1px dashed;
margin-top: 0;
- position: relative;
+ overflow: auto;
}
h2, h3:not(.impl):not(.method):not(.type):not(.tymethod), h4:not(.method):not(.type):not(.tymethod):not(.associatedconstant) {
border-bottom: 1px solid;
}
.content .out-of-band {
+ float: right;
font-size: 23px;
margin: 0px;
padding: 0px;
- text-align: right;
- display: inline-block;
font-weight: normal;
- position: absolute;
- right: 0;
}
h3.impl > .out-of-band {
// initialization closure panics, the Once enters a "poisoned" state which means
// that all future calls will immediately panic as well.
//
-// So to implement this, one might first reach for a `StaticMutex`, but those
-// unfortunately need to be deallocated (e.g. call `destroy()`) to free memory
-// on all OSes (some of the BSDs allocate memory for mutexes). It also gets a
-// lot harder with poisoning to figure out when the mutex needs to be
-// deallocated because it's not after the closure finishes, but after the first
-// successful closure finishes.
+// So to implement this, one might first reach for a `Mutex`, but those cannot
+// be put into a `static`. It also gets a lot harder with poisoning to figure
+// out when the mutex needs to be deallocated because it's not after the closure
+// finishes, but after the first successful closure finishes.
//
// All in all, this is instead implemented with atomics and lock-free
// operations! Whee! Each `Once` has one word of atomic state, and this state is
// references, we instead create the mutex with type
// PTHREAD_MUTEX_NORMAL which is guaranteed to deadlock if we try to
// re-lock it from the same thread, thus avoiding undefined behavior.
- //
- // We can't do anything for StaticMutex, but that type is deprecated
- // anyways.
let mut attr: libc::pthread_mutexattr_t = mem::uninitialized();
let r = libc::pthread_mutexattr_init(&mut attr);
debug_assert_eq!(r, 0);
(active, abi_x86_interrupt, "1.17.0", Some(40180), None),
// Allows the `catch {...}` expression
- (active, catch_expr, "1.17.0", Some(31436), Some(Edition::Edition2018)),
+ (active, catch_expr, "1.17.0", Some(31436), None),
// Used to preserve symbols (see llvm.used)
(active, used, "1.18.0", Some(40289), None),
BinOp(Minus) => true,
Ident(ident, false) if ident.name == keywords::True.name() => true,
Ident(ident, false) if ident.name == keywords::False.name() => true,
+ Interpolated(ref nt) => match nt.0 {
+ NtLiteral(..) => true,
+ _ => false,
+ },
_ => false,
}
}
#include "llvm/IR/DebugInfoMetadata.h"
#include "llvm/IR/DiagnosticInfo.h"
#include "llvm/IR/DiagnosticPrinter.h"
+#include "llvm/IR/GlobalVariable.h"
#include "llvm/IR/Instructions.h"
#include "llvm/Object/Archive.h"
#include "llvm/Object/ObjectFile.h"
return wrap(unwrap(M)->getOrInsertGlobal(Name, unwrap(Ty)));
}
+extern "C" LLVMValueRef
+LLVMRustInsertPrivateGlobal(LLVMModuleRef M, LLVMTypeRef Ty) {
+ return wrap(new GlobalVariable(*unwrap(M),
+ unwrap(Ty),
+ false,
+ GlobalValue::PrivateLinkage,
+ nullptr));
+}
+
extern "C" LLVMTypeRef LLVMRustMetadataTypeInContext(LLVMContextRef C) {
return wrap(Type::getMetadataTy(*unwrap(C)));
}
// CHECK: @STATIC = {{.*}}, align 4
// This checks the constants from inline_enum_const
-// CHECK: @byte_str.{{[0-9]+}} = {{.*}}, align 2
+// CHECK: @{{[0-9]+}} = {{.*}}, align 2
// This checks the constants from {low,high}_align_const, they share the same
// constant, but the alignment differs, so the higher one should be used
-// CHECK: [[LOW_HIGH:@byte_str.[0-9]+]] = {{.*}}, align 4
+// CHECK: [[LOW_HIGH:@[0-9]+]] = {{.*}}, align 4
#[derive(Copy, Clone)]
include!("aux_mod.rs");
// Here we check that the expansion of the file!() macro is mapped.
-// CHECK: @byte_str.1 = private unnamed_addr constant <{ [34 x i8] }> <{ [34 x i8] c"/the/src/remap_path_prefix/main.rs" }>, align 1
+// CHECK: @0 = private unnamed_addr constant <{ [34 x i8] }> <{ [34 x i8] c"/the/src/remap_path_prefix/main.rs" }>, align 1
pub static FILE_PATH: &'static str = file!();
fn main() {
+++ /dev/null
--include ../tools.mk
-
-# check that the compile generated symbols for strings, binaries,
-# vtables, etc. have semisane names (e.g. `str.1234`); it's relatively
-# easy to accidentally modify the compiler internals to make them
-# become things like `str"str"(1234)`.
-
-OUT=$(TMPDIR)/lib.s
-
-all:
- $(RUSTC) lib.rs --emit=asm --crate-type=staticlib
- # just check for symbol declarations with the names we're expecting.
- $(CGREP) -e 'str\.[0-9]+:' 'byte_str\.[0-9]+:' 'vtable\.[0-9]+' < $(OUT)
+++ /dev/null
-// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
-// option. This file may not be copied, modified, or distributed
-// except according to those terms.
-
-pub static X: &'static str = "foobarbaz";
-pub static Y: &'static [u8] = include_bytes!("lib.rs");
-
-trait Foo { fn dummy(&self) { } }
-impl Foo for usize {}
-
-#[no_mangle]
-pub extern "C" fn dummy() {
- // force the vtable to be created
- let _x = &1usize as &Foo;
-}
// See https://github.com/rust-lang/rust/issues/34793 for more information.
// Make sure we don't optimize anything away:
-// compile-flags: -C no-prepopulate-passes
+// compile-flags: -C no-prepopulate-passes -Cpasses=name-anon-globals
// Expand something exponentially
macro_rules! go_bacterial {
use std::future::FutureObj;
use std::task::{
Context, Poll, Wake,
- Executor, SpawnObjError,
+ Spawn, SpawnObjError,
local_waker_from_nonlocal,
};
}
}
-struct NoopExecutor;
-impl Executor for NoopExecutor {
+struct NoopSpawner;
+impl Spawn for NoopSpawner {
fn spawn_obj(&mut self, _: FutureObj<'static, ()>) -> Result<(), SpawnObjError> {
Ok(())
}
let mut fut = PinBox::new(f(9));
let counter = Arc::new(Counter { wakes: AtomicUsize::new(0) });
let waker = local_waker_from_nonlocal(counter.clone());
- let executor = &mut NoopExecutor;
- let cx = &mut Context::new(&waker, executor);
+ let spawner = &mut NoopSpawner;
+ let cx = &mut Context::new(&waker, spawner);
assert_eq!(0, counter.wakes.load(atomic::Ordering::SeqCst));
assert_eq!(Poll::Pending, fut.as_pin_mut().poll(cx));
use std::task::{
Context, Poll,
Wake, Waker, LocalWaker,
- Executor, SpawnObjError,
+ Spawn, SpawnObjError,
local_waker, local_waker_from_nonlocal,
};
}
}
-struct NoopExecutor;
+struct NoopSpawner;
-impl Executor for NoopExecutor {
+impl Spawn for NoopSpawner {
fn spawn_obj(&mut self, _: FutureObj<'static, ()>) -> Result<(), SpawnObjError> {
Ok(())
}
cx.waker().wake();
cx.waker().wake();
cx.local_waker().wake();
- cx.executor().spawn_obj(PinBox::new(MyFuture).into()).unwrap();
+ cx.spawner().spawn_obj(PinBox::new(MyFuture).into()).unwrap();
Poll::Ready(())
}
}
nonlocal_wakes: AtomicUsize::new(0),
});
let waker = unsafe { local_waker(counter.clone()) };
- let executor = &mut NoopExecutor;
- let cx = &mut Context::new(&waker, executor);
+ let spawner = &mut NoopSpawner;
+ let cx = &mut Context::new(&waker, spawner);
assert_eq!(Poll::Ready(()), PinMut::new(&mut MyFuture).poll(cx));
assert_eq!(1, counter.local_wakes.load(atomic::Ordering::SeqCst));
assert_eq!(2, counter.nonlocal_wakes.load(atomic::Ordering::SeqCst));
nonlocal_wakes: AtomicUsize::new(0),
});
let waker: LocalWaker = local_waker_from_nonlocal(counter.clone());
- let executor = &mut NoopExecutor;
- let cx = &mut Context::new(&waker, executor);
+ let spawner = &mut NoopSpawner;
+ let cx = &mut Context::new(&waker, spawner);
assert_eq!(Poll::Ready(()), PinMut::new(&mut MyFuture).poll(cx));
assert_eq!(0, counter.local_wakes.load(atomic::Ordering::SeqCst));
assert_eq!(3, counter.nonlocal_wakes.load(atomic::Ordering::SeqCst));
// Need -Cno-prepopulate-passes to really disable inlining, otherwise the faulty
// code gets optimized out:
-// compile-flags: -Cno-prepopulate-passes
+// compile-flags: -Cno-prepopulate-passes -Cpasses=name-anon-globals
extern crate issue_38226_aux;
--- /dev/null
+// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+#![feature(macro_literal_matcher)]
+
+macro_rules! a {
+ ($i:literal) => { "right" };
+ ($i:tt) => { "wrong" };
+}
+
+macro_rules! b {
+ ($i:literal) => { a!($i) };
+}
+
+fn main() {
+ assert_eq!(b!(0), "right");
+}
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-// compile-flags: -C no-prepopulate-passes
+// compile-flags: -C no-prepopulate-passes -Cpasses=name-anon-globals
#![crate_type = "lib"]