Replace TimeLine with SelfProfiler
This commit is contained in:
parent
913ad6d1f0
commit
4c8cc14186
12 changed files with 155 additions and 435 deletions
|
@ -136,7 +136,6 @@ pub mod util {
|
||||||
pub mod common;
|
pub mod common;
|
||||||
pub mod ppaux;
|
pub mod ppaux;
|
||||||
pub mod nodemap;
|
pub mod nodemap;
|
||||||
pub mod time_graph;
|
|
||||||
pub mod profiling;
|
pub mod profiling;
|
||||||
pub mod bug;
|
pub mod bug;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,3 +1,4 @@
|
||||||
|
use std::borrow::Cow;
|
||||||
use std::fs;
|
use std::fs;
|
||||||
use std::io::{BufWriter, Write};
|
use std::io::{BufWriter, Write};
|
||||||
use std::mem;
|
use std::mem;
|
||||||
|
@ -20,12 +21,12 @@ pub enum ProfileCategory {
|
||||||
Other,
|
Other,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
|
#[derive(Clone, Debug, Eq, PartialEq)]
|
||||||
pub enum ProfilerEvent {
|
pub enum ProfilerEvent {
|
||||||
QueryStart { query_name: &'static str, category: ProfileCategory, time: u64 },
|
QueryStart { query_name: &'static str, category: ProfileCategory, time: u64 },
|
||||||
QueryEnd { query_name: &'static str, category: ProfileCategory, time: u64 },
|
QueryEnd { query_name: &'static str, category: ProfileCategory, time: u64 },
|
||||||
GenericActivityStart { category: ProfileCategory, time: u64 },
|
GenericActivityStart { category: ProfileCategory, label: Cow<'static, str>, time: u64 },
|
||||||
GenericActivityEnd { category: ProfileCategory, time: u64 },
|
GenericActivityEnd { category: ProfileCategory, label: Cow<'static, str>, time: u64 },
|
||||||
IncrementalLoadResultStart { query_name: &'static str, time: u64 },
|
IncrementalLoadResultStart { query_name: &'static str, time: u64 },
|
||||||
IncrementalLoadResultEnd { query_name: &'static str, time: u64 },
|
IncrementalLoadResultEnd { query_name: &'static str, time: u64 },
|
||||||
QueryCacheHit { query_name: &'static str, category: ProfileCategory, time: u64 },
|
QueryCacheHit { query_name: &'static str, category: ProfileCategory, time: u64 },
|
||||||
|
@ -75,17 +76,27 @@ impl SelfProfiler {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn start_activity(&mut self, category: ProfileCategory) {
|
pub fn start_activity(
|
||||||
|
&mut self,
|
||||||
|
category: ProfileCategory,
|
||||||
|
label: impl Into<Cow<'static, str>>,
|
||||||
|
) {
|
||||||
self.record(ProfilerEvent::GenericActivityStart {
|
self.record(ProfilerEvent::GenericActivityStart {
|
||||||
category,
|
category,
|
||||||
|
label: label.into(),
|
||||||
time: self.get_time_from_start(),
|
time: self.get_time_from_start(),
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn end_activity(&mut self, category: ProfileCategory) {
|
pub fn end_activity(
|
||||||
|
&mut self,
|
||||||
|
category: ProfileCategory,
|
||||||
|
label: impl Into<Cow<'static, str>>,
|
||||||
|
) {
|
||||||
self.record(ProfilerEvent::GenericActivityEnd {
|
self.record(ProfilerEvent::GenericActivityEnd {
|
||||||
category,
|
category,
|
||||||
|
label: label.into(),
|
||||||
time: self.get_time_from_start(),
|
time: self.get_time_from_start(),
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
@ -273,11 +284,12 @@ impl SelfProfiler {
|
||||||
nanos,
|
nanos,
|
||||||
thread_id,
|
thread_id,
|
||||||
).unwrap(),
|
).unwrap(),
|
||||||
GenericActivityStart { category, time: _ } =>
|
GenericActivityStart { category, label, time: _ } =>
|
||||||
write!(file,
|
write!(file,
|
||||||
"{{
|
"{{
|
||||||
\"GenericActivityStart\": {{\
|
\"GenericActivityStart\": {{\
|
||||||
\"category\": \"{:?}\",\
|
\"category\": \"{:?}\",\
|
||||||
|
\"label\": \"{}\",\
|
||||||
\"time\": {{\
|
\"time\": {{\
|
||||||
\"secs\": {},\
|
\"secs\": {},\
|
||||||
\"nanos\": {}\
|
\"nanos\": {}\
|
||||||
|
@ -286,15 +298,17 @@ impl SelfProfiler {
|
||||||
}}\
|
}}\
|
||||||
}}",
|
}}",
|
||||||
category,
|
category,
|
||||||
|
label,
|
||||||
secs,
|
secs,
|
||||||
nanos,
|
nanos,
|
||||||
thread_id,
|
thread_id,
|
||||||
).unwrap(),
|
).unwrap(),
|
||||||
GenericActivityEnd { category, time: _ } =>
|
GenericActivityEnd { category, label, time: _ } =>
|
||||||
write!(file,
|
write!(file,
|
||||||
"{{\
|
"{{\
|
||||||
\"GenericActivityEnd\": {{\
|
\"GenericActivityEnd\": {{\
|
||||||
\"category\": \"{:?}\",\
|
\"category\": \"{:?}\",\
|
||||||
|
\"label\": \"{}\",\
|
||||||
\"time\": {{\
|
\"time\": {{\
|
||||||
\"secs\": {},\
|
\"secs\": {},\
|
||||||
\"nanos\": {}\
|
\"nanos\": {}\
|
||||||
|
@ -303,6 +317,7 @@ impl SelfProfiler {
|
||||||
}}\
|
}}\
|
||||||
}}",
|
}}",
|
||||||
category,
|
category,
|
||||||
|
label,
|
||||||
secs,
|
secs,
|
||||||
nanos,
|
nanos,
|
||||||
thread_id,
|
thread_id,
|
||||||
|
@ -418,7 +433,7 @@ impl SelfProfiler {
|
||||||
secs,
|
secs,
|
||||||
nanos,
|
nanos,
|
||||||
thread_id,
|
thread_id,
|
||||||
).unwrap()
|
).unwrap(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,268 +0,0 @@
|
||||||
use rustc_data_structures::fx::FxHashMap;
|
|
||||||
use std::fs::File;
|
|
||||||
use std::io::prelude::*;
|
|
||||||
use std::marker::PhantomData;
|
|
||||||
use std::mem;
|
|
||||||
use std::sync::{Arc, Mutex};
|
|
||||||
use std::time::Instant;
|
|
||||||
|
|
||||||
const OUTPUT_WIDTH_IN_PX: u64 = 1000;
|
|
||||||
const TIME_LINE_HEIGHT_IN_PX: u64 = 20;
|
|
||||||
const TIME_LINE_HEIGHT_STRIDE_IN_PX: usize = 30;
|
|
||||||
|
|
||||||
#[derive(Clone)]
|
|
||||||
struct Timing {
|
|
||||||
start: Instant,
|
|
||||||
end: Instant,
|
|
||||||
work_package_kind: WorkPackageKind,
|
|
||||||
name: String,
|
|
||||||
events: Vec<(String, Instant)>,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Clone, Copy, Hash, Eq, PartialEq, Debug)]
|
|
||||||
pub struct TimelineId(pub usize);
|
|
||||||
|
|
||||||
#[derive(Clone)]
|
|
||||||
struct PerThread {
|
|
||||||
timings: Vec<Timing>,
|
|
||||||
open_work_package: Option<(Instant, WorkPackageKind, String)>,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Clone)]
|
|
||||||
pub struct TimeGraph {
|
|
||||||
data: Arc<Mutex<FxHashMap<TimelineId, PerThread>>>,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Clone, Copy)]
|
|
||||||
pub struct WorkPackageKind(pub &'static [&'static str]);
|
|
||||||
|
|
||||||
pub struct Timeline {
|
|
||||||
token: Option<RaiiToken>,
|
|
||||||
}
|
|
||||||
|
|
||||||
struct RaiiToken {
|
|
||||||
graph: TimeGraph,
|
|
||||||
timeline: TimelineId,
|
|
||||||
events: Vec<(String, Instant)>,
|
|
||||||
// The token must not be Send:
|
|
||||||
_marker: PhantomData<*const ()>
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
impl Drop for RaiiToken {
|
|
||||||
fn drop(&mut self) {
|
|
||||||
self.graph.end(self.timeline, mem::replace(&mut self.events, Vec::new()));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl TimeGraph {
|
|
||||||
pub fn new() -> TimeGraph {
|
|
||||||
TimeGraph {
|
|
||||||
data: Arc::new(Mutex::new(FxHashMap::default()))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn start(&self,
|
|
||||||
timeline: TimelineId,
|
|
||||||
work_package_kind: WorkPackageKind,
|
|
||||||
name: &str) -> Timeline {
|
|
||||||
{
|
|
||||||
let mut table = self.data.lock().unwrap();
|
|
||||||
|
|
||||||
let data = table.entry(timeline).or_insert(PerThread {
|
|
||||||
timings: Vec::new(),
|
|
||||||
open_work_package: None,
|
|
||||||
});
|
|
||||||
|
|
||||||
assert!(data.open_work_package.is_none());
|
|
||||||
data.open_work_package = Some((Instant::now(), work_package_kind, name.to_string()));
|
|
||||||
}
|
|
||||||
|
|
||||||
Timeline {
|
|
||||||
token: Some(RaiiToken {
|
|
||||||
graph: self.clone(),
|
|
||||||
timeline,
|
|
||||||
events: Vec::new(),
|
|
||||||
_marker: PhantomData,
|
|
||||||
}),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn end(&self, timeline: TimelineId, events: Vec<(String, Instant)>) {
|
|
||||||
let end = Instant::now();
|
|
||||||
|
|
||||||
let mut table = self.data.lock().unwrap();
|
|
||||||
let data = table.get_mut(&timeline).unwrap();
|
|
||||||
|
|
||||||
if let Some((start, work_package_kind, name)) = data.open_work_package.take() {
|
|
||||||
data.timings.push(Timing {
|
|
||||||
start,
|
|
||||||
end,
|
|
||||||
work_package_kind,
|
|
||||||
name,
|
|
||||||
events,
|
|
||||||
});
|
|
||||||
} else {
|
|
||||||
bug!("end timing without start?")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn dump(&self, output_filename: &str) {
|
|
||||||
let table = self.data.lock().unwrap();
|
|
||||||
|
|
||||||
for data in table.values() {
|
|
||||||
assert!(data.open_work_package.is_none());
|
|
||||||
}
|
|
||||||
|
|
||||||
let mut threads: Vec<PerThread> =
|
|
||||||
table.values().map(|data| data.clone()).collect();
|
|
||||||
|
|
||||||
threads.sort_by_key(|timeline| timeline.timings[0].start);
|
|
||||||
|
|
||||||
let earliest_instant = threads[0].timings[0].start;
|
|
||||||
let latest_instant = threads.iter()
|
|
||||||
.map(|timeline| timeline.timings
|
|
||||||
.last()
|
|
||||||
.unwrap()
|
|
||||||
.end)
|
|
||||||
.max()
|
|
||||||
.unwrap();
|
|
||||||
let max_distance = distance(earliest_instant, latest_instant);
|
|
||||||
|
|
||||||
let mut file = File::create(format!("{}.html", output_filename)).unwrap();
|
|
||||||
|
|
||||||
writeln!(file, "
|
|
||||||
<html>
|
|
||||||
<head>
|
|
||||||
<style>
|
|
||||||
#threads a {{
|
|
||||||
position: absolute;
|
|
||||||
overflow: hidden;
|
|
||||||
}}
|
|
||||||
#threads {{
|
|
||||||
height: {total_height}px;
|
|
||||||
width: {width}px;
|
|
||||||
}}
|
|
||||||
|
|
||||||
.timeline {{
|
|
||||||
display: none;
|
|
||||||
width: {width}px;
|
|
||||||
position: relative;
|
|
||||||
}}
|
|
||||||
|
|
||||||
.timeline:target {{
|
|
||||||
display: block;
|
|
||||||
}}
|
|
||||||
|
|
||||||
.event {{
|
|
||||||
position: absolute;
|
|
||||||
}}
|
|
||||||
</style>
|
|
||||||
</head>
|
|
||||||
<body>
|
|
||||||
<div id='threads'>
|
|
||||||
",
|
|
||||||
total_height = threads.len() * TIME_LINE_HEIGHT_STRIDE_IN_PX,
|
|
||||||
width = OUTPUT_WIDTH_IN_PX,
|
|
||||||
).unwrap();
|
|
||||||
|
|
||||||
let mut color = 0;
|
|
||||||
for (line_index, thread) in threads.iter().enumerate() {
|
|
||||||
let line_top = line_index * TIME_LINE_HEIGHT_STRIDE_IN_PX;
|
|
||||||
|
|
||||||
for span in &thread.timings {
|
|
||||||
let start = distance(earliest_instant, span.start);
|
|
||||||
let end = distance(earliest_instant, span.end);
|
|
||||||
|
|
||||||
let start = normalize(start, max_distance, OUTPUT_WIDTH_IN_PX);
|
|
||||||
let end = normalize(end, max_distance, OUTPUT_WIDTH_IN_PX);
|
|
||||||
|
|
||||||
let colors = span.work_package_kind.0;
|
|
||||||
|
|
||||||
writeln!(file, "<a href='#timing{}'
|
|
||||||
style='top:{}px; \
|
|
||||||
left:{}px; \
|
|
||||||
width:{}px; \
|
|
||||||
height:{}px; \
|
|
||||||
background:{};'>{}</a>",
|
|
||||||
color,
|
|
||||||
line_top,
|
|
||||||
start,
|
|
||||||
end - start,
|
|
||||||
TIME_LINE_HEIGHT_IN_PX,
|
|
||||||
colors[color % colors.len()],
|
|
||||||
span.name,
|
|
||||||
).unwrap();
|
|
||||||
|
|
||||||
color += 1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
writeln!(file, "
|
|
||||||
</div>
|
|
||||||
").unwrap();
|
|
||||||
|
|
||||||
let mut idx = 0;
|
|
||||||
for thread in threads.iter() {
|
|
||||||
for timing in &thread.timings {
|
|
||||||
let colors = timing.work_package_kind.0;
|
|
||||||
let height = TIME_LINE_HEIGHT_STRIDE_IN_PX * timing.events.len();
|
|
||||||
writeln!(file, "<div class='timeline'
|
|
||||||
id='timing{}'
|
|
||||||
style='background:{};height:{}px;'>",
|
|
||||||
idx,
|
|
||||||
colors[idx % colors.len()],
|
|
||||||
height).unwrap();
|
|
||||||
idx += 1;
|
|
||||||
let max = distance(timing.start, timing.end);
|
|
||||||
for (i, &(ref event, time)) in timing.events.iter().enumerate() {
|
|
||||||
let i = i as u64;
|
|
||||||
let time = distance(timing.start, time);
|
|
||||||
let at = normalize(time, max, OUTPUT_WIDTH_IN_PX);
|
|
||||||
writeln!(file, "<span class='event'
|
|
||||||
style='left:{}px;\
|
|
||||||
top:{}px;'>{}</span>",
|
|
||||||
at,
|
|
||||||
TIME_LINE_HEIGHT_IN_PX * i,
|
|
||||||
event).unwrap();
|
|
||||||
}
|
|
||||||
writeln!(file, "</div>").unwrap();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
writeln!(file, "
|
|
||||||
</body>
|
|
||||||
</html>
|
|
||||||
").unwrap();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Timeline {
|
|
||||||
pub fn noop() -> Timeline {
|
|
||||||
Timeline { token: None }
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Record an event which happened at this moment on this timeline.
|
|
||||||
///
|
|
||||||
/// Events are displayed in the eventual HTML output where you can click on
|
|
||||||
/// a particular timeline and it'll expand to all of the events that
|
|
||||||
/// happened on that timeline. This can then be used to drill into a
|
|
||||||
/// particular timeline and see what events are happening and taking the
|
|
||||||
/// most time.
|
|
||||||
pub fn record(&mut self, name: &str) {
|
|
||||||
if let Some(ref mut token) = self.token {
|
|
||||||
token.events.push((name.to_string(), Instant::now()));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn distance(zero: Instant, x: Instant) -> u64 {
|
|
||||||
|
|
||||||
let duration = x.duration_since(zero);
|
|
||||||
(duration.as_secs() * 1_000_000_000 + duration.subsec_nanos() as u64) // / div
|
|
||||||
}
|
|
||||||
|
|
||||||
fn normalize(distance: u64, max: u64, max_pixels: u64) -> u64 {
|
|
||||||
(max_pixels * distance) / max
|
|
||||||
}
|
|
||||||
|
|
|
@ -3,7 +3,6 @@ use crate::back::write::{self, DiagnosticHandlers, with_llvm_pmb, save_temp_bitc
|
||||||
to_llvm_opt_settings};
|
to_llvm_opt_settings};
|
||||||
use crate::llvm::archive_ro::ArchiveRO;
|
use crate::llvm::archive_ro::ArchiveRO;
|
||||||
use crate::llvm::{self, True, False};
|
use crate::llvm::{self, True, False};
|
||||||
use crate::time_graph::Timeline;
|
|
||||||
use crate::{ModuleLlvm, LlvmCodegenBackend};
|
use crate::{ModuleLlvm, LlvmCodegenBackend};
|
||||||
use rustc_codegen_ssa::back::symbol_export;
|
use rustc_codegen_ssa::back::symbol_export;
|
||||||
use rustc_codegen_ssa::back::write::{ModuleConfig, CodegenContext, FatLTOInput};
|
use rustc_codegen_ssa::back::write::{ModuleConfig, CodegenContext, FatLTOInput};
|
||||||
|
@ -16,6 +15,7 @@ use rustc::hir::def_id::LOCAL_CRATE;
|
||||||
use rustc::middle::exported_symbols::SymbolExportLevel;
|
use rustc::middle::exported_symbols::SymbolExportLevel;
|
||||||
use rustc::session::config::{self, Lto};
|
use rustc::session::config::{self, Lto};
|
||||||
use rustc::util::common::time_ext;
|
use rustc::util::common::time_ext;
|
||||||
|
use rustc::util::profiling::ProfileCategory;
|
||||||
use rustc_data_structures::fx::FxHashMap;
|
use rustc_data_structures::fx::FxHashMap;
|
||||||
use rustc_codegen_ssa::{ModuleCodegen, ModuleKind};
|
use rustc_codegen_ssa::{ModuleCodegen, ModuleKind};
|
||||||
|
|
||||||
|
@ -37,7 +37,6 @@ pub fn crate_type_allows_lto(crate_type: config::CrateType) -> bool {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn prepare_lto(cgcx: &CodegenContext<LlvmCodegenBackend>,
|
fn prepare_lto(cgcx: &CodegenContext<LlvmCodegenBackend>,
|
||||||
timeline: &mut Timeline,
|
|
||||||
diag_handler: &Handler)
|
diag_handler: &Handler)
|
||||||
-> Result<(Vec<CString>, Vec<(SerializedModule<ModuleBuffer>, CString)>), FatalError>
|
-> Result<(Vec<CString>, Vec<(SerializedModule<ModuleBuffer>, CString)>), FatalError>
|
||||||
{
|
{
|
||||||
|
@ -68,7 +67,8 @@ fn prepare_lto(cgcx: &CodegenContext<LlvmCodegenBackend>,
|
||||||
.iter()
|
.iter()
|
||||||
.filter_map(symbol_filter)
|
.filter_map(symbol_filter)
|
||||||
.collect::<Vec<CString>>();
|
.collect::<Vec<CString>>();
|
||||||
timeline.record("whitelist");
|
let _timer = cgcx.profile_activity(ProfileCategory::Codegen,
|
||||||
|
"generate_symbol_white_list_for_thinlto");
|
||||||
info!("{} symbols to preserve in this crate", symbol_white_list.len());
|
info!("{} symbols to preserve in this crate", symbol_white_list.len());
|
||||||
|
|
||||||
// If we're performing LTO for the entire crate graph, then for each of our
|
// If we're performing LTO for the entire crate graph, then for each of our
|
||||||
|
@ -97,6 +97,8 @@ fn prepare_lto(cgcx: &CodegenContext<LlvmCodegenBackend>,
|
||||||
}
|
}
|
||||||
|
|
||||||
for &(cnum, ref path) in cgcx.each_linked_rlib_for_lto.iter() {
|
for &(cnum, ref path) in cgcx.each_linked_rlib_for_lto.iter() {
|
||||||
|
let _timer = cgcx.profile_activity(ProfileCategory::Codegen,
|
||||||
|
format!("load: {}", path.display()));
|
||||||
let exported_symbols = cgcx.exported_symbols
|
let exported_symbols = cgcx.exported_symbols
|
||||||
.as_ref().expect("needs exported symbols for LTO");
|
.as_ref().expect("needs exported symbols for LTO");
|
||||||
symbol_white_list.extend(
|
symbol_white_list.extend(
|
||||||
|
@ -121,7 +123,6 @@ fn prepare_lto(cgcx: &CodegenContext<LlvmCodegenBackend>,
|
||||||
let bc = SerializedModule::FromRlib(bc);
|
let bc = SerializedModule::FromRlib(bc);
|
||||||
upstream_modules.push((bc, CString::new(id).unwrap()));
|
upstream_modules.push((bc, CString::new(id).unwrap()));
|
||||||
}
|
}
|
||||||
timeline.record(&format!("load: {}", path.display()));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -132,12 +133,11 @@ fn prepare_lto(cgcx: &CodegenContext<LlvmCodegenBackend>,
|
||||||
/// for further optimization.
|
/// for further optimization.
|
||||||
pub(crate) fn run_fat(cgcx: &CodegenContext<LlvmCodegenBackend>,
|
pub(crate) fn run_fat(cgcx: &CodegenContext<LlvmCodegenBackend>,
|
||||||
modules: Vec<FatLTOInput<LlvmCodegenBackend>>,
|
modules: Vec<FatLTOInput<LlvmCodegenBackend>>,
|
||||||
cached_modules: Vec<(SerializedModule<ModuleBuffer>, WorkProduct)>,
|
cached_modules: Vec<(SerializedModule<ModuleBuffer>, WorkProduct)>)
|
||||||
timeline: &mut Timeline)
|
|
||||||
-> Result<LtoModuleCodegen<LlvmCodegenBackend>, FatalError>
|
-> Result<LtoModuleCodegen<LlvmCodegenBackend>, FatalError>
|
||||||
{
|
{
|
||||||
let diag_handler = cgcx.create_diag_handler();
|
let diag_handler = cgcx.create_diag_handler();
|
||||||
let (symbol_white_list, upstream_modules) = prepare_lto(cgcx, timeline, &diag_handler)?;
|
let (symbol_white_list, upstream_modules) = prepare_lto(cgcx, &diag_handler)?;
|
||||||
let symbol_white_list = symbol_white_list.iter()
|
let symbol_white_list = symbol_white_list.iter()
|
||||||
.map(|c| c.as_ptr())
|
.map(|c| c.as_ptr())
|
||||||
.collect::<Vec<_>>();
|
.collect::<Vec<_>>();
|
||||||
|
@ -148,7 +148,6 @@ pub(crate) fn run_fat(cgcx: &CodegenContext<LlvmCodegenBackend>,
|
||||||
cached_modules,
|
cached_modules,
|
||||||
upstream_modules,
|
upstream_modules,
|
||||||
&symbol_white_list,
|
&symbol_white_list,
|
||||||
timeline,
|
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -157,12 +156,11 @@ pub(crate) fn run_fat(cgcx: &CodegenContext<LlvmCodegenBackend>,
|
||||||
/// can simply be copied over from the incr. comp. cache.
|
/// can simply be copied over from the incr. comp. cache.
|
||||||
pub(crate) fn run_thin(cgcx: &CodegenContext<LlvmCodegenBackend>,
|
pub(crate) fn run_thin(cgcx: &CodegenContext<LlvmCodegenBackend>,
|
||||||
modules: Vec<(String, ThinBuffer)>,
|
modules: Vec<(String, ThinBuffer)>,
|
||||||
cached_modules: Vec<(SerializedModule<ModuleBuffer>, WorkProduct)>,
|
cached_modules: Vec<(SerializedModule<ModuleBuffer>, WorkProduct)>)
|
||||||
timeline: &mut Timeline)
|
|
||||||
-> Result<(Vec<LtoModuleCodegen<LlvmCodegenBackend>>, Vec<WorkProduct>), FatalError>
|
-> Result<(Vec<LtoModuleCodegen<LlvmCodegenBackend>>, Vec<WorkProduct>), FatalError>
|
||||||
{
|
{
|
||||||
let diag_handler = cgcx.create_diag_handler();
|
let diag_handler = cgcx.create_diag_handler();
|
||||||
let (symbol_white_list, upstream_modules) = prepare_lto(cgcx, timeline, &diag_handler)?;
|
let (symbol_white_list, upstream_modules) = prepare_lto(cgcx, &diag_handler)?;
|
||||||
let symbol_white_list = symbol_white_list.iter()
|
let symbol_white_list = symbol_white_list.iter()
|
||||||
.map(|c| c.as_ptr())
|
.map(|c| c.as_ptr())
|
||||||
.collect::<Vec<_>>();
|
.collect::<Vec<_>>();
|
||||||
|
@ -175,8 +173,7 @@ pub(crate) fn run_thin(cgcx: &CodegenContext<LlvmCodegenBackend>,
|
||||||
modules,
|
modules,
|
||||||
upstream_modules,
|
upstream_modules,
|
||||||
cached_modules,
|
cached_modules,
|
||||||
&symbol_white_list,
|
&symbol_white_list)
|
||||||
timeline)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn prepare_thin(
|
pub(crate) fn prepare_thin(
|
||||||
|
@ -192,8 +189,7 @@ fn fat_lto(cgcx: &CodegenContext<LlvmCodegenBackend>,
|
||||||
mut modules: Vec<FatLTOInput<LlvmCodegenBackend>>,
|
mut modules: Vec<FatLTOInput<LlvmCodegenBackend>>,
|
||||||
cached_modules: Vec<(SerializedModule<ModuleBuffer>, WorkProduct)>,
|
cached_modules: Vec<(SerializedModule<ModuleBuffer>, WorkProduct)>,
|
||||||
mut serialized_modules: Vec<(SerializedModule<ModuleBuffer>, CString)>,
|
mut serialized_modules: Vec<(SerializedModule<ModuleBuffer>, CString)>,
|
||||||
symbol_white_list: &[*const libc::c_char],
|
symbol_white_list: &[*const libc::c_char])
|
||||||
timeline: &mut Timeline)
|
|
||||||
-> Result<LtoModuleCodegen<LlvmCodegenBackend>, FatalError>
|
-> Result<LtoModuleCodegen<LlvmCodegenBackend>, FatalError>
|
||||||
{
|
{
|
||||||
info!("going for a fat lto");
|
info!("going for a fat lto");
|
||||||
|
@ -303,7 +299,6 @@ fn fat_lto(cgcx: &CodegenContext<LlvmCodegenBackend>,
|
||||||
write::llvm_err(&diag_handler, &msg)
|
write::llvm_err(&diag_handler, &msg)
|
||||||
})
|
})
|
||||||
})?;
|
})?;
|
||||||
timeline.record(&format!("link {:?}", name));
|
|
||||||
serialized_bitcode.push(bc_decoded);
|
serialized_bitcode.push(bc_decoded);
|
||||||
}
|
}
|
||||||
drop(linker);
|
drop(linker);
|
||||||
|
@ -325,7 +320,6 @@ fn fat_lto(cgcx: &CodegenContext<LlvmCodegenBackend>,
|
||||||
}
|
}
|
||||||
save_temp_bitcode(&cgcx, &module, "lto.after-nounwind");
|
save_temp_bitcode(&cgcx, &module, "lto.after-nounwind");
|
||||||
}
|
}
|
||||||
timeline.record("passes");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(LtoModuleCodegen::Fat {
|
Ok(LtoModuleCodegen::Fat {
|
||||||
|
@ -395,8 +389,7 @@ fn thin_lto(cgcx: &CodegenContext<LlvmCodegenBackend>,
|
||||||
modules: Vec<(String, ThinBuffer)>,
|
modules: Vec<(String, ThinBuffer)>,
|
||||||
serialized_modules: Vec<(SerializedModule<ModuleBuffer>, CString)>,
|
serialized_modules: Vec<(SerializedModule<ModuleBuffer>, CString)>,
|
||||||
cached_modules: Vec<(SerializedModule<ModuleBuffer>, WorkProduct)>,
|
cached_modules: Vec<(SerializedModule<ModuleBuffer>, WorkProduct)>,
|
||||||
symbol_white_list: &[*const libc::c_char],
|
symbol_white_list: &[*const libc::c_char])
|
||||||
timeline: &mut Timeline)
|
|
||||||
-> Result<(Vec<LtoModuleCodegen<LlvmCodegenBackend>>, Vec<WorkProduct>), FatalError>
|
-> Result<(Vec<LtoModuleCodegen<LlvmCodegenBackend>>, Vec<WorkProduct>), FatalError>
|
||||||
{
|
{
|
||||||
unsafe {
|
unsafe {
|
||||||
|
@ -422,7 +415,6 @@ fn thin_lto(cgcx: &CodegenContext<LlvmCodegenBackend>,
|
||||||
});
|
});
|
||||||
thin_buffers.push(buffer);
|
thin_buffers.push(buffer);
|
||||||
module_names.push(cname);
|
module_names.push(cname);
|
||||||
timeline.record(&name);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// FIXME: All upstream crates are deserialized internally in the
|
// FIXME: All upstream crates are deserialized internally in the
|
||||||
|
@ -475,7 +467,6 @@ fn thin_lto(cgcx: &CodegenContext<LlvmCodegenBackend>,
|
||||||
})?;
|
})?;
|
||||||
|
|
||||||
info!("thin LTO data created");
|
info!("thin LTO data created");
|
||||||
timeline.record("data");
|
|
||||||
|
|
||||||
let import_map = if cgcx.incr_comp_session_dir.is_some() {
|
let import_map = if cgcx.incr_comp_session_dir.is_some() {
|
||||||
ThinLTOImports::from_thin_lto_data(data)
|
ThinLTOImports::from_thin_lto_data(data)
|
||||||
|
@ -486,7 +477,6 @@ fn thin_lto(cgcx: &CodegenContext<LlvmCodegenBackend>,
|
||||||
ThinLTOImports::default()
|
ThinLTOImports::default()
|
||||||
};
|
};
|
||||||
info!("thin LTO import map loaded");
|
info!("thin LTO import map loaded");
|
||||||
timeline.record("import-map-loaded");
|
|
||||||
|
|
||||||
let data = ThinData(data);
|
let data = ThinData(data);
|
||||||
|
|
||||||
|
@ -691,7 +681,6 @@ impl Drop for ThinBuffer {
|
||||||
pub unsafe fn optimize_thin_module(
|
pub unsafe fn optimize_thin_module(
|
||||||
thin_module: &mut ThinModule<LlvmCodegenBackend>,
|
thin_module: &mut ThinModule<LlvmCodegenBackend>,
|
||||||
cgcx: &CodegenContext<LlvmCodegenBackend>,
|
cgcx: &CodegenContext<LlvmCodegenBackend>,
|
||||||
timeline: &mut Timeline
|
|
||||||
) -> Result<ModuleCodegen<ModuleLlvm>, FatalError> {
|
) -> Result<ModuleCodegen<ModuleLlvm>, FatalError> {
|
||||||
let diag_handler = cgcx.create_diag_handler();
|
let diag_handler = cgcx.create_diag_handler();
|
||||||
let tm = (cgcx.tm_factory.0)().map_err(|e| {
|
let tm = (cgcx.tm_factory.0)().map_err(|e| {
|
||||||
|
@ -738,9 +727,10 @@ pub unsafe fn optimize_thin_module(
|
||||||
// Like with "fat" LTO, get some better optimizations if landing pads
|
// Like with "fat" LTO, get some better optimizations if landing pads
|
||||||
// are disabled by removing all landing pads.
|
// are disabled by removing all landing pads.
|
||||||
if cgcx.no_landing_pads {
|
if cgcx.no_landing_pads {
|
||||||
|
let _timer = cgcx.profile_activity(ProfileCategory::Codegen,
|
||||||
|
"LLVM_remove_landing_pads");
|
||||||
llvm::LLVMRustMarkAllFunctionsNounwind(llmod);
|
llvm::LLVMRustMarkAllFunctionsNounwind(llmod);
|
||||||
save_temp_bitcode(&cgcx, &module, "thin-lto-after-nounwind");
|
save_temp_bitcode(&cgcx, &module, "thin-lto-after-nounwind");
|
||||||
timeline.record("nounwind");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Up next comes the per-module local analyses that we do for Thin LTO.
|
// Up next comes the per-module local analyses that we do for Thin LTO.
|
||||||
|
@ -756,25 +746,21 @@ pub unsafe fn optimize_thin_module(
|
||||||
return Err(write::llvm_err(&diag_handler, msg))
|
return Err(write::llvm_err(&diag_handler, msg))
|
||||||
}
|
}
|
||||||
save_temp_bitcode(cgcx, &module, "thin-lto-after-rename");
|
save_temp_bitcode(cgcx, &module, "thin-lto-after-rename");
|
||||||
timeline.record("rename");
|
|
||||||
if !llvm::LLVMRustPrepareThinLTOResolveWeak(thin_module.shared.data.0, llmod) {
|
if !llvm::LLVMRustPrepareThinLTOResolveWeak(thin_module.shared.data.0, llmod) {
|
||||||
let msg = "failed to prepare thin LTO module";
|
let msg = "failed to prepare thin LTO module";
|
||||||
return Err(write::llvm_err(&diag_handler, msg))
|
return Err(write::llvm_err(&diag_handler, msg))
|
||||||
}
|
}
|
||||||
save_temp_bitcode(cgcx, &module, "thin-lto-after-resolve");
|
save_temp_bitcode(cgcx, &module, "thin-lto-after-resolve");
|
||||||
timeline.record("resolve");
|
|
||||||
if !llvm::LLVMRustPrepareThinLTOInternalize(thin_module.shared.data.0, llmod) {
|
if !llvm::LLVMRustPrepareThinLTOInternalize(thin_module.shared.data.0, llmod) {
|
||||||
let msg = "failed to prepare thin LTO module";
|
let msg = "failed to prepare thin LTO module";
|
||||||
return Err(write::llvm_err(&diag_handler, msg))
|
return Err(write::llvm_err(&diag_handler, msg))
|
||||||
}
|
}
|
||||||
save_temp_bitcode(cgcx, &module, "thin-lto-after-internalize");
|
save_temp_bitcode(cgcx, &module, "thin-lto-after-internalize");
|
||||||
timeline.record("internalize");
|
|
||||||
if !llvm::LLVMRustPrepareThinLTOImport(thin_module.shared.data.0, llmod) {
|
if !llvm::LLVMRustPrepareThinLTOImport(thin_module.shared.data.0, llmod) {
|
||||||
let msg = "failed to prepare thin LTO module";
|
let msg = "failed to prepare thin LTO module";
|
||||||
return Err(write::llvm_err(&diag_handler, msg))
|
return Err(write::llvm_err(&diag_handler, msg))
|
||||||
}
|
}
|
||||||
save_temp_bitcode(cgcx, &module, "thin-lto-after-import");
|
save_temp_bitcode(cgcx, &module, "thin-lto-after-import");
|
||||||
timeline.record("import");
|
|
||||||
|
|
||||||
// Ok now this is a bit unfortunate. This is also something you won't
|
// Ok now this is a bit unfortunate. This is also something you won't
|
||||||
// find upstream in LLVM's ThinLTO passes! This is a hack for now to
|
// find upstream in LLVM's ThinLTO passes! This is a hack for now to
|
||||||
|
@ -807,7 +793,6 @@ pub unsafe fn optimize_thin_module(
|
||||||
// fixed in LLVM.
|
// fixed in LLVM.
|
||||||
llvm::LLVMRustThinLTOPatchDICompileUnit(llmod, cu1);
|
llvm::LLVMRustThinLTOPatchDICompileUnit(llmod, cu1);
|
||||||
save_temp_bitcode(cgcx, &module, "thin-lto-after-patch");
|
save_temp_bitcode(cgcx, &module, "thin-lto-after-patch");
|
||||||
timeline.record("patch");
|
|
||||||
|
|
||||||
// Alright now that we've done everything related to the ThinLTO
|
// Alright now that we've done everything related to the ThinLTO
|
||||||
// analysis it's time to run some optimizations! Here we use the same
|
// analysis it's time to run some optimizations! Here we use the same
|
||||||
|
@ -818,7 +803,6 @@ pub unsafe fn optimize_thin_module(
|
||||||
let config = cgcx.config(module.kind);
|
let config = cgcx.config(module.kind);
|
||||||
run_pass_manager(cgcx, &module, config, true);
|
run_pass_manager(cgcx, &module, config, true);
|
||||||
save_temp_bitcode(cgcx, &module, "thin-lto-after-pm");
|
save_temp_bitcode(cgcx, &module, "thin-lto-after-pm");
|
||||||
timeline.record("thin-done");
|
|
||||||
}
|
}
|
||||||
Ok(module)
|
Ok(module)
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,7 +3,6 @@ use crate::back::bytecode::{self, RLIB_BYTECODE_EXTENSION};
|
||||||
use crate::back::lto::ThinBuffer;
|
use crate::back::lto::ThinBuffer;
|
||||||
use crate::base;
|
use crate::base;
|
||||||
use crate::consts;
|
use crate::consts;
|
||||||
use crate::time_graph::Timeline;
|
|
||||||
use crate::llvm::{self, DiagnosticInfo, PassManager, SMDiagnostic};
|
use crate::llvm::{self, DiagnosticInfo, PassManager, SMDiagnostic};
|
||||||
use crate::llvm_util;
|
use crate::llvm_util;
|
||||||
use crate::ModuleLlvm;
|
use crate::ModuleLlvm;
|
||||||
|
@ -19,6 +18,7 @@ use rustc::session::Session;
|
||||||
use rustc::ty::TyCtxt;
|
use rustc::ty::TyCtxt;
|
||||||
use rustc_codegen_ssa::{ModuleCodegen, CompiledModule};
|
use rustc_codegen_ssa::{ModuleCodegen, CompiledModule};
|
||||||
use rustc::util::common::time_ext;
|
use rustc::util::common::time_ext;
|
||||||
|
use rustc::util::profiling::ProfileCategory;
|
||||||
use rustc_fs_util::{path_to_c_string, link_or_copy};
|
use rustc_fs_util::{path_to_c_string, link_or_copy};
|
||||||
use rustc_data_structures::small_c_str::SmallCStr;
|
use rustc_data_structures::small_c_str::SmallCStr;
|
||||||
use errors::{Handler, FatalError};
|
use errors::{Handler, FatalError};
|
||||||
|
@ -305,8 +305,7 @@ unsafe extern "C" fn diagnostic_handler(info: &DiagnosticInfo, user: *mut c_void
|
||||||
pub(crate) unsafe fn optimize(cgcx: &CodegenContext<LlvmCodegenBackend>,
|
pub(crate) unsafe fn optimize(cgcx: &CodegenContext<LlvmCodegenBackend>,
|
||||||
diag_handler: &Handler,
|
diag_handler: &Handler,
|
||||||
module: &ModuleCodegen<ModuleLlvm>,
|
module: &ModuleCodegen<ModuleLlvm>,
|
||||||
config: &ModuleConfig,
|
config: &ModuleConfig)
|
||||||
timeline: &mut Timeline)
|
|
||||||
-> Result<(), FatalError>
|
-> Result<(), FatalError>
|
||||||
{
|
{
|
||||||
let llmod = module.module_llvm.llmod();
|
let llmod = module.module_llvm.llmod();
|
||||||
|
@ -415,19 +414,24 @@ pub(crate) unsafe fn optimize(cgcx: &CodegenContext<LlvmCodegenBackend>,
|
||||||
diag_handler.abort_if_errors();
|
diag_handler.abort_if_errors();
|
||||||
|
|
||||||
// Finally, run the actual optimization passes
|
// Finally, run the actual optimization passes
|
||||||
|
{
|
||||||
|
let _timer = cgcx.profile_activity(ProfileCategory::Codegen, "LLVM_function_passes");
|
||||||
time_ext(config.time_passes,
|
time_ext(config.time_passes,
|
||||||
None,
|
None,
|
||||||
&format!("llvm function passes [{}]", module_name.unwrap()),
|
&format!("llvm function passes [{}]", module_name.unwrap()),
|
||||||
|| {
|
|| {
|
||||||
llvm::LLVMRustRunFunctionPassManager(fpm, llmod)
|
llvm::LLVMRustRunFunctionPassManager(fpm, llmod)
|
||||||
});
|
});
|
||||||
timeline.record("fpm");
|
}
|
||||||
|
{
|
||||||
|
let _timer = cgcx.profile_activity(ProfileCategory::Codegen, "LLVM_module_passes");
|
||||||
time_ext(config.time_passes,
|
time_ext(config.time_passes,
|
||||||
None,
|
None,
|
||||||
&format!("llvm module passes [{}]", module_name.unwrap()),
|
&format!("llvm module passes [{}]", module_name.unwrap()),
|
||||||
|| {
|
|| {
|
||||||
llvm::LLVMRunPassManager(mpm, llmod)
|
llvm::LLVMRunPassManager(mpm, llmod)
|
||||||
});
|
});
|
||||||
|
}
|
||||||
|
|
||||||
// Deallocate managers that we're now done with
|
// Deallocate managers that we're now done with
|
||||||
llvm::LLVMDisposePassManager(fpm);
|
llvm::LLVMDisposePassManager(fpm);
|
||||||
|
@ -439,11 +443,10 @@ pub(crate) unsafe fn optimize(cgcx: &CodegenContext<LlvmCodegenBackend>,
|
||||||
pub(crate) unsafe fn codegen(cgcx: &CodegenContext<LlvmCodegenBackend>,
|
pub(crate) unsafe fn codegen(cgcx: &CodegenContext<LlvmCodegenBackend>,
|
||||||
diag_handler: &Handler,
|
diag_handler: &Handler,
|
||||||
module: ModuleCodegen<ModuleLlvm>,
|
module: ModuleCodegen<ModuleLlvm>,
|
||||||
config: &ModuleConfig,
|
config: &ModuleConfig)
|
||||||
timeline: &mut Timeline)
|
|
||||||
-> Result<CompiledModule, FatalError>
|
-> Result<CompiledModule, FatalError>
|
||||||
{
|
{
|
||||||
timeline.record("codegen");
|
let _timer = cgcx.profile_activity(ProfileCategory::Codegen, "codegen");
|
||||||
{
|
{
|
||||||
let llmod = module.module_llvm.llmod();
|
let llmod = module.module_llvm.llmod();
|
||||||
let llcx = &*module.module_llvm.llcx;
|
let llcx = &*module.module_llvm.llcx;
|
||||||
|
@ -494,29 +497,30 @@ pub(crate) unsafe fn codegen(cgcx: &CodegenContext<LlvmCodegenBackend>,
|
||||||
|
|
||||||
|
|
||||||
if write_bc || config.emit_bc_compressed || config.embed_bitcode {
|
if write_bc || config.emit_bc_compressed || config.embed_bitcode {
|
||||||
|
let _timer = cgcx.profile_activity(ProfileCategory::Codegen, "LLVM_make_bitcode");
|
||||||
let thin = ThinBuffer::new(llmod);
|
let thin = ThinBuffer::new(llmod);
|
||||||
let data = thin.data();
|
let data = thin.data();
|
||||||
timeline.record("make-bc");
|
|
||||||
|
|
||||||
if write_bc {
|
if write_bc {
|
||||||
|
let _timer = cgcx.profile_activity(ProfileCategory::Codegen, "LLVM_emit_bitcode");
|
||||||
if let Err(e) = fs::write(&bc_out, data) {
|
if let Err(e) = fs::write(&bc_out, data) {
|
||||||
diag_handler.err(&format!("failed to write bytecode: {}", e));
|
diag_handler.err(&format!("failed to write bytecode: {}", e));
|
||||||
}
|
}
|
||||||
timeline.record("write-bc");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if config.embed_bitcode {
|
if config.embed_bitcode {
|
||||||
|
let _timer = cgcx.profile_activity(ProfileCategory::Codegen, "LLVM_embed_bitcode");
|
||||||
embed_bitcode(cgcx, llcx, llmod, Some(data));
|
embed_bitcode(cgcx, llcx, llmod, Some(data));
|
||||||
timeline.record("embed-bc");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if config.emit_bc_compressed {
|
if config.emit_bc_compressed {
|
||||||
|
let _timer = cgcx.profile_activity(ProfileCategory::Codegen,
|
||||||
|
"LLVM_compress_bitcode");
|
||||||
let dst = bc_out.with_extension(RLIB_BYTECODE_EXTENSION);
|
let dst = bc_out.with_extension(RLIB_BYTECODE_EXTENSION);
|
||||||
let data = bytecode::encode(&module.name, data);
|
let data = bytecode::encode(&module.name, data);
|
||||||
if let Err(e) = fs::write(&dst, data) {
|
if let Err(e) = fs::write(&dst, data) {
|
||||||
diag_handler.err(&format!("failed to write bytecode: {}", e));
|
diag_handler.err(&format!("failed to write bytecode: {}", e));
|
||||||
}
|
}
|
||||||
timeline.record("compress-bc");
|
|
||||||
}
|
}
|
||||||
} else if config.embed_bitcode_marker {
|
} else if config.embed_bitcode_marker {
|
||||||
embed_bitcode(cgcx, llcx, llmod, None);
|
embed_bitcode(cgcx, llcx, llmod, None);
|
||||||
|
@ -525,6 +529,7 @@ pub(crate) unsafe fn codegen(cgcx: &CodegenContext<LlvmCodegenBackend>,
|
||||||
time_ext(config.time_passes, None, &format!("codegen passes [{}]", module_name.unwrap()),
|
time_ext(config.time_passes, None, &format!("codegen passes [{}]", module_name.unwrap()),
|
||||||
|| -> Result<(), FatalError> {
|
|| -> Result<(), FatalError> {
|
||||||
if config.emit_ir {
|
if config.emit_ir {
|
||||||
|
let _timer = cgcx.profile_activity(ProfileCategory::Codegen, "LLVM_emit_ir");
|
||||||
let out = cgcx.output_filenames.temp_path(OutputType::LlvmAssembly, module_name);
|
let out = cgcx.output_filenames.temp_path(OutputType::LlvmAssembly, module_name);
|
||||||
let out = path_to_c_string(&out);
|
let out = path_to_c_string(&out);
|
||||||
|
|
||||||
|
@ -563,10 +568,10 @@ pub(crate) unsafe fn codegen(cgcx: &CodegenContext<LlvmCodegenBackend>,
|
||||||
llvm::LLVMRustPrintModule(cpm, llmod, out.as_ptr(), demangle_callback);
|
llvm::LLVMRustPrintModule(cpm, llmod, out.as_ptr(), demangle_callback);
|
||||||
llvm::LLVMDisposePassManager(cpm);
|
llvm::LLVMDisposePassManager(cpm);
|
||||||
});
|
});
|
||||||
timeline.record("ir");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if config.emit_asm || asm_to_obj {
|
if config.emit_asm || asm_to_obj {
|
||||||
|
let _timer = cgcx.profile_activity(ProfileCategory::Codegen, "LLVM_emit_asm");
|
||||||
let path = cgcx.output_filenames.temp_path(OutputType::Assembly, module_name);
|
let path = cgcx.output_filenames.temp_path(OutputType::Assembly, module_name);
|
||||||
|
|
||||||
// We can't use the same module for asm and binary output, because that triggers
|
// We can't use the same module for asm and binary output, because that triggers
|
||||||
|
@ -581,19 +586,18 @@ pub(crate) unsafe fn codegen(cgcx: &CodegenContext<LlvmCodegenBackend>,
|
||||||
write_output_file(diag_handler, tm, cpm, llmod, &path,
|
write_output_file(diag_handler, tm, cpm, llmod, &path,
|
||||||
llvm::FileType::AssemblyFile)
|
llvm::FileType::AssemblyFile)
|
||||||
})?;
|
})?;
|
||||||
timeline.record("asm");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if write_obj {
|
if write_obj {
|
||||||
|
let _timer = cgcx.profile_activity(ProfileCategory::Codegen, "LLVM_emit_obj");
|
||||||
with_codegen(tm, llmod, config.no_builtins, |cpm| {
|
with_codegen(tm, llmod, config.no_builtins, |cpm| {
|
||||||
write_output_file(diag_handler, tm, cpm, llmod, &obj_out,
|
write_output_file(diag_handler, tm, cpm, llmod, &obj_out,
|
||||||
llvm::FileType::ObjectFile)
|
llvm::FileType::ObjectFile)
|
||||||
})?;
|
})?;
|
||||||
timeline.record("obj");
|
|
||||||
} else if asm_to_obj {
|
} else if asm_to_obj {
|
||||||
|
let _timer = cgcx.profile_activity(ProfileCategory::Codegen, "LLVM_asm_to_obj");
|
||||||
let assembly = cgcx.output_filenames.temp_path(OutputType::Assembly, module_name);
|
let assembly = cgcx.output_filenames.temp_path(OutputType::Assembly, module_name);
|
||||||
run_assembler(cgcx, diag_handler, &assembly, &obj_out);
|
run_assembler(cgcx, diag_handler, &assembly, &obj_out);
|
||||||
timeline.record("asm_to_obj");
|
|
||||||
|
|
||||||
if !config.emit_asm && !cgcx.save_temps {
|
if !config.emit_asm && !cgcx.save_temps {
|
||||||
drop(fs::remove_file(&assembly));
|
drop(fs::remove_file(&assembly));
|
||||||
|
|
|
@ -53,7 +53,6 @@ use rustc_codegen_ssa::back::lto::{SerializedModule, LtoModuleCodegen, ThinModul
|
||||||
use rustc_codegen_ssa::CompiledModule;
|
use rustc_codegen_ssa::CompiledModule;
|
||||||
use errors::{FatalError, Handler};
|
use errors::{FatalError, Handler};
|
||||||
use rustc::dep_graph::WorkProduct;
|
use rustc::dep_graph::WorkProduct;
|
||||||
use rustc::util::time_graph::Timeline;
|
|
||||||
use syntax_pos::symbol::InternedString;
|
use syntax_pos::symbol::InternedString;
|
||||||
use rustc::mir::mono::Stats;
|
use rustc::mir::mono::Stats;
|
||||||
pub use llvm_util::target_features;
|
pub use llvm_util::target_features;
|
||||||
|
@ -66,7 +65,6 @@ use rustc::middle::cstore::{EncodedMetadata, MetadataLoader};
|
||||||
use rustc::session::Session;
|
use rustc::session::Session;
|
||||||
use rustc::session::config::{OutputFilenames, OutputType, PrintRequest, OptLevel};
|
use rustc::session::config::{OutputFilenames, OutputType, PrintRequest, OptLevel};
|
||||||
use rustc::ty::{self, TyCtxt};
|
use rustc::ty::{self, TyCtxt};
|
||||||
use rustc::util::time_graph;
|
|
||||||
use rustc::util::profiling::ProfileCategory;
|
use rustc::util::profiling::ProfileCategory;
|
||||||
use rustc::util::common::ErrorReported;
|
use rustc::util::common::ErrorReported;
|
||||||
use rustc_mir::monomorphize;
|
use rustc_mir::monomorphize;
|
||||||
|
@ -167,42 +165,37 @@ impl WriteBackendMethods for LlvmCodegenBackend {
|
||||||
cgcx: &CodegenContext<Self>,
|
cgcx: &CodegenContext<Self>,
|
||||||
modules: Vec<FatLTOInput<Self>>,
|
modules: Vec<FatLTOInput<Self>>,
|
||||||
cached_modules: Vec<(SerializedModule<Self::ModuleBuffer>, WorkProduct)>,
|
cached_modules: Vec<(SerializedModule<Self::ModuleBuffer>, WorkProduct)>,
|
||||||
timeline: &mut Timeline
|
|
||||||
) -> Result<LtoModuleCodegen<Self>, FatalError> {
|
) -> Result<LtoModuleCodegen<Self>, FatalError> {
|
||||||
back::lto::run_fat(cgcx, modules, cached_modules, timeline)
|
back::lto::run_fat(cgcx, modules, cached_modules)
|
||||||
}
|
}
|
||||||
fn run_thin_lto(
|
fn run_thin_lto(
|
||||||
cgcx: &CodegenContext<Self>,
|
cgcx: &CodegenContext<Self>,
|
||||||
modules: Vec<(String, Self::ThinBuffer)>,
|
modules: Vec<(String, Self::ThinBuffer)>,
|
||||||
cached_modules: Vec<(SerializedModule<Self::ModuleBuffer>, WorkProduct)>,
|
cached_modules: Vec<(SerializedModule<Self::ModuleBuffer>, WorkProduct)>,
|
||||||
timeline: &mut Timeline
|
|
||||||
) -> Result<(Vec<LtoModuleCodegen<Self>>, Vec<WorkProduct>), FatalError> {
|
) -> Result<(Vec<LtoModuleCodegen<Self>>, Vec<WorkProduct>), FatalError> {
|
||||||
back::lto::run_thin(cgcx, modules, cached_modules, timeline)
|
back::lto::run_thin(cgcx, modules, cached_modules)
|
||||||
}
|
}
|
||||||
unsafe fn optimize(
|
unsafe fn optimize(
|
||||||
cgcx: &CodegenContext<Self>,
|
cgcx: &CodegenContext<Self>,
|
||||||
diag_handler: &Handler,
|
diag_handler: &Handler,
|
||||||
module: &ModuleCodegen<Self::Module>,
|
module: &ModuleCodegen<Self::Module>,
|
||||||
config: &ModuleConfig,
|
config: &ModuleConfig,
|
||||||
timeline: &mut Timeline
|
|
||||||
) -> Result<(), FatalError> {
|
) -> Result<(), FatalError> {
|
||||||
back::write::optimize(cgcx, diag_handler, module, config, timeline)
|
back::write::optimize(cgcx, diag_handler, module, config)
|
||||||
}
|
}
|
||||||
unsafe fn optimize_thin(
|
unsafe fn optimize_thin(
|
||||||
cgcx: &CodegenContext<Self>,
|
cgcx: &CodegenContext<Self>,
|
||||||
thin: &mut ThinModule<Self>,
|
thin: &mut ThinModule<Self>,
|
||||||
timeline: &mut Timeline
|
|
||||||
) -> Result<ModuleCodegen<Self::Module>, FatalError> {
|
) -> Result<ModuleCodegen<Self::Module>, FatalError> {
|
||||||
back::lto::optimize_thin_module(thin, cgcx, timeline)
|
back::lto::optimize_thin_module(thin, cgcx)
|
||||||
}
|
}
|
||||||
unsafe fn codegen(
|
unsafe fn codegen(
|
||||||
cgcx: &CodegenContext<Self>,
|
cgcx: &CodegenContext<Self>,
|
||||||
diag_handler: &Handler,
|
diag_handler: &Handler,
|
||||||
module: ModuleCodegen<Self::Module>,
|
module: ModuleCodegen<Self::Module>,
|
||||||
config: &ModuleConfig,
|
config: &ModuleConfig,
|
||||||
timeline: &mut Timeline
|
|
||||||
) -> Result<CompiledModule, FatalError> {
|
) -> Result<CompiledModule, FatalError> {
|
||||||
back::write::codegen(cgcx, diag_handler, module, config, timeline)
|
back::write::codegen(cgcx, diag_handler, module, config)
|
||||||
}
|
}
|
||||||
fn prepare_thin(
|
fn prepare_thin(
|
||||||
module: ModuleCodegen<Self::Module>
|
module: ModuleCodegen<Self::Module>
|
||||||
|
@ -336,12 +329,12 @@ impl CodegenBackend for LlvmCodegenBackend {
|
||||||
|
|
||||||
// Run the linker on any artifacts that resulted from the LLVM run.
|
// Run the linker on any artifacts that resulted from the LLVM run.
|
||||||
// This should produce either a finished executable or library.
|
// This should produce either a finished executable or library.
|
||||||
sess.profiler(|p| p.start_activity(ProfileCategory::Linking));
|
sess.profiler(|p| p.start_activity(ProfileCategory::Linking, "link_crate"));
|
||||||
time(sess, "linking", || {
|
time(sess, "linking", || {
|
||||||
back::link::link_binary(sess, &codegen_results,
|
back::link::link_binary(sess, &codegen_results,
|
||||||
outputs, &codegen_results.crate_name.as_str());
|
outputs, &codegen_results.crate_name.as_str());
|
||||||
});
|
});
|
||||||
sess.profiler(|p| p.end_activity(ProfileCategory::Linking));
|
sess.profiler(|p| p.end_activity(ProfileCategory::Linking, "link_crate"));
|
||||||
|
|
||||||
// Now that we won't touch anything in the incremental compilation directory
|
// Now that we won't touch anything in the incremental compilation directory
|
||||||
// any more, we can finalize it (which involves renaming it)
|
// any more, we can finalize it (which involves renaming it)
|
||||||
|
|
|
@ -2,7 +2,6 @@ use super::write::CodegenContext;
|
||||||
use crate::traits::*;
|
use crate::traits::*;
|
||||||
use crate::ModuleCodegen;
|
use crate::ModuleCodegen;
|
||||||
|
|
||||||
use rustc::util::time_graph::Timeline;
|
|
||||||
use rustc_errors::FatalError;
|
use rustc_errors::FatalError;
|
||||||
|
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
|
@ -67,7 +66,6 @@ impl<B: WriteBackendMethods> LtoModuleCodegen<B> {
|
||||||
pub unsafe fn optimize(
|
pub unsafe fn optimize(
|
||||||
&mut self,
|
&mut self,
|
||||||
cgcx: &CodegenContext<B>,
|
cgcx: &CodegenContext<B>,
|
||||||
timeline: &mut Timeline
|
|
||||||
) -> Result<ModuleCodegen<B::Module>, FatalError> {
|
) -> Result<ModuleCodegen<B::Module>, FatalError> {
|
||||||
match *self {
|
match *self {
|
||||||
LtoModuleCodegen::Fat { ref mut module, .. } => {
|
LtoModuleCodegen::Fat { ref mut module, .. } => {
|
||||||
|
@ -75,11 +73,10 @@ impl<B: WriteBackendMethods> LtoModuleCodegen<B> {
|
||||||
{
|
{
|
||||||
let config = cgcx.config(module.kind);
|
let config = cgcx.config(module.kind);
|
||||||
B::run_lto_pass_manager(cgcx, &module, config, false);
|
B::run_lto_pass_manager(cgcx, &module, config, false);
|
||||||
timeline.record("fat-done");
|
|
||||||
}
|
}
|
||||||
Ok(module)
|
Ok(module)
|
||||||
}
|
}
|
||||||
LtoModuleCodegen::Thin(ref mut thin) => B::optimize_thin(cgcx, thin, timeline),
|
LtoModuleCodegen::Thin(ref mut thin) => B::optimize_thin(cgcx, thin),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -15,11 +15,10 @@ use rustc::middle::cstore::EncodedMetadata;
|
||||||
use rustc::session::config::{self, OutputFilenames, OutputType, Passes, Sanitizer, Lto};
|
use rustc::session::config::{self, OutputFilenames, OutputType, Passes, Sanitizer, Lto};
|
||||||
use rustc::session::Session;
|
use rustc::session::Session;
|
||||||
use rustc::util::nodemap::FxHashMap;
|
use rustc::util::nodemap::FxHashMap;
|
||||||
use rustc::util::time_graph::{self, TimeGraph, Timeline};
|
|
||||||
use rustc::hir::def_id::{CrateNum, LOCAL_CRATE};
|
use rustc::hir::def_id::{CrateNum, LOCAL_CRATE};
|
||||||
use rustc::ty::TyCtxt;
|
use rustc::ty::TyCtxt;
|
||||||
use rustc::util::common::{time_depth, set_time_depth, print_time_passes_entry};
|
use rustc::util::common::{time_depth, set_time_depth, print_time_passes_entry};
|
||||||
use rustc::util::profiling::SelfProfiler;
|
use rustc::util::profiling::{ProfileCategory, SelfProfiler};
|
||||||
use rustc_fs_util::link_or_copy;
|
use rustc_fs_util::link_or_copy;
|
||||||
use rustc_data_structures::svh::Svh;
|
use rustc_data_structures::svh::Svh;
|
||||||
use rustc_errors::{Handler, Level, DiagnosticBuilder, FatalError, DiagnosticId};
|
use rustc_errors::{Handler, Level, DiagnosticBuilder, FatalError, DiagnosticId};
|
||||||
|
@ -33,6 +32,7 @@ use jobserver::{Client, Acquired};
|
||||||
use parking_lot::Mutex as PlMutex;
|
use parking_lot::Mutex as PlMutex;
|
||||||
|
|
||||||
use std::any::Any;
|
use std::any::Any;
|
||||||
|
use std::borrow::Cow;
|
||||||
use std::fs;
|
use std::fs;
|
||||||
use std::io;
|
use std::io;
|
||||||
use std::mem;
|
use std::mem;
|
||||||
|
@ -197,6 +197,40 @@ impl<B: WriteBackendMethods> Clone for TargetMachineFactory<B> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub struct ProfileGenericActivityTimer {
|
||||||
|
profiler: Option<Arc<PlMutex<SelfProfiler>>>,
|
||||||
|
category: ProfileCategory,
|
||||||
|
label: Cow<'static, str>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl ProfileGenericActivityTimer {
|
||||||
|
pub fn start(
|
||||||
|
profiler: Option<Arc<PlMutex<SelfProfiler>>>,
|
||||||
|
category: ProfileCategory,
|
||||||
|
label: Cow<'static, str>,
|
||||||
|
) -> ProfileGenericActivityTimer {
|
||||||
|
if let Some(profiler) = &profiler {
|
||||||
|
let mut p = profiler.lock();
|
||||||
|
p.start_activity(category, label.clone());
|
||||||
|
}
|
||||||
|
|
||||||
|
ProfileGenericActivityTimer {
|
||||||
|
profiler,
|
||||||
|
category,
|
||||||
|
label,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Drop for ProfileGenericActivityTimer {
|
||||||
|
fn drop(&mut self) {
|
||||||
|
if let Some(profiler) = &self.profiler {
|
||||||
|
let mut p = profiler.lock();
|
||||||
|
p.end_activity(self.category, self.label.clone());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// Additional resources used by optimize_and_codegen (not module specific)
|
/// Additional resources used by optimize_and_codegen (not module specific)
|
||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
pub struct CodegenContext<B: WriteBackendMethods> {
|
pub struct CodegenContext<B: WriteBackendMethods> {
|
||||||
|
@ -238,9 +272,6 @@ pub struct CodegenContext<B: WriteBackendMethods> {
|
||||||
pub cgu_reuse_tracker: CguReuseTracker,
|
pub cgu_reuse_tracker: CguReuseTracker,
|
||||||
// Channel back to the main control thread to send messages to
|
// Channel back to the main control thread to send messages to
|
||||||
pub coordinator_send: Sender<Box<dyn Any + Send>>,
|
pub coordinator_send: Sender<Box<dyn Any + Send>>,
|
||||||
// A reference to the TimeGraph so we can register timings. None means that
|
|
||||||
// measuring is disabled.
|
|
||||||
pub time_graph: Option<TimeGraph>,
|
|
||||||
// The assembler command if no_integrated_as option is enabled, None otherwise
|
// The assembler command if no_integrated_as option is enabled, None otherwise
|
||||||
pub assembler_cmd: Option<Arc<AssemblerCommand>>
|
pub assembler_cmd: Option<Arc<AssemblerCommand>>
|
||||||
}
|
}
|
||||||
|
@ -277,6 +308,14 @@ impl<B: WriteBackendMethods> CodegenContext<B> {
|
||||||
self.profiler_active(f)
|
self.profiler_active(f)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn profile_activity(
|
||||||
|
&self,
|
||||||
|
category: ProfileCategory,
|
||||||
|
label: impl Into<Cow<'static, str>>,
|
||||||
|
) -> ProfileGenericActivityTimer {
|
||||||
|
ProfileGenericActivityTimer::start(self.profiler.clone(), category, label.into())
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn generate_lto_work<B: ExtraBackendMethods>(
|
fn generate_lto_work<B: ExtraBackendMethods>(
|
||||||
|
@ -285,11 +324,7 @@ fn generate_lto_work<B: ExtraBackendMethods>(
|
||||||
needs_thin_lto: Vec<(String, B::ThinBuffer)>,
|
needs_thin_lto: Vec<(String, B::ThinBuffer)>,
|
||||||
import_only_modules: Vec<(SerializedModule<B::ModuleBuffer>, WorkProduct)>
|
import_only_modules: Vec<(SerializedModule<B::ModuleBuffer>, WorkProduct)>
|
||||||
) -> Vec<(WorkItem<B>, u64)> {
|
) -> Vec<(WorkItem<B>, u64)> {
|
||||||
let mut timeline = cgcx.time_graph.as_ref().map(|tg| {
|
cgcx.profile(|p| p.start_activity(ProfileCategory::Linking, "codegen_run_lto"));
|
||||||
tg.start(CODEGEN_WORKER_TIMELINE,
|
|
||||||
CODEGEN_WORK_PACKAGE_KIND,
|
|
||||||
"generate lto")
|
|
||||||
}).unwrap_or(Timeline::noop());
|
|
||||||
|
|
||||||
let (lto_modules, copy_jobs) = if !needs_fat_lto.is_empty() {
|
let (lto_modules, copy_jobs) = if !needs_fat_lto.is_empty() {
|
||||||
assert!(needs_thin_lto.is_empty());
|
assert!(needs_thin_lto.is_empty());
|
||||||
|
@ -297,17 +332,16 @@ fn generate_lto_work<B: ExtraBackendMethods>(
|
||||||
cgcx,
|
cgcx,
|
||||||
needs_fat_lto,
|
needs_fat_lto,
|
||||||
import_only_modules,
|
import_only_modules,
|
||||||
&mut timeline,
|
|
||||||
)
|
)
|
||||||
.unwrap_or_else(|e| e.raise());
|
.unwrap_or_else(|e| e.raise());
|
||||||
(vec![lto_module], vec![])
|
(vec![lto_module], vec![])
|
||||||
} else {
|
} else {
|
||||||
assert!(needs_fat_lto.is_empty());
|
assert!(needs_fat_lto.is_empty());
|
||||||
B::run_thin_lto(cgcx, needs_thin_lto, import_only_modules, &mut timeline)
|
B::run_thin_lto(cgcx, needs_thin_lto, import_only_modules)
|
||||||
.unwrap_or_else(|e| e.raise())
|
.unwrap_or_else(|e| e.raise())
|
||||||
};
|
};
|
||||||
|
|
||||||
lto_modules.into_iter().map(|module| {
|
let result = lto_modules.into_iter().map(|module| {
|
||||||
let cost = module.cost();
|
let cost = module.cost();
|
||||||
(WorkItem::LTO(module), cost)
|
(WorkItem::LTO(module), cost)
|
||||||
}).chain(copy_jobs.into_iter().map(|wp| {
|
}).chain(copy_jobs.into_iter().map(|wp| {
|
||||||
|
@ -315,7 +349,11 @@ fn generate_lto_work<B: ExtraBackendMethods>(
|
||||||
name: wp.cgu_name.clone(),
|
name: wp.cgu_name.clone(),
|
||||||
source: wp,
|
source: wp,
|
||||||
}), 0)
|
}), 0)
|
||||||
})).collect()
|
})).collect();
|
||||||
|
|
||||||
|
cgcx.profile(|p| p.end_activity(ProfileCategory::Linking, "codegen_run_lto"));
|
||||||
|
|
||||||
|
result
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct CompiledModules {
|
pub struct CompiledModules {
|
||||||
|
@ -345,7 +383,6 @@ fn need_pre_lto_bitcode_for_incr_comp(sess: &Session) -> bool {
|
||||||
pub fn start_async_codegen<B: ExtraBackendMethods>(
|
pub fn start_async_codegen<B: ExtraBackendMethods>(
|
||||||
backend: B,
|
backend: B,
|
||||||
tcx: TyCtxt<'_, '_, '_>,
|
tcx: TyCtxt<'_, '_, '_>,
|
||||||
time_graph: Option<TimeGraph>,
|
|
||||||
metadata: EncodedMetadata,
|
metadata: EncodedMetadata,
|
||||||
coordinator_receive: Receiver<Box<dyn Any + Send>>,
|
coordinator_receive: Receiver<Box<dyn Any + Send>>,
|
||||||
total_cgus: usize
|
total_cgus: usize
|
||||||
|
@ -469,7 +506,6 @@ pub fn start_async_codegen<B: ExtraBackendMethods>(
|
||||||
coordinator_receive,
|
coordinator_receive,
|
||||||
total_cgus,
|
total_cgus,
|
||||||
sess.jobserver.clone(),
|
sess.jobserver.clone(),
|
||||||
time_graph.clone(),
|
|
||||||
Arc::new(modules_config),
|
Arc::new(modules_config),
|
||||||
Arc::new(metadata_config),
|
Arc::new(metadata_config),
|
||||||
Arc::new(allocator_config));
|
Arc::new(allocator_config));
|
||||||
|
@ -483,7 +519,6 @@ pub fn start_async_codegen<B: ExtraBackendMethods>(
|
||||||
linker_info,
|
linker_info,
|
||||||
crate_info,
|
crate_info,
|
||||||
|
|
||||||
time_graph,
|
|
||||||
coordinator_send: tcx.tx_to_llvm_workers.lock().clone(),
|
coordinator_send: tcx.tx_to_llvm_workers.lock().clone(),
|
||||||
codegen_worker_receive,
|
codegen_worker_receive,
|
||||||
shared_emitter_main,
|
shared_emitter_main,
|
||||||
|
@ -728,19 +763,18 @@ pub enum FatLTOInput<B: WriteBackendMethods> {
|
||||||
fn execute_work_item<B: ExtraBackendMethods>(
|
fn execute_work_item<B: ExtraBackendMethods>(
|
||||||
cgcx: &CodegenContext<B>,
|
cgcx: &CodegenContext<B>,
|
||||||
work_item: WorkItem<B>,
|
work_item: WorkItem<B>,
|
||||||
timeline: &mut Timeline
|
|
||||||
) -> Result<WorkItemResult<B>, FatalError> {
|
) -> Result<WorkItemResult<B>, FatalError> {
|
||||||
let module_config = cgcx.config(work_item.module_kind());
|
let module_config = cgcx.config(work_item.module_kind());
|
||||||
|
|
||||||
match work_item {
|
match work_item {
|
||||||
WorkItem::Optimize(module) => {
|
WorkItem::Optimize(module) => {
|
||||||
execute_optimize_work_item(cgcx, module, module_config, timeline)
|
execute_optimize_work_item(cgcx, module, module_config)
|
||||||
}
|
}
|
||||||
WorkItem::CopyPostLtoArtifacts(module) => {
|
WorkItem::CopyPostLtoArtifacts(module) => {
|
||||||
execute_copy_from_cache_work_item(cgcx, module, module_config, timeline)
|
execute_copy_from_cache_work_item(cgcx, module, module_config)
|
||||||
}
|
}
|
||||||
WorkItem::LTO(module) => {
|
WorkItem::LTO(module) => {
|
||||||
execute_lto_work_item(cgcx, module, module_config, timeline)
|
execute_lto_work_item(cgcx, module, module_config)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -756,12 +790,11 @@ fn execute_optimize_work_item<B: ExtraBackendMethods>(
|
||||||
cgcx: &CodegenContext<B>,
|
cgcx: &CodegenContext<B>,
|
||||||
module: ModuleCodegen<B::Module>,
|
module: ModuleCodegen<B::Module>,
|
||||||
module_config: &ModuleConfig,
|
module_config: &ModuleConfig,
|
||||||
timeline: &mut Timeline
|
|
||||||
) -> Result<WorkItemResult<B>, FatalError> {
|
) -> Result<WorkItemResult<B>, FatalError> {
|
||||||
let diag_handler = cgcx.create_diag_handler();
|
let diag_handler = cgcx.create_diag_handler();
|
||||||
|
|
||||||
unsafe {
|
unsafe {
|
||||||
B::optimize(cgcx, &diag_handler, &module, module_config, timeline)?;
|
B::optimize(cgcx, &diag_handler, &module, module_config)?;
|
||||||
}
|
}
|
||||||
|
|
||||||
// After we've done the initial round of optimizations we need to
|
// After we've done the initial round of optimizations we need to
|
||||||
|
@ -818,7 +851,7 @@ fn execute_optimize_work_item<B: ExtraBackendMethods>(
|
||||||
Ok(match lto_type {
|
Ok(match lto_type {
|
||||||
ComputedLtoType::No => {
|
ComputedLtoType::No => {
|
||||||
let module = unsafe {
|
let module = unsafe {
|
||||||
B::codegen(cgcx, &diag_handler, module, module_config, timeline)?
|
B::codegen(cgcx, &diag_handler, module, module_config)?
|
||||||
};
|
};
|
||||||
WorkItemResult::Compiled(module)
|
WorkItemResult::Compiled(module)
|
||||||
}
|
}
|
||||||
|
@ -854,7 +887,6 @@ fn execute_copy_from_cache_work_item<B: ExtraBackendMethods>(
|
||||||
cgcx: &CodegenContext<B>,
|
cgcx: &CodegenContext<B>,
|
||||||
module: CachedModuleCodegen,
|
module: CachedModuleCodegen,
|
||||||
module_config: &ModuleConfig,
|
module_config: &ModuleConfig,
|
||||||
_: &mut Timeline
|
|
||||||
) -> Result<WorkItemResult<B>, FatalError> {
|
) -> Result<WorkItemResult<B>, FatalError> {
|
||||||
let incr_comp_session_dir = cgcx.incr_comp_session_dir
|
let incr_comp_session_dir = cgcx.incr_comp_session_dir
|
||||||
.as_ref()
|
.as_ref()
|
||||||
|
@ -916,13 +948,12 @@ fn execute_lto_work_item<B: ExtraBackendMethods>(
|
||||||
cgcx: &CodegenContext<B>,
|
cgcx: &CodegenContext<B>,
|
||||||
mut module: lto::LtoModuleCodegen<B>,
|
mut module: lto::LtoModuleCodegen<B>,
|
||||||
module_config: &ModuleConfig,
|
module_config: &ModuleConfig,
|
||||||
timeline: &mut Timeline
|
|
||||||
) -> Result<WorkItemResult<B>, FatalError> {
|
) -> Result<WorkItemResult<B>, FatalError> {
|
||||||
let diag_handler = cgcx.create_diag_handler();
|
let diag_handler = cgcx.create_diag_handler();
|
||||||
|
|
||||||
unsafe {
|
unsafe {
|
||||||
let module = module.optimize(cgcx, timeline)?;
|
let module = module.optimize(cgcx)?;
|
||||||
let module = B::codegen(cgcx, &diag_handler, module, module_config, timeline)?;
|
let module = B::codegen(cgcx, &diag_handler, module, module_config)?;
|
||||||
Ok(WorkItemResult::Compiled(module))
|
Ok(WorkItemResult::Compiled(module))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -977,7 +1008,6 @@ fn start_executing_work<B: ExtraBackendMethods>(
|
||||||
coordinator_receive: Receiver<Box<dyn Any + Send>>,
|
coordinator_receive: Receiver<Box<dyn Any + Send>>,
|
||||||
total_cgus: usize,
|
total_cgus: usize,
|
||||||
jobserver: Client,
|
jobserver: Client,
|
||||||
time_graph: Option<TimeGraph>,
|
|
||||||
modules_config: Arc<ModuleConfig>,
|
modules_config: Arc<ModuleConfig>,
|
||||||
metadata_config: Arc<ModuleConfig>,
|
metadata_config: Arc<ModuleConfig>,
|
||||||
allocator_config: Arc<ModuleConfig>
|
allocator_config: Arc<ModuleConfig>
|
||||||
|
@ -1065,7 +1095,6 @@ fn start_executing_work<B: ExtraBackendMethods>(
|
||||||
cgu_reuse_tracker: sess.cgu_reuse_tracker.clone(),
|
cgu_reuse_tracker: sess.cgu_reuse_tracker.clone(),
|
||||||
coordinator_send,
|
coordinator_send,
|
||||||
diag_emitter: shared_emitter.clone(),
|
diag_emitter: shared_emitter.clone(),
|
||||||
time_graph,
|
|
||||||
output_filenames: tcx.output_filenames(LOCAL_CRATE),
|
output_filenames: tcx.output_filenames(LOCAL_CRATE),
|
||||||
regular_module_config: modules_config,
|
regular_module_config: modules_config,
|
||||||
metadata_module_config: metadata_config,
|
metadata_module_config: metadata_config,
|
||||||
|
@ -1570,12 +1599,6 @@ fn start_executing_work<B: ExtraBackendMethods>(
|
||||||
}
|
}
|
||||||
|
|
||||||
pub const CODEGEN_WORKER_ID: usize = ::std::usize::MAX;
|
pub const CODEGEN_WORKER_ID: usize = ::std::usize::MAX;
|
||||||
pub const CODEGEN_WORKER_TIMELINE: time_graph::TimelineId =
|
|
||||||
time_graph::TimelineId(CODEGEN_WORKER_ID);
|
|
||||||
pub const CODEGEN_WORK_PACKAGE_KIND: time_graph::WorkPackageKind =
|
|
||||||
time_graph::WorkPackageKind(&["#DE9597", "#FED1D3", "#FDC5C7", "#B46668", "#88494B"]);
|
|
||||||
const LLVM_WORK_PACKAGE_KIND: time_graph::WorkPackageKind =
|
|
||||||
time_graph::WorkPackageKind(&["#7DB67A", "#C6EEC4", "#ACDAAA", "#579354", "#3E6F3C"]);
|
|
||||||
|
|
||||||
fn spawn_work<B: ExtraBackendMethods>(
|
fn spawn_work<B: ExtraBackendMethods>(
|
||||||
cgcx: CodegenContext<B>,
|
cgcx: CodegenContext<B>,
|
||||||
|
@ -1625,13 +1648,12 @@ fn spawn_work<B: ExtraBackendMethods>(
|
||||||
// as a diagnostic was already sent off to the main thread - just
|
// as a diagnostic was already sent off to the main thread - just
|
||||||
// surface that there was an error in this worker.
|
// surface that there was an error in this worker.
|
||||||
bomb.result = {
|
bomb.result = {
|
||||||
let timeline = cgcx.time_graph.as_ref().map(|tg| {
|
let label = work.name();
|
||||||
tg.start(time_graph::TimelineId(cgcx.worker),
|
cgcx.profile(|p| p.start_activity(ProfileCategory::Codegen, label.clone()));
|
||||||
LLVM_WORK_PACKAGE_KIND,
|
let result = execute_work_item(&cgcx, work).ok();
|
||||||
&work.name())
|
cgcx.profile(|p| p.end_activity(ProfileCategory::Codegen, label));
|
||||||
});
|
|
||||||
let mut timeline = timeline.unwrap_or(Timeline::noop());
|
result
|
||||||
execute_work_item(&cgcx, work, &mut timeline).ok()
|
|
||||||
};
|
};
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -1785,7 +1807,6 @@ pub struct OngoingCodegen<B: ExtraBackendMethods> {
|
||||||
pub windows_subsystem: Option<String>,
|
pub windows_subsystem: Option<String>,
|
||||||
pub linker_info: LinkerInfo,
|
pub linker_info: LinkerInfo,
|
||||||
pub crate_info: CrateInfo,
|
pub crate_info: CrateInfo,
|
||||||
pub time_graph: Option<TimeGraph>,
|
|
||||||
pub coordinator_send: Sender<Box<dyn Any + Send>>,
|
pub coordinator_send: Sender<Box<dyn Any + Send>>,
|
||||||
pub codegen_worker_receive: Receiver<Message<B>>,
|
pub codegen_worker_receive: Receiver<Message<B>>,
|
||||||
pub shared_emitter_main: SharedEmitterMain,
|
pub shared_emitter_main: SharedEmitterMain,
|
||||||
|
@ -1814,10 +1835,6 @@ impl<B: ExtraBackendMethods> OngoingCodegen<B> {
|
||||||
|
|
||||||
sess.abort_if_errors();
|
sess.abort_if_errors();
|
||||||
|
|
||||||
if let Some(time_graph) = self.time_graph {
|
|
||||||
time_graph.dump(&format!("{}-timings", self.crate_name));
|
|
||||||
}
|
|
||||||
|
|
||||||
let work_products =
|
let work_products =
|
||||||
copy_all_cgu_workproducts_to_incr_comp_cache_dir(sess,
|
copy_all_cgu_workproducts_to_incr_comp_cache_dir(sess,
|
||||||
&compiled_modules);
|
&compiled_modules);
|
||||||
|
|
|
@ -29,7 +29,6 @@ use rustc::util::profiling::ProfileCategory;
|
||||||
use rustc::session::config::{self, EntryFnType, Lto};
|
use rustc::session::config::{self, EntryFnType, Lto};
|
||||||
use rustc::session::Session;
|
use rustc::session::Session;
|
||||||
use rustc_mir::monomorphize::item::DefPathBasedNames;
|
use rustc_mir::monomorphize::item::DefPathBasedNames;
|
||||||
use rustc::util::time_graph;
|
|
||||||
use rustc_mir::monomorphize::Instance;
|
use rustc_mir::monomorphize::Instance;
|
||||||
use rustc_mir::monomorphize::partitioning::{CodegenUnit, CodegenUnitExt};
|
use rustc_mir::monomorphize::partitioning::{CodegenUnit, CodegenUnitExt};
|
||||||
use rustc::util::nodemap::FxHashMap;
|
use rustc::util::nodemap::FxHashMap;
|
||||||
|
@ -528,11 +527,6 @@ pub fn maybe_create_entry_wrapper<'a, 'tcx: 'a, Bx: BuilderMethods<'a, 'tcx>>(
|
||||||
}
|
}
|
||||||
|
|
||||||
pub const CODEGEN_WORKER_ID: usize = ::std::usize::MAX;
|
pub const CODEGEN_WORKER_ID: usize = ::std::usize::MAX;
|
||||||
pub const CODEGEN_WORKER_TIMELINE: time_graph::TimelineId =
|
|
||||||
time_graph::TimelineId(CODEGEN_WORKER_ID);
|
|
||||||
pub const CODEGEN_WORK_PACKAGE_KIND: time_graph::WorkPackageKind =
|
|
||||||
time_graph::WorkPackageKind(&["#DE9597", "#FED1D3", "#FDC5C7", "#B46668", "#88494B"]);
|
|
||||||
|
|
||||||
|
|
||||||
pub fn codegen_crate<B: ExtraBackendMethods>(
|
pub fn codegen_crate<B: ExtraBackendMethods>(
|
||||||
backend: B,
|
backend: B,
|
||||||
|
@ -545,7 +539,7 @@ pub fn codegen_crate<B: ExtraBackendMethods>(
|
||||||
let cgu_name_builder = &mut CodegenUnitNameBuilder::new(tcx);
|
let cgu_name_builder = &mut CodegenUnitNameBuilder::new(tcx);
|
||||||
|
|
||||||
// Codegen the metadata.
|
// Codegen the metadata.
|
||||||
tcx.sess.profiler(|p| p.start_activity(ProfileCategory::Codegen));
|
tcx.sess.profiler(|p| p.start_activity(ProfileCategory::Codegen, "codegen crate metadata"));
|
||||||
|
|
||||||
let metadata_cgu_name = cgu_name_builder.build_cgu_name(LOCAL_CRATE,
|
let metadata_cgu_name = cgu_name_builder.build_cgu_name(LOCAL_CRATE,
|
||||||
&["crate"],
|
&["crate"],
|
||||||
|
@ -555,7 +549,7 @@ pub fn codegen_crate<B: ExtraBackendMethods>(
|
||||||
let metadata = time(tcx.sess, "write metadata", || {
|
let metadata = time(tcx.sess, "write metadata", || {
|
||||||
backend.write_metadata(tcx, &mut metadata_llvm_module)
|
backend.write_metadata(tcx, &mut metadata_llvm_module)
|
||||||
});
|
});
|
||||||
tcx.sess.profiler(|p| p.end_activity(ProfileCategory::Codegen));
|
tcx.sess.profiler(|p| p.end_activity(ProfileCategory::Codegen, "codegen crate metadata"));
|
||||||
|
|
||||||
let metadata_module = ModuleCodegen {
|
let metadata_module = ModuleCodegen {
|
||||||
name: metadata_cgu_name,
|
name: metadata_cgu_name,
|
||||||
|
@ -563,19 +557,12 @@ pub fn codegen_crate<B: ExtraBackendMethods>(
|
||||||
kind: ModuleKind::Metadata,
|
kind: ModuleKind::Metadata,
|
||||||
};
|
};
|
||||||
|
|
||||||
let time_graph = if tcx.sess.opts.debugging_opts.codegen_time_graph {
|
|
||||||
Some(time_graph::TimeGraph::new())
|
|
||||||
} else {
|
|
||||||
None
|
|
||||||
};
|
|
||||||
|
|
||||||
// Skip crate items and just output metadata in -Z no-codegen mode.
|
// Skip crate items and just output metadata in -Z no-codegen mode.
|
||||||
if tcx.sess.opts.debugging_opts.no_codegen ||
|
if tcx.sess.opts.debugging_opts.no_codegen ||
|
||||||
!tcx.sess.opts.output_types.should_codegen() {
|
!tcx.sess.opts.output_types.should_codegen() {
|
||||||
let ongoing_codegen = start_async_codegen(
|
let ongoing_codegen = start_async_codegen(
|
||||||
backend,
|
backend,
|
||||||
tcx,
|
tcx,
|
||||||
time_graph,
|
|
||||||
metadata,
|
metadata,
|
||||||
rx,
|
rx,
|
||||||
1);
|
1);
|
||||||
|
@ -609,7 +596,6 @@ pub fn codegen_crate<B: ExtraBackendMethods>(
|
||||||
let ongoing_codegen = start_async_codegen(
|
let ongoing_codegen = start_async_codegen(
|
||||||
backend.clone(),
|
backend.clone(),
|
||||||
tcx,
|
tcx,
|
||||||
time_graph.clone(),
|
|
||||||
metadata,
|
metadata,
|
||||||
rx,
|
rx,
|
||||||
codegen_units.len());
|
codegen_units.len());
|
||||||
|
@ -676,15 +662,14 @@ pub fn codegen_crate<B: ExtraBackendMethods>(
|
||||||
|
|
||||||
match cgu_reuse {
|
match cgu_reuse {
|
||||||
CguReuse::No => {
|
CguReuse::No => {
|
||||||
let _timing_guard = time_graph.as_ref().map(|time_graph| {
|
tcx.sess.profiler(|p| p.start_activity(ProfileCategory::Codegen,
|
||||||
time_graph.start(CODEGEN_WORKER_TIMELINE,
|
format!("codegen {}", cgu.name())));
|
||||||
CODEGEN_WORK_PACKAGE_KIND,
|
|
||||||
&format!("codegen {}", cgu.name()))
|
|
||||||
});
|
|
||||||
let start_time = Instant::now();
|
let start_time = Instant::now();
|
||||||
let stats = backend.compile_codegen_unit(tcx, *cgu.name());
|
let stats = backend.compile_codegen_unit(tcx, *cgu.name());
|
||||||
all_stats.extend(stats);
|
all_stats.extend(stats);
|
||||||
total_codegen_time += start_time.elapsed();
|
total_codegen_time += start_time.elapsed();
|
||||||
|
tcx.sess.profiler(|p| p.end_activity(ProfileCategory::Codegen,
|
||||||
|
format!("codegen {}", cgu.name())));
|
||||||
false
|
false
|
||||||
}
|
}
|
||||||
CguReuse::PreLto => {
|
CguReuse::PreLto => {
|
||||||
|
|
|
@ -3,7 +3,6 @@ use crate::back::write::{CodegenContext, ModuleConfig, FatLTOInput};
|
||||||
use crate::{CompiledModule, ModuleCodegen};
|
use crate::{CompiledModule, ModuleCodegen};
|
||||||
|
|
||||||
use rustc::dep_graph::WorkProduct;
|
use rustc::dep_graph::WorkProduct;
|
||||||
use rustc::util::time_graph::Timeline;
|
|
||||||
use rustc_errors::{FatalError, Handler};
|
use rustc_errors::{FatalError, Handler};
|
||||||
|
|
||||||
pub trait WriteBackendMethods: 'static + Sized + Clone {
|
pub trait WriteBackendMethods: 'static + Sized + Clone {
|
||||||
|
@ -20,7 +19,6 @@ pub trait WriteBackendMethods: 'static + Sized + Clone {
|
||||||
cgcx: &CodegenContext<Self>,
|
cgcx: &CodegenContext<Self>,
|
||||||
modules: Vec<FatLTOInput<Self>>,
|
modules: Vec<FatLTOInput<Self>>,
|
||||||
cached_modules: Vec<(SerializedModule<Self::ModuleBuffer>, WorkProduct)>,
|
cached_modules: Vec<(SerializedModule<Self::ModuleBuffer>, WorkProduct)>,
|
||||||
timeline: &mut Timeline,
|
|
||||||
) -> Result<LtoModuleCodegen<Self>, FatalError>;
|
) -> Result<LtoModuleCodegen<Self>, FatalError>;
|
||||||
/// Performs thin LTO by performing necessary global analysis and returning two
|
/// Performs thin LTO by performing necessary global analysis and returning two
|
||||||
/// lists, one of the modules that need optimization and another for modules that
|
/// lists, one of the modules that need optimization and another for modules that
|
||||||
|
@ -29,7 +27,6 @@ pub trait WriteBackendMethods: 'static + Sized + Clone {
|
||||||
cgcx: &CodegenContext<Self>,
|
cgcx: &CodegenContext<Self>,
|
||||||
modules: Vec<(String, Self::ThinBuffer)>,
|
modules: Vec<(String, Self::ThinBuffer)>,
|
||||||
cached_modules: Vec<(SerializedModule<Self::ModuleBuffer>, WorkProduct)>,
|
cached_modules: Vec<(SerializedModule<Self::ModuleBuffer>, WorkProduct)>,
|
||||||
timeline: &mut Timeline,
|
|
||||||
) -> Result<(Vec<LtoModuleCodegen<Self>>, Vec<WorkProduct>), FatalError>;
|
) -> Result<(Vec<LtoModuleCodegen<Self>>, Vec<WorkProduct>), FatalError>;
|
||||||
fn print_pass_timings(&self);
|
fn print_pass_timings(&self);
|
||||||
unsafe fn optimize(
|
unsafe fn optimize(
|
||||||
|
@ -37,19 +34,16 @@ pub trait WriteBackendMethods: 'static + Sized + Clone {
|
||||||
diag_handler: &Handler,
|
diag_handler: &Handler,
|
||||||
module: &ModuleCodegen<Self::Module>,
|
module: &ModuleCodegen<Self::Module>,
|
||||||
config: &ModuleConfig,
|
config: &ModuleConfig,
|
||||||
timeline: &mut Timeline,
|
|
||||||
) -> Result<(), FatalError>;
|
) -> Result<(), FatalError>;
|
||||||
unsafe fn optimize_thin(
|
unsafe fn optimize_thin(
|
||||||
cgcx: &CodegenContext<Self>,
|
cgcx: &CodegenContext<Self>,
|
||||||
thin: &mut ThinModule<Self>,
|
thin: &mut ThinModule<Self>,
|
||||||
timeline: &mut Timeline,
|
|
||||||
) -> Result<ModuleCodegen<Self::Module>, FatalError>;
|
) -> Result<ModuleCodegen<Self::Module>, FatalError>;
|
||||||
unsafe fn codegen(
|
unsafe fn codegen(
|
||||||
cgcx: &CodegenContext<Self>,
|
cgcx: &CodegenContext<Self>,
|
||||||
diag_handler: &Handler,
|
diag_handler: &Handler,
|
||||||
module: ModuleCodegen<Self::Module>,
|
module: ModuleCodegen<Self::Module>,
|
||||||
config: &ModuleConfig,
|
config: &ModuleConfig,
|
||||||
timeline: &mut Timeline,
|
|
||||||
) -> Result<CompiledModule, FatalError>;
|
) -> Result<CompiledModule, FatalError>;
|
||||||
fn prepare_thin(
|
fn prepare_thin(
|
||||||
module: ModuleCodegen<Self::Module>
|
module: ModuleCodegen<Self::Module>
|
||||||
|
|
|
@ -67,7 +67,7 @@ pub fn parse<'a>(sess: &'a Session, input: &Input) -> PResult<'a, ast::Crate> {
|
||||||
.set_continue_after_error(sess.opts.debugging_opts.continue_parse_after_error);
|
.set_continue_after_error(sess.opts.debugging_opts.continue_parse_after_error);
|
||||||
hygiene::set_default_edition(sess.edition());
|
hygiene::set_default_edition(sess.edition());
|
||||||
|
|
||||||
sess.profiler(|p| p.start_activity(ProfileCategory::Parsing));
|
sess.profiler(|p| p.start_activity(ProfileCategory::Parsing, "parsing"));
|
||||||
let krate = time(sess, "parsing", || match *input {
|
let krate = time(sess, "parsing", || match *input {
|
||||||
Input::File(ref file) => parse::parse_crate_from_file(file, &sess.parse_sess),
|
Input::File(ref file) => parse::parse_crate_from_file(file, &sess.parse_sess),
|
||||||
Input::Str {
|
Input::Str {
|
||||||
|
@ -75,7 +75,7 @@ pub fn parse<'a>(sess: &'a Session, input: &Input) -> PResult<'a, ast::Crate> {
|
||||||
ref name,
|
ref name,
|
||||||
} => parse::parse_crate_from_source_str(name.clone(), input.clone(), &sess.parse_sess),
|
} => parse::parse_crate_from_source_str(name.clone(), input.clone(), &sess.parse_sess),
|
||||||
})?;
|
})?;
|
||||||
sess.profiler(|p| p.end_activity(ProfileCategory::Parsing));
|
sess.profiler(|p| p.end_activity(ProfileCategory::Parsing, "parsing"));
|
||||||
|
|
||||||
sess.diagnostic().set_continue_after_error(true);
|
sess.diagnostic().set_continue_after_error(true);
|
||||||
|
|
||||||
|
@ -374,7 +374,7 @@ fn configure_and_expand_inner<'a>(
|
||||||
syntax_ext::register_builtins(&mut resolver, plugin_info.syntax_exts);
|
syntax_ext::register_builtins(&mut resolver, plugin_info.syntax_exts);
|
||||||
|
|
||||||
// Expand all macros
|
// Expand all macros
|
||||||
sess.profiler(|p| p.start_activity(ProfileCategory::Expansion));
|
sess.profiler(|p| p.start_activity(ProfileCategory::Expansion, "macro expansion"));
|
||||||
krate = time(sess, "expansion", || {
|
krate = time(sess, "expansion", || {
|
||||||
// Windows dlls do not have rpaths, so they don't know how to find their
|
// Windows dlls do not have rpaths, so they don't know how to find their
|
||||||
// dependencies. It's up to us to tell the system where to find all the
|
// dependencies. It's up to us to tell the system where to find all the
|
||||||
|
@ -449,7 +449,7 @@ fn configure_and_expand_inner<'a>(
|
||||||
}
|
}
|
||||||
krate
|
krate
|
||||||
});
|
});
|
||||||
sess.profiler(|p| p.end_activity(ProfileCategory::Expansion));
|
sess.profiler(|p| p.end_activity(ProfileCategory::Expansion, "macro expansion"));
|
||||||
|
|
||||||
time(sess, "maybe building test harness", || {
|
time(sess, "maybe building test harness", || {
|
||||||
syntax::test::modify_for_testing(
|
syntax::test::modify_for_testing(
|
||||||
|
@ -1018,9 +1018,9 @@ pub fn start_codegen<'tcx>(
|
||||||
::rustc::middle::dependency_format::calculate(tcx)
|
::rustc::middle::dependency_format::calculate(tcx)
|
||||||
});
|
});
|
||||||
|
|
||||||
tcx.sess.profiler(|p| p.start_activity(ProfileCategory::Codegen));
|
tcx.sess.profiler(|p| p.start_activity(ProfileCategory::Codegen, "codegen crate"));
|
||||||
let codegen = time(tcx.sess, "codegen", move || codegen_backend.codegen_crate(tcx, rx));
|
let codegen = time(tcx.sess, "codegen", move || codegen_backend.codegen_crate(tcx, rx));
|
||||||
tcx.sess.profiler(|p| p.end_activity(ProfileCategory::Codegen));
|
tcx.sess.profiler(|p| p.end_activity(ProfileCategory::Codegen, "codegen crate"));
|
||||||
|
|
||||||
if log_enabled!(::log::Level::Info) {
|
if log_enabled!(::log::Level::Info) {
|
||||||
println!("Post-codegen");
|
println!("Post-codegen");
|
||||||
|
|
|
@ -317,7 +317,7 @@ pub fn provide(providers: &mut Providers<'_>) {
|
||||||
pub fn check_crate<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>)
|
pub fn check_crate<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>)
|
||||||
-> Result<(), ErrorReported>
|
-> Result<(), ErrorReported>
|
||||||
{
|
{
|
||||||
tcx.sess.profiler(|p| p.start_activity(ProfileCategory::TypeChecking));
|
tcx.sess.profiler(|p| p.start_activity(ProfileCategory::TypeChecking, "type-check crate"));
|
||||||
|
|
||||||
// this ensures that later parts of type checking can assume that items
|
// this ensures that later parts of type checking can assume that items
|
||||||
// have valid types and not error
|
// have valid types and not error
|
||||||
|
@ -368,7 +368,7 @@ pub fn check_crate<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>)
|
||||||
check_unused::check_crate(tcx);
|
check_unused::check_crate(tcx);
|
||||||
check_for_entry_fn(tcx);
|
check_for_entry_fn(tcx);
|
||||||
|
|
||||||
tcx.sess.profiler(|p| p.end_activity(ProfileCategory::TypeChecking));
|
tcx.sess.profiler(|p| p.end_activity(ProfileCategory::TypeChecking, "type-check crate"));
|
||||||
|
|
||||||
if tcx.sess.err_count() == 0 {
|
if tcx.sess.err_count() == 0 {
|
||||||
Ok(())
|
Ok(())
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue