Skip to content
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.

Commit dfa7e21

Browse files
committedJun 14, 2017
Auto merge of #42433 - marco-c:profiling, r=alexcrichton
Build instruction profiler runtime as part of compiler-rt r? @alexcrichton This is #38608 with some fixes. Still missing: - [x] testing with profiler enabled on some builders (on which ones? Should I add the option to some of the already existing configurations, or create a new configuration?); - [x] enabling distribution (on which builders?); - [x] documentation.
2 parents e40ef96 + 5c084fd commit dfa7e21

File tree

38 files changed

+319
-17
lines changed

38 files changed

+319
-17
lines changed
 

‎.travis.yml

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -54,7 +54,7 @@ matrix:
5454
# version that we're using, 8.2, cannot compile LLVM for OSX 10.7.
5555
- env: >
5656
RUST_CHECK_TARGET=check
57-
RUST_CONFIGURE_ARGS="--build=x86_64-apple-darwin --enable-sanitizers"
57+
RUST_CONFIGURE_ARGS="--build=x86_64-apple-darwin --enable-sanitizers --enable-profiler"
5858
SRC=.
5959
RUSTC_RETRY_LINKER_ON_SEGFAULT=1
6060
SCCACHE_ERROR_LOG=/tmp/sccache.log
@@ -87,7 +87,7 @@ matrix:
8787
# OSX 10.7 and `xcode7` is the latest Xcode able to compile LLVM for 10.7.
8888
- env: >
8989
RUST_CHECK_TARGET=dist
90-
RUST_CONFIGURE_ARGS="--build=i686-apple-darwin --enable-extended"
90+
RUST_CONFIGURE_ARGS="--build=i686-apple-darwin --enable-extended --enable-profiler"
9191
SRC=.
9292
DEPLOY=1
9393
RUSTC_RETRY_LINKER_ON_SEGFAULT=1
@@ -101,7 +101,7 @@ matrix:
101101
- *osx_install_sccache
102102
- env: >
103103
RUST_CHECK_TARGET=dist
104-
RUST_CONFIGURE_ARGS="--target=aarch64-apple-ios,armv7-apple-ios,armv7s-apple-ios,i386-apple-ios,x86_64-apple-ios --enable-extended --enable-sanitizers"
104+
RUST_CONFIGURE_ARGS="--target=aarch64-apple-ios,armv7-apple-ios,armv7s-apple-ios,i386-apple-ios,x86_64-apple-ios --enable-extended --enable-sanitizers --enable-profiler"
105105
SRC=.
106106
DEPLOY=1
107107
RUSTC_RETRY_LINKER_ON_SEGFAULT=1

‎appveyor.yml

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ environment:
77
matrix:
88
# 32/64 bit MSVC tests
99
- MSYS_BITS: 64
10-
RUST_CONFIGURE_ARGS: --build=x86_64-pc-windows-msvc
10+
RUST_CONFIGURE_ARGS: --build=x86_64-pc-windows-msvc --enable-profiler
1111
SCRIPT: python x.py test
1212
- MSYS_BITS: 32
1313
RUST_CONFIGURE_ARGS: --build=i686-pc-windows-msvc --target=i586-pc-windows-msvc
@@ -48,12 +48,14 @@ environment:
4848
- RUST_CONFIGURE_ARGS: >
4949
--build=x86_64-pc-windows-msvc
5050
--enable-extended
51+
--enable-profiler
5152
SCRIPT: python x.py dist
5253
DEPLOY: 1
5354
- RUST_CONFIGURE_ARGS: >
5455
--build=i686-pc-windows-msvc
5556
--target=i586-pc-windows-msvc
5657
--enable-extended
58+
--enable-profiler
5759
SCRIPT: python x.py dist
5860
DEPLOY: 1
5961
- MSYS_BITS: 32

‎configure

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -452,6 +452,7 @@ opt vendor 0 "enable usage of vendored Rust crates"
452452
opt sanitizers 0 "build the sanitizer runtimes (asan, lsan, msan, tsan)"
453453
opt dist-src 1 "when building tarballs enables building a source tarball"
454454
opt cargo-openssl-static 0 "static openssl in cargo"
455+
opt profiler 0 "build the profiler runtime"
455456

456457
# Optimization and debugging options. These may be overridden by the release channel, etc.
457458
opt_nosave optimize 1 "build optimized rust code"

‎src/Cargo.lock

Lines changed: 9 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

‎src/bootstrap/check.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -299,6 +299,10 @@ pub fn compiletest(build: &Build,
299299
cmd.env("SANITIZER_SUPPORT", "1");
300300
}
301301

302+
if build.config.profiler {
303+
cmd.env("PROFILER_SUPPORT", "1");
304+
}
305+
302306
cmd.arg("--adb-path").arg("adb");
303307
cmd.arg("--adb-test-dir").arg(ADB_TEST_DIR);
304308
if target.contains("android") {

‎src/bootstrap/config.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,7 @@ pub struct Config {
5050
pub full_bootstrap: bool,
5151
pub extended: bool,
5252
pub sanitizers: bool,
53+
pub profiler: bool,
5354

5455
// llvm codegen options
5556
pub llvm_assertions: bool,
@@ -162,6 +163,7 @@ struct Build {
162163
extended: Option<bool>,
163164
verbose: Option<usize>,
164165
sanitizers: Option<bool>,
166+
profiler: Option<bool>,
165167
openssl_static: Option<bool>,
166168
}
167169

@@ -318,6 +320,7 @@ impl Config {
318320
set(&mut config.extended, build.extended);
319321
set(&mut config.verbose, build.verbose);
320322
set(&mut config.sanitizers, build.sanitizers);
323+
set(&mut config.profiler, build.profiler);
321324
set(&mut config.openssl_static, build.openssl_static);
322325

323326
if let Some(ref install) = toml.install {
@@ -471,6 +474,7 @@ impl Config {
471474
("FULL_BOOTSTRAP", self.full_bootstrap),
472475
("EXTENDED", self.extended),
473476
("SANITIZERS", self.sanitizers),
477+
("PROFILER", self.profiler),
474478
("DIST_SRC", self.rust_dist_src),
475479
("CARGO_OPENSSL_STATIC", self.openssl_static),
476480
}

‎src/bootstrap/config.toml.example

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -147,6 +147,9 @@
147147
# Build the sanitizer runtimes
148148
#sanitizers = false
149149

150+
# Build the profiler runtime
151+
#profiler = false
152+
150153
# Indicates whether the OpenSSL linked into Cargo will be statically linked or
151154
# not. If static linkage is specified then the build system will download a
152155
# known-good version of OpenSSL, compile it, and link it to Cargo.

‎src/bootstrap/dist.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -570,6 +570,7 @@ pub fn rust_src(build: &Build) {
570570
"src/libgetopts",
571571
"src/compiler-rt",
572572
"src/jemalloc",
573+
"src/libprofiler_builtins",
573574
];
574575
let std_src_dirs_exclude = [
575576
"src/compiler-rt/test",

‎src/bootstrap/lib.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -594,6 +594,9 @@ impl Build {
594594
if self.config.backtrace {
595595
features.push_str(" backtrace");
596596
}
597+
if self.config.profiler {
598+
features.push_str(" profiler");
599+
}
597600
return features
598601
}
599602

‎src/ci/docker/dist-i686-linux/Dockerfile

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -90,7 +90,8 @@ ENV HOSTS=i686-unknown-linux-gnu
9090
ENV RUST_CONFIGURE_ARGS \
9191
--host=$HOSTS \
9292
--enable-extended \
93-
--enable-sanitizers
93+
--enable-sanitizers \
94+
--enable-profiler
9495
ENV SCRIPT python2.7 ../x.py dist --host $HOSTS --target $HOSTS
9596

9697
# This is the only builder which will create source tarballs

‎src/ci/docker/dist-x86_64-linux/Dockerfile

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -90,7 +90,8 @@ ENV HOSTS=x86_64-unknown-linux-gnu
9090
ENV RUST_CONFIGURE_ARGS \
9191
--host=$HOSTS \
9292
--enable-extended \
93-
--enable-sanitizers
93+
--enable-sanitizers \
94+
--enable-profiler
9495
ENV SCRIPT python2.7 ../x.py dist --host $HOSTS --target $HOSTS
9596

9697
# This is the only builder which will create source tarballs

‎src/ci/docker/x86_64-gnu/Dockerfile

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,5 +22,5 @@ RUN curl -OL https://github.com/Yelp/dumb-init/releases/download/v1.2.0/dumb-ini
2222
rm dumb-init_*.deb
2323
ENTRYPOINT ["/usr/bin/dumb-init", "--"]
2424

25-
ENV RUST_CONFIGURE_ARGS --build=x86_64-unknown-linux-gnu --enable-sanitizers
25+
ENV RUST_CONFIGURE_ARGS --build=x86_64-unknown-linux-gnu --enable-sanitizers --enable-profiler
2626
ENV SCRIPT python2.7 ../x.py test

‎src/doc/unstable-book/src/SUMMARY.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22

33
- [Compiler flags](compiler-flags.md)
44
- [linker_flavor](compiler-flags/linker-flavor.md)
5+
- [profile](compiler-flags/profile.md)
56
- [remap_path_prefix](compiler-flags/remap-path-prefix.md)
67
- [Language features](language-features.md)
78
- [abi_msp430_interrupt](language-features/abi-msp430-interrupt.md)
@@ -70,6 +71,7 @@
7071
- [plugin_registrar](language-features/plugin-registrar.md)
7172
- [prelude_import](language-features/prelude-import.md)
7273
- [proc_macro](language-features/proc-macro.md)
74+
- [profiler_runtime](language-features/profiler-runtime.md)
7375
- [quote](language-features/quote.md)
7476
- [repr_align](language-features/repr-align.md)
7577
- [repr_simd](language-features/repr-simd.md)
@@ -178,6 +180,7 @@
178180
- [placement_new_protocol](library-features/placement-new-protocol.md)
179181
- [print_internals](library-features/print-internals.md)
180182
- [proc_macro_internals](library-features/proc-macro-internals.md)
183+
- [profiler_runtime_lib](library-features/sanitizer-runtime-lib.md)
181184
- [question_mark_carrier](library-features/question-mark-carrier.md)
182185
- [rand](library-features/rand.md)
183186
- [range_contains](library-features/range-contains.md)
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
# `profile`
2+
3+
The tracking issue for this feature is: [#42524](https://github.com/rust-lang/rust/issues/42524).
4+
5+
------------------------
6+
7+
This feature allows the generation of code coverage reports.
8+
9+
Set the `-Zprofile` compiler flag in order to enable gcov profiling.
10+
11+
For example:
12+
```Bash
13+
cargo new testgcov --bin
14+
cd testgcov
15+
export RUSTFLAGS="-Zprofile"
16+
cargo build
17+
cargo run
18+
```
19+
20+
Once you've built and run your program, files with the `gcno` (after build) and `gcda` (after execution) extensions will be created.
21+
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).
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
# `profiler_runtime`
2+
3+
The tracking issue for this feature is: [#42524](https://github.com/rust-lang/rust/issues/42524).
4+
5+
------------------------
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
# `profiler_runtime_lib`
2+
3+
This feature is internal to the Rust compiler and is not intended for general use.
4+
5+
------------------------

‎src/libprofiler_builtins/Cargo.toml

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
[package]
2+
authors = ["The Rust Project Developers"]
3+
build = "build.rs"
4+
name = "profiler_builtins"
5+
version = "0.0.0"
6+
7+
[lib]
8+
name = "profiler_builtins"
9+
path = "lib.rs"
10+
test = false
11+
bench = false
12+
doc = false
13+
14+
[dependencies]
15+
core = { path = "../libcore" }
16+
17+
[build-dependencies]
18+
gcc = "0.3.50"

‎src/libprofiler_builtins/build.rs

Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
// Copyright 2017 The Rust Project Developers. See the COPYRIGHT
2+
// file at the top-level directory of this distribution and at
3+
// http://rust-lang.org/COPYRIGHT.
4+
//
5+
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6+
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7+
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8+
// option. This file may not be copied, modified, or distributed
9+
// except according to those terms.
10+
11+
//! Compiles the profiler part of the `compiler-rt` library.
12+
//!
13+
//! See the build.rs for libcompiler_builtins crate for details.
14+
15+
extern crate gcc;
16+
17+
use std::env;
18+
use std::path::Path;
19+
20+
fn main() {
21+
let target = env::var("TARGET").expect("TARGET was not set");
22+
let cfg = &mut gcc::Config::new();
23+
24+
let mut profile_sources = vec!["GCDAProfiling.c",
25+
"InstrProfiling.c",
26+
"InstrProfilingBuffer.c",
27+
"InstrProfilingFile.c",
28+
"InstrProfilingMerge.c",
29+
"InstrProfilingMergeFile.c",
30+
"InstrProfilingPlatformDarwin.c",
31+
"InstrProfilingPlatformLinux.c",
32+
"InstrProfilingPlatformOther.c",
33+
"InstrProfilingRuntime.cc",
34+
"InstrProfilingUtil.c",
35+
"InstrProfilingValue.c",
36+
"InstrProfilingWriter.c"];
37+
38+
if target.contains("msvc") {
39+
// Don't pull in extra libraries on MSVC
40+
cfg.flag("/Zl");
41+
profile_sources.push("WindowsMMap.c");
42+
cfg.define("strdup", Some("_strdup"));
43+
cfg.define("open", Some("_open"));
44+
cfg.define("fdopen", Some("_fdopen"));
45+
} else {
46+
// Turn off various features of gcc and such, mostly copying
47+
// compiler-rt's build system already
48+
cfg.flag("-fno-builtin");
49+
cfg.flag("-fvisibility=hidden");
50+
cfg.flag("-fomit-frame-pointer");
51+
cfg.flag("-ffreestanding");
52+
cfg.define("VISIBILITY_HIDDEN", None);
53+
}
54+
55+
for src in profile_sources {
56+
cfg.file(Path::new("../compiler-rt/lib/profile").join(src));
57+
}
58+
59+
cfg.compile("libprofiler-rt.a");
60+
}

‎src/libprofiler_builtins/lib.rs

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
// Copyright 2017 The Rust Project Developers. See the COPYRIGHT
2+
// file at the top-level directory of this distribution and at
3+
// http://rust-lang.org/COPYRIGHT.
4+
//
5+
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6+
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7+
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8+
// option. This file may not be copied, modified, or distributed
9+
// except according to those terms.
10+
11+
#![no_std]
12+
#![cfg_attr(not(stage0), feature(profiler_runtime))]
13+
#![cfg_attr(not(stage0), profiler_runtime)]
14+
#![unstable(feature = "profiler_runtime_lib",
15+
reason = "internal implementation detail of rustc right now",
16+
issue = "0")]
17+
#![crate_name = "profiler_builtins"]
18+
#![crate_type = "rlib"]
19+
#![allow(unused_features)]
20+
#![feature(staged_api)]

‎src/librustc/middle/cstore.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -258,6 +258,7 @@ pub trait CrateStore {
258258
fn is_panic_runtime(&self, cnum: CrateNum) -> bool;
259259
fn is_compiler_builtins(&self, cnum: CrateNum) -> bool;
260260
fn is_sanitizer_runtime(&self, cnum: CrateNum) -> bool;
261+
fn is_profiler_runtime(&self, cnum: CrateNum) -> bool;
261262
fn panic_strategy(&self, cnum: CrateNum) -> PanicStrategy;
262263
fn extern_crate(&self, cnum: CrateNum) -> Option<ExternCrate>;
263264
/// The name of the crate as it is referred to in source code of the current
@@ -381,6 +382,7 @@ impl CrateStore for DummyCrateStore {
381382
fn is_allocator(&self, cnum: CrateNum) -> bool { bug!("is_allocator") }
382383
fn is_panic_runtime(&self, cnum: CrateNum) -> bool { bug!("is_panic_runtime") }
383384
fn is_compiler_builtins(&self, cnum: CrateNum) -> bool { bug!("is_compiler_builtins") }
385+
fn is_profiler_runtime(&self, cnum: CrateNum) -> bool { bug!("is_profiler_runtime") }
384386
fn is_sanitizer_runtime(&self, cnum: CrateNum) -> bool { bug!("is_sanitizer_runtime") }
385387
fn panic_strategy(&self, cnum: CrateNum) -> PanicStrategy {
386388
bug!("panic_strategy")

‎src/librustc/session/config.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1033,6 +1033,8 @@ options! {DebuggingOptions, DebuggingSetter, basic_debugging_options,
10331033
"a single extra argument to prepend the linker invocation (can be used several times)"),
10341034
pre_link_args: Option<Vec<String>> = (None, parse_opt_list, [UNTRACKED],
10351035
"extra arguments to prepend to the linker invocation (space separated)"),
1036+
profile: bool = (false, parse_bool, [TRACKED],
1037+
"insert profiling code"),
10361038
}
10371039

10381040
pub fn default_lib_output() -> CrateType {

‎src/librustc_driver/driver.rs

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -204,7 +204,8 @@ pub fn compile_input(sess: &Session,
204204
println!("Pre-trans");
205205
tcx.print_debug_stats();
206206
}
207-
let trans = phase_4_translate_to_llvm(tcx, analysis, &incremental_hashes_map);
207+
let trans = phase_4_translate_to_llvm(tcx, analysis, &incremental_hashes_map,
208+
&outputs);
208209

209210
if log_enabled!(::log::LogLevel::Info) {
210211
println!("Post-trans");
@@ -1042,7 +1043,8 @@ pub fn phase_3_run_analysis_passes<'tcx, F, R>(sess: &'tcx Session,
10421043
/// be discarded.
10431044
pub fn phase_4_translate_to_llvm<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
10441045
analysis: ty::CrateAnalysis,
1045-
incremental_hashes_map: &IncrementalHashesMap)
1046+
incremental_hashes_map: &IncrementalHashesMap,
1047+
output_filenames: &OutputFilenames)
10461048
-> trans::CrateTranslation {
10471049
let time_passes = tcx.sess.time_passes();
10481050

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

10581060
time(time_passes,
10591061
"assert dep graph",

‎src/librustc_llvm/ffi.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -591,7 +591,9 @@ extern "C" {
591591
pub fn LLVMIsUndef(Val: ValueRef) -> Bool;
592592

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

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

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

1337+
pub fn LLVMRustMetadataAsValue(C: ContextRef, MD: MetadataRef) -> ValueRef;
1338+
13351339
pub fn LLVMRustDIBuilderCreate(M: ModuleRef) -> DIBuilderRef;
13361340

13371341
pub fn LLVMRustDIBuilderDispose(Builder: DIBuilderRef);

‎src/librustc_metadata/creader.rs

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -902,6 +902,24 @@ impl<'a> CrateLoader<'a> {
902902
}
903903
}
904904

905+
fn inject_profiler_runtime(&mut self) {
906+
if self.sess.opts.debugging_opts.profile {
907+
info!("loading profiler");
908+
909+
let symbol = Symbol::intern("profiler_builtins");
910+
let dep_kind = DepKind::Implicit;
911+
let (_, data) =
912+
self.resolve_crate(&None, symbol, symbol, None, DUMMY_SP,
913+
PathKind::Crate, dep_kind);
914+
915+
// Sanity check the loaded crate to ensure it is indeed a profiler runtime
916+
if !data.is_profiler_runtime(&self.sess.dep_graph) {
917+
self.sess.err(&format!("the crate `profiler_builtins` is not \
918+
a profiler runtime"));
919+
}
920+
}
921+
}
922+
905923
fn inject_allocator_crate(&mut self) {
906924
// Make sure that we actually need an allocator, if none of our
907925
// dependencies need one then we definitely don't!
@@ -1104,6 +1122,7 @@ impl<'a> middle::cstore::CrateLoader for CrateLoader<'a> {
11041122
// inject the sanitizer runtime before the allocator runtime because all
11051123
// sanitizers force the use of the `alloc_system` allocator
11061124
self.inject_sanitizer_runtime();
1125+
self.inject_profiler_runtime();
11071126
self.inject_allocator_crate();
11081127
self.inject_panic_runtime(krate);
11091128

‎src/librustc_metadata/cstore.rs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -305,6 +305,11 @@ impl CrateMetadata {
305305
attr::contains_name(&attrs, "sanitizer_runtime")
306306
}
307307

308+
pub fn is_profiler_runtime(&self, dep_graph: &DepGraph) -> bool {
309+
let attrs = self.get_item_attrs(CRATE_DEF_INDEX, dep_graph);
310+
attr::contains_name(&attrs, "profiler_runtime")
311+
}
312+
308313
pub fn is_no_builtins(&self, dep_graph: &DepGraph) -> bool {
309314
let attrs = self.get_item_attrs(CRATE_DEF_INDEX, dep_graph);
310315
attr::contains_name(&attrs, "no_builtins")

‎src/librustc_metadata/cstore_impl.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -245,6 +245,10 @@ impl CrateStore for cstore::CStore {
245245
self.get_crate_data(cnum).is_sanitizer_runtime(&self.dep_graph)
246246
}
247247

248+
fn is_profiler_runtime(&self, cnum: CrateNum) -> bool {
249+
self.get_crate_data(cnum).is_profiler_runtime(&self.dep_graph)
250+
}
251+
248252
fn panic_strategy(&self, cnum: CrateNum) -> PanicStrategy {
249253
self.get_crate_data(cnum).panic_strategy(&self.dep_graph)
250254
}

‎src/librustc_trans/back/link.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1101,6 +1101,9 @@ fn add_upstream_rust_crates(cmd: &mut Linker,
11011101
// symbols from the dylib.
11021102
let src = sess.cstore.used_crate_source(cnum);
11031103
match data[cnum.as_usize() - 1] {
1104+
_ if sess.cstore.is_profiler_runtime(cnum) => {
1105+
add_static_crate(cmd, sess, tmpdir, crate_type, cnum);
1106+
}
11041107
_ if sess.cstore.is_sanitizer_runtime(cnum) => {
11051108
link_sanitizer_runtime(cmd, sess, tmpdir, cnum);
11061109
}

‎src/librustc_trans/back/write.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -701,6 +701,10 @@ pub fn run_passes(sess: &Session,
701701
}
702702
}
703703

704+
if sess.opts.debugging_opts.profile {
705+
modules_config.passes.push("insert-gcov-profiling".to_owned())
706+
}
707+
704708
modules_config.opt_level = Some(get_llvm_opt_level(sess.opts.optimize));
705709
modules_config.opt_size = Some(get_llvm_opt_size(sess.opts.optimize));
706710

‎src/librustc_trans/base.rs

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,7 @@ use rustc::dep_graph::AssertDepGraphSafe;
4343
use rustc::middle::cstore::LinkMeta;
4444
use rustc::hir::map as hir_map;
4545
use rustc::util::common::time;
46-
use rustc::session::config::{self, NoDebugInfo};
46+
use rustc::session::config::{self, NoDebugInfo, OutputFilenames};
4747
use rustc::session::Session;
4848
use rustc_incremental::IncrementalHashesMap;
4949
use abi;
@@ -1049,7 +1049,8 @@ pub fn find_exported_symbols(tcx: TyCtxt, reachable: &NodeSet) -> NodeSet {
10491049

10501050
pub fn trans_crate<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
10511051
analysis: ty::CrateAnalysis,
1052-
incremental_hashes_map: &IncrementalHashesMap)
1052+
incremental_hashes_map: &IncrementalHashesMap,
1053+
output_filenames: &OutputFilenames)
10531054
-> CrateTranslation {
10541055
// Be careful with this krate: obviously it gives access to the
10551056
// entire contents of the krate. So if you push any subtasks of
@@ -1066,7 +1067,8 @@ pub fn trans_crate<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
10661067

10671068
let shared_ccx = SharedCrateContext::new(tcx,
10681069
exported_symbols,
1069-
check_overflow);
1070+
check_overflow,
1071+
output_filenames);
10701072
// Translate the metadata.
10711073
let (metadata_llcx, metadata_llmod, metadata) =
10721074
time(tcx.sess.time_passes(), "write metadata", || {

‎src/librustc_trans/context.rs

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ use monomorphize::Instance;
2323
use partitioning::CodegenUnit;
2424
use type_::Type;
2525
use rustc_data_structures::base_n;
26-
use rustc::session::config::{self, NoDebugInfo};
26+
use rustc::session::config::{self, NoDebugInfo, OutputFilenames};
2727
use rustc::session::Session;
2828
use rustc::ty::subst::Substs;
2929
use rustc::ty::{self, Ty, TyCtxt};
@@ -81,6 +81,8 @@ pub struct SharedCrateContext<'a, 'tcx: 'a> {
8181
check_overflow: bool,
8282

8383
use_dll_storage_attrs: bool,
84+
85+
output_filenames: &'a OutputFilenames,
8486
}
8587

8688
/// The local portion of a `CrateContext`. There is one `LocalCrateContext`
@@ -264,7 +266,8 @@ pub unsafe fn create_context_and_module(sess: &Session, mod_name: &str) -> (Cont
264266
impl<'b, 'tcx> SharedCrateContext<'b, 'tcx> {
265267
pub fn new(tcx: TyCtxt<'b, 'tcx, 'tcx>,
266268
exported_symbols: NodeSet,
267-
check_overflow: bool)
269+
check_overflow: bool,
270+
output_filenames: &'b OutputFilenames)
268271
-> SharedCrateContext<'b, 'tcx> {
269272
// An interesting part of Windows which MSVC forces our hand on (and
270273
// apparently MinGW didn't) is the usage of `dllimport` and `dllexport`
@@ -316,6 +319,7 @@ impl<'b, 'tcx> SharedCrateContext<'b, 'tcx> {
316319
tcx: tcx,
317320
check_overflow: check_overflow,
318321
use_dll_storage_attrs: use_dll_storage_attrs,
322+
output_filenames: output_filenames,
319323
}
320324
}
321325

@@ -350,6 +354,10 @@ impl<'b, 'tcx> SharedCrateContext<'b, 'tcx> {
350354
pub fn use_dll_storage_attrs(&self) -> bool {
351355
self.use_dll_storage_attrs
352356
}
357+
358+
pub fn output_filenames(&self) -> &OutputFilenames {
359+
self.output_filenames
360+
}
353361
}
354362

355363
impl<'a, 'tcx> LocalCrateContext<'a, 'tcx> {

‎src/librustc_trans/debuginfo/metadata.rs

Lines changed: 36 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -38,10 +38,12 @@ use rustc::ty::{self, AdtKind, Ty};
3838
use rustc::ty::layout::{self, LayoutTyper};
3939
use rustc::session::{Session, config};
4040
use rustc::util::nodemap::FxHashMap;
41+
use rustc::util::common::path2cstr;
4142

4243
use libc::{c_uint, c_longlong};
4344
use std::ffi::CString;
4445
use std::ptr;
46+
use std::path::Path;
4547
use syntax::ast;
4648
use syntax::symbol::{Interner, InternedString, Symbol};
4749
use syntax_pos::{self, Span};
@@ -794,16 +796,48 @@ pub fn compile_unit_metadata(scc: &SharedCrateContext,
794796
let file_metadata = llvm::LLVMRustDIBuilderCreateFile(
795797
debug_context.builder, name_in_debuginfo.as_ptr(), work_dir.as_ptr());
796798

797-
return llvm::LLVMRustDIBuilderCreateCompileUnit(
799+
let unit_metadata = llvm::LLVMRustDIBuilderCreateCompileUnit(
798800
debug_context.builder,
799801
DW_LANG_RUST,
800802
file_metadata,
801803
producer.as_ptr(),
802804
sess.opts.optimize != config::OptLevel::No,
803805
flags.as_ptr() as *const _,
804806
0,
805-
split_name.as_ptr() as *const _)
807+
split_name.as_ptr() as *const _);
808+
809+
if sess.opts.debugging_opts.profile {
810+
let cu_desc_metadata = llvm::LLVMRustMetadataAsValue(debug_context.llcontext,
811+
unit_metadata);
812+
813+
let gcov_cu_info = [
814+
path_to_mdstring(debug_context.llcontext,
815+
&scc.output_filenames().with_extension("gcno")),
816+
path_to_mdstring(debug_context.llcontext,
817+
&scc.output_filenames().with_extension("gcda")),
818+
cu_desc_metadata,
819+
];
820+
let gcov_metadata = llvm::LLVMMDNodeInContext(debug_context.llcontext,
821+
gcov_cu_info.as_ptr(),
822+
gcov_cu_info.len() as c_uint);
823+
824+
let llvm_gcov_ident = CString::new("llvm.gcov").unwrap();
825+
llvm::LLVMAddNamedMetadataOperand(debug_context.llmod,
826+
llvm_gcov_ident.as_ptr(),
827+
gcov_metadata);
828+
}
829+
830+
return unit_metadata;
806831
};
832+
833+
fn path_to_mdstring(llcx: llvm::ContextRef, path: &Path) -> llvm::ValueRef {
834+
let path_str = path2cstr(path);
835+
unsafe {
836+
llvm::LLVMMDStringInContext(llcx,
837+
path_str.as_ptr(),
838+
path_str.as_bytes().len() as c_uint)
839+
}
840+
}
807841
}
808842

809843
struct MetadataCreationResult {

‎src/librustc_trans/debuginfo/mod.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,7 @@ const DW_TAG_arg_variable: c_uint = 0x101;
6767
/// A context object for maintaining all state needed by the debuginfo module.
6868
pub struct CrateDebugContext<'tcx> {
6969
llcontext: ContextRef,
70+
llmod: ModuleRef,
7071
builder: DIBuilderRef,
7172
created_files: RefCell<FxHashMap<(Symbol, Symbol), DIFile>>,
7273
created_enum_disr_types: RefCell<FxHashMap<(DefId, layout::Integer), DIType>>,
@@ -87,6 +88,7 @@ impl<'tcx> CrateDebugContext<'tcx> {
8788
let llcontext = unsafe { llvm::LLVMGetModuleContext(llmod) };
8889
CrateDebugContext {
8990
llcontext: llcontext,
91+
llmod: llmod,
9092
builder: builder,
9193
created_files: RefCell::new(FxHashMap()),
9294
created_enum_disr_types: RefCell::new(FxHashMap()),

‎src/libstd/Cargo.toml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ core = { path = "../libcore" }
2020
libc = { path = "../rustc/libc_shim" }
2121
rand = { path = "../librand" }
2222
compiler_builtins = { path = "../libcompiler_builtins" }
23+
profiler_builtins = { path = "../libprofiler_builtins", optional = true }
2324
std_unicode = { path = "../libstd_unicode" }
2425
unwind = { path = "../libunwind" }
2526

@@ -43,3 +44,4 @@ debug-jemalloc = ["alloc_jemalloc/debug"]
4344
jemalloc = ["alloc_jemalloc"]
4445
force_alloc_system = []
4546
panic-unwind = ["panic_unwind"]
47+
profiler = ["profiler_builtins"]

‎src/libsyntax/feature_gate.rs

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -325,6 +325,10 @@ declare_features! (
325325
// rustc internal
326326
(active, sanitizer_runtime, "1.17.0", None),
327327

328+
// Used to identify crates that contain the profiler runtime
329+
// rustc internal
330+
(active, profiler_runtime, "1.18.0", None),
331+
328332
// `extern "x86-interrupt" fn()`
329333
(active, abi_x86_interrupt, "1.17.0", Some(40180)),
330334

@@ -691,6 +695,13 @@ pub const BUILTIN_ATTRIBUTES: &'static [(&'static str, AttributeType, AttributeG
691695
identify crates that contain the runtime of a \
692696
sanitizer and will never be stable",
693697
cfg_fn!(sanitizer_runtime))),
698+
("profiler_runtime", Whitelisted, Gated(Stability::Unstable,
699+
"profiler_runtime",
700+
"the `#[profiler_runtime]` attribute is used to \
701+
identify the `profiler_builtins` crate which \
702+
contains the profiler runtime and will never be \
703+
stable",
704+
cfg_fn!(profiler_runtime))),
694705

695706
("allow_internal_unstable", Normal, Gated(Stability::Unstable,
696707
"allow_internal_unstable",

‎src/rustllvm/RustWrapper.cpp

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -466,6 +466,10 @@ extern "C" void LLVMRustAddModuleFlag(LLVMModuleRef M, const char *Name,
466466
unwrap(M)->addModuleFlag(Module::Warning, Name, Value);
467467
}
468468

469+
extern "C" void LLVMRustMetadataAsValue(LLVMContextRef C, LLVMRustMetadataRef MD) {
470+
wrap(MetadataAsValue::get(*unwrap(C), unwrap(MD)));
471+
}
472+
469473
extern "C" LLVMRustDIBuilderRef LLVMRustDIBuilderCreate(LLVMModuleRef M) {
470474
return new DIBuilder(*unwrap(M));
471475
}
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
2+
// file at the top-level directory of this distribution and at
3+
// http://rust-lang.org/COPYRIGHT.
4+
//
5+
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6+
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7+
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8+
// option. This file may not be copied, modified, or distributed
9+
// except according to those terms.
10+
11+
#![profiler_runtime] //~ ERROR the `#[profiler_runtime]` attribute is
12+
13+
fn main() {}

‎src/test/run-make/profile/Makefile

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
-include ../tools.mk
2+
3+
all:
4+
ifeq ($(PROFILER_SUPPORT),1)
5+
$(RUSTC) -g -Z profile test.rs
6+
$(call RUN,test) || exit 1
7+
[ -e "$(TMPDIR)/test.gcno" ] || (echo "No .gcno file"; exit 1)
8+
[ -e "$(TMPDIR)/test.gcda" ] || (echo "No .gcda file"; exit 1)
9+
endif

‎src/test/run-make/profile/test.rs

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
// Copyright 2017 The Rust Project Developers. See the COPYRIGHT
2+
// file at the top-level directory of this distribution and at
3+
// http://rust-lang.org/COPYRIGHT.
4+
//
5+
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6+
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7+
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8+
// option. This file may not be copied, modified, or distributed
9+
// except according to those terms.
10+
11+
fn main() {}

0 commit comments

Comments
 (0)
Please sign in to comment.