2013-10-15 00:21:54 -05:00
|
|
|
// Copyright 2012-2013 The Rust Project Developers. See the COPYRIGHT
|
2012-12-03 18:48:01 -06:00
|
|
|
// 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.
|
|
|
|
|
2013-05-17 17:28:44 -05:00
|
|
|
|
2012-12-13 15:05:22 -06:00
|
|
|
use back::target_strs;
|
2012-12-23 16:41:37 -06:00
|
|
|
use back;
|
2013-03-01 12:44:43 -06:00
|
|
|
use driver::driver::host_triple;
|
2014-02-24 14:45:31 -06:00
|
|
|
use front;
|
2012-12-13 15:05:22 -06:00
|
|
|
use metadata::filesearch;
|
2012-12-23 16:41:37 -06:00
|
|
|
use metadata;
|
2012-12-13 15:05:22 -06:00
|
|
|
use middle::lint;
|
|
|
|
|
Implement LTO
This commit implements LTO for rust leveraging LLVM's passes. What this means
is:
* When compiling an rlib, in addition to insdering foo.o into the archive, also
insert foo.bc (the LLVM bytecode) of the optimized module.
* When the compiler detects the -Z lto option, it will attempt to perform LTO on
a staticlib or binary output. The compiler will emit an error if a dylib or
rlib output is being generated.
* The actual act of performing LTO is as follows:
1. Force all upstream libraries to have an rlib version available.
2. Load the bytecode of each upstream library from the rlib.
3. Link all this bytecode into the current LLVM module (just using llvm
apis)
4. Run an internalization pass which internalizes all symbols except those
found reachable for the local crate of compilation.
5. Run the LLVM LTO pass manager over this entire module
6a. If assembling an archive, then add all upstream rlibs into the output
archive. This ignores all of the object/bitcode/metadata files rust
generated and placed inside the rlibs.
6b. If linking a binary, create copies of all upstream rlibs, remove the
rust-generated object-file, and then link everything as usual.
As I have explained in #10741, this process is excruciatingly slow, so this is
*not* turned on by default, and it is also why I have decided to hide it behind
a -Z flag for now. The good news is that the binary sizes are about as small as
they can be as a result of LTO, so it's definitely working.
Closes #10741
Closes #10740
2013-12-03 01:19:29 -06:00
|
|
|
use syntax::attr::AttrMetaMethods;
|
2013-07-27 03:25:59 -05:00
|
|
|
use syntax::ast::NodeId;
|
2014-01-09 07:05:33 -06:00
|
|
|
use syntax::ast::{IntTy, UintTy};
|
2013-08-31 11:13:04 -05:00
|
|
|
use syntax::codemap::Span;
|
2012-12-23 16:41:37 -06:00
|
|
|
use syntax::diagnostic;
|
2013-02-21 02:16:31 -06:00
|
|
|
use syntax::parse::ParseSess;
|
2014-02-13 23:07:09 -06:00
|
|
|
use syntax::{abi, ast, codemap};
|
2012-12-23 16:41:37 -06:00
|
|
|
use syntax;
|
2012-06-04 18:07:54 -05:00
|
|
|
|
2013-12-21 19:25:27 -06:00
|
|
|
use std::cell::{Cell, RefCell};
|
2014-02-28 17:25:15 -06:00
|
|
|
use std::vec_ng::Vec;
|
2014-02-19 21:29:58 -06:00
|
|
|
use collections::{HashMap,HashSet};
|
2013-04-30 00:15:17 -05:00
|
|
|
|
2014-01-13 10:31:05 -06:00
|
|
|
pub struct Config {
|
2013-11-08 13:06:57 -06:00
|
|
|
os: abi::Os,
|
2013-03-13 21:25:28 -05:00
|
|
|
arch: abi::Architecture,
|
2013-02-19 01:40:42 -06:00
|
|
|
target_strs: target_strs::t,
|
2014-01-09 07:05:33 -06:00
|
|
|
int_type: IntTy,
|
|
|
|
uint_type: UintTy,
|
2013-02-19 01:40:42 -06:00
|
|
|
}
|
2011-06-15 13:19:50 -05:00
|
|
|
|
2014-01-19 03:17:54 -06:00
|
|
|
macro_rules! debugging_opts(
|
|
|
|
([ $opt:ident ] $cnt:expr ) => (
|
2014-01-20 15:55:10 -06:00
|
|
|
pub static $opt: u64 = 1 << $cnt;
|
2014-01-19 03:17:54 -06:00
|
|
|
);
|
|
|
|
([ $opt:ident, $($rest:ident),* ] $cnt:expr ) => (
|
2014-01-20 15:55:10 -06:00
|
|
|
pub static $opt: u64 = 1 << $cnt;
|
2014-01-19 03:17:54 -06:00
|
|
|
debugging_opts!([ $($rest),* ] $cnt + 1)
|
|
|
|
)
|
|
|
|
)
|
|
|
|
|
|
|
|
debugging_opts!(
|
|
|
|
[
|
2014-01-20 15:55:10 -06:00
|
|
|
VERBOSE,
|
|
|
|
TIME_PASSES,
|
|
|
|
COUNT_LLVM_INSNS,
|
|
|
|
TIME_LLVM_PASSES,
|
|
|
|
TRANS_STATS,
|
|
|
|
ASM_COMMENTS,
|
|
|
|
NO_VERIFY,
|
|
|
|
BORROWCK_STATS,
|
|
|
|
NO_LANDING_PADS,
|
|
|
|
DEBUG_LLVM,
|
2014-02-07 04:50:07 -06:00
|
|
|
SHOW_SPAN,
|
2014-01-20 15:55:10 -06:00
|
|
|
COUNT_TYPE_SIZES,
|
|
|
|
META_STATS,
|
|
|
|
NO_OPT,
|
|
|
|
GC,
|
|
|
|
PRINT_LINK_ARGS,
|
|
|
|
PRINT_LLVM_PASSES,
|
2014-02-19 01:27:49 -06:00
|
|
|
LTO,
|
|
|
|
AST_JSON,
|
|
|
|
AST_JSON_NOEXPAND
|
2014-01-19 03:17:54 -06:00
|
|
|
]
|
|
|
|
0
|
|
|
|
)
|
2013-01-29 17:16:07 -06:00
|
|
|
|
2014-03-04 12:02:49 -06:00
|
|
|
pub fn debugging_opts_map() -> Vec<(&'static str, &'static str, u64)> {
|
|
|
|
vec!(("verbose", "in general, enable more debug printouts", VERBOSE),
|
2014-01-20 15:55:10 -06:00
|
|
|
("time-passes", "measure time of each rustc pass", TIME_PASSES),
|
2013-10-04 12:46:53 -05:00
|
|
|
("count-llvm-insns", "count where LLVM \
|
2014-01-20 15:55:10 -06:00
|
|
|
instrs originate", COUNT_LLVM_INSNS),
|
2013-10-04 12:46:53 -05:00
|
|
|
("time-llvm-passes", "measure time of each LLVM pass",
|
2014-01-20 15:55:10 -06:00
|
|
|
TIME_LLVM_PASSES),
|
|
|
|
("trans-stats", "gather trans statistics", TRANS_STATS),
|
|
|
|
("asm-comments", "generate comments into the assembly (may change behavior)",
|
|
|
|
ASM_COMMENTS),
|
|
|
|
("no-verify", "skip LLVM verification", NO_VERIFY),
|
|
|
|
("borrowck-stats", "gather borrowck statistics", BORROWCK_STATS),
|
2013-10-04 12:46:53 -05:00
|
|
|
("no-landing-pads", "omit landing pads for unwinding",
|
2014-01-20 15:55:10 -06:00
|
|
|
NO_LANDING_PADS),
|
|
|
|
("debug-llvm", "enable debug output from LLVM", DEBUG_LLVM),
|
2014-02-07 05:13:07 -06:00
|
|
|
("show-span", "show spans for compiler debugging", SHOW_SPAN),
|
2013-10-04 12:46:53 -05:00
|
|
|
("count-type-sizes", "count the sizes of aggregate types",
|
2014-01-20 15:55:10 -06:00
|
|
|
COUNT_TYPE_SIZES),
|
|
|
|
("meta-stats", "gather metadata statistics", META_STATS),
|
|
|
|
("no-opt", "do not optimize, even if -O is passed", NO_OPT),
|
|
|
|
("print-link-args", "Print the arguments passed to the linker",
|
|
|
|
PRINT_LINK_ARGS),
|
|
|
|
("gc", "Garbage collect shared data (experimental)", GC),
|
2013-10-04 12:46:53 -05:00
|
|
|
("print-llvm-passes",
|
|
|
|
"Prints the llvm optimization passes being run",
|
2014-01-20 15:55:10 -06:00
|
|
|
PRINT_LLVM_PASSES),
|
|
|
|
("lto", "Perform LLVM link-time optimizations", LTO),
|
2014-02-19 01:27:49 -06:00
|
|
|
("ast-json", "Print the AST as JSON and halt", AST_JSON),
|
2014-03-04 12:02:49 -06:00
|
|
|
("ast-json-noexpand", "Print the pre-expansion AST as JSON and halt", AST_JSON_NOEXPAND))
|
2012-05-17 23:53:49 -05:00
|
|
|
}
|
|
|
|
|
2013-07-02 14:47:32 -05:00
|
|
|
#[deriving(Clone, Eq)]
|
2013-01-29 17:16:07 -06:00
|
|
|
pub enum OptLevel {
|
2012-08-21 19:22:45 -05:00
|
|
|
No, // -O0
|
|
|
|
Less, // -O1
|
|
|
|
Default, // -O2
|
|
|
|
Aggressive // -O3
|
|
|
|
}
|
|
|
|
|
2014-03-05 02:51:47 -06:00
|
|
|
#[deriving(Clone, Eq)]
|
|
|
|
pub enum DebugInfoLevel {
|
|
|
|
NoDebugInfo,
|
|
|
|
LimitedDebugInfo,
|
|
|
|
FullDebugInfo,
|
|
|
|
}
|
|
|
|
|
2013-07-02 14:47:32 -05:00
|
|
|
#[deriving(Clone)]
|
2014-01-13 10:31:05 -06:00
|
|
|
pub struct Options {
|
2011-07-27 07:19:39 -05:00
|
|
|
// The crate config requested for the session, which may be combined
|
|
|
|
// with additional crate configurations during the compile process
|
2014-03-04 12:02:49 -06:00
|
|
|
crate_types: Vec<CrateType> ,
|
Add generation of static libraries to rustc
This commit implements the support necessary for generating both intermediate
and result static rust libraries. This is an implementation of my thoughts in
https://mail.mozilla.org/pipermail/rust-dev/2013-November/006686.html.
When compiling a library, we still retain the "lib" option, although now there
are "rlib", "staticlib", and "dylib" as options for crate_type (and these are
stackable). The idea of "lib" is to generate the "compiler default" instead of
having too choose (although all are interchangeable). For now I have left the
"complier default" to be a dynamic library for size reasons.
Of the rust libraries, lib{std,extra,rustuv} will bootstrap with an
rlib/dylib pair, but lib{rustc,syntax,rustdoc,rustpkg} will only be built as a
dynamic object. I chose this for size reasons, but also because you're probably
not going to be embedding the rustc compiler anywhere any time soon.
Other than the options outlined above, there are a few defaults/preferences that
are now opinionated in the compiler:
* If both a .dylib and .rlib are found for a rust library, the compiler will
prefer the .rlib variant. This is overridable via the -Z prefer-dynamic option
* If generating a "lib", the compiler will generate a dynamic library. This is
overridable by explicitly saying what flavor you'd like (rlib, staticlib,
dylib).
* If no options are passed to the command line, and no crate_type is found in
the destination crate, then an executable is generated
With this change, you can successfully build a rust program with 0 dynamic
dependencies on rust libraries. There is still a dynamic dependency on
librustrt, but I plan on removing that in a subsequent commit.
This change includes no tests just yet. Our current testing
infrastructure/harnesses aren't very amenable to doing flavorful things with
linking, so I'm planning on adding a new mode of testing which I believe belongs
as a separate commit.
Closes #552
2013-11-15 16:03:29 -06:00
|
|
|
|
2013-02-19 01:40:42 -06:00
|
|
|
gc: bool,
|
|
|
|
optimize: OptLevel,
|
2014-03-05 02:51:47 -06:00
|
|
|
debuginfo: DebugInfoLevel,
|
2014-03-04 12:02:49 -06:00
|
|
|
lint_opts: Vec<(lint::Lint, lint::level)> ,
|
|
|
|
output_types: Vec<back::link::OutputType> ,
|
2014-02-02 01:56:55 -06:00
|
|
|
// This was mutable for rustpkg, which updates search paths based on the
|
|
|
|
// parsed code. It remains mutable in case its replacements wants to use
|
|
|
|
// this.
|
2014-03-09 07:24:58 -05:00
|
|
|
addl_lib_search_paths: RefCell<HashSet<Path>>,
|
|
|
|
maybe_sysroot: Option<Path>,
|
2013-02-19 01:40:42 -06:00
|
|
|
target_triple: ~str,
|
|
|
|
// User-specified cfg meta items. The compiler itself will add additional
|
|
|
|
// items to the crate config, and during parsing the entire crate config
|
|
|
|
// will be added to the crate AST node. This should not be used for
|
|
|
|
// anything except building the full crate config prior to parsing.
|
2013-07-19 00:38:55 -05:00
|
|
|
cfg: ast::CrateConfig,
|
2013-02-19 01:40:42 -06:00
|
|
|
test: bool,
|
|
|
|
parse_only: bool,
|
|
|
|
no_trans: bool,
|
2013-12-26 16:39:36 -06:00
|
|
|
no_analysis: bool,
|
2014-01-20 15:55:10 -06:00
|
|
|
debugging_opts: u64,
|
2013-12-22 14:38:55 -06:00
|
|
|
/// Whether to write dependency files. It's (enabled, optional filename).
|
|
|
|
write_dependency_info: (bool, Option<Path>),
|
2013-12-19 09:18:37 -06:00
|
|
|
/// Crate id-related things to maybe print. It's (crate_id, crate_name, crate_file_name).
|
|
|
|
print_metas: (bool, bool, bool),
|
2014-02-06 21:57:09 -06:00
|
|
|
cg: CodegenOptions,
|
2013-02-19 01:40:42 -06:00
|
|
|
}
|
2011-06-15 13:19:50 -05:00
|
|
|
|
2013-04-09 03:16:06 -05:00
|
|
|
// The type of entry function, so
|
|
|
|
// users can have their own entry
|
|
|
|
// functions that don't start a
|
|
|
|
// scheduler
|
|
|
|
#[deriving(Eq)]
|
|
|
|
pub enum EntryFnType {
|
|
|
|
EntryMain,
|
2013-08-03 21:59:46 -05:00
|
|
|
EntryStart,
|
|
|
|
EntryNone,
|
2013-04-09 03:16:06 -05:00
|
|
|
}
|
|
|
|
|
2014-02-24 07:11:00 -06:00
|
|
|
#[deriving(Eq, Ord, Clone, TotalOrd, TotalEq)]
|
Redesign output flags for rustc
This commit removes the -c, --emit-llvm, -s, --rlib, --dylib, --staticlib,
--lib, and --bin flags from rustc, adding the following flags:
* --emit=[asm,ir,bc,obj,link]
* --crate-type=[dylib,rlib,staticlib,bin,lib]
The -o option has also been redefined to be used for *all* flavors of outputs.
This means that we no longer ignore it for libraries. The --out-dir remains the
same as before.
The new logic for files that rustc emits is as follows:
1. Output types are dictated by the --emit flag. The default value is
--emit=link, and this option can be passed multiple times and have all
options stacked on one another.
2. Crate types are dictated by the --crate-type flag and the #[crate_type]
attribute. The flags can be passed many times and stack with the crate
attribute.
3. If the -o flag is specified, and only one output type is specified, the
output will be emitted at this location. If more than one output type is
specified, then the filename of -o is ignored, and all output goes in the
directory that -o specifies. The -o option always ignores the --out-dir
option.
4. If the --out-dir flag is specified, all output goes in this directory.
5. If -o and --out-dir are both not present, all output goes in the current
directory of the process.
6. When multiple output types are specified, the filestem of all output is the
same as the name of the CrateId (derived from a crate attribute or from the
filestem of the crate file).
Closes #7791
Closes #11056
Closes #11667
2014-02-03 17:27:54 -06:00
|
|
|
pub enum CrateType {
|
|
|
|
CrateTypeExecutable,
|
|
|
|
CrateTypeDylib,
|
|
|
|
CrateTypeRlib,
|
|
|
|
CrateTypeStaticlib,
|
Add generation of static libraries to rustc
This commit implements the support necessary for generating both intermediate
and result static rust libraries. This is an implementation of my thoughts in
https://mail.mozilla.org/pipermail/rust-dev/2013-November/006686.html.
When compiling a library, we still retain the "lib" option, although now there
are "rlib", "staticlib", and "dylib" as options for crate_type (and these are
stackable). The idea of "lib" is to generate the "compiler default" instead of
having too choose (although all are interchangeable). For now I have left the
"complier default" to be a dynamic library for size reasons.
Of the rust libraries, lib{std,extra,rustuv} will bootstrap with an
rlib/dylib pair, but lib{rustc,syntax,rustdoc,rustpkg} will only be built as a
dynamic object. I chose this for size reasons, but also because you're probably
not going to be embedding the rustc compiler anywhere any time soon.
Other than the options outlined above, there are a few defaults/preferences that
are now opinionated in the compiler:
* If both a .dylib and .rlib are found for a rust library, the compiler will
prefer the .rlib variant. This is overridable via the -Z prefer-dynamic option
* If generating a "lib", the compiler will generate a dynamic library. This is
overridable by explicitly saying what flavor you'd like (rlib, staticlib,
dylib).
* If no options are passed to the command line, and no crate_type is found in
the destination crate, then an executable is generated
With this change, you can successfully build a rust program with 0 dynamic
dependencies on rust libraries. There is still a dynamic dependency on
librustrt, but I plan on removing that in a subsequent commit.
This change includes no tests just yet. Our current testing
infrastructure/harnesses aren't very amenable to doing flavorful things with
linking, so I'm planning on adding a new mode of testing which I believe belongs
as a separate commit.
Closes #552
2013-11-15 16:03:29 -06:00
|
|
|
}
|
|
|
|
|
2014-03-05 08:36:01 -06:00
|
|
|
pub struct Session {
|
2014-01-13 10:31:05 -06:00
|
|
|
targ_cfg: @Config,
|
|
|
|
opts: @Options,
|
2014-03-09 08:20:44 -05:00
|
|
|
cstore: metadata::cstore::CStore,
|
2014-03-09 09:54:34 -05:00
|
|
|
parse_sess: ParseSess,
|
2013-02-04 16:02:01 -06:00
|
|
|
codemap: @codemap::CodeMap,
|
|
|
|
// For a library crate, this is always none
|
2013-12-21 19:25:27 -06:00
|
|
|
entry_fn: RefCell<Option<(NodeId, codemap::Span)>>,
|
|
|
|
entry_type: Cell<Option<EntryFnType>>,
|
2013-12-27 15:48:00 -06:00
|
|
|
span_diagnostic: @diagnostic::SpanHandler,
|
2013-12-25 12:10:33 -06:00
|
|
|
macro_registrar_fn: RefCell<Option<ast::DefId>>,
|
2014-03-09 07:24:58 -05:00
|
|
|
default_sysroot: Option<Path>,
|
2013-12-22 16:40:03 -06:00
|
|
|
building_library: Cell<bool>,
|
2014-01-27 07:58:40 -06:00
|
|
|
// The name of the root source file of the crate, in the local file system. The path is always
|
|
|
|
// expected to be absolute. `None` means that there is no source file.
|
|
|
|
local_crate_source_file: Option<Path>,
|
2013-02-04 16:02:01 -06:00
|
|
|
working_dir: Path,
|
2013-12-20 22:04:17 -06:00
|
|
|
lints: RefCell<HashMap<ast::NodeId,
|
2014-03-04 12:02:49 -06:00
|
|
|
Vec<(lint::Lint, codemap::Span, ~str)> >>,
|
2013-12-22 16:36:50 -06:00
|
|
|
node_id: Cell<ast::NodeId>,
|
2014-03-04 12:02:49 -06:00
|
|
|
crate_types: @RefCell<Vec<CrateType> >,
|
2014-03-06 12:37:24 -06:00
|
|
|
features: front::feature_gate::Features,
|
|
|
|
|
|
|
|
/// The maximum recursion limit for potentially infinitely recursive
|
|
|
|
/// operations such as auto-dereference and monomorphization.
|
|
|
|
recursion_limit: Cell<uint>,
|
2012-07-11 17:00:40 -05:00
|
|
|
}
|
|
|
|
|
2014-03-05 08:36:01 -06:00
|
|
|
impl Session {
|
2013-09-06 21:11:55 -05:00
|
|
|
pub fn span_fatal(&self, sp: Span, msg: &str) -> ! {
|
2012-01-24 23:42:54 -06:00
|
|
|
self.span_diagnostic.span_fatal(sp, msg)
|
2010-09-01 15:24:14 -05:00
|
|
|
}
|
2013-09-06 21:11:55 -05:00
|
|
|
pub fn fatal(&self, msg: &str) -> ! {
|
2012-01-24 23:42:54 -06:00
|
|
|
self.span_diagnostic.handler().fatal(msg)
|
2010-09-01 15:24:14 -05:00
|
|
|
}
|
2013-09-06 21:11:55 -05:00
|
|
|
pub fn span_err(&self, sp: Span, msg: &str) {
|
2012-01-24 23:42:54 -06:00
|
|
|
self.span_diagnostic.span_err(sp, msg)
|
2011-06-19 00:55:53 -05:00
|
|
|
}
|
2013-09-06 21:11:55 -05:00
|
|
|
pub fn err(&self, msg: &str) {
|
2012-01-24 23:42:54 -06:00
|
|
|
self.span_diagnostic.handler().err(msg)
|
2012-01-13 19:08:47 -06:00
|
|
|
}
|
2013-09-06 21:11:55 -05:00
|
|
|
pub fn err_count(&self) -> uint {
|
2013-05-06 08:00:37 -05:00
|
|
|
self.span_diagnostic.handler().err_count()
|
|
|
|
}
|
2013-09-06 21:11:55 -05:00
|
|
|
pub fn has_errors(&self) -> bool {
|
2012-01-24 23:42:54 -06:00
|
|
|
self.span_diagnostic.handler().has_errors()
|
2011-06-19 00:55:53 -05:00
|
|
|
}
|
2013-09-06 21:11:55 -05:00
|
|
|
pub fn abort_if_errors(&self) {
|
2012-01-24 23:42:54 -06:00
|
|
|
self.span_diagnostic.handler().abort_if_errors()
|
2011-06-19 00:55:53 -05:00
|
|
|
}
|
2013-09-06 21:11:55 -05:00
|
|
|
pub fn span_warn(&self, sp: Span, msg: &str) {
|
2012-01-24 23:42:54 -06:00
|
|
|
self.span_diagnostic.span_warn(sp, msg)
|
2012-01-12 10:59:49 -06:00
|
|
|
}
|
2013-09-06 21:11:55 -05:00
|
|
|
pub fn warn(&self, msg: &str) {
|
2012-01-24 23:42:54 -06:00
|
|
|
self.span_diagnostic.handler().warn(msg)
|
2011-08-27 16:57:47 -05:00
|
|
|
}
|
2013-09-06 21:11:55 -05:00
|
|
|
pub fn span_note(&self, sp: Span, msg: &str) {
|
2012-01-24 23:42:54 -06:00
|
|
|
self.span_diagnostic.span_note(sp, msg)
|
2012-01-12 10:59:49 -06:00
|
|
|
}
|
2014-01-21 23:33:37 -06:00
|
|
|
pub fn span_end_note(&self, sp: Span, msg: &str) {
|
|
|
|
self.span_diagnostic.span_end_note(sp, msg)
|
|
|
|
}
|
2013-09-06 21:11:55 -05:00
|
|
|
pub fn note(&self, msg: &str) {
|
2012-01-24 23:42:54 -06:00
|
|
|
self.span_diagnostic.handler().note(msg)
|
2011-08-27 16:57:47 -05:00
|
|
|
}
|
2013-09-06 21:11:55 -05:00
|
|
|
pub fn span_bug(&self, sp: Span, msg: &str) -> ! {
|
2012-01-24 23:42:54 -06:00
|
|
|
self.span_diagnostic.span_bug(sp, msg)
|
2011-05-17 16:12:49 -05:00
|
|
|
}
|
2013-09-06 21:11:55 -05:00
|
|
|
pub fn bug(&self, msg: &str) -> ! {
|
2012-01-24 23:42:54 -06:00
|
|
|
self.span_diagnostic.handler().bug(msg)
|
2010-11-22 18:27:00 -06:00
|
|
|
}
|
2013-09-06 21:11:55 -05:00
|
|
|
pub fn span_unimpl(&self, sp: Span, msg: &str) -> ! {
|
2012-01-24 23:42:54 -06:00
|
|
|
self.span_diagnostic.span_unimpl(sp, msg)
|
2012-01-13 19:08:47 -06:00
|
|
|
}
|
2013-09-06 21:11:55 -05:00
|
|
|
pub fn unimpl(&self, msg: &str) -> ! {
|
2012-01-24 23:42:54 -06:00
|
|
|
self.span_diagnostic.handler().unimpl(msg)
|
2011-03-18 14:30:44 -05:00
|
|
|
}
|
2013-09-06 21:11:55 -05:00
|
|
|
pub fn add_lint(&self,
|
2014-01-09 20:29:45 -06:00
|
|
|
lint: lint::Lint,
|
2013-07-27 03:25:59 -05:00
|
|
|
id: ast::NodeId,
|
2013-08-31 11:13:04 -05:00
|
|
|
sp: Span,
|
2013-05-31 17:17:22 -05:00
|
|
|
msg: ~str) {
|
2013-12-20 22:04:17 -06:00
|
|
|
let mut lints = self.lints.borrow_mut();
|
|
|
|
match lints.get().find_mut(&id) {
|
2013-04-30 00:15:17 -05:00
|
|
|
Some(arr) => { arr.push((lint, sp, msg)); return; }
|
|
|
|
None => {}
|
|
|
|
}
|
2014-03-04 12:02:49 -06:00
|
|
|
lints.get().insert(id, vec!((lint, sp, msg)));
|
2012-06-04 18:07:54 -05:00
|
|
|
}
|
2013-09-06 21:11:55 -05:00
|
|
|
pub fn next_node_id(&self) -> ast::NodeId {
|
|
|
|
self.reserve_node_ids(1)
|
2011-12-19 02:42:58 -06:00
|
|
|
}
|
2013-11-26 23:02:25 -06:00
|
|
|
pub fn reserve_node_ids(&self, count: ast::NodeId) -> ast::NodeId {
|
2013-12-22 16:36:50 -06:00
|
|
|
let v = self.node_id.get();
|
2013-11-26 23:02:25 -06:00
|
|
|
|
|
|
|
match v.checked_add(&count) {
|
2013-12-22 16:36:50 -06:00
|
|
|
Some(next) => { self.node_id.set(next); }
|
2013-11-26 23:02:25 -06:00
|
|
|
None => self.bug("Input too large, ran out of node ids!")
|
2013-09-06 21:11:55 -05:00
|
|
|
}
|
2013-11-26 23:02:25 -06:00
|
|
|
|
|
|
|
v
|
2013-09-06 21:11:55 -05:00
|
|
|
}
|
2013-12-27 15:48:00 -06:00
|
|
|
pub fn diagnostic(&self) -> @diagnostic::SpanHandler {
|
2012-03-22 19:39:45 -05:00
|
|
|
self.span_diagnostic
|
|
|
|
}
|
2014-01-20 15:55:10 -06:00
|
|
|
pub fn debugging_opt(&self, opt: u64) -> bool {
|
|
|
|
(self.opts.debugging_opts & opt) != 0
|
2012-05-17 23:53:49 -05:00
|
|
|
}
|
2012-08-21 19:22:45 -05:00
|
|
|
// This exists to help with refactoring to eliminate impossible
|
|
|
|
// cases later on
|
2013-09-06 21:11:55 -05:00
|
|
|
pub fn impossible_case(&self, sp: Span, msg: &str) -> ! {
|
2014-02-06 03:38:08 -06:00
|
|
|
self.span_bug(sp, format!("impossible case reached: {}", msg));
|
2012-08-21 19:22:45 -05:00
|
|
|
}
|
2014-01-20 15:55:10 -06:00
|
|
|
pub fn verbose(&self) -> bool { self.debugging_opt(VERBOSE) }
|
|
|
|
pub fn time_passes(&self) -> bool { self.debugging_opt(TIME_PASSES) }
|
2013-09-06 21:11:55 -05:00
|
|
|
pub fn count_llvm_insns(&self) -> bool {
|
2014-01-20 15:55:10 -06:00
|
|
|
self.debugging_opt(COUNT_LLVM_INSNS)
|
2013-02-22 00:41:37 -06:00
|
|
|
}
|
2013-09-06 21:11:55 -05:00
|
|
|
pub fn count_type_sizes(&self) -> bool {
|
2014-01-20 15:55:10 -06:00
|
|
|
self.debugging_opt(COUNT_TYPE_SIZES)
|
2013-02-22 00:41:37 -06:00
|
|
|
}
|
2013-09-06 21:11:55 -05:00
|
|
|
pub fn time_llvm_passes(&self) -> bool {
|
2014-01-20 15:55:10 -06:00
|
|
|
self.debugging_opt(TIME_LLVM_PASSES)
|
2013-02-22 00:41:37 -06:00
|
|
|
}
|
2014-01-20 15:55:10 -06:00
|
|
|
pub fn trans_stats(&self) -> bool { self.debugging_opt(TRANS_STATS) }
|
|
|
|
pub fn meta_stats(&self) -> bool { self.debugging_opt(META_STATS) }
|
|
|
|
pub fn asm_comments(&self) -> bool { self.debugging_opt(ASM_COMMENTS) }
|
|
|
|
pub fn no_verify(&self) -> bool { self.debugging_opt(NO_VERIFY) }
|
|
|
|
pub fn borrowck_stats(&self) -> bool { self.debugging_opt(BORROWCK_STATS) }
|
2013-09-06 21:11:55 -05:00
|
|
|
pub fn print_llvm_passes(&self) -> bool {
|
2014-01-20 15:55:10 -06:00
|
|
|
self.debugging_opt(PRINT_LLVM_PASSES)
|
2013-08-22 22:58:42 -05:00
|
|
|
}
|
Implement LTO
This commit implements LTO for rust leveraging LLVM's passes. What this means
is:
* When compiling an rlib, in addition to insdering foo.o into the archive, also
insert foo.bc (the LLVM bytecode) of the optimized module.
* When the compiler detects the -Z lto option, it will attempt to perform LTO on
a staticlib or binary output. The compiler will emit an error if a dylib or
rlib output is being generated.
* The actual act of performing LTO is as follows:
1. Force all upstream libraries to have an rlib version available.
2. Load the bytecode of each upstream library from the rlib.
3. Link all this bytecode into the current LLVM module (just using llvm
apis)
4. Run an internalization pass which internalizes all symbols except those
found reachable for the local crate of compilation.
5. Run the LLVM LTO pass manager over this entire module
6a. If assembling an archive, then add all upstream rlibs into the output
archive. This ignores all of the object/bitcode/metadata files rust
generated and placed inside the rlibs.
6b. If linking a binary, create copies of all upstream rlibs, remove the
rust-generated object-file, and then link everything as usual.
As I have explained in #10741, this process is excruciatingly slow, so this is
*not* turned on by default, and it is also why I have decided to hide it behind
a -Z flag for now. The good news is that the binary sizes are about as small as
they can be as a result of LTO, so it's definitely working.
Closes #10741
Closes #10740
2013-12-03 01:19:29 -06:00
|
|
|
pub fn lto(&self) -> bool {
|
2014-01-20 15:55:10 -06:00
|
|
|
self.debugging_opt(LTO)
|
Implement LTO
This commit implements LTO for rust leveraging LLVM's passes. What this means
is:
* When compiling an rlib, in addition to insdering foo.o into the archive, also
insert foo.bc (the LLVM bytecode) of the optimized module.
* When the compiler detects the -Z lto option, it will attempt to perform LTO on
a staticlib or binary output. The compiler will emit an error if a dylib or
rlib output is being generated.
* The actual act of performing LTO is as follows:
1. Force all upstream libraries to have an rlib version available.
2. Load the bytecode of each upstream library from the rlib.
3. Link all this bytecode into the current LLVM module (just using llvm
apis)
4. Run an internalization pass which internalizes all symbols except those
found reachable for the local crate of compilation.
5. Run the LLVM LTO pass manager over this entire module
6a. If assembling an archive, then add all upstream rlibs into the output
archive. This ignores all of the object/bitcode/metadata files rust
generated and placed inside the rlibs.
6b. If linking a binary, create copies of all upstream rlibs, remove the
rust-generated object-file, and then link everything as usual.
As I have explained in #10741, this process is excruciatingly slow, so this is
*not* turned on by default, and it is also why I have decided to hide it behind
a -Z flag for now. The good news is that the binary sizes are about as small as
they can be as a result of LTO, so it's definitely working.
Closes #10741
Closes #10740
2013-12-03 01:19:29 -06:00
|
|
|
}
|
2013-12-11 01:27:15 -06:00
|
|
|
pub fn no_landing_pads(&self) -> bool {
|
2014-01-20 15:55:10 -06:00
|
|
|
self.debugging_opt(NO_LANDING_PADS)
|
2013-12-11 01:27:15 -06:00
|
|
|
}
|
2014-02-07 04:50:07 -06:00
|
|
|
pub fn show_span(&self) -> bool {
|
|
|
|
self.debugging_opt(SHOW_SPAN)
|
|
|
|
}
|
2014-03-09 07:24:58 -05:00
|
|
|
pub fn filesearch<'a>(&'a self) -> filesearch::FileSearch<'a> {
|
|
|
|
let sysroot = match self.opts.maybe_sysroot {
|
|
|
|
Some(ref sysroot) => sysroot,
|
|
|
|
None => self.default_sysroot.as_ref()
|
|
|
|
.expect("missing sysroot and default_sysroot in Session")
|
|
|
|
};
|
|
|
|
filesearch::FileSearch::new(
|
|
|
|
sysroot,
|
|
|
|
self.opts.target_triple,
|
|
|
|
&self.opts.addl_lib_search_paths)
|
|
|
|
}
|
2010-09-01 15:24:14 -05:00
|
|
|
}
|
2011-12-08 23:05:44 -06:00
|
|
|
|
2012-07-04 16:53:12 -05:00
|
|
|
/// Some reasonable defaults
|
2014-01-13 10:31:05 -06:00
|
|
|
pub fn basic_options() -> @Options {
|
|
|
|
@Options {
|
2014-03-04 12:02:49 -06:00
|
|
|
crate_types: Vec::new(),
|
2012-06-26 16:27:09 -05:00
|
|
|
gc: false,
|
2012-08-21 19:22:45 -05:00
|
|
|
optimize: No,
|
2014-03-05 02:51:47 -06:00
|
|
|
debuginfo: NoDebugInfo,
|
2014-03-04 12:02:49 -06:00
|
|
|
lint_opts: Vec::new(),
|
|
|
|
output_types: Vec::new(),
|
2014-03-09 07:24:58 -05:00
|
|
|
addl_lib_search_paths: RefCell::new(HashSet::new()),
|
2012-08-20 14:23:37 -05:00
|
|
|
maybe_sysroot: None,
|
2013-03-01 12:44:43 -06:00
|
|
|
target_triple: host_triple(),
|
2014-02-28 17:25:15 -06:00
|
|
|
cfg: Vec::new(),
|
2012-05-09 00:25:22 -05:00
|
|
|
test: false,
|
|
|
|
parse_only: false,
|
|
|
|
no_trans: false,
|
2013-12-26 16:39:36 -06:00
|
|
|
no_analysis: false,
|
2014-01-20 15:55:10 -06:00
|
|
|
debugging_opts: 0,
|
2013-12-22 14:38:55 -06:00
|
|
|
write_dependency_info: (false, None),
|
2013-12-19 09:18:37 -06:00
|
|
|
print_metas: (false, false, false),
|
2014-02-06 21:57:09 -06:00
|
|
|
cg: basic_codegen_options(),
|
2012-05-09 00:25:22 -05:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-02-06 21:57:09 -06:00
|
|
|
/// Declare a macro that will define all CodegenOptions fields and parsers all
|
|
|
|
/// at once. The goal of this macro is to define an interface that can be
|
|
|
|
/// programmatically used by the option parser in order to initialize the struct
|
|
|
|
/// without hardcoding field names all over the place.
|
|
|
|
///
|
|
|
|
/// The goal is to invoke this macro once with the correct fields, and then this
|
|
|
|
/// macro generates all necessary code. The main gotcha of this macro is the
|
|
|
|
/// cgsetters module which is a bunch of generated code to parse an option into
|
|
|
|
/// its respective field in the struct. There are a few hand-written parsers for
|
|
|
|
/// parsing specific types of values in this module.
|
|
|
|
macro_rules! cgoptions(
|
|
|
|
($($opt:ident : $t:ty = ($init:expr, $parse:ident, $desc:expr)),* ,) =>
|
|
|
|
(
|
|
|
|
#[deriving(Clone)]
|
|
|
|
pub struct CodegenOptions { $($opt: $t),* }
|
|
|
|
|
|
|
|
pub fn basic_codegen_options() -> CodegenOptions {
|
|
|
|
CodegenOptions { $($opt: $init),* }
|
|
|
|
}
|
|
|
|
|
|
|
|
pub type CodegenSetter = fn(&mut CodegenOptions, v: Option<&str>) -> bool;
|
|
|
|
pub static CG_OPTIONS: &'static [(&'static str, CodegenSetter,
|
|
|
|
&'static str)] =
|
|
|
|
&[ $( (stringify!($opt), cgsetters::$opt, $desc) ),* ];
|
|
|
|
|
|
|
|
mod cgsetters {
|
|
|
|
use super::CodegenOptions;
|
|
|
|
|
|
|
|
$(
|
|
|
|
pub fn $opt(cg: &mut CodegenOptions, v: Option<&str>) -> bool {
|
|
|
|
$parse(&mut cg.$opt, v)
|
|
|
|
}
|
|
|
|
)*
|
|
|
|
|
|
|
|
fn parse_bool(slot: &mut bool, v: Option<&str>) -> bool {
|
|
|
|
match v {
|
|
|
|
Some(..) => false,
|
|
|
|
None => { *slot = true; true }
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
fn parse_opt_string(slot: &mut Option<~str>, v: Option<&str>) -> bool {
|
|
|
|
match v {
|
|
|
|
Some(s) => { *slot = Some(s.to_owned()); true },
|
|
|
|
None => false,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
fn parse_string(slot: &mut ~str, v: Option<&str>) -> bool {
|
|
|
|
match v {
|
|
|
|
Some(s) => { *slot = s.to_owned(); true },
|
|
|
|
None => false,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-03-08 14:36:22 -06:00
|
|
|
fn parse_list(slot: &mut ::std::vec_ng::Vec<~str>, v: Option<&str>)
|
|
|
|
-> bool {
|
2014-02-06 21:57:09 -06:00
|
|
|
match v {
|
|
|
|
Some(s) => {
|
|
|
|
for s in s.words() {
|
|
|
|
slot.push(s.to_owned());
|
|
|
|
}
|
|
|
|
true
|
|
|
|
},
|
|
|
|
None => false,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
) )
|
|
|
|
|
|
|
|
cgoptions!(
|
|
|
|
ar: Option<~str> = (None, parse_opt_string,
|
|
|
|
"tool to assemble archives with"),
|
|
|
|
linker: Option<~str> = (None, parse_opt_string,
|
|
|
|
"system linker to link outputs with"),
|
2014-03-04 12:02:49 -06:00
|
|
|
link_args: Vec<~str> = (Vec::new(), parse_list,
|
2014-02-06 21:57:09 -06:00
|
|
|
"extra arguments to pass to the linker (space separated)"),
|
|
|
|
target_cpu: ~str = (~"generic", parse_string,
|
|
|
|
"select target processor (llc -mcpu=help for details)"),
|
|
|
|
target_feature: ~str = (~"", parse_string,
|
|
|
|
"target specific attributes (llc -mattr=help for details)"),
|
2014-03-04 12:02:49 -06:00
|
|
|
passes: Vec<~str> = (Vec::new(), parse_list,
|
2014-02-06 21:57:09 -06:00
|
|
|
"a list of extra LLVM passes to run (space separated)"),
|
2014-03-04 12:02:49 -06:00
|
|
|
llvm_args: Vec<~str> = (Vec::new(), parse_list,
|
2014-02-06 21:57:09 -06:00
|
|
|
"a list of arguments to pass to llvm (space separated)"),
|
|
|
|
save_temps: bool = (false, parse_bool,
|
|
|
|
"save all temporary output files during compilation"),
|
|
|
|
android_cross_path: Option<~str> = (None, parse_opt_string,
|
|
|
|
"the path to the Android NDK"),
|
|
|
|
no_rpath: bool = (false, parse_bool,
|
|
|
|
"disables setting the rpath in libs/exes"),
|
|
|
|
no_prepopulate_passes: bool = (false, parse_bool,
|
|
|
|
"don't pre-populate the pass manager with a list of passes"),
|
|
|
|
no_vectorize_loops: bool = (false, parse_bool,
|
|
|
|
"don't run the loop vectorization optimization passes"),
|
|
|
|
no_vectorize_slp: bool = (false, parse_bool,
|
|
|
|
"don't run LLVM's SLP vectorization pass"),
|
|
|
|
soft_float: bool = (false, parse_bool,
|
|
|
|
"generate software floating point library calls"),
|
|
|
|
gen_crate_map: bool = (false, parse_bool,
|
|
|
|
"force generation of a toplevel crate map"),
|
|
|
|
prefer_dynamic: bool = (false, parse_bool,
|
|
|
|
"prefer dynamic linking to static linking"),
|
|
|
|
no_integrated_as: bool = (false, parse_bool,
|
|
|
|
"use an external assembler rather than LLVM's integrated one"),
|
|
|
|
)
|
|
|
|
|
2012-03-19 12:19:00 -05:00
|
|
|
// Seems out of place, but it uses session, so I'm putting it here
|
2014-03-05 08:36:01 -06:00
|
|
|
pub fn expect<T:Clone>(sess: &Session, opt: Option<T>, msg: || -> ~str) -> T {
|
2012-05-22 16:55:39 -05:00
|
|
|
diagnostic::expect(sess.diagnostic(), opt, msg)
|
2012-03-19 12:19:00 -05:00
|
|
|
}
|
|
|
|
|
2014-02-05 15:15:24 -06:00
|
|
|
pub fn building_library(options: &Options, krate: &ast::Crate) -> bool {
|
2013-12-15 01:11:13 -06:00
|
|
|
if options.test { return false }
|
Redesign output flags for rustc
This commit removes the -c, --emit-llvm, -s, --rlib, --dylib, --staticlib,
--lib, and --bin flags from rustc, adding the following flags:
* --emit=[asm,ir,bc,obj,link]
* --crate-type=[dylib,rlib,staticlib,bin,lib]
The -o option has also been redefined to be used for *all* flavors of outputs.
This means that we no longer ignore it for libraries. The --out-dir remains the
same as before.
The new logic for files that rustc emits is as follows:
1. Output types are dictated by the --emit flag. The default value is
--emit=link, and this option can be passed multiple times and have all
options stacked on one another.
2. Crate types are dictated by the --crate-type flag and the #[crate_type]
attribute. The flags can be passed many times and stack with the crate
attribute.
3. If the -o flag is specified, and only one output type is specified, the
output will be emitted at this location. If more than one output type is
specified, then the filename of -o is ignored, and all output goes in the
directory that -o specifies. The -o option always ignores the --out-dir
option.
4. If the --out-dir flag is specified, all output goes in this directory.
5. If -o and --out-dir are both not present, all output goes in the current
directory of the process.
6. When multiple output types are specified, the filestem of all output is the
same as the name of the CrateId (derived from a crate attribute or from the
filestem of the crate file).
Closes #7791
Closes #11056
Closes #11667
2014-02-03 17:27:54 -06:00
|
|
|
for output in options.crate_types.iter() {
|
Add generation of static libraries to rustc
This commit implements the support necessary for generating both intermediate
and result static rust libraries. This is an implementation of my thoughts in
https://mail.mozilla.org/pipermail/rust-dev/2013-November/006686.html.
When compiling a library, we still retain the "lib" option, although now there
are "rlib", "staticlib", and "dylib" as options for crate_type (and these are
stackable). The idea of "lib" is to generate the "compiler default" instead of
having too choose (although all are interchangeable). For now I have left the
"complier default" to be a dynamic library for size reasons.
Of the rust libraries, lib{std,extra,rustuv} will bootstrap with an
rlib/dylib pair, but lib{rustc,syntax,rustdoc,rustpkg} will only be built as a
dynamic object. I chose this for size reasons, but also because you're probably
not going to be embedding the rustc compiler anywhere any time soon.
Other than the options outlined above, there are a few defaults/preferences that
are now opinionated in the compiler:
* If both a .dylib and .rlib are found for a rust library, the compiler will
prefer the .rlib variant. This is overridable via the -Z prefer-dynamic option
* If generating a "lib", the compiler will generate a dynamic library. This is
overridable by explicitly saying what flavor you'd like (rlib, staticlib,
dylib).
* If no options are passed to the command line, and no crate_type is found in
the destination crate, then an executable is generated
With this change, you can successfully build a rust program with 0 dynamic
dependencies on rust libraries. There is still a dynamic dependency on
librustrt, but I plan on removing that in a subsequent commit.
This change includes no tests just yet. Our current testing
infrastructure/harnesses aren't very amenable to doing flavorful things with
linking, so I'm planning on adding a new mode of testing which I believe belongs
as a separate commit.
Closes #552
2013-11-15 16:03:29 -06:00
|
|
|
match *output {
|
Redesign output flags for rustc
This commit removes the -c, --emit-llvm, -s, --rlib, --dylib, --staticlib,
--lib, and --bin flags from rustc, adding the following flags:
* --emit=[asm,ir,bc,obj,link]
* --crate-type=[dylib,rlib,staticlib,bin,lib]
The -o option has also been redefined to be used for *all* flavors of outputs.
This means that we no longer ignore it for libraries. The --out-dir remains the
same as before.
The new logic for files that rustc emits is as follows:
1. Output types are dictated by the --emit flag. The default value is
--emit=link, and this option can be passed multiple times and have all
options stacked on one another.
2. Crate types are dictated by the --crate-type flag and the #[crate_type]
attribute. The flags can be passed many times and stack with the crate
attribute.
3. If the -o flag is specified, and only one output type is specified, the
output will be emitted at this location. If more than one output type is
specified, then the filename of -o is ignored, and all output goes in the
directory that -o specifies. The -o option always ignores the --out-dir
option.
4. If the --out-dir flag is specified, all output goes in this directory.
5. If -o and --out-dir are both not present, all output goes in the current
directory of the process.
6. When multiple output types are specified, the filestem of all output is the
same as the name of the CrateId (derived from a crate attribute or from the
filestem of the crate file).
Closes #7791
Closes #11056
Closes #11667
2014-02-03 17:27:54 -06:00
|
|
|
CrateTypeExecutable => {}
|
|
|
|
CrateTypeStaticlib | CrateTypeDylib | CrateTypeRlib => return true
|
2011-12-08 23:05:44 -06:00
|
|
|
}
|
Add generation of static libraries to rustc
This commit implements the support necessary for generating both intermediate
and result static rust libraries. This is an implementation of my thoughts in
https://mail.mozilla.org/pipermail/rust-dev/2013-November/006686.html.
When compiling a library, we still retain the "lib" option, although now there
are "rlib", "staticlib", and "dylib" as options for crate_type (and these are
stackable). The idea of "lib" is to generate the "compiler default" instead of
having too choose (although all are interchangeable). For now I have left the
"complier default" to be a dynamic library for size reasons.
Of the rust libraries, lib{std,extra,rustuv} will bootstrap with an
rlib/dylib pair, but lib{rustc,syntax,rustdoc,rustpkg} will only be built as a
dynamic object. I chose this for size reasons, but also because you're probably
not going to be embedding the rustc compiler anywhere any time soon.
Other than the options outlined above, there are a few defaults/preferences that
are now opinionated in the compiler:
* If both a .dylib and .rlib are found for a rust library, the compiler will
prefer the .rlib variant. This is overridable via the -Z prefer-dynamic option
* If generating a "lib", the compiler will generate a dynamic library. This is
overridable by explicitly saying what flavor you'd like (rlib, staticlib,
dylib).
* If no options are passed to the command line, and no crate_type is found in
the destination crate, then an executable is generated
With this change, you can successfully build a rust program with 0 dynamic
dependencies on rust libraries. There is still a dynamic dependency on
librustrt, but I plan on removing that in a subsequent commit.
This change includes no tests just yet. Our current testing
infrastructure/harnesses aren't very amenable to doing flavorful things with
linking, so I'm planning on adding a new mode of testing which I believe belongs
as a separate commit.
Closes #552
2013-11-15 16:03:29 -06:00
|
|
|
}
|
2014-02-28 17:25:15 -06:00
|
|
|
match syntax::attr::first_attr_value_str_by_name(krate.attrs.as_slice(),
|
|
|
|
"crate_type") {
|
2014-01-10 16:02:36 -06:00
|
|
|
Some(s) => {
|
|
|
|
s.equiv(&("lib")) ||
|
|
|
|
s.equiv(&("rlib")) ||
|
|
|
|
s.equiv(&("dylib")) ||
|
|
|
|
s.equiv(&("staticlib"))
|
|
|
|
}
|
Add generation of static libraries to rustc
This commit implements the support necessary for generating both intermediate
and result static rust libraries. This is an implementation of my thoughts in
https://mail.mozilla.org/pipermail/rust-dev/2013-November/006686.html.
When compiling a library, we still retain the "lib" option, although now there
are "rlib", "staticlib", and "dylib" as options for crate_type (and these are
stackable). The idea of "lib" is to generate the "compiler default" instead of
having too choose (although all are interchangeable). For now I have left the
"complier default" to be a dynamic library for size reasons.
Of the rust libraries, lib{std,extra,rustuv} will bootstrap with an
rlib/dylib pair, but lib{rustc,syntax,rustdoc,rustpkg} will only be built as a
dynamic object. I chose this for size reasons, but also because you're probably
not going to be embedding the rustc compiler anywhere any time soon.
Other than the options outlined above, there are a few defaults/preferences that
are now opinionated in the compiler:
* If both a .dylib and .rlib are found for a rust library, the compiler will
prefer the .rlib variant. This is overridable via the -Z prefer-dynamic option
* If generating a "lib", the compiler will generate a dynamic library. This is
overridable by explicitly saying what flavor you'd like (rlib, staticlib,
dylib).
* If no options are passed to the command line, and no crate_type is found in
the destination crate, then an executable is generated
With this change, you can successfully build a rust program with 0 dynamic
dependencies on rust libraries. There is still a dynamic dependency on
librustrt, but I plan on removing that in a subsequent commit.
This change includes no tests just yet. Our current testing
infrastructure/harnesses aren't very amenable to doing flavorful things with
linking, so I'm planning on adding a new mode of testing which I believe belongs
as a separate commit.
Closes #552
2013-11-15 16:03:29 -06:00
|
|
|
_ => false
|
2011-12-08 23:05:44 -06:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
Redesign output flags for rustc
This commit removes the -c, --emit-llvm, -s, --rlib, --dylib, --staticlib,
--lib, and --bin flags from rustc, adding the following flags:
* --emit=[asm,ir,bc,obj,link]
* --crate-type=[dylib,rlib,staticlib,bin,lib]
The -o option has also been redefined to be used for *all* flavors of outputs.
This means that we no longer ignore it for libraries. The --out-dir remains the
same as before.
The new logic for files that rustc emits is as follows:
1. Output types are dictated by the --emit flag. The default value is
--emit=link, and this option can be passed multiple times and have all
options stacked on one another.
2. Crate types are dictated by the --crate-type flag and the #[crate_type]
attribute. The flags can be passed many times and stack with the crate
attribute.
3. If the -o flag is specified, and only one output type is specified, the
output will be emitted at this location. If more than one output type is
specified, then the filename of -o is ignored, and all output goes in the
directory that -o specifies. The -o option always ignores the --out-dir
option.
4. If the --out-dir flag is specified, all output goes in this directory.
5. If -o and --out-dir are both not present, all output goes in the current
directory of the process.
6. When multiple output types are specified, the filestem of all output is the
same as the name of the CrateId (derived from a crate attribute or from the
filestem of the crate file).
Closes #7791
Closes #11056
Closes #11667
2014-02-03 17:27:54 -06:00
|
|
|
pub fn default_lib_output() -> CrateType {
|
|
|
|
CrateTypeRlib
|
2014-01-21 13:49:04 -06:00
|
|
|
}
|
|
|
|
|
Redesign output flags for rustc
This commit removes the -c, --emit-llvm, -s, --rlib, --dylib, --staticlib,
--lib, and --bin flags from rustc, adding the following flags:
* --emit=[asm,ir,bc,obj,link]
* --crate-type=[dylib,rlib,staticlib,bin,lib]
The -o option has also been redefined to be used for *all* flavors of outputs.
This means that we no longer ignore it for libraries. The --out-dir remains the
same as before.
The new logic for files that rustc emits is as follows:
1. Output types are dictated by the --emit flag. The default value is
--emit=link, and this option can be passed multiple times and have all
options stacked on one another.
2. Crate types are dictated by the --crate-type flag and the #[crate_type]
attribute. The flags can be passed many times and stack with the crate
attribute.
3. If the -o flag is specified, and only one output type is specified, the
output will be emitted at this location. If more than one output type is
specified, then the filename of -o is ignored, and all output goes in the
directory that -o specifies. The -o option always ignores the --out-dir
option.
4. If the --out-dir flag is specified, all output goes in this directory.
5. If -o and --out-dir are both not present, all output goes in the current
directory of the process.
6. When multiple output types are specified, the filestem of all output is the
same as the name of the CrateId (derived from a crate attribute or from the
filestem of the crate file).
Closes #7791
Closes #11056
Closes #11667
2014-02-03 17:27:54 -06:00
|
|
|
pub fn collect_crate_types(session: &Session,
|
2014-03-04 12:02:49 -06:00
|
|
|
attrs: &[ast::Attribute]) -> Vec<CrateType> {
|
2013-12-15 01:11:13 -06:00
|
|
|
// If we're generating a test executable, then ignore all other output
|
|
|
|
// styles at all other locations
|
2014-01-01 15:26:07 -06:00
|
|
|
if session.opts.test {
|
2014-03-08 14:36:22 -06:00
|
|
|
return vec!(CrateTypeExecutable)
|
2013-12-15 01:11:13 -06:00
|
|
|
}
|
Redesign output flags for rustc
This commit removes the -c, --emit-llvm, -s, --rlib, --dylib, --staticlib,
--lib, and --bin flags from rustc, adding the following flags:
* --emit=[asm,ir,bc,obj,link]
* --crate-type=[dylib,rlib,staticlib,bin,lib]
The -o option has also been redefined to be used for *all* flavors of outputs.
This means that we no longer ignore it for libraries. The --out-dir remains the
same as before.
The new logic for files that rustc emits is as follows:
1. Output types are dictated by the --emit flag. The default value is
--emit=link, and this option can be passed multiple times and have all
options stacked on one another.
2. Crate types are dictated by the --crate-type flag and the #[crate_type]
attribute. The flags can be passed many times and stack with the crate
attribute.
3. If the -o flag is specified, and only one output type is specified, the
output will be emitted at this location. If more than one output type is
specified, then the filename of -o is ignored, and all output goes in the
directory that -o specifies. The -o option always ignores the --out-dir
option.
4. If the --out-dir flag is specified, all output goes in this directory.
5. If -o and --out-dir are both not present, all output goes in the current
directory of the process.
6. When multiple output types are specified, the filestem of all output is the
same as the name of the CrateId (derived from a crate attribute or from the
filestem of the crate file).
Closes #7791
Closes #11056
Closes #11667
2014-02-03 17:27:54 -06:00
|
|
|
let mut base = session.opts.crate_types.clone();
|
2013-12-19 14:23:39 -06:00
|
|
|
let mut iter = attrs.iter().filter_map(|a| {
|
2014-01-08 12:35:15 -06:00
|
|
|
if a.name().equiv(&("crate_type")) {
|
Implement LTO
This commit implements LTO for rust leveraging LLVM's passes. What this means
is:
* When compiling an rlib, in addition to insdering foo.o into the archive, also
insert foo.bc (the LLVM bytecode) of the optimized module.
* When the compiler detects the -Z lto option, it will attempt to perform LTO on
a staticlib or binary output. The compiler will emit an error if a dylib or
rlib output is being generated.
* The actual act of performing LTO is as follows:
1. Force all upstream libraries to have an rlib version available.
2. Load the bytecode of each upstream library from the rlib.
3. Link all this bytecode into the current LLVM module (just using llvm
apis)
4. Run an internalization pass which internalizes all symbols except those
found reachable for the local crate of compilation.
5. Run the LLVM LTO pass manager over this entire module
6a. If assembling an archive, then add all upstream rlibs into the output
archive. This ignores all of the object/bitcode/metadata files rust
generated and placed inside the rlibs.
6b. If linking a binary, create copies of all upstream rlibs, remove the
rust-generated object-file, and then link everything as usual.
As I have explained in #10741, this process is excruciatingly slow, so this is
*not* turned on by default, and it is also why I have decided to hide it behind
a -Z flag for now. The good news is that the binary sizes are about as small as
they can be as a result of LTO, so it's definitely working.
Closes #10741
Closes #10740
2013-12-03 01:19:29 -06:00
|
|
|
match a.value_str() {
|
Redesign output flags for rustc
This commit removes the -c, --emit-llvm, -s, --rlib, --dylib, --staticlib,
--lib, and --bin flags from rustc, adding the following flags:
* --emit=[asm,ir,bc,obj,link]
* --crate-type=[dylib,rlib,staticlib,bin,lib]
The -o option has also been redefined to be used for *all* flavors of outputs.
This means that we no longer ignore it for libraries. The --out-dir remains the
same as before.
The new logic for files that rustc emits is as follows:
1. Output types are dictated by the --emit flag. The default value is
--emit=link, and this option can be passed multiple times and have all
options stacked on one another.
2. Crate types are dictated by the --crate-type flag and the #[crate_type]
attribute. The flags can be passed many times and stack with the crate
attribute.
3. If the -o flag is specified, and only one output type is specified, the
output will be emitted at this location. If more than one output type is
specified, then the filename of -o is ignored, and all output goes in the
directory that -o specifies. The -o option always ignores the --out-dir
option.
4. If the --out-dir flag is specified, all output goes in this directory.
5. If -o and --out-dir are both not present, all output goes in the current
directory of the process.
6. When multiple output types are specified, the filestem of all output is the
same as the name of the CrateId (derived from a crate attribute or from the
filestem of the crate file).
Closes #7791
Closes #11056
Closes #11667
2014-02-03 17:27:54 -06:00
|
|
|
Some(ref n) if n.equiv(&("rlib")) => Some(CrateTypeRlib),
|
|
|
|
Some(ref n) if n.equiv(&("dylib")) => Some(CrateTypeDylib),
|
2014-01-10 16:02:36 -06:00
|
|
|
Some(ref n) if n.equiv(&("lib")) => {
|
|
|
|
Some(default_lib_output())
|
|
|
|
}
|
|
|
|
Some(ref n) if n.equiv(&("staticlib")) => {
|
Redesign output flags for rustc
This commit removes the -c, --emit-llvm, -s, --rlib, --dylib, --staticlib,
--lib, and --bin flags from rustc, adding the following flags:
* --emit=[asm,ir,bc,obj,link]
* --crate-type=[dylib,rlib,staticlib,bin,lib]
The -o option has also been redefined to be used for *all* flavors of outputs.
This means that we no longer ignore it for libraries. The --out-dir remains the
same as before.
The new logic for files that rustc emits is as follows:
1. Output types are dictated by the --emit flag. The default value is
--emit=link, and this option can be passed multiple times and have all
options stacked on one another.
2. Crate types are dictated by the --crate-type flag and the #[crate_type]
attribute. The flags can be passed many times and stack with the crate
attribute.
3. If the -o flag is specified, and only one output type is specified, the
output will be emitted at this location. If more than one output type is
specified, then the filename of -o is ignored, and all output goes in the
directory that -o specifies. The -o option always ignores the --out-dir
option.
4. If the --out-dir flag is specified, all output goes in this directory.
5. If -o and --out-dir are both not present, all output goes in the current
directory of the process.
6. When multiple output types are specified, the filestem of all output is the
same as the name of the CrateId (derived from a crate attribute or from the
filestem of the crate file).
Closes #7791
Closes #11056
Closes #11667
2014-02-03 17:27:54 -06:00
|
|
|
Some(CrateTypeStaticlib)
|
2014-01-10 16:02:36 -06:00
|
|
|
}
|
Redesign output flags for rustc
This commit removes the -c, --emit-llvm, -s, --rlib, --dylib, --staticlib,
--lib, and --bin flags from rustc, adding the following flags:
* --emit=[asm,ir,bc,obj,link]
* --crate-type=[dylib,rlib,staticlib,bin,lib]
The -o option has also been redefined to be used for *all* flavors of outputs.
This means that we no longer ignore it for libraries. The --out-dir remains the
same as before.
The new logic for files that rustc emits is as follows:
1. Output types are dictated by the --emit flag. The default value is
--emit=link, and this option can be passed multiple times and have all
options stacked on one another.
2. Crate types are dictated by the --crate-type flag and the #[crate_type]
attribute. The flags can be passed many times and stack with the crate
attribute.
3. If the -o flag is specified, and only one output type is specified, the
output will be emitted at this location. If more than one output type is
specified, then the filename of -o is ignored, and all output goes in the
directory that -o specifies. The -o option always ignores the --out-dir
option.
4. If the --out-dir flag is specified, all output goes in this directory.
5. If -o and --out-dir are both not present, all output goes in the current
directory of the process.
6. When multiple output types are specified, the filestem of all output is the
same as the name of the CrateId (derived from a crate attribute or from the
filestem of the crate file).
Closes #7791
Closes #11056
Closes #11667
2014-02-03 17:27:54 -06:00
|
|
|
Some(ref n) if n.equiv(&("bin")) => Some(CrateTypeExecutable),
|
2014-01-01 15:26:07 -06:00
|
|
|
Some(_) => {
|
2014-01-10 16:02:36 -06:00
|
|
|
session.add_lint(lint::UnknownCrateType,
|
|
|
|
ast::CRATE_NODE_ID,
|
|
|
|
a.span,
|
|
|
|
~"invalid `crate_type` value");
|
2014-01-01 15:26:07 -06:00
|
|
|
None
|
|
|
|
}
|
|
|
|
_ => {
|
2014-01-09 20:29:45 -06:00
|
|
|
session.add_lint(lint::UnknownCrateType, ast::CRATE_NODE_ID,
|
2014-01-01 15:26:07 -06:00
|
|
|
a.span, ~"`crate_type` requires a value");
|
|
|
|
None
|
|
|
|
}
|
Implement LTO
This commit implements LTO for rust leveraging LLVM's passes. What this means
is:
* When compiling an rlib, in addition to insdering foo.o into the archive, also
insert foo.bc (the LLVM bytecode) of the optimized module.
* When the compiler detects the -Z lto option, it will attempt to perform LTO on
a staticlib or binary output. The compiler will emit an error if a dylib or
rlib output is being generated.
* The actual act of performing LTO is as follows:
1. Force all upstream libraries to have an rlib version available.
2. Load the bytecode of each upstream library from the rlib.
3. Link all this bytecode into the current LLVM module (just using llvm
apis)
4. Run an internalization pass which internalizes all symbols except those
found reachable for the local crate of compilation.
5. Run the LLVM LTO pass manager over this entire module
6a. If assembling an archive, then add all upstream rlibs into the output
archive. This ignores all of the object/bitcode/metadata files rust
generated and placed inside the rlibs.
6b. If linking a binary, create copies of all upstream rlibs, remove the
rust-generated object-file, and then link everything as usual.
As I have explained in #10741, this process is excruciatingly slow, so this is
*not* turned on by default, and it is also why I have decided to hide it behind
a -Z flag for now. The good news is that the binary sizes are about as small as
they can be as a result of LTO, so it's definitely working.
Closes #10741
Closes #10740
2013-12-03 01:19:29 -06:00
|
|
|
}
|
|
|
|
} else {
|
|
|
|
None
|
|
|
|
}
|
|
|
|
});
|
|
|
|
base.extend(&mut iter);
|
|
|
|
if base.len() == 0 {
|
Redesign output flags for rustc
This commit removes the -c, --emit-llvm, -s, --rlib, --dylib, --staticlib,
--lib, and --bin flags from rustc, adding the following flags:
* --emit=[asm,ir,bc,obj,link]
* --crate-type=[dylib,rlib,staticlib,bin,lib]
The -o option has also been redefined to be used for *all* flavors of outputs.
This means that we no longer ignore it for libraries. The --out-dir remains the
same as before.
The new logic for files that rustc emits is as follows:
1. Output types are dictated by the --emit flag. The default value is
--emit=link, and this option can be passed multiple times and have all
options stacked on one another.
2. Crate types are dictated by the --crate-type flag and the #[crate_type]
attribute. The flags can be passed many times and stack with the crate
attribute.
3. If the -o flag is specified, and only one output type is specified, the
output will be emitted at this location. If more than one output type is
specified, then the filename of -o is ignored, and all output goes in the
directory that -o specifies. The -o option always ignores the --out-dir
option.
4. If the --out-dir flag is specified, all output goes in this directory.
5. If -o and --out-dir are both not present, all output goes in the current
directory of the process.
6. When multiple output types are specified, the filestem of all output is the
same as the name of the CrateId (derived from a crate attribute or from the
filestem of the crate file).
Closes #7791
Closes #11056
Closes #11667
2014-02-03 17:27:54 -06:00
|
|
|
base.push(CrateTypeExecutable);
|
Implement LTO
This commit implements LTO for rust leveraging LLVM's passes. What this means
is:
* When compiling an rlib, in addition to insdering foo.o into the archive, also
insert foo.bc (the LLVM bytecode) of the optimized module.
* When the compiler detects the -Z lto option, it will attempt to perform LTO on
a staticlib or binary output. The compiler will emit an error if a dylib or
rlib output is being generated.
* The actual act of performing LTO is as follows:
1. Force all upstream libraries to have an rlib version available.
2. Load the bytecode of each upstream library from the rlib.
3. Link all this bytecode into the current LLVM module (just using llvm
apis)
4. Run an internalization pass which internalizes all symbols except those
found reachable for the local crate of compilation.
5. Run the LLVM LTO pass manager over this entire module
6a. If assembling an archive, then add all upstream rlibs into the output
archive. This ignores all of the object/bitcode/metadata files rust
generated and placed inside the rlibs.
6b. If linking a binary, create copies of all upstream rlibs, remove the
rust-generated object-file, and then link everything as usual.
As I have explained in #10741, this process is excruciatingly slow, so this is
*not* turned on by default, and it is also why I have decided to hide it behind
a -Z flag for now. The good news is that the binary sizes are about as small as
they can be as a result of LTO, so it's definitely working.
Closes #10741
Closes #10740
2013-12-03 01:19:29 -06:00
|
|
|
}
|
2014-03-08 14:36:22 -06:00
|
|
|
base.as_mut_slice().sort();
|
2014-01-06 11:23:24 -06:00
|
|
|
base.dedup();
|
Implement LTO
This commit implements LTO for rust leveraging LLVM's passes. What this means
is:
* When compiling an rlib, in addition to insdering foo.o into the archive, also
insert foo.bc (the LLVM bytecode) of the optimized module.
* When the compiler detects the -Z lto option, it will attempt to perform LTO on
a staticlib or binary output. The compiler will emit an error if a dylib or
rlib output is being generated.
* The actual act of performing LTO is as follows:
1. Force all upstream libraries to have an rlib version available.
2. Load the bytecode of each upstream library from the rlib.
3. Link all this bytecode into the current LLVM module (just using llvm
apis)
4. Run an internalization pass which internalizes all symbols except those
found reachable for the local crate of compilation.
5. Run the LLVM LTO pass manager over this entire module
6a. If assembling an archive, then add all upstream rlibs into the output
archive. This ignores all of the object/bitcode/metadata files rust
generated and placed inside the rlibs.
6b. If linking a binary, create copies of all upstream rlibs, remove the
rust-generated object-file, and then link everything as usual.
As I have explained in #10741, this process is excruciatingly slow, so this is
*not* turned on by default, and it is also why I have decided to hide it behind
a -Z flag for now. The good news is that the binary sizes are about as small as
they can be as a result of LTO, so it's definitely working.
Closes #10741
Closes #10740
2013-12-03 01:19:29 -06:00
|
|
|
return base;
|
|
|
|
}
|
|
|
|
|
2013-11-08 13:06:57 -06:00
|
|
|
pub fn sess_os_to_meta_os(os: abi::Os) -> metadata::loader::Os {
|
2012-09-07 20:08:21 -05:00
|
|
|
use metadata::loader;
|
2012-05-22 19:16:26 -05:00
|
|
|
|
2012-08-06 14:34:08 -05:00
|
|
|
match os {
|
2013-11-08 13:06:57 -06:00
|
|
|
abi::OsWin32 => loader::OsWin32,
|
|
|
|
abi::OsLinux => loader::OsLinux,
|
|
|
|
abi::OsAndroid => loader::OsAndroid,
|
|
|
|
abi::OsMacos => loader::OsMacos,
|
|
|
|
abi::OsFreebsd => loader::OsFreebsd
|
2012-05-22 19:16:26 -05:00
|
|
|
}
|
|
|
|
}
|