// Copyright 2014-2015 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.

//! The Rust compiler.
//!
//! # Note
//!
//! This API is completely unstable and subject to change.

#![doc(html_logo_url = "https://www.rust-lang.org/logos/rust-logo-128x128-blk-v2.png",
      html_favicon_url = "https://doc.rust-lang.org/favicon.ico",
      html_root_url = "https://doc.rust-lang.org/nightly/")]

#![feature(box_syntax)]
#![cfg_attr(unix, feature(libc))]
#![feature(nll)]
#![feature(quote)]
#![feature(rustc_diagnostic_macros)]
#![feature(slice_sort_by_cached_key)]
#![feature(set_stdio)]
#![feature(rustc_stack_internals)]
#![feature(no_debug)]

#![recursion_limit="256"]

extern crate arena;
pub extern crate getopts;
extern crate graphviz;
extern crate env_logger;
#[cfg(unix)]
extern crate libc;
extern crate rustc_rayon as rayon;
extern crate rustc;
extern crate rustc_allocator;
extern crate rustc_target;
extern crate rustc_borrowck;
extern crate rustc_data_structures;
extern crate rustc_errors as errors;
extern crate rustc_passes;
extern crate rustc_lint;
extern crate rustc_plugin;
extern crate rustc_privacy;
extern crate rustc_incremental;
extern crate rustc_metadata;
extern crate rustc_mir;
extern crate rustc_resolve;
extern crate rustc_save_analysis;
extern crate rustc_traits;
extern crate rustc_codegen_utils;
extern crate rustc_typeck;
extern crate scoped_tls;
extern crate serialize;
extern crate smallvec;
#[macro_use]
extern crate log;
extern crate syntax;
extern crate syntax_ext;
extern crate syntax_pos;

use driver::CompileController;
use pretty::{PpMode, UserIdentifiedItem};

use rustc_resolve as resolve;
use rustc_save_analysis as save;
use rustc_save_analysis::DumpHandler;
use rustc_data_structures::sync::{self, Lrc};
use rustc_data_structures::OnDrop;
use rustc::session::{self, config, Session, build_session, CompileResult};
use rustc::session::CompileIncomplete;
use rustc::session::config::{Input, PrintRequest, ErrorOutputType};
use rustc::session::config::nightly_options;
use rustc::session::filesearch;
use rustc::session::{early_error, early_warn};
use rustc::lint::Lint;
use rustc::lint;
use rustc_metadata::locator;
use rustc_metadata::cstore::CStore;
use rustc_metadata::dynamic_lib::DynamicLibrary;
use rustc::util::common::{time, ErrorReported};
use rustc_codegen_utils::codegen_backend::CodegenBackend;

use serialize::json::ToJson;

use std::any::Any;
use std::borrow::Cow;
use std::cmp::max;
use std::default::Default;
use std::env::consts::{DLL_PREFIX, DLL_SUFFIX};
use std::env;
use std::error::Error;
use std::ffi::OsString;
use std::fmt::{self, Display};
use std::io::{self, Read, Write};
use std::mem;
use std::panic;
use std::path::{PathBuf, Path};
use std::process::{self, Command, Stdio};
use std::str;
use std::sync::atomic::{AtomicBool, ATOMIC_BOOL_INIT, Ordering};
use std::sync::{Once, ONCE_INIT};
use std::thread;

use syntax::ast;
use syntax::source_map::{SourceMap, FileLoader, RealFileLoader};
use syntax::feature_gate::{GatedCfg, UnstableFeatures};
use syntax::parse::{self, PResult};
use syntax_pos::{DUMMY_SP, MultiSpan, FileName};

#[cfg(test)]
mod test;

pub mod profile;
pub mod driver;
pub mod pretty;
mod derive_registrar;

pub mod target_features {
    use syntax::ast;
    use syntax::symbol::Symbol;
    use rustc::session::Session;
    use rustc_codegen_utils::codegen_backend::CodegenBackend;

    /// Add `target_feature = "..."` cfgs for a variety of platform
    /// specific features (SSE, NEON etc.).
    ///
    /// This is performed by checking whether a whitelisted set of
    /// features is available on the target machine, by querying LLVM.
    pub fn add_configuration(cfg: &mut ast::CrateConfig,
                             sess: &Session,
                             codegen_backend: &dyn CodegenBackend) {
        let tf = Symbol::intern("target_feature");

        cfg.extend(codegen_backend.target_features(sess).into_iter().map(|feat| (tf, Some(feat))));

        if sess.crt_static_feature() {
            cfg.insert((tf, Some(Symbol::intern("crt-static"))));
        }
    }
}

/// Exit status code used for successful compilation and help output.
pub const EXIT_SUCCESS: isize = 0;

/// Exit status code used for compilation failures and  invalid flags.
pub const EXIT_FAILURE: isize = 1;

const BUG_REPORT_URL: &str = "https://github.com/rust-lang/rust/blob/master/CONTRIBUTING.\
                              md#bug-reports";

const ICE_REPORT_COMPILER_FLAGS: &[&str] = &["Z", "C", "crate-type"];

const ICE_REPORT_COMPILER_FLAGS_EXCLUDE: &[&str] = &["metadata", "extra-filename"];

const ICE_REPORT_COMPILER_FLAGS_STRIP_VALUE: &[&str] = &["incremental"];

pub fn abort_on_err<T>(result: Result<T, CompileIncomplete>, sess: &Session) -> T {
    match result {
        Err(CompileIncomplete::Errored(ErrorReported)) => {
            sess.abort_if_errors();
            panic!("error reported but abort_if_errors didn't abort???");
        }
        Err(CompileIncomplete::Stopped) => {
            sess.fatal("compilation terminated");
        }
        Ok(x) => x,
    }
}

pub fn run<F>(run_compiler: F) -> isize
    where F: FnOnce() -> (CompileResult, Option<Session>) + Send + 'static
{
    let result = monitor(move || {
        syntax::with_globals(|| {
            let (result, session) = run_compiler();
            if let Err(CompileIncomplete::Errored(_)) = result {
                match session {
                    Some(sess) => {
                        sess.abort_if_errors();
                        panic!("error reported but abort_if_errors didn't abort???");
                    }
                    None => {
                        let emitter =
                            errors::emitter::EmitterWriter::stderr(
                                errors::ColorConfig::Auto,
                                None,
                                true,
                                false
                            );
                        let handler = errors::Handler::with_emitter(true, false, Box::new(emitter));
                        handler.emit(&MultiSpan::new(),
                                     "aborting due to previous error(s)",
                                     errors::Level::Fatal);
                        panic::resume_unwind(Box::new(errors::FatalErrorMarker));
                    }
                }
            }
        });
    });

    match result {
        Ok(()) => EXIT_SUCCESS,
        Err(_) => EXIT_FAILURE,
    }
}

fn load_backend_from_dylib(path: &Path) -> fn() -> Box<dyn CodegenBackend> {
    // Note that we're specifically using `open_global_now` here rather than
    // `open`, namely we want the behavior on Unix of RTLD_GLOBAL and RTLD_NOW,
    // where NOW means "bind everything right now" because we don't want
    // surprises later on and RTLD_GLOBAL allows the symbols to be made
    // available for future dynamic libraries opened. This is currently used by
    // loading LLVM and then making its symbols available for other dynamic
    // libraries.
    let lib = DynamicLibrary::open_global_now(path).unwrap_or_else(|err| {
        let err = format!("couldn't load codegen backend {:?}: {:?}", path, err);
        early_error(ErrorOutputType::default(), &err);
    });
    unsafe {
        match lib.symbol("__rustc_codegen_backend") {
            Ok(f) => {
                mem::forget(lib);
                mem::transmute::<*mut u8, _>(f)
            }
            Err(e) => {
                let err = format!("couldn't load codegen backend as it \
                                   doesn't export the `__rustc_codegen_backend` \
                                   symbol: {:?}", e);
                early_error(ErrorOutputType::default(), &err);
            }
        }
    }
}

pub fn get_codegen_backend(sess: &Session) -> Box<dyn CodegenBackend> {
    static INIT: Once = ONCE_INIT;

    #[allow(deprecated)]
    #[no_debug]
    static mut LOAD: fn() -> Box<dyn CodegenBackend> = || unreachable!();

    INIT.call_once(|| {
        let codegen_name = sess.opts.debugging_opts.codegen_backend.as_ref()
            .unwrap_or(&sess.target.target.options.codegen_backend);
        let backend = match &codegen_name[..] {
            "metadata_only" => {
                rustc_codegen_utils::codegen_backend::MetadataOnlyCodegenBackend::new
            }
            filename if filename.contains(".") => {
                load_backend_from_dylib(filename.as_ref())
            }
            codegen_name => get_codegen_sysroot(codegen_name),
        };

        unsafe {
            LOAD = backend;
        }
    });
    let backend = unsafe { LOAD() };
    backend.init(sess);
    backend
}

fn get_codegen_sysroot(backend_name: &str) -> fn() -> Box<dyn CodegenBackend> {
    // For now we only allow this function to be called once as it'll dlopen a
    // few things, which seems to work best if we only do that once. In
    // general this assertion never trips due to the once guard in `get_codegen_backend`,
    // but there's a few manual calls to this function in this file we protect
    // against.
    static LOADED: AtomicBool = ATOMIC_BOOL_INIT;
    assert!(!LOADED.fetch_or(true, Ordering::SeqCst),
            "cannot load the default codegen backend twice");

    // When we're compiling this library with `--test` it'll run as a binary but
    // not actually exercise much functionality. As a result most of the logic
    // here is defunkt (it assumes we're a dynamic library in a sysroot) so
    // let's just return a dummy creation function which won't be used in
    // general anyway.
    if cfg!(test) {
        return rustc_codegen_utils::codegen_backend::MetadataOnlyCodegenBackend::new
    }

    let target = session::config::host_triple();
    let mut sysroot_candidates = vec![filesearch::get_or_default_sysroot()];
    let path = current_dll_path()
        .and_then(|s| s.canonicalize().ok());
    if let Some(dll) = path {
        // use `parent` twice to chop off the file name and then also the
        // directory containing the dll which should be either `lib` or `bin`.
        if let Some(path) = dll.parent().and_then(|p| p.parent()) {
            // The original `path` pointed at the `rustc_driver` crate's dll.
            // Now that dll should only be in one of two locations. The first is
            // in the compiler's libdir, for example `$sysroot/lib/*.dll`. The
            // other is the target's libdir, for example
            // `$sysroot/lib/rustlib/$target/lib/*.dll`.
            //
            // We don't know which, so let's assume that if our `path` above
            // ends in `$target` we *could* be in the target libdir, and always
            // assume that we may be in the main libdir.
            sysroot_candidates.push(path.to_owned());

            if path.ends_with(target) {
                sysroot_candidates.extend(path.parent() // chop off `$target`
                    .and_then(|p| p.parent())           // chop off `rustlib`
                    .and_then(|p| p.parent())           // chop off `lib`
                    .map(|s| s.to_owned()));
            }
        }
    }

    let sysroot = sysroot_candidates.iter()
        .map(|sysroot| {
            let libdir = filesearch::relative_target_lib_path(&sysroot, &target);
            sysroot.join(libdir).with_file_name(
                option_env!("CFG_CODEGEN_BACKENDS_DIR").unwrap_or("codegen-backends"))
        })
        .filter(|f| {
            info!("codegen backend candidate: {}", f.display());
            f.exists()
        })
        .next();
    let sysroot = sysroot.unwrap_or_else(|| {
        let candidates = sysroot_candidates.iter()
            .map(|p| p.display().to_string())
            .collect::<Vec<_>>()
            .join("\n* ");
        let err = format!("failed to find a `codegen-backends` folder \
                           in the sysroot candidates:\n* {}", candidates);
        early_error(ErrorOutputType::default(), &err);
    });
    info!("probing {} for a codegen backend", sysroot.display());

    let d = sysroot.read_dir().unwrap_or_else(|e| {
        let err = format!("failed to load default codegen backend, couldn't \
                           read `{}`: {}", sysroot.display(), e);
        early_error(ErrorOutputType::default(), &err);
    });

    let mut file: Option<PathBuf> = None;

    let expected_name = format!("rustc_codegen_llvm-{}", backend_name);
    for entry in d.filter_map(|e| e.ok()) {
        let path = entry.path();
        let filename = match path.file_name().and_then(|s| s.to_str()) {
            Some(s) => s,
            None => continue,
        };
        if !(filename.starts_with(DLL_PREFIX) && filename.ends_with(DLL_SUFFIX)) {
            continue
        }
        let name = &filename[DLL_PREFIX.len() .. filename.len() - DLL_SUFFIX.len()];
        if name != expected_name {
            continue
        }
        if let Some(ref prev) = file {
            let err = format!("duplicate codegen backends found\n\
                               first:  {}\n\
                               second: {}\n\
            ", prev.display(), path.display());
            early_error(ErrorOutputType::default(), &err);
        }
        file = Some(path.clone());
    }

    match file {
        Some(ref s) => return load_backend_from_dylib(s),
        None => {
            let err = format!("failed to load default codegen backend for `{}`, \
                               no appropriate codegen dylib found in `{}`",
                              backend_name, sysroot.display());
            early_error(ErrorOutputType::default(), &err);
        }
    }

    #[cfg(unix)]
    fn current_dll_path() -> Option<PathBuf> {
        use std::ffi::{OsStr, CStr};
        use std::os::unix::prelude::*;

        unsafe {
            let addr = current_dll_path as usize as *mut _;
            let mut info = mem::zeroed();
            if libc::dladdr(addr, &mut info) == 0 {
                info!("dladdr failed");
                return None
            }
            if info.dli_fname.is_null() {
                info!("dladdr returned null pointer");
                return None
            }
            let bytes = CStr::from_ptr(info.dli_fname).to_bytes();
            let os = OsStr::from_bytes(bytes);
            Some(PathBuf::from(os))
        }
    }

    #[cfg(windows)]
    fn current_dll_path() -> Option<PathBuf> {
        use std::ffi::OsString;
        use std::os::windows::prelude::*;

        extern "system" {
            fn GetModuleHandleExW(dwFlags: u32,
                                  lpModuleName: usize,
                                  phModule: *mut usize) -> i32;
            fn GetModuleFileNameW(hModule: usize,
                                  lpFilename: *mut u16,
                                  nSize: u32) -> u32;
        }

        const GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS: u32 = 0x00000004;

        unsafe {
            let mut module = 0;
            let r = GetModuleHandleExW(GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS,
                                       current_dll_path as usize,
                                       &mut module);
            if r == 0 {
                info!("GetModuleHandleExW failed: {}", io::Error::last_os_error());
                return None
            }
            let mut space = Vec::with_capacity(1024);
            let r = GetModuleFileNameW(module,
                                       space.as_mut_ptr(),
                                       space.capacity() as u32);
            if r == 0 {
                info!("GetModuleFileNameW failed: {}", io::Error::last_os_error());
                return None
            }
            let r = r as usize;
            if r >= space.capacity() {
                info!("our buffer was too small? {}",
                      io::Error::last_os_error());
                return None
            }
            space.set_len(r);
            let os = OsString::from_wide(&space);
            Some(PathBuf::from(os))
        }
    }
}

// Parse args and run the compiler. This is the primary entry point for rustc.
// See comments on CompilerCalls below for details about the callbacks argument.
// The FileLoader provides a way to load files from sources other than the file system.
pub fn run_compiler<'a>(args: &[String],
                        callbacks: Box<dyn CompilerCalls<'a> + sync::Send + 'a>,
                        file_loader: Option<Box<dyn FileLoader + Send + Sync + 'static>>,
                        emitter_dest: Option<Box<dyn Write + Send>>)
                        -> (CompileResult, Option<Session>)
{
    let matches = match handle_options(args) {
        Some(matches) => matches,
        None => return (Ok(()), None),
    };

    let (sopts, cfg) = config::build_session_options_and_crate_config(&matches);

    driver::spawn_thread_pool(sopts, |sopts| {
        run_compiler_with_pool(matches, sopts, cfg, callbacks, file_loader, emitter_dest)
    })
}

fn run_compiler_with_pool<'a>(
    matches: getopts::Matches,
    sopts: config::Options,
    cfg: ast::CrateConfig,
    mut callbacks: Box<dyn CompilerCalls<'a> + sync::Send + 'a>,
    file_loader: Option<Box<dyn FileLoader + Send + Sync + 'static>>,
    emitter_dest: Option<Box<dyn Write + Send>>
) -> (CompileResult, Option<Session>) {
    macro_rules! do_or_return {($expr: expr, $sess: expr) => {
        match $expr {
            Compilation::Stop => return (Ok(()), $sess),
            Compilation::Continue => {}
        }
    }}

    let descriptions = diagnostics_registry();

    do_or_return!(callbacks.early_callback(&matches,
                                           &sopts,
                                           &cfg,
                                           &descriptions,
                                           sopts.error_format),
                                           None);

    let (odir, ofile) = make_output(&matches);
    let (input, input_file_path, input_err) = match make_input(&matches.free) {
        Some((input, input_file_path, input_err)) => {
            let (input, input_file_path) = callbacks.some_input(input, input_file_path);
            (input, input_file_path, input_err)
        },
        None => match callbacks.no_input(&matches, &sopts, &cfg, &odir, &ofile, &descriptions) {
            Some((input, input_file_path)) => (input, input_file_path, None),
            None => return (Ok(()), None),
        },
    };

    let loader = file_loader.unwrap_or(box RealFileLoader);
    let source_map = Lrc::new(SourceMap::with_file_loader(loader, sopts.file_path_mapping()));
    let mut sess = session::build_session_with_source_map(
        sopts, input_file_path.clone(), descriptions, source_map, emitter_dest,
    );

    if let Some(err) = input_err {
        // Immediately stop compilation if there was an issue reading
        // the input (for example if the input stream is not UTF-8).
        sess.err(&err.to_string());
        return (Err(CompileIncomplete::Stopped), Some(sess));
    }

    let codegen_backend = get_codegen_backend(&sess);

    rustc_lint::register_builtins(&mut sess.lint_store.borrow_mut(), Some(&sess));

    let mut cfg = config::build_configuration(&sess, cfg);
    target_features::add_configuration(&mut cfg, &sess, &*codegen_backend);
    sess.parse_sess.config = cfg;

    let result = {
        let plugins = sess.opts.debugging_opts.extra_plugins.clone();

        let cstore = CStore::new(codegen_backend.metadata_loader());

        do_or_return!(callbacks.late_callback(&*codegen_backend,
                                              &matches,
                                              &sess,
                                              &cstore,
                                              &input,
                                              &odir,
                                              &ofile), Some(sess));

        let _sess_abort_error = OnDrop(|| sess.diagnostic().print_error_count());

        let control = callbacks.build_controller(&sess, &matches);

        driver::compile_input(codegen_backend,
                              &sess,
                              &cstore,
                              &input_file_path,
                              &input,
                              &odir,
                              &ofile,
                              Some(plugins),
                              &control)
    };

    (result, Some(sess))
}

#[cfg(unix)]
pub fn set_sigpipe_handler() {
    unsafe {
        // Set the SIGPIPE signal handler, so that an EPIPE
        // will cause rustc to terminate, as expected.
        assert_ne!(libc::signal(libc::SIGPIPE, libc::SIG_DFL), libc::SIG_ERR);
    }
}

#[cfg(windows)]
pub fn set_sigpipe_handler() {}

// Extract output directory and file from matches.
fn make_output(matches: &getopts::Matches) -> (Option<PathBuf>, Option<PathBuf>) {
    let odir = matches.opt_str("out-dir").map(|o| PathBuf::from(&o));
    let ofile = matches.opt_str("o").map(|o| PathBuf::from(&o));
    (odir, ofile)
}

// Extract input (string or file and optional path) from matches.
fn make_input(free_matches: &[String]) -> Option<(Input, Option<PathBuf>, Option<io::Error>)> {
    if free_matches.len() == 1 {
        let ifile = &free_matches[0];
        if ifile == "-" {
            let mut src = String::new();
            let err = if io::stdin().read_to_string(&mut src).is_err() {
                Some(io::Error::new(io::ErrorKind::InvalidData,
                                    "couldn't read from stdin, as it did not contain valid UTF-8"))
            } else {
                None
            };
            Some((Input::Str { name: FileName::Anon, input: src },
                  None, err))
        } else {
            Some((Input::File(PathBuf::from(ifile)),
                  Some(PathBuf::from(ifile)), None))
        }
    } else {
        None
    }
}

fn parse_pretty(sess: &Session,
                matches: &getopts::Matches)
                -> Option<(PpMode, Option<UserIdentifiedItem>)> {
    let pretty = if sess.opts.debugging_opts.unstable_options {
        matches.opt_default("pretty", "normal").map(|a| {
            // stable pretty-print variants only
            pretty::parse_pretty(sess, &a, false)
        })
    } else {
        None
    };

    if pretty.is_none() {
        sess.opts.debugging_opts.unpretty.as_ref().map(|a| {
            // extended with unstable pretty-print variants
            pretty::parse_pretty(sess, &a, true)
        })
    } else {
        pretty
    }
}

// Whether to stop or continue compilation.
#[derive(Copy, Clone, Debug, Eq, PartialEq)]
pub enum Compilation {
    Stop,
    Continue,
}

impl Compilation {
    pub fn and_then<F: FnOnce() -> Compilation>(self, next: F) -> Compilation {
        match self {
            Compilation::Stop => Compilation::Stop,
            Compilation::Continue => next(),
        }
    }
}

/// A trait for customising the compilation process. Offers a number of hooks for
/// executing custom code or customising input.
pub trait CompilerCalls<'a> {
    /// Hook for a callback early in the process of handling arguments. This will
    /// be called straight after options have been parsed but before anything
    /// else (e.g., selecting input and output).
    fn early_callback(&mut self,
                      _: &getopts::Matches,
                      _: &config::Options,
                      _: &ast::CrateConfig,
                      _: &errors::registry::Registry,
                      _: ErrorOutputType)
                      -> Compilation {
        Compilation::Continue
    }

    /// Hook for a callback late in the process of handling arguments. This will
    /// be called just before actual compilation starts (and before build_controller
    /// is called), after all arguments etc. have been completely handled.
    fn late_callback(&mut self,
                     _: &dyn CodegenBackend,
                     _: &getopts::Matches,
                     _: &Session,
                     _: &CStore,
                     _: &Input,
                     _: &Option<PathBuf>,
                     _: &Option<PathBuf>)
                     -> Compilation {
        Compilation::Continue
    }

    /// Called after we extract the input from the arguments. Gives the implementer
    /// an opportunity to change the inputs or to add some custom input handling.
    /// The default behaviour is to simply pass through the inputs.
    fn some_input(&mut self,
                  input: Input,
                  input_path: Option<PathBuf>)
                  -> (Input, Option<PathBuf>) {
        (input, input_path)
    }

    /// Called after we extract the input from the arguments if there is no valid
    /// input. Gives the implementer an opportunity to supply alternate input (by
    /// returning a Some value) or to add custom behaviour for this error such as
    /// emitting error messages. Returning None will cause compilation to stop
    /// at this point.
    fn no_input(&mut self,
                _: &getopts::Matches,
                _: &config::Options,
                _: &ast::CrateConfig,
                _: &Option<PathBuf>,
                _: &Option<PathBuf>,
                _: &errors::registry::Registry)
                -> Option<(Input, Option<PathBuf>)> {
        None
    }

    // Create a CompilController struct for controlling the behaviour of
    // compilation.
    fn build_controller(
        self: Box<Self>,
        _: &Session,
        _: &getopts::Matches
    ) -> CompileController<'a>;
}

/// CompilerCalls instance for a regular rustc build.
#[derive(Copy, Clone)]
pub struct RustcDefaultCalls;

// FIXME remove these and use winapi 0.3 instead
// Duplicates: bootstrap/compile.rs, librustc_errors/emitter.rs
#[cfg(unix)]
fn stdout_isatty() -> bool {
    unsafe { libc::isatty(libc::STDOUT_FILENO) != 0 }
}

#[cfg(windows)]
fn stdout_isatty() -> bool {
    type DWORD = u32;
    type BOOL = i32;
    type HANDLE = *mut u8;
    type LPDWORD = *mut u32;
    const STD_OUTPUT_HANDLE: DWORD = -11i32 as DWORD;
    extern "system" {
        fn GetStdHandle(which: DWORD) -> HANDLE;
        fn GetConsoleMode(hConsoleHandle: HANDLE, lpMode: LPDWORD) -> BOOL;
    }
    unsafe {
        let handle = GetStdHandle(STD_OUTPUT_HANDLE);
        let mut out = 0;
        GetConsoleMode(handle, &mut out) != 0
    }
}

fn handle_explain(code: &str,
                  descriptions: &errors::registry::Registry,
                  output: ErrorOutputType) {
    let normalised = if code.starts_with("E") {
        code.to_string()
    } else {
        format!("E{0:0>4}", code)
    };
    match descriptions.find_description(&normalised) {
        Some(ref description) => {
            let mut is_in_code_block = false;
            let mut text = String::new();

            // Slice off the leading newline and print.
            for line in description[1..].lines() {
                let indent_level = line.find(|c: char| !c.is_whitespace())
                    .unwrap_or_else(|| line.len());
                let dedented_line = &line[indent_level..];
                if dedented_line.starts_with("```") {
                    is_in_code_block = !is_in_code_block;
                    text.push_str(&line[..(indent_level+3)]);
                } else if is_in_code_block && dedented_line.starts_with("# ") {
                    continue;
                } else {
                    text.push_str(line);
                }
                text.push('\n');
            }

            if stdout_isatty() {
                show_content_with_pager(&text);
            } else {
                print!("{}", text);
            }
        }
        None => {
            early_error(output, &format!("no extended information for {}", code));
        }
    }
}

fn show_content_with_pager(content: &String) {
    let pager_name = env::var_os("PAGER").unwrap_or_else(|| if cfg!(windows) {
        OsString::from("more.com")
    } else {
        OsString::from("less")
    });

    let mut fallback_to_println = false;

    match Command::new(pager_name).stdin(Stdio::piped()).spawn() {
        Ok(mut pager) => {
            if let Some(pipe) = pager.stdin.as_mut() {
                if pipe.write_all(content.as_bytes()).is_err() {
                    fallback_to_println = true;
                }
            }

            if pager.wait().is_err() {
                fallback_to_println = true;
            }
        }
        Err(_) => {
            fallback_to_println = true;
        }
    }

    // If pager fails for whatever reason, we should still print the content
    // to standard output
    if fallback_to_println {
        print!("{}", content);
    }
}

impl<'a> CompilerCalls<'a> for RustcDefaultCalls {
    fn early_callback(&mut self,
                      matches: &getopts::Matches,
                      _: &config::Options,
                      _: &ast::CrateConfig,
                      descriptions: &errors::registry::Registry,
                      output: ErrorOutputType)
                      -> Compilation {
        if let Some(ref code) = matches.opt_str("explain") {
            handle_explain(code, descriptions, output);
            return Compilation::Stop;
        }

        Compilation::Continue
    }

    fn no_input(&mut self,
                matches: &getopts::Matches,
                sopts: &config::Options,
                cfg: &ast::CrateConfig,
                odir: &Option<PathBuf>,
                ofile: &Option<PathBuf>,
                descriptions: &errors::registry::Registry)
                -> Option<(Input, Option<PathBuf>)> {
        match matches.free.len() {
            0 => {
                let mut sess = build_session(sopts.clone(),
                    None,
                    descriptions.clone());
                if sopts.describe_lints {
                    let mut ls = lint::LintStore::new();
                    rustc_lint::register_builtins(&mut ls, Some(&sess));
                    describe_lints(&sess, &ls, false);
                    return None;
                }
                rustc_lint::register_builtins(&mut sess.lint_store.borrow_mut(), Some(&sess));
                let mut cfg = config::build_configuration(&sess, cfg.clone());
                let codegen_backend = get_codegen_backend(&sess);
                target_features::add_configuration(&mut cfg, &sess, &*codegen_backend);
                sess.parse_sess.config = cfg;
                let should_stop = RustcDefaultCalls::print_crate_info(
                    &*codegen_backend,
                    &sess,
                    None,
                    odir,
                    ofile
                );

                if should_stop == Compilation::Stop {
                    return None;
                }
                early_error(sopts.error_format, "no input filename given");
            }
            1 => panic!("make_input should have provided valid inputs"),
            _ => early_error(sopts.error_format, "multiple input filenames provided"),
        }
    }

    fn late_callback(&mut self,
                     codegen_backend: &dyn CodegenBackend,
                     matches: &getopts::Matches,
                     sess: &Session,
                     cstore: &CStore,
                     input: &Input,
                     odir: &Option<PathBuf>,
                     ofile: &Option<PathBuf>)
                     -> Compilation {
        RustcDefaultCalls::print_crate_info(codegen_backend, sess, Some(input), odir, ofile)
            .and_then(|| RustcDefaultCalls::list_metadata(sess, cstore, matches, input))
    }

    fn build_controller(self: Box<Self>,
                        sess: &Session,
                        matches: &getopts::Matches)
                        -> CompileController<'a> {
        let mut control = CompileController::basic();

        control.keep_ast = sess.opts.debugging_opts.keep_ast;
        control.continue_parse_after_error = sess.opts.debugging_opts.continue_parse_after_error;

        if let Some((ppm, opt_uii)) = parse_pretty(sess, matches) {
            if ppm.needs_ast_map(&opt_uii) {
                control.after_hir_lowering.stop = Compilation::Stop;

                control.after_parse.callback = box move |state| {
                    state.krate = Some(pretty::fold_crate(state.session,
                                                          state.krate.take().unwrap(),
                                                          ppm));
                };
                control.after_hir_lowering.callback = box move |state| {
                    pretty::print_after_hir_lowering(state.session,
                                                     state.cstore.unwrap(),
                                                     state.hir_map.unwrap(),
                                                     state.analysis.unwrap(),
                                                     state.resolutions.unwrap(),
                                                     state.input,
                                                     &state.expanded_crate.take().unwrap(),
                                                     state.crate_name.unwrap(),
                                                     ppm,
                                                     state.arenas.unwrap(),
                                                     state.output_filenames.unwrap(),
                                                     opt_uii.clone(),
                                                     state.out_file);
                };
            } else {
                control.after_parse.stop = Compilation::Stop;

                control.after_parse.callback = box move |state| {
                    let krate = pretty::fold_crate(state.session, state.krate.take().unwrap(), ppm);
                    pretty::print_after_parsing(state.session,
                                                state.input,
                                                &krate,
                                                ppm,
                                                state.out_file);
                };
            }

            return control;
        }

        if sess.opts.debugging_opts.parse_only ||
           sess.opts.debugging_opts.show_span.is_some() ||
           sess.opts.debugging_opts.ast_json_noexpand {
            control.after_parse.stop = Compilation::Stop;
        }

        if sess.opts.debugging_opts.no_analysis ||
           sess.opts.debugging_opts.ast_json {
            control.after_hir_lowering.stop = Compilation::Stop;
        }

        if sess.opts.debugging_opts.save_analysis {
            enable_save_analysis(&mut control);
        }

        if sess.print_fuel_crate.is_some() {
            let old_callback = control.compilation_done.callback;
            control.compilation_done.callback = box move |state| {
                old_callback(state);
                let sess = state.session;
                println!("Fuel used by {}: {}",
                    sess.print_fuel_crate.as_ref().unwrap(),
                    sess.print_fuel.get());
            }
        }
        control
    }
}

pub fn enable_save_analysis(control: &mut CompileController) {
    control.keep_ast = true;
    control.after_analysis.callback = box |state| {
        time(state.session, "save analysis", || {
            save::process_crate(state.tcx.unwrap(),
                                state.expanded_crate.unwrap(),
                                state.analysis.unwrap(),
                                state.crate_name.unwrap(),
                                state.input,
                                None,
                                DumpHandler::new(state.out_dir,
                                                 state.crate_name.unwrap()))
        });
    };
    control.after_analysis.run_callback_on_error = true;
    control.make_glob_map = resolve::MakeGlobMap::Yes;
}

impl RustcDefaultCalls {
    pub fn list_metadata(sess: &Session,
                         cstore: &CStore,
                         matches: &getopts::Matches,
                         input: &Input)
                         -> Compilation {
        let r = matches.opt_strs("Z");
        if r.iter().any(|s| *s == "ls") {
            match input {
                &Input::File(ref ifile) => {
                    let path = &(*ifile);
                    let mut v = Vec::new();
                    locator::list_file_metadata(&sess.target.target,
                                                path,
                                                &*cstore.metadata_loader,
                                                &mut v)
                            .unwrap();
                    println!("{}", String::from_utf8(v).unwrap());
                }
                &Input::Str { .. } => {
                    early_error(ErrorOutputType::default(), "cannot list metadata for stdin");
                }
            }
            return Compilation::Stop;
        }

        Compilation::Continue
    }


    fn print_crate_info(codegen_backend: &dyn CodegenBackend,
                        sess: &Session,
                        input: Option<&Input>,
                        odir: &Option<PathBuf>,
                        ofile: &Option<PathBuf>)
                        -> Compilation {
        use rustc::session::config::PrintRequest::*;
        // PrintRequest::NativeStaticLibs is special - printed during linking
        // (empty iterator returns true)
        if sess.opts.prints.iter().all(|&p| p == PrintRequest::NativeStaticLibs) {
            return Compilation::Continue;
        }

        let attrs = match input {
            None => None,
            Some(input) => {
                let result = parse_crate_attrs(sess, input);
                match result {
                    Ok(attrs) => Some(attrs),
                    Err(mut parse_error) => {
                        parse_error.emit();
                        return Compilation::Stop;
                    }
                }
            }
        };
        for req in &sess.opts.prints {
            match *req {
                TargetList => {
                    let mut targets = rustc_target::spec::get_targets().collect::<Vec<String>>();
                    targets.sort();
                    println!("{}", targets.join("\n"));
                },
                Sysroot => println!("{}", sess.sysroot().display()),
                TargetSpec => println!("{}", sess.target.target.to_json().pretty()),
                FileNames | CrateName => {
                    let input = input.unwrap_or_else(||
                        early_error(ErrorOutputType::default(), "no input file provided"));
                    let attrs = attrs.as_ref().unwrap();
                    let t_outputs = driver::build_output_filenames(input, odir, ofile, attrs, sess);
                    let id = rustc_codegen_utils::link::find_crate_name(Some(sess), attrs, input);
                    if *req == PrintRequest::CrateName {
                        println!("{}", id);
                        continue;
                    }
                    let crate_types = driver::collect_crate_types(sess, attrs);
                    for &style in &crate_types {
                        let fname = rustc_codegen_utils::link::filename_for_input(
                            sess,
                            style,
                            &id,
                            &t_outputs
                        );
                        println!("{}", fname.file_name().unwrap().to_string_lossy());
                    }
                }
                Cfg => {
                    let allow_unstable_cfg = UnstableFeatures::from_environment()
                        .is_nightly_build();

                    let mut cfgs = sess.parse_sess.config.iter().filter_map(|&(name, ref value)| {
                        let gated_cfg = GatedCfg::gate(&ast::MetaItem {
                            ident: ast::Path::from_ident(ast::Ident::with_empty_ctxt(name)),
                            node: ast::MetaItemKind::Word,
                            span: DUMMY_SP,
                        });

                        // Note that crt-static is a specially recognized cfg
                        // directive that's printed out here as part of
                        // rust-lang/rust#37406, but in general the
                        // `target_feature` cfg is gated under
                        // rust-lang/rust#29717. For now this is just
                        // specifically allowing the crt-static cfg and that's
                        // it, this is intended to get into Cargo and then go
                        // through to build scripts.
                        let value = value.as_ref().map(|s| s.as_str());
                        let value = value.as_ref().map(|s| s.as_ref());
                        if name != "target_feature" || value != Some("crt-static") {
                            if !allow_unstable_cfg && gated_cfg.is_some() {
                                return None
                            }
                        }

                        if let Some(value) = value {
                            Some(format!("{}=\"{}\"", name, value))
                        } else {
                            Some(name.to_string())
                        }
                    }).collect::<Vec<String>>();

                    cfgs.sort();
                    for cfg in cfgs {
                        println!("{}", cfg);
                    }
                }
                RelocationModels | CodeModels | TlsModels | TargetCPUs | TargetFeatures => {
                    codegen_backend.print(*req, sess);
                }
                // Any output here interferes with Cargo's parsing of other printed output
                PrintRequest::NativeStaticLibs => {}
            }
        }
        return Compilation::Stop;
    }
}

/// Returns a version string such as "0.12.0-dev".
fn release_str() -> Option<&'static str> {
    option_env!("CFG_RELEASE")
}

/// Returns the full SHA1 hash of HEAD of the Git repo from which rustc was built.
fn commit_hash_str() -> Option<&'static str> {
    option_env!("CFG_VER_HASH")
}

/// Returns the "commit date" of HEAD of the Git repo from which rustc was built as a static string.
fn commit_date_str() -> Option<&'static str> {
    option_env!("CFG_VER_DATE")
}

/// Prints version information
pub fn version(binary: &str, matches: &getopts::Matches) {
    let verbose = matches.opt_present("verbose");

    println!("{} {}", binary, option_env!("CFG_VERSION").unwrap_or("unknown version"));

    if verbose {
        fn unw(x: Option<&str>) -> &str {
            x.unwrap_or("unknown")
        }
        println!("binary: {}", binary);
        println!("commit-hash: {}", unw(commit_hash_str()));
        println!("commit-date: {}", unw(commit_date_str()));
        println!("host: {}", config::host_triple());
        println!("release: {}", unw(release_str()));
        get_codegen_sysroot("llvm")().print_version();
    }
}

fn usage(verbose: bool, include_unstable_options: bool) {
    let groups = if verbose {
        config::rustc_optgroups()
    } else {
        config::rustc_short_optgroups()
    };
    let mut options = getopts::Options::new();
    for option in groups.iter().filter(|x| include_unstable_options || x.is_stable()) {
        (option.apply)(&mut options);
    }
    let message = "Usage: rustc [OPTIONS] INPUT";
    let nightly_help = if nightly_options::is_nightly_build() {
        "\n    -Z help             Print internal options for debugging rustc"
    } else {
        ""
    };
    let verbose_help = if verbose {
        ""
    } else {
        "\n    --help -v           Print the full set of options rustc accepts"
    };
    println!("{}\nAdditional help:
    -C help             Print codegen options
    -W help             \
              Print 'lint' options and default settings{}{}\n",
             options.usage(message),
             nightly_help,
             verbose_help);
}

fn print_wall_help() {
    println!("
The flag `-Wall` does not exist in `rustc`. Most useful lints are enabled by
default. Use `rustc -W help` to see all available lints. It's more common to put
warning settings in the crate root using `#![warn(LINT_NAME)]` instead of using
the command line flag directly.
");
}

fn describe_lints(sess: &Session, lint_store: &lint::LintStore, loaded_plugins: bool) {
    println!("
Available lint options:
    -W <foo>           Warn about <foo>
    -A <foo>           \
              Allow <foo>
    -D <foo>           Deny <foo>
    -F <foo>           Forbid <foo> \
              (deny <foo> and all attempts to override)

");

    fn sort_lints(sess: &Session, lints: Vec<(&'static Lint, bool)>) -> Vec<&'static Lint> {
        let mut lints: Vec<_> = lints.into_iter().map(|(x, _)| x).collect();
        // The sort doesn't case-fold but it's doubtful we care.
        lints.sort_by_cached_key(|x: &&Lint| (x.default_level(sess), x.name));
        lints
    }

    fn sort_lint_groups(lints: Vec<(&'static str, Vec<lint::LintId>, bool)>)
                        -> Vec<(&'static str, Vec<lint::LintId>)> {
        let mut lints: Vec<_> = lints.into_iter().map(|(x, y, _)| (x, y)).collect();
        lints.sort_by_key(|l| l.0);
        lints
    }

    let (plugin, builtin): (Vec<_>, _) = lint_store.get_lints()
                                                   .iter()
                                                   .cloned()
                                                   .partition(|&(_, p)| p);
    let plugin = sort_lints(sess, plugin);
    let builtin = sort_lints(sess, builtin);

    let (plugin_groups, builtin_groups): (Vec<_>, _) = lint_store.get_lint_groups()
                                                                 .iter()
                                                                 .cloned()
                                                                 .partition(|&(.., p)| p);
    let plugin_groups = sort_lint_groups(plugin_groups);
    let builtin_groups = sort_lint_groups(builtin_groups);

    let max_name_len = plugin.iter()
                             .chain(&builtin)
                             .map(|&s| s.name.chars().count())
                             .max()
                             .unwrap_or(0);
    let padded = |x: &str| {
        let mut s = " ".repeat(max_name_len - x.chars().count());
        s.push_str(x);
        s
    };

    println!("Lint checks provided by rustc:\n");
    println!("    {}  {:7.7}  {}", padded("name"), "default", "meaning");
    println!("    {}  {:7.7}  {}", padded("----"), "-------", "-------");

    let print_lints = |lints: Vec<&Lint>| {
        for lint in lints {
            let name = lint.name_lower().replace("_", "-");
            println!("    {}  {:7.7}  {}",
                     padded(&name),
                     lint.default_level.as_str(),
                     lint.desc);
        }
        println!("\n");
    };

    print_lints(builtin);

    let max_name_len = max("warnings".len(),
                           plugin_groups.iter()
                                        .chain(&builtin_groups)
                                        .map(|&(s, _)| s.chars().count())
                                        .max()
                                        .unwrap_or(0));

    let padded = |x: &str| {
        let mut s = " ".repeat(max_name_len - x.chars().count());
        s.push_str(x);
        s
    };

    println!("Lint groups provided by rustc:\n");
    println!("    {}  {}", padded("name"), "sub-lints");
    println!("    {}  {}", padded("----"), "---------");
    println!("    {}  {}", padded("warnings"), "all lints that are set to issue warnings");

    let print_lint_groups = |lints: Vec<(&'static str, Vec<lint::LintId>)>| {
        for (name, to) in lints {
            let name = name.to_lowercase().replace("_", "-");
            let desc = to.into_iter()
                         .map(|x| x.to_string().replace("_", "-"))
                         .collect::<Vec<String>>()
                         .join(", ");
            println!("    {}  {}", padded(&name), desc);
        }
        println!("\n");
    };

    print_lint_groups(builtin_groups);

    match (loaded_plugins, plugin.len(), plugin_groups.len()) {
        (false, 0, _) | (false, _, 0) => {
            println!("Compiler plugins can provide additional lints and lint groups. To see a \
                      listing of these, re-run `rustc -W help` with a crate filename.");
        }
        (false, ..) => panic!("didn't load lint plugins but got them anyway!"),
        (true, 0, 0) => println!("This crate does not load any lint plugins or lint groups."),
        (true, l, g) => {
            if l > 0 {
                println!("Lint checks provided by plugins loaded by this crate:\n");
                print_lints(plugin);
            }
            if g > 0 {
                println!("Lint groups provided by plugins loaded by this crate:\n");
                print_lint_groups(plugin_groups);
            }
        }
    }
}

fn describe_debug_flags() {
    println!("\nAvailable debug options:\n");
    print_flag_list("-Z", config::DB_OPTIONS);
}

fn describe_codegen_flags() {
    println!("\nAvailable codegen options:\n");
    print_flag_list("-C", config::CG_OPTIONS);
}

fn print_flag_list<T>(cmdline_opt: &str,
                      flag_list: &[(&'static str, T, Option<&'static str>, &'static str)]) {
    let max_len = flag_list.iter()
                           .map(|&(name, _, opt_type_desc, _)| {
                               let extra_len = match opt_type_desc {
                                   Some(..) => 4,
                                   None => 0,
                               };
                               name.chars().count() + extra_len
                           })
                           .max()
                           .unwrap_or(0);

    for &(name, _, opt_type_desc, desc) in flag_list {
        let (width, extra) = match opt_type_desc {
            Some(..) => (max_len - 4, "=val"),
            None => (max_len, ""),
        };
        println!("    {} {:>width$}{} -- {}",
                 cmdline_opt,
                 name.replace("_", "-"),
                 extra,
                 desc,
                 width = width);
    }
}

/// Process command line options. Emits messages as appropriate. If compilation
/// should continue, returns a getopts::Matches object parsed from args,
/// otherwise returns None.
///
/// The compiler's handling of options is a little complicated as it ties into
/// our stability story, and it's even *more* complicated by historical
/// accidents. The current intention of each compiler option is to have one of
/// three modes:
///
/// 1. An option is stable and can be used everywhere.
/// 2. An option is unstable, but was historically allowed on the stable
///    channel.
/// 3. An option is unstable, and can only be used on nightly.
///
/// Like unstable library and language features, however, unstable options have
/// always required a form of "opt in" to indicate that you're using them. This
/// provides the easy ability to scan a code base to check to see if anything
/// unstable is being used. Currently, this "opt in" is the `-Z` "zed" flag.
///
/// All options behind `-Z` are considered unstable by default. Other top-level
/// options can also be considered unstable, and they were unlocked through the
/// `-Z unstable-options` flag. Note that `-Z` remains to be the root of
/// instability in both cases, though.
///
/// So with all that in mind, the comments below have some more detail about the
/// contortions done here to get things to work out correctly.
pub fn handle_options(args: &[String]) -> Option<getopts::Matches> {
    // Throw away the first argument, the name of the binary
    let args = &args[1..];

    if args.is_empty() {
        // user did not write `-v` nor `-Z unstable-options`, so do not
        // include that extra information.
        usage(false, false);
        return None;
    }

    // Parse with *all* options defined in the compiler, we don't worry about
    // option stability here we just want to parse as much as possible.
    let mut options = getopts::Options::new();
    for option in config::rustc_optgroups() {
        (option.apply)(&mut options);
    }
    let matches = options.parse(args).unwrap_or_else(|f|
        early_error(ErrorOutputType::default(), &f.to_string()));

    // For all options we just parsed, we check a few aspects:
    //
    // * If the option is stable, we're all good
    // * If the option wasn't passed, we're all good
    // * If `-Z unstable-options` wasn't passed (and we're not a -Z option
    //   ourselves), then we require the `-Z unstable-options` flag to unlock
    //   this option that was passed.
    // * If we're a nightly compiler, then unstable options are now unlocked, so
    //   we're good to go.
    // * Otherwise, if we're a truly unstable option then we generate an error
    //   (unstable option being used on stable)
    // * If we're a historically stable-but-should-be-unstable option then we
    //   emit a warning that we're going to turn this into an error soon.
    nightly_options::check_nightly_options(&matches, &config::rustc_optgroups());

    if matches.opt_present("h") || matches.opt_present("help") {
        // Only show unstable options in --help if we *really* accept unstable
        // options, which catches the case where we got `-Z unstable-options` on
        // the stable channel of Rust which was accidentally allowed
        // historically.
        usage(matches.opt_present("verbose"),
              nightly_options::is_unstable_enabled(&matches));
        return None;
    }

    // Handle the special case of -Wall.
    let wall = matches.opt_strs("W");
    if wall.iter().any(|x| *x == "all") {
        print_wall_help();
        return None;
    }

    // Don't handle -W help here, because we might first load plugins.
    let r = matches.opt_strs("Z");
    if r.iter().any(|x| *x == "help") {
        describe_debug_flags();
        return None;
    }

    let cg_flags = matches.opt_strs("C");

    if cg_flags.iter().any(|x| *x == "help") {
        describe_codegen_flags();
        return None;
    }

    if cg_flags.iter().any(|x| *x == "no-stack-check") {
        early_warn(ErrorOutputType::default(),
                   "the --no-stack-check flag is deprecated and does nothing");
    }

    if cg_flags.iter().any(|x| *x == "passes=list") {
        get_codegen_sysroot("llvm")().print_passes();
        return None;
    }

    if matches.opt_present("version") {
        version("rustc", &matches);
        return None;
    }

    Some(matches)
}

fn parse_crate_attrs<'a>(sess: &'a Session, input: &Input) -> PResult<'a, Vec<ast::Attribute>> {
    match *input {
        Input::File(ref ifile) => {
            parse::parse_crate_attrs_from_file(ifile, &sess.parse_sess)
        }
        Input::Str { ref name, ref input } => {
            parse::parse_crate_attrs_from_source_str(name.clone(),
                                                     input.clone(),
                                                     &sess.parse_sess)
        }
    }
}

/// Runs `f` in a suitable thread for running `rustc`; returns a `Result` with either the return
/// value of `f` or -- if a panic occurs -- the panic value.
///
/// This version applies the given name to the thread. This is used by rustdoc to ensure consistent
/// doctest output across platforms and executions.
pub fn in_named_rustc_thread<F, R>(name: String, f: F) -> Result<R, Box<dyn Any + Send>>
    where F: FnOnce() -> R + Send + 'static,
          R: Send + 'static,
{
    // Temporarily have stack size set to 16MB to deal with nom-using crates failing
    const STACK_SIZE: usize = 16 * 1024 * 1024; // 16MB

    #[cfg(all(unix, not(target_os = "haiku")))]
    let spawn_thread = unsafe {
        // Fetch the current resource limits
        let mut rlim = libc::rlimit {
            rlim_cur: 0,
            rlim_max: 0,
        };
        if libc::getrlimit(libc::RLIMIT_STACK, &mut rlim) != 0 {
            let err = io::Error::last_os_error();
            error!("in_rustc_thread: error calling getrlimit: {}", err);
            true
        } else if rlim.rlim_max < STACK_SIZE as libc::rlim_t {
            true
        } else if rlim.rlim_cur < STACK_SIZE as libc::rlim_t {
            std::rt::deinit_stack_guard();
            rlim.rlim_cur = STACK_SIZE as libc::rlim_t;
            if libc::setrlimit(libc::RLIMIT_STACK, &mut rlim) != 0 {
                let err = io::Error::last_os_error();
                error!("in_rustc_thread: error calling setrlimit: {}", err);
                std::rt::update_stack_guard();
                true
            } else {
                std::rt::update_stack_guard();
                false
            }
        } else {
            false
        }
    };

    // We set the stack size at link time. See src/rustc/rustc.rs.
    #[cfg(windows)]
    let spawn_thread = false;

    #[cfg(target_os = "haiku")]
    let spawn_thread = unsafe {
        // Haiku does not have setrlimit implemented for the stack size.
        // By default it does have the 16 MB stack limit, but we check this in
        // case the minimum STACK_SIZE changes or Haiku's defaults change.
        let mut rlim = libc::rlimit {
            rlim_cur: 0,
            rlim_max: 0,
        };
        if libc::getrlimit(libc::RLIMIT_STACK, &mut rlim) != 0 {
            let err = io::Error::last_os_error();
            error!("in_rustc_thread: error calling getrlimit: {}", err);
            true
        } else if rlim.rlim_cur >= STACK_SIZE {
            false
        } else {
            true
        }
    };

    #[cfg(not(any(windows, unix)))]
    let spawn_thread = true;

    // The or condition is added from backward compatibility.
    if spawn_thread || env::var_os("RUST_MIN_STACK").is_some() {
        let mut cfg = thread::Builder::new().name(name);

        // FIXME: Hacks on hacks. If the env is trying to override the stack size
        // then *don't* set it explicitly.
        if env::var_os("RUST_MIN_STACK").is_none() {
            cfg = cfg.stack_size(STACK_SIZE);
        }

        let thread = cfg.spawn(f);
        thread.unwrap().join()
    } else {
        let f = panic::AssertUnwindSafe(f);
        panic::catch_unwind(f)
    }
}

/// Runs `f` in a suitable thread for running `rustc`; returns a
/// `Result` with either the return value of `f` or -- if a panic
/// occurs -- the panic value.
pub fn in_rustc_thread<F, R>(f: F) -> Result<R, Box<dyn Any + Send>>
    where F: FnOnce() -> R + Send + 'static,
          R: Send + 'static,
{
    in_named_rustc_thread("rustc".to_string(), f)
}

/// Get a list of extra command-line flags provided by the user, as strings.
///
/// This function is used during ICEs to show more information useful for
/// debugging, since some ICEs only happens with non-default compiler flags
/// (and the users don't always report them).
fn extra_compiler_flags() -> Option<(Vec<String>, bool)> {
    let args = env::args_os().map(|arg| arg.to_string_lossy().to_string()).collect::<Vec<_>>();

    // Avoid printing help because of empty args. This can suggest the compiler
    // itself is not the program root (consider RLS).
    if args.len() < 2 {
        return None;
    }

    let matches = if let Some(matches) = handle_options(&args) {
        matches
    } else {
        return None;
    };

    let mut result = Vec::new();
    let mut excluded_cargo_defaults = false;
    for flag in ICE_REPORT_COMPILER_FLAGS {
        let prefix = if flag.len() == 1 { "-" } else { "--" };

        for content in &matches.opt_strs(flag) {
            // Split always returns the first element
            let name = if let Some(first) = content.split('=').next() {
                first
            } else {
                &content
            };

            let content = if ICE_REPORT_COMPILER_FLAGS_STRIP_VALUE.contains(&name) {
                name
            } else {
                content
            };

            if !ICE_REPORT_COMPILER_FLAGS_EXCLUDE.contains(&name) {
                result.push(format!("{}{} {}", prefix, flag, content));
            } else {
                excluded_cargo_defaults = true;
            }
        }
    }

    if !result.is_empty() {
        Some((result, excluded_cargo_defaults))
    } else {
        None
    }
}

#[derive(Debug)]
pub struct CompilationFailure;

impl Error for CompilationFailure {}

impl Display for CompilationFailure {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "compilation had errors")
    }
}

/// Run a procedure which will detect panics in the compiler and print nicer
/// error messages rather than just failing the test.
///
/// The diagnostic emitter yielded to the procedure should be used for reporting
/// errors of the compiler.
pub fn monitor<F: FnOnce() + Send + 'static>(f: F) -> Result<(), CompilationFailure> {
    in_rustc_thread(move || {
        f()
    }).map_err(|value| {
        if value.is::<errors::FatalErrorMarker>() {
            CompilationFailure
        } else {
            // Thread panicked without emitting a fatal diagnostic
            eprintln!("");

            let emitter =
                Box::new(errors::emitter::EmitterWriter::stderr(errors::ColorConfig::Auto,
                                                                None,
                                                                false,
                                                                false));
            let handler = errors::Handler::with_emitter(true, false, emitter);

            // a .span_bug or .bug call has already printed what
            // it wants to print.
            if !value.is::<errors::ExplicitBug>() {
                handler.emit(&MultiSpan::new(),
                             "unexpected panic",
                             errors::Level::Bug);
            }

            let mut xs: Vec<Cow<'static, str>> = vec![
                "the compiler unexpectedly panicked. this is a bug.".into(),
                format!("we would appreciate a bug report: {}", BUG_REPORT_URL).into(),
                format!("rustc {} running on {}",
                        option_env!("CFG_VERSION").unwrap_or("unknown_version"),
                        config::host_triple()).into(),
            ];

            if let Some((flags, excluded_cargo_defaults)) = extra_compiler_flags() {
                xs.push(format!("compiler flags: {}", flags.join(" ")).into());

                if excluded_cargo_defaults {
                    xs.push("some of the compiler flags provided by cargo are hidden".into());
                }
            }

            for note in &xs {
                handler.emit(&MultiSpan::new(),
                             note,
                             errors::Level::Note);
            }

            panic::resume_unwind(Box::new(errors::FatalErrorMarker));
        }
    })
}

pub fn diagnostics_registry() -> errors::registry::Registry {
    use errors::registry::Registry;

    let mut all_errors = Vec::new();
    all_errors.extend_from_slice(&rustc::DIAGNOSTICS);
    all_errors.extend_from_slice(&rustc_typeck::DIAGNOSTICS);
    all_errors.extend_from_slice(&rustc_resolve::DIAGNOSTICS);
    all_errors.extend_from_slice(&rustc_privacy::DIAGNOSTICS);
    // FIXME: need to figure out a way to get these back in here
    // all_errors.extend_from_slice(get_codegen_backend(sess).diagnostics());
    all_errors.extend_from_slice(&rustc_codegen_utils::DIAGNOSTICS);
    all_errors.extend_from_slice(&rustc_metadata::DIAGNOSTICS);
    all_errors.extend_from_slice(&rustc_passes::DIAGNOSTICS);
    all_errors.extend_from_slice(&rustc_plugin::DIAGNOSTICS);
    all_errors.extend_from_slice(&rustc_mir::DIAGNOSTICS);
    all_errors.extend_from_slice(&syntax::DIAGNOSTICS);

    Registry::new(&all_errors)
}

/// This allows tools to enable rust logging without having to magically match rustc's
/// log crate version
pub fn init_rustc_env_logger() {
    env_logger::init();
}

pub fn main() {
    init_rustc_env_logger();
    let result = run(|| {
        let args = env::args_os().enumerate()
            .map(|(i, arg)| arg.into_string().unwrap_or_else(|arg| {
                early_error(ErrorOutputType::default(),
                            &format!("Argument {} is not valid Unicode: {:?}", i, arg))
            }))
            .collect::<Vec<_>>();
        run_compiler(&args,
                     Box::new(RustcDefaultCalls),
                     None,
                     None)
    });
    process::exit(result as i32);
}
