Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Build instruction profiler runtime as part of compiler-rt #42433

Merged
merged 17 commits into from Jun 14, 2017
Merged
Show file tree
Hide file tree
Changes from 9 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
1 change: 1 addition & 0 deletions configure
Expand Up @@ -452,6 +452,7 @@ opt vendor 0 "enable usage of vendored Rust crates"
opt sanitizers 0 "build the sanitizer runtimes (asan, lsan, msan, tsan)"
opt dist-src 1 "when building tarballs enables building a source tarball"
opt cargo-openssl-static 0 "static openssl in cargo"
opt profiler 0 "build the profiler runtime"

# Optimization and debugging options. These may be overridden by the release channel, etc.
opt_nosave optimize 1 "build optimized rust code"
Expand Down
9 changes: 9 additions & 0 deletions src/Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 4 additions & 0 deletions src/bootstrap/check.rs
Expand Up @@ -298,6 +298,10 @@ pub fn compiletest(build: &Build,
cmd.env("SANITIZER_SUPPORT", "1");
}

if build.config.profiler {
cmd.env("PROFILER_SUPPORT", "1");
}

cmd.arg("--adb-path").arg("adb");
cmd.arg("--adb-test-dir").arg(ADB_TEST_DIR);
if target.contains("android") {
Expand Down
4 changes: 4 additions & 0 deletions src/bootstrap/config.rs
Expand Up @@ -50,6 +50,7 @@ pub struct Config {
pub full_bootstrap: bool,
pub extended: bool,
pub sanitizers: bool,
pub profiler: bool,

// llvm codegen options
pub llvm_assertions: bool,
Expand Down Expand Up @@ -162,6 +163,7 @@ struct Build {
extended: Option<bool>,
verbose: Option<usize>,
sanitizers: Option<bool>,
profiler: Option<bool>,
openssl_static: Option<bool>,
}

Expand Down Expand Up @@ -318,6 +320,7 @@ impl Config {
set(&mut config.extended, build.extended);
set(&mut config.verbose, build.verbose);
set(&mut config.sanitizers, build.sanitizers);
set(&mut config.profiler, build.profiler);
set(&mut config.openssl_static, build.openssl_static);

if let Some(ref install) = toml.install {
Expand Down Expand Up @@ -471,6 +474,7 @@ impl Config {
("FULL_BOOTSTRAP", self.full_bootstrap),
("EXTENDED", self.extended),
("SANITIZERS", self.sanitizers),
("PROFILER", self.profiler),
("DIST_SRC", self.rust_dist_src),
("CARGO_OPENSSL_STATIC", self.openssl_static),
}
Expand Down
3 changes: 3 additions & 0 deletions src/bootstrap/config.toml.example
Expand Up @@ -147,6 +147,9 @@
# Build the sanitizer runtimes
#sanitizers = false

# Build the profiler runtime
#profiler = false

# Indicates whether the OpenSSL linked into Cargo will be statically linked or
# not. If static linkage is specified then the build system will download a
# known-good version of OpenSSL, compile it, and link it to Cargo.
Expand Down
3 changes: 3 additions & 0 deletions src/bootstrap/lib.rs
Expand Up @@ -594,6 +594,9 @@ impl Build {
if self.config.backtrace {
features.push_str(" backtrace");
}
if self.config.profiler {
features.push_str(" profiler");
}
return features
}

Expand Down
1 change: 1 addition & 0 deletions src/ci/run.sh
Expand Up @@ -32,6 +32,7 @@ RUST_CONFIGURE_ARGS="$RUST_CONFIGURE_ARGS --disable-manage-submodules"
RUST_CONFIGURE_ARGS="$RUST_CONFIGURE_ARGS --enable-locked-deps"
RUST_CONFIGURE_ARGS="$RUST_CONFIGURE_ARGS --enable-cargo-openssl-static"
RUST_CONFIGURE_ARGS="$RUST_CONFIGURE_ARGS --enable-llvm-clean-rebuild"
RUST_CONFIGURE_ARGS="$RUST_CONFIGURE_ARGS --enable-profiler"

if [ "$DIST_SRC" = "" ]; then
RUST_CONFIGURE_ARGS="$RUST_CONFIGURE_ARGS --disable-dist-src"
Expand Down
3 changes: 3 additions & 0 deletions src/doc/unstable-book/src/SUMMARY.md
Expand Up @@ -2,6 +2,7 @@

- [Compiler flags](compiler-flags.md)
- [linker_flavor](compiler-flags/linker-flavor.md)
- [profile](compiler-flags/profile.md)
- [remap_path_prefix](compiler-flags/remap-path-prefix.md)
- [Language features](language-features.md)
- [abi_msp430_interrupt](language-features/abi-msp430-interrupt.md)
Expand Down Expand Up @@ -70,6 +71,7 @@
- [plugin_registrar](language-features/plugin-registrar.md)
- [prelude_import](language-features/prelude-import.md)
- [proc_macro](language-features/proc-macro.md)
- [profiler_runtime](language-features/profiler-runtime.md)
- [quote](language-features/quote.md)
- [repr_align](language-features/repr-align.md)
- [repr_simd](language-features/repr-simd.md)
Expand Down Expand Up @@ -177,6 +179,7 @@
- [placement_new_protocol](library-features/placement-new-protocol.md)
- [print_internals](library-features/print-internals.md)
- [proc_macro_internals](library-features/proc-macro-internals.md)
- [profiler_runtime_lib](library-features/sanitizer-runtime-lib.md)
- [question_mark_carrier](library-features/question-mark-carrier.md)
- [rand](library-features/rand.md)
- [range_contains](library-features/range-contains.md)
Expand Down
21 changes: 21 additions & 0 deletions src/doc/unstable-book/src/compiler-flags/profile.md
@@ -0,0 +1,21 @@
# `profile`

The tracking issue for this feature is: None
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ah actually can you fill this in with #42524?


------------------------

This feature allows the generation of code coverage reports.

Set the compiler flags `-Ccodegen-units=1 -Clink-dead-code -Cpasses=insert-gcov-profiling -Zno-landing-pads` to enable gcov profiling.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Shouldn't -Z profile be mentioned here? If all these other flags are required, could -Z profile imply them?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Right, I think they aren't strictly required. I've replaced them with -Zprofile.


For example:
```Bash
cargo new testgcov --bin
cd testgcov
export RUSTFLAGS="-Ccodegen-units=1 -Clink-dead-code -Cpasses=insert-gcov-profiling -Zno-landing-pads"
cargo build
cargo run
```

Once you've built and run your program, files with the `gcno` (after build) and `gcda` (after execution) extensions will be created.
You can parse them with [llvm-cov gcov](http://llvm.org/docs/CommandGuide/llvm-cov.html#llvm-cov-gcov) or [grcov](https://github.com/marco-c/grcov).
@@ -0,0 +1,5 @@
# `profiler_runtime`

The tracking issue for this feature is: None.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

(this'd also get linked to #42524)


------------------------
@@ -0,0 +1,5 @@
# `profiler_runtime_lib`

This feature is internal to the Rust compiler and is not intended for general use.

------------------------
18 changes: 18 additions & 0 deletions src/libprofiler_builtins/Cargo.toml
@@ -0,0 +1,18 @@
[package]
authors = ["The Rust Project Developers"]
build = "build.rs"
name = "profiler_builtins"
version = "0.0.0"

[lib]
name = "profiler_builtins"
path = "lib.rs"
test = false
bench = false
doc = false

[dependencies]
core = { path = "../libcore" }

[build-dependencies]
gcc = "0.3.27"
56 changes: 56 additions & 0 deletions src/libprofiler_builtins/build.rs
@@ -0,0 +1,56 @@
// Copyright 2017 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.

//! Compiles the profiler part of the `compiler-rt` library.
//!
//! See the build.rs for libcompiler_builtins crate for details.

extern crate gcc;

use std::env;
use std::path::Path;

fn main() {
let target = env::var("TARGET").expect("TARGET was not set");
let cfg = &mut gcc::Config::new();

if target.contains("msvc") {
// Don't pull in extra libraries on MSVC
cfg.flag("/Zl");
} else {
// Turn off various features of gcc and such, mostly copying
// compiler-rt's build system already
cfg.flag("-fno-builtin");
cfg.flag("-fvisibility=hidden");
cfg.flag("-fomit-frame-pointer");
cfg.flag("-ffreestanding");
cfg.define("VISIBILITY_HIDDEN", None);
}

let profile_sources = &["GCDAProfiling.c",
"InstrProfiling.c",
"InstrProfilingBuffer.c",
"InstrProfilingFile.c",
"InstrProfilingMerge.c",
"InstrProfilingMergeFile.c",
"InstrProfilingPlatformDarwin.c",
"InstrProfilingPlatformLinux.c",
"InstrProfilingPlatformOther.c",
"InstrProfilingRuntime.cc",
"InstrProfilingUtil.c",
"InstrProfilingValue.c",
"InstrProfilingWriter.c"];

for src in profile_sources {
cfg.file(Path::new("../compiler-rt/lib/profile").join(src));
}

cfg.compile("libprofiler-rt.a");
}
20 changes: 20 additions & 0 deletions src/libprofiler_builtins/lib.rs
@@ -0,0 +1,20 @@
// Copyright 2017 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.

#![no_std]
#![cfg_attr(not(stage0), feature(profiler_runtime))]
#![cfg_attr(not(stage0), profiler_runtime)]
#![unstable(feature = "profiler_runtime_lib",
reason = "internal implementation detail of rustc right now",
issue = "0")]
#![crate_name = "profiler_builtins"]
#![crate_type = "rlib"]
#![allow(unused_features)]
#![feature(staged_api)]
2 changes: 2 additions & 0 deletions src/librustc/middle/cstore.rs
Expand Up @@ -260,6 +260,7 @@ pub trait CrateStore {
fn is_panic_runtime(&self, cnum: CrateNum) -> bool;
fn is_compiler_builtins(&self, cnum: CrateNum) -> bool;
fn is_sanitizer_runtime(&self, cnum: CrateNum) -> bool;
fn is_profiler_runtime(&self, cnum: CrateNum) -> bool;
fn panic_strategy(&self, cnum: CrateNum) -> PanicStrategy;
fn extern_crate(&self, cnum: CrateNum) -> Option<ExternCrate>;
/// The name of the crate as it is referred to in source code of the current
Expand Down Expand Up @@ -381,6 +382,7 @@ impl CrateStore for DummyCrateStore {
fn is_allocator(&self, cnum: CrateNum) -> bool { bug!("is_allocator") }
fn is_panic_runtime(&self, cnum: CrateNum) -> bool { bug!("is_panic_runtime") }
fn is_compiler_builtins(&self, cnum: CrateNum) -> bool { bug!("is_compiler_builtins") }
fn is_profiler_runtime(&self, cnum: CrateNum) -> bool { bug!("is_profiler_runtime") }
fn is_sanitizer_runtime(&self, cnum: CrateNum) -> bool { bug!("is_sanitizer_runtime") }
fn panic_strategy(&self, cnum: CrateNum) -> PanicStrategy {
bug!("panic_strategy")
Expand Down
2 changes: 2 additions & 0 deletions src/librustc/session/config.rs
Expand Up @@ -1033,6 +1033,8 @@ options! {DebuggingOptions, DebuggingSetter, basic_debugging_options,
"a single extra argument to prepend the linker invocation (can be used several times)"),
pre_link_args: Option<Vec<String>> = (None, parse_opt_list, [UNTRACKED],
"extra arguments to prepend to the linker invocation (space separated)"),
profile: bool = (false, parse_bool, [TRACKED],
"insert profiling code"),
}

pub fn default_lib_output() -> CrateType {
Expand Down
8 changes: 5 additions & 3 deletions src/librustc_driver/driver.rs
Expand Up @@ -204,7 +204,8 @@ pub fn compile_input(sess: &Session,
println!("Pre-trans");
tcx.print_debug_stats();
}
let trans = phase_4_translate_to_llvm(tcx, analysis, &incremental_hashes_map);
let trans = phase_4_translate_to_llvm(tcx, analysis, &incremental_hashes_map,
&outputs);

if log_enabled!(::log::LogLevel::Info) {
println!("Post-trans");
Expand Down Expand Up @@ -1042,7 +1043,8 @@ pub fn phase_3_run_analysis_passes<'tcx, F, R>(sess: &'tcx Session,
/// be discarded.
pub fn phase_4_translate_to_llvm<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
analysis: ty::CrateAnalysis,
incremental_hashes_map: &IncrementalHashesMap)
incremental_hashes_map: &IncrementalHashesMap,
output_filenames: &OutputFilenames)
-> trans::CrateTranslation {
let time_passes = tcx.sess.time_passes();

Expand All @@ -1053,7 +1055,7 @@ pub fn phase_4_translate_to_llvm<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
let translation =
time(time_passes,
"translation",
move || trans::trans_crate(tcx, analysis, &incremental_hashes_map));
move || trans::trans_crate(tcx, analysis, &incremental_hashes_map, output_filenames));

time(time_passes,
"assert dep graph",
Expand Down
4 changes: 4 additions & 0 deletions src/librustc_llvm/ffi.rs
Expand Up @@ -591,7 +591,9 @@ extern "C" {
pub fn LLVMIsUndef(Val: ValueRef) -> Bool;

// Operations on metadata
pub fn LLVMMDStringInContext(C: ContextRef, Str: *const c_char, SLen: c_uint) -> ValueRef;
pub fn LLVMMDNodeInContext(C: ContextRef, Vals: *const ValueRef, Count: c_uint) -> ValueRef;
pub fn LLVMAddNamedMetadataOperand(M: ModuleRef, Name: *const c_char, Val: ValueRef);

// Operations on scalar constants
pub fn LLVMConstInt(IntTy: TypeRef, N: c_ulonglong, SignExtend: Bool) -> ValueRef;
Expand Down Expand Up @@ -1332,6 +1334,8 @@ extern "C" {

pub fn LLVMRustAddModuleFlag(M: ModuleRef, name: *const c_char, value: u32);

pub fn LLVMRustMetadataAsValue(C: ContextRef, MD: MetadataRef) -> ValueRef;

pub fn LLVMRustDIBuilderCreate(M: ModuleRef) -> DIBuilderRef;

pub fn LLVMRustDIBuilderDispose(Builder: DIBuilderRef);
Expand Down
19 changes: 19 additions & 0 deletions src/librustc_metadata/creader.rs
Expand Up @@ -906,6 +906,24 @@ impl<'a> CrateLoader<'a> {
}
}

fn inject_profiler_runtime(&mut self) {
if self.sess.opts.debugging_opts.profile {
info!("loading profiler");

let symbol = Symbol::intern("profiler_builtins");
let dep_kind = DepKind::Implicit;
let (_, data) =
self.resolve_crate(&None, symbol, symbol, None, DUMMY_SP,
PathKind::Crate, dep_kind);

// Sanity check the loaded crate to ensure it is indeed a profiler runtime
if !data.is_profiler_runtime(&self.sess.dep_graph) {
self.sess.err(&format!("the crate `profiler_builtins` is not \
a profiler runtime"));
}
}
}

fn inject_allocator_crate(&mut self) {
// Make sure that we actually need an allocator, if none of our
// dependencies need one then we definitely don't!
Expand Down Expand Up @@ -1108,6 +1126,7 @@ impl<'a> middle::cstore::CrateLoader for CrateLoader<'a> {
// inject the sanitizer runtime before the allocator runtime because all
// sanitizers force the use of the `alloc_system` allocator
self.inject_sanitizer_runtime();
self.inject_profiler_runtime();
self.inject_allocator_crate();
self.inject_panic_runtime(krate);

Expand Down
5 changes: 5 additions & 0 deletions src/librustc_metadata/cstore.rs
Expand Up @@ -298,6 +298,11 @@ impl CrateMetadata {
attr::contains_name(&attrs, "sanitizer_runtime")
}

pub fn is_profiler_runtime(&self, dep_graph: &DepGraph) -> bool {
let attrs = self.get_item_attrs(CRATE_DEF_INDEX, dep_graph);
attr::contains_name(&attrs, "profiler_runtime")
}

pub fn is_no_builtins(&self, dep_graph: &DepGraph) -> bool {
let attrs = self.get_item_attrs(CRATE_DEF_INDEX, dep_graph);
attr::contains_name(&attrs, "no_builtins")
Expand Down
4 changes: 4 additions & 0 deletions src/librustc_metadata/cstore_impl.rs
Expand Up @@ -244,6 +244,10 @@ impl CrateStore for cstore::CStore {
self.get_crate_data(cnum).is_sanitizer_runtime(&self.dep_graph)
}

fn is_profiler_runtime(&self, cnum: CrateNum) -> bool {
self.get_crate_data(cnum).is_profiler_runtime(&self.dep_graph)
}

fn panic_strategy(&self, cnum: CrateNum) -> PanicStrategy {
self.get_crate_data(cnum).panic_strategy(&self.dep_graph)
}
Expand Down
3 changes: 3 additions & 0 deletions src/librustc_trans/back/link.rs
Expand Up @@ -1098,6 +1098,9 @@ fn add_upstream_rust_crates(cmd: &mut Linker,
// symbols from the dylib.
let src = sess.cstore.used_crate_source(cnum);
match data[cnum.as_usize() - 1] {
_ if sess.cstore.is_profiler_runtime(cnum) => {
add_static_crate(cmd, sess, tmpdir, crate_type, cnum);
}
_ if sess.cstore.is_sanitizer_runtime(cnum) => {
link_sanitizer_runtime(cmd, sess, tmpdir, cnum);
}
Expand Down