Auto merge of #51590 - bjorn3:codegen_llvm_extract, r=alexcrichton
Mostly fix metadata_only backend and extract some code out of rustc_codegen_llvm Removes dependency on the `ar` crate and removes the `llvm.enabled` config option in favour of setting `rust.codegen-backends` to `[]`.
This commit is contained in:
commit
9342f293e9
15 changed files with 30 additions and 110 deletions
|
|
@ -56,6 +56,7 @@ use builder::{Builder, MemFlags};
|
|||
use callee;
|
||||
use common::{C_bool, C_bytes_in_context, C_i32, C_usize};
|
||||
use rustc_mir::monomorphize::collector::{self, MonoItemCollectionMode};
|
||||
use rustc_mir::monomorphize::item::DefPathBasedNames;
|
||||
use common::{self, C_struct_in_context, C_array, val_ty};
|
||||
use consts;
|
||||
use context::{self, CodegenCx};
|
||||
|
|
@ -67,7 +68,7 @@ use monomorphize::Instance;
|
|||
use monomorphize::partitioning::{self, PartitioningStrategy, CodegenUnit, CodegenUnitExt};
|
||||
use rustc_codegen_utils::symbol_names_test;
|
||||
use time_graph;
|
||||
use mono_item::{MonoItem, BaseMonoItemExt, MonoItemExt, DefPathBasedNames};
|
||||
use mono_item::{MonoItem, BaseMonoItemExt, MonoItemExt};
|
||||
use type_::Type;
|
||||
use type_of::LayoutLlvmExt;
|
||||
use rustc::util::nodemap::{FxHashMap, FxHashSet, DefIdSet};
|
||||
|
|
@ -92,7 +93,7 @@ use syntax::ast;
|
|||
|
||||
use mir::operand::OperandValue;
|
||||
|
||||
pub use rustc_codegen_utils::check_for_rustc_errors_attr;
|
||||
use rustc_codegen_utils::check_for_rustc_errors_attr;
|
||||
|
||||
pub struct StatRecorder<'a, 'tcx: 'a> {
|
||||
cx: &'a CodegenCx<'a, 'tcx>,
|
||||
|
|
|
|||
|
|
@ -76,6 +76,7 @@ use rustc::middle::lang_items::LangItem;
|
|||
use rustc::session::{Session, CompileIncomplete};
|
||||
use rustc::session::config::{OutputFilenames, OutputType, PrintRequest};
|
||||
use rustc::ty::{self, TyCtxt};
|
||||
use rustc::util::time_graph;
|
||||
use rustc::util::nodemap::{FxHashSet, FxHashMap};
|
||||
use rustc_mir::monomorphize;
|
||||
use rustc_codegen_utils::codegen_backend::CodegenBackend;
|
||||
|
|
@ -114,7 +115,6 @@ mod llvm_util;
|
|||
mod metadata;
|
||||
mod meth;
|
||||
mod mir;
|
||||
mod time_graph;
|
||||
mod mono_item;
|
||||
mod type_;
|
||||
mod type_of;
|
||||
|
|
@ -368,7 +368,7 @@ struct CodegenResults {
|
|||
crate_info: CrateInfo,
|
||||
}
|
||||
|
||||
// Misc info we load from metadata to persist beyond the tcx
|
||||
/// Misc info we load from metadata to persist beyond the tcx
|
||||
struct CrateInfo {
|
||||
panic_runtime: Option<CrateNum>,
|
||||
compiler_builtins: Option<CrateNum>,
|
||||
|
|
|
|||
|
|
@ -33,7 +33,6 @@ use std::fmt;
|
|||
|
||||
pub use rustc::mir::mono::MonoItem;
|
||||
|
||||
pub use rustc_mir::monomorphize::item::*;
|
||||
pub use rustc_mir::monomorphize::item::MonoItemExt as BaseMonoItemExt;
|
||||
|
||||
pub trait MonoItemExt<'a, 'tcx>: fmt::Debug + BaseMonoItemExt<'a, 'tcx> {
|
||||
|
|
|
|||
|
|
@ -1,278 +0,0 @@
|
|||
// 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.
|
||||
|
||||
use std::collections::HashMap;
|
||||
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<HashMap<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(HashMap::new()))
|
||||
}
|
||||
}
|
||||
|
||||
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
|
||||
}
|
||||
|
||||
|
|
@ -16,7 +16,7 @@ use rustc::ty::{self, Ty, TypeFoldable};
|
|||
use rustc::ty::layout::{self, Align, LayoutOf, Size, TyLayout};
|
||||
use rustc_target::spec::PanicStrategy;
|
||||
use rustc_target::abi::FloatTy;
|
||||
use mono_item::DefPathBasedNames;
|
||||
use rustc_mir::monomorphize::item::DefPathBasedNames;
|
||||
use type_::Type;
|
||||
|
||||
use std::fmt::Write;
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue