mirror of https://github.com/rust-lang/rust.git
Merge branch 'profiling' of github.com:whitequark/rust into profiling
This commit is contained in:
commit
ecba8d6a23
|
@ -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"
|
||||
|
|
|
@ -889,6 +889,14 @@ dependencies = [
|
|||
"syntax_pos 0.0.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "profiler_builtins"
|
||||
version = "0.0.0"
|
||||
dependencies = [
|
||||
"core 0.0.0",
|
||||
"gcc 0.3.50 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "psapi-sys"
|
||||
version = "0.1.0"
|
||||
|
@ -1582,6 +1590,7 @@ dependencies = [
|
|||
"libc 0.0.0",
|
||||
"panic_abort 0.0.0",
|
||||
"panic_unwind 0.0.0",
|
||||
"profiler_builtins 0.0.0",
|
||||
"rand 0.0.0",
|
||||
"rustc_asan 0.0.0",
|
||||
"rustc_lsan 0.0.0",
|
||||
|
|
|
@ -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") {
|
||||
|
|
|
@ -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,
|
||||
|
@ -162,6 +163,7 @@ struct Build {
|
|||
extended: Option<bool>,
|
||||
verbose: Option<usize>,
|
||||
sanitizers: Option<bool>,
|
||||
profiler: Option<bool>,
|
||||
openssl_static: Option<bool>,
|
||||
}
|
||||
|
||||
|
@ -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 {
|
||||
|
@ -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),
|
||||
}
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -594,6 +594,9 @@ impl Build {
|
|||
if self.config.backtrace {
|
||||
features.push_str(" backtrace");
|
||||
}
|
||||
if self.config.profiler {
|
||||
features.push_str(" profiler");
|
||||
}
|
||||
return features
|
||||
}
|
||||
|
||||
|
|
|
@ -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)
|
||||
|
@ -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)
|
||||
|
@ -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)
|
||||
|
|
|
@ -0,0 +1,5 @@
|
|||
# `profile`
|
||||
|
||||
The tracking issue for this feature is: None
|
||||
|
||||
------------------------
|
|
@ -0,0 +1,5 @@
|
|||
# `profiler_runtime`
|
||||
|
||||
The tracking issue for this feature is: None.
|
||||
|
||||
------------------------
|
|
@ -0,0 +1,5 @@
|
|||
# `profiler_runtime_lib`
|
||||
|
||||
This feature is internal to the Rust compiler and is not intended for general use.
|
||||
|
||||
------------------------
|
|
@ -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"
|
|
@ -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");
|
||||
}
|
|
@ -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)]
|
|
@ -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
|
||||
|
@ -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")
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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");
|
||||
|
@ -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();
|
||||
|
||||
|
@ -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",
|
||||
|
|
|
@ -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;
|
||||
|
@ -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);
|
||||
|
|
|
@ -906,6 +906,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| {
|
||||
if data.name == "std" {
|
||||
uses_std = true;
|
||||
}
|
||||
});
|
||||
|
||||
if uses_std {
|
||||
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!
|
||||
|
@ -1108,6 +1135,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);
|
||||
|
||||
|
|
|
@ -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")
|
||||
|
|
|
@ -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)
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -701,6 +701,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));
|
||||
|
||||
|
|
|
@ -43,7 +43,7 @@ use rustc::dep_graph::AssertDepGraphSafe;
|
|||
use rustc::middle::cstore::LinkMeta;
|
||||
use rustc::hir::map as hir_map;
|
||||
use rustc::util::common::time;
|
||||
use rustc::session::config::{self, NoDebugInfo};
|
||||
use rustc::session::config::{self, NoDebugInfo, OutputFilenames};
|
||||
use rustc::session::Session;
|
||||
use rustc_incremental::IncrementalHashesMap;
|
||||
use abi;
|
||||
|
@ -1049,7 +1049,8 @@ pub fn find_exported_symbols(tcx: TyCtxt, reachable: &NodeSet) -> NodeSet {
|
|||
|
||||
pub fn trans_crate<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
|
||||
analysis: ty::CrateAnalysis,
|
||||
incremental_hashes_map: &IncrementalHashesMap)
|
||||
incremental_hashes_map: &IncrementalHashesMap,
|
||||
output_filenames: &OutputFilenames)
|
||||
-> CrateTranslation {
|
||||
// Be careful with this krate: obviously it gives access to the
|
||||
// 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>,
|
|||
|
||||
let shared_ccx = SharedCrateContext::new(tcx,
|
||||
exported_symbols,
|
||||
check_overflow);
|
||||
check_overflow,
|
||||
output_filenames);
|
||||
// Translate the metadata.
|
||||
let (metadata_llcx, metadata_llmod, metadata) =
|
||||
time(tcx.sess.time_passes(), "write metadata", || {
|
||||
|
|
|
@ -23,7 +23,7 @@ use monomorphize::Instance;
|
|||
use partitioning::CodegenUnit;
|
||||
use type_::Type;
|
||||
use rustc_data_structures::base_n;
|
||||
use rustc::session::config::{self, NoDebugInfo};
|
||||
use rustc::session::config::{self, NoDebugInfo, OutputFilenames};
|
||||
use rustc::session::Session;
|
||||
use rustc::ty::subst::Substs;
|
||||
use rustc::ty::{self, Ty, TyCtxt};
|
||||
|
@ -81,6 +81,8 @@ pub struct SharedCrateContext<'a, 'tcx: 'a> {
|
|||
check_overflow: bool,
|
||||
|
||||
use_dll_storage_attrs: bool,
|
||||
|
||||
output_filenames: &'a OutputFilenames,
|
||||
}
|
||||
|
||||
/// 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
|
|||
impl<'b, 'tcx> SharedCrateContext<'b, 'tcx> {
|
||||
pub fn new(tcx: TyCtxt<'b, 'tcx, 'tcx>,
|
||||
exported_symbols: NodeSet,
|
||||
check_overflow: bool)
|
||||
check_overflow: bool,
|
||||
output_filenames: &'b OutputFilenames)
|
||||
-> SharedCrateContext<'b, 'tcx> {
|
||||
// An interesting part of Windows which MSVC forces our hand on (and
|
||||
// apparently MinGW didn't) is the usage of `dllimport` and `dllexport`
|
||||
|
@ -316,6 +319,7 @@ impl<'b, 'tcx> SharedCrateContext<'b, 'tcx> {
|
|||
tcx: tcx,
|
||||
check_overflow: check_overflow,
|
||||
use_dll_storage_attrs: use_dll_storage_attrs,
|
||||
output_filenames: output_filenames,
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -350,6 +354,10 @@ impl<'b, 'tcx> SharedCrateContext<'b, 'tcx> {
|
|||
pub fn use_dll_storage_attrs(&self) -> bool {
|
||||
self.use_dll_storage_attrs
|
||||
}
|
||||
|
||||
pub fn output_filenames(&self) -> &OutputFilenames {
|
||||
self.output_filenames
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, 'tcx> LocalCrateContext<'a, 'tcx> {
|
||||
|
|
|
@ -38,10 +38,12 @@ use rustc::ty::{self, AdtKind, Ty};
|
|||
use rustc::ty::layout::{self, LayoutTyper};
|
||||
use rustc::session::{Session, config};
|
||||
use rustc::util::nodemap::FxHashMap;
|
||||
use rustc::util::common::path2cstr;
|
||||
|
||||
use libc::{c_uint, c_longlong};
|
||||
use std::ffi::CString;
|
||||
use std::ptr;
|
||||
use std::path::Path;
|
||||
use syntax::ast;
|
||||
use syntax::symbol::{Interner, InternedString, Symbol};
|
||||
use syntax_pos::{self, Span};
|
||||
|
@ -794,7 +796,7 @@ pub fn compile_unit_metadata(scc: &SharedCrateContext,
|
|||
let file_metadata = llvm::LLVMRustDIBuilderCreateFile(
|
||||
debug_context.builder, name_in_debuginfo.as_ptr(), work_dir.as_ptr());
|
||||
|
||||
return llvm::LLVMRustDIBuilderCreateCompileUnit(
|
||||
let unit_metadata = llvm::LLVMRustDIBuilderCreateCompileUnit(
|
||||
debug_context.builder,
|
||||
DW_LANG_RUST,
|
||||
file_metadata,
|
||||
|
@ -802,8 +804,42 @@ pub fn compile_unit_metadata(scc: &SharedCrateContext,
|
|||
sess.opts.optimize != config::OptLevel::No,
|
||||
flags.as_ptr() as *const _,
|
||||
0,
|
||||
split_name.as_ptr() as *const _)
|
||||
split_name.as_ptr() as *const _);
|
||||
|
||||
let cu_desc_metadata = llvm::LLVMRustMetadataAsValue(debug_context.llcontext,
|
||||
unit_metadata);
|
||||
|
||||
let gcov_cu_info = [
|
||||
// Ideally we would be using the three-element form of !llvm.gcov metadata,
|
||||
// which allows us to specify gcno/gcda files explicitly, but that's only
|
||||
// available in LLVM 3.9+; so we rely on LLVM chopping off the extension
|
||||
// and replacing it with gcno/gcda, instead.
|
||||
path_to_mdstring(debug_context.llcontext,
|
||||
&scc.output_filenames().with_extension("gcno")),
|
||||
// path_to_mdstring(debug_context.llcontext,
|
||||
// &scc.output_filenames().with_extension("gcda")),
|
||||
cu_desc_metadata,
|
||||
];
|
||||
let gcov_metadata = llvm::LLVMMDNodeInContext(debug_context.llcontext,
|
||||
gcov_cu_info.as_ptr(),
|
||||
gcov_cu_info.len() as c_uint);
|
||||
|
||||
let llvm_gcov_ident = CString::new("llvm.gcov").unwrap();
|
||||
llvm::LLVMAddNamedMetadataOperand(debug_context.llmod,
|
||||
llvm_gcov_ident.as_ptr(),
|
||||
gcov_metadata);
|
||||
|
||||
return unit_metadata;
|
||||
};
|
||||
|
||||
fn path_to_mdstring(llcx: llvm::ContextRef, path: &Path) -> llvm::ValueRef {
|
||||
let path_str = path2cstr(path);
|
||||
unsafe {
|
||||
llvm::LLVMMDStringInContext(llcx,
|
||||
path_str.as_ptr(),
|
||||
path_str.as_bytes().len() as c_uint)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
struct MetadataCreationResult {
|
||||
|
|
|
@ -67,6 +67,7 @@ const DW_TAG_arg_variable: c_uint = 0x101;
|
|||
/// A context object for maintaining all state needed by the debuginfo module.
|
||||
pub struct CrateDebugContext<'tcx> {
|
||||
llcontext: ContextRef,
|
||||
llmod: ModuleRef,
|
||||
builder: DIBuilderRef,
|
||||
created_files: RefCell<FxHashMap<(Symbol, Symbol), DIFile>>,
|
||||
created_enum_disr_types: RefCell<FxHashMap<(DefId, layout::Integer), DIType>>,
|
||||
|
@ -87,6 +88,7 @@ impl<'tcx> CrateDebugContext<'tcx> {
|
|||
let llcontext = unsafe { llvm::LLVMGetModuleContext(llmod) };
|
||||
CrateDebugContext {
|
||||
llcontext: llcontext,
|
||||
llmod: llmod,
|
||||
builder: builder,
|
||||
created_files: RefCell::new(FxHashMap()),
|
||||
created_enum_disr_types: RefCell::new(FxHashMap()),
|
||||
|
|
|
@ -20,6 +20,7 @@ core = { path = "../libcore" }
|
|||
libc = { path = "../rustc/libc_shim" }
|
||||
rand = { path = "../librand" }
|
||||
compiler_builtins = { path = "../libcompiler_builtins" }
|
||||
profiler_builtins = { path = "../libprofiler_builtins", optional = true }
|
||||
std_unicode = { path = "../libstd_unicode" }
|
||||
unwind = { path = "../libunwind" }
|
||||
|
||||
|
@ -43,3 +44,4 @@ debug-jemalloc = ["alloc_jemalloc/debug"]
|
|||
jemalloc = ["alloc_jemalloc"]
|
||||
force_alloc_system = []
|
||||
panic-unwind = ["panic_unwind"]
|
||||
profiler = ["profiler_builtins"]
|
||||
|
|
|
@ -325,6 +325,10 @@ declare_features! (
|
|||
// rustc internal
|
||||
(active, sanitizer_runtime, "1.17.0", None),
|
||||
|
||||
// Used to identify crates that contain the profiler runtime
|
||||
// rustc internal
|
||||
(active, profiler_runtime, "1.18.0", None),
|
||||
|
||||
// `extern "x86-interrupt" fn()`
|
||||
(active, abi_x86_interrupt, "1.17.0", Some(40180)),
|
||||
|
||||
|
@ -691,6 +695,13 @@ pub const BUILTIN_ATTRIBUTES: &'static [(&'static str, AttributeType, AttributeG
|
|||
identify crates that contain the runtime of a \
|
||||
sanitizer and will never be stable",
|
||||
cfg_fn!(sanitizer_runtime))),
|
||||
("profiler_runtime", Whitelisted, Gated(Stability::Unstable,
|
||||
"profiler_runtime",
|
||||
"the `#[profiler_runtime]` attribute is used to \
|
||||
identify the `profiler_builtins` crate which \
|
||||
contains the profiler runtime and will never be \
|
||||
stable",
|
||||
cfg_fn!(profiler_runtime))),
|
||||
|
||||
("allow_internal_unstable", Normal, Gated(Stability::Unstable,
|
||||
"allow_internal_unstable",
|
||||
|
|
|
@ -466,6 +466,10 @@ extern "C" void LLVMRustAddModuleFlag(LLVMModuleRef M, const char *Name,
|
|||
unwrap(M)->addModuleFlag(Module::Warning, Name, Value);
|
||||
}
|
||||
|
||||
extern "C" void LLVMRustMetadataAsValue(LLVMContextRef C, LLVMRustMetadataRef MD) {
|
||||
wrap(MetadataAsValue::get(*unwrap(C), unwrap(MD)));
|
||||
}
|
||||
|
||||
extern "C" LLVMRustDIBuilderRef LLVMRustDIBuilderCreate(LLVMModuleRef M) {
|
||||
return new DIBuilder(*unwrap(M));
|
||||
}
|
||||
|
|
|
@ -0,0 +1,13 @@
|
|||
// Copyright 2016 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.
|
||||
|
||||
#![profiler_runtime] //~ ERROR the `#[profiler_runtime]` attribute is
|
||||
|
||||
fn main() {}
|
|
@ -0,0 +1,7 @@
|
|||
-include ../tools.mk
|
||||
|
||||
all:
|
||||
$(RUSTC) -g -Z profile test.rs
|
||||
$(call RUN,test) || exit 1
|
||||
[ -e "$(TMPDIR)/test.gcno" ] || (echo "No .gcno file"; exit 1)
|
||||
[ -e "$(TMPDIR)/test.gcda" ] || (echo "No .gcda file"; exit 1)
|
|
@ -0,0 +1,11 @@
|
|||
// 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.
|
||||
|
||||
fn main() {}
|
Loading…
Reference in New Issue