Skip to content

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

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

Closed
wants to merge 1 commit into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions configure
Original file line number Diff line number Diff line change
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
Original file line number Diff line number Diff line change
Expand Up @@ -268,6 +268,10 @@ pub fn compiletest(build: &Build,
cmd.env("SANITIZER_SUPPORT", "1");
}

if build.config.profiler {
cmd.env("PROFILER_SUPPORT", "1");
Copy link
Member

Choose a reason for hiding this comment

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

I'm not sure that this is ever read, is it still needed?

Copy link
Member Author

Choose a reason for hiding this comment

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

It's needed for a test. That's yet to be written.

}

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
Original file line number Diff line number Diff line change
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 @@ -158,6 +159,7 @@ struct Build {
extended: Option<bool>,
verbose: Option<usize>,
sanitizers: Option<bool>,
profiler: Option<bool>,
openssl_static: Option<bool>,
}

Expand Down Expand Up @@ -311,6 +313,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 @@ -462,6 +465,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
Original file line number Diff line number Diff line change
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
Original file line number Diff line number Diff line change
Expand Up @@ -667,6 +667,9 @@ impl Build {
if self.config.backtrace {
features.push_str(" backtrace");
}
if self.config.profiler {
features.push_str(" profiler");
}
return features
}

Expand Down
3 changes: 3 additions & 0 deletions src/doc/unstable-book/src/SUMMARY.md
Original file line number Diff line number Diff line change
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 @@ -71,6 +72,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)
- [relaxed_adts](language-features/relaxed-adts.md)
- [repr_align](language-features/repr-align.md)
Expand Down Expand Up @@ -180,6 +182,7 @@
- [print](library-features/print.md)
- [proc_macro_internals](library-features/proc-macro-internals.md)
- [process_try_wait](library-features/process-try-wait.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
5 changes: 5 additions & 0 deletions src/doc/unstable-book/src/compiler-flags/profile.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
# `profile`

The tracking issue for this feature is: None

------------------------
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
# `profiler_runtime`

The tracking issue for this feature is: None.

------------------------
Original file line number Diff line number Diff line change
@@ -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
Original file line number Diff line number Diff line change
@@ -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
Original file line number Diff line number Diff line change
@@ -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
Original file line number Diff line number Diff line change
@@ -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
Original file line number Diff line number Diff line change
Expand Up @@ -220,6 +220,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 @@ -356,6 +357,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
Original file line number Diff line number Diff line change
Expand Up @@ -1025,6 +1025,8 @@ options! {DebuggingOptions, DebuggingSetter, basic_debugging_options,
"add a source pattern to the file path remapping config"),
remap_path_prefix_to: Vec<String> = (vec![], parse_string_push, [TRACKED],
"add a mapping target to the file path remapping config"),
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
Original file line number Diff line number Diff line change
Expand Up @@ -203,7 +203,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 @@ -1029,7 +1030,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 Down Expand Up @@ -1077,7 +1079,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
Original file line number Diff line number Diff line change
Expand Up @@ -587,7 +587,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 @@ -1328,6 +1330,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
28 changes: 28 additions & 0 deletions src/librustc_metadata/creader.rs
Original file line number Diff line number Diff line change
Expand Up @@ -870,6 +870,33 @@ impl<'a> CrateLoader<'a> {
}
}

fn inject_profiler_runtime(&mut self) {
if self.sess.opts.debugging_opts.profile {
let mut uses_std = false;
self.cstore.iter_crate_data(|_, data| {
Copy link
Member

Choose a reason for hiding this comment

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

@japaric can you remind me why this is needed?

Naively I'd expect that a crate would require the profiler runtime regardless of whether it links to std or not, but I forget why this clause is above.

Copy link
Member Author

Choose a reason for hiding this comment

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

I orignially copied that over from compiler_builtins. I think it's useful because a no_std crate may want to supply their own profiler builtins, e.g. to submit the results somewhere in a semihosting implementation.

Copy link
Member

Choose a reason for hiding this comment

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

@alexcrichton iirc, because the sanitizers only work with alloc_system (they depend on memcpy and co.), use libc functions like write to print results to the console and pretty much depend on the Linux kernel so you need an OS to use them and that's guaranteed to be there when you link to std.

But since -Z sanitizer is restricted to only work with the x86_64-unknown-linux-gnu target, this check may not be that necessary. Still no_std + x86_64-unknown-linux-gnu will not work unless you link to libc.

Copy link
Member

Choose a reason for hiding this comment

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

Ah ok. @whitequark perhaps this clause (checking uses_std) be removed for now?

Is it really feasible for someone to write their own profiler builtins?

Copy link
Member Author

Choose a reason for hiding this comment

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

@alexcrichton Sure, I'll remove it.

I imagine someone would replace the libc calls in the stock profiler builtins with something else and then link to that, not write them from scratch. I am thinking of doing this for my embedded system work, incidentally.

if data.name == "std" {
uses_std = true;
}
});

if uses_std {
Copy link
Member

Choose a reason for hiding this comment

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

Mentioned above, we can remove this clause, right?

(just execute the code below if -Z profile is provided)

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.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 @@ -1071,6 +1098,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
Original file line number Diff line number Diff line change
Expand Up @@ -308,6 +308,11 @@ impl CrateMetadata {
attr::contains_name(&attrs, "sanitizer_runtime")
}

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

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

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

fn panic_strategy(&self, cnum: CrateNum) -> PanicStrategy {
self.get_crate_data(cnum).panic_strategy()
}
Expand Down
3 changes: 3 additions & 0 deletions src/librustc_trans/back/link.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1074,6 +1074,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
4 changes: 4 additions & 0 deletions src/librustc_trans/back/write.rs
Original file line number Diff line number Diff line change
Expand Up @@ -699,6 +699,10 @@ pub fn run_passes(sess: &Session,
}
}

if sess.opts.debugging_opts.profile {
modules_config.passes.push("insert-gcov-profiling".to_owned())
}

modules_config.opt_level = Some(get_llvm_opt_level(sess.opts.optimize));
modules_config.opt_size = Some(get_llvm_opt_size(sess.opts.optimize));

Expand Down
Loading