Skip to content

Commit e8cd8fd

Browse files
author
Keegan McAllister
committed
---
yaml --- r: 155107 b: refs/heads/try2 c: ad9a1da h: refs/heads/master i: 155105: d6c2595 155103: c748b25 v: v3
1 parent b655906 commit e8cd8fd

File tree

7 files changed

+298
-14
lines changed

7 files changed

+298
-14
lines changed

[refs]

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ refs/heads/snap-stage3: 78a7676898d9f80ab540c6df5d4c9ce35bb50463
55
refs/heads/try: 519addf6277dbafccbb4159db4b710c37eaa2ec5
66
refs/tags/release-0.1: 1f5c5126e96c79d22cb7862f75304136e204f105
77
refs/heads/ndm: f3868061cd7988080c30d6d5bf352a5a5fe2460b
8-
refs/heads/try2: 225353d8bbad5730c941fc88e854627004e74f2c
8+
refs/heads/try2: ad9a1daa819bbeb8e643a01167b3b69055b88d57
99
refs/heads/dist-snap: ba4081a5a8573875fed17545846f6f6902c8ba8d
1010
refs/tags/release-0.2: c870d2dffb391e14efb05aa27898f1f6333a9596
1111
refs/tags/release-0.3: b5f0d0f648d9a6153664837026ba1be43d3e2503

branches/try2/src/librustc/back/write.rs

Lines changed: 56 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -11,11 +11,11 @@
1111
use back::lto;
1212
use back::link::{get_cc_prog, remove};
1313
use driver::driver::{CrateTranslation, ModuleTranslation, OutputFilenames};
14-
use driver::config::NoDebugInfo;
14+
use driver::config::{NoDebugInfo, Passes, AllPasses};
1515
use driver::session::Session;
1616
use driver::config;
1717
use llvm;
18-
use llvm::{ModuleRef, TargetMachineRef, PassManagerRef};
18+
use llvm::{ModuleRef, TargetMachineRef, PassManagerRef, DiagnosticInfoRef, ContextRef};
1919
use util::common::time;
2020
use syntax::abi;
2121
use syntax::codemap;
@@ -28,9 +28,10 @@ use std::io::fs;
2828
use std::iter::Unfold;
2929
use std::ptr;
3030
use std::str;
31+
use std::mem;
3132
use std::sync::{Arc, Mutex};
3233
use std::task::TaskBuilder;
33-
use libc::{c_uint, c_int};
34+
use libc::{c_uint, c_int, c_void};
3435

3536

3637
#[deriving(Clone, PartialEq, PartialOrd, Ord, Eq)]
@@ -311,21 +312,49 @@ struct CodegenContext<'a> {
311312
lto_ctxt: Option<(&'a Session, &'a [String])>,
312313
// Handler to use for diagnostics produced during codegen.
313314
handler: &'a Handler,
315+
// LLVM optimizations for which we want to print remarks.
316+
remark: Passes,
314317
}
315318

316319
impl<'a> CodegenContext<'a> {
317-
fn new(handler: &'a Handler) -> CodegenContext<'a> {
318-
CodegenContext {
319-
lto_ctxt: None,
320-
handler: handler,
321-
}
322-
}
323-
324320
fn new_with_session(sess: &'a Session, reachable: &'a [String]) -> CodegenContext<'a> {
325321
CodegenContext {
326322
lto_ctxt: Some((sess, reachable)),
327323
handler: sess.diagnostic().handler(),
324+
remark: sess.opts.cg.remark.clone(),
325+
}
326+
}
327+
}
328+
329+
struct DiagHandlerFreeVars<'a> {
330+
llcx: ContextRef,
331+
cgcx: &'a CodegenContext<'a>,
332+
}
333+
334+
unsafe extern "C" fn diagnostic_handler(info: DiagnosticInfoRef, user: *mut c_void) {
335+
let DiagHandlerFreeVars { llcx, cgcx }
336+
= *mem::transmute::<_, *const DiagHandlerFreeVars>(user);
337+
338+
match llvm::diagnostic::Diagnostic::unpack(info) {
339+
llvm::diagnostic::Optimization(opt) => {
340+
let pass_name = CString::new(opt.pass_name, false);
341+
let pass_name = pass_name.as_str().expect("got a non-UTF8 pass name from LLVM");
342+
let enabled = match cgcx.remark {
343+
AllPasses => true,
344+
Passes(ref v) => v.iter().any(|s| s.as_slice() == pass_name),
345+
};
346+
347+
if enabled {
348+
let loc = llvm::debug_loc_to_string(llcx, opt.debug_loc);
349+
cgcx.handler.note(format!("optimization {:s} for {:s} at {:s}: {:s}",
350+
opt.kind.describe(),
351+
pass_name,
352+
if loc.is_empty() { "[unknown]" } else { loc.as_slice() },
353+
llvm::twine_to_string(opt.message)).as_slice());
354+
}
328355
}
356+
357+
_ => (),
329358
}
330359
}
331360

@@ -338,6 +367,17 @@ unsafe fn optimize_and_codegen(cgcx: &CodegenContext,
338367
let ModuleTranslation { llmod, llcx } = mtrans;
339368
let tm = config.tm;
340369

370+
// llcx doesn't outlive this function, so we can put this on the stack.
371+
let fv = DiagHandlerFreeVars {
372+
llcx: llcx,
373+
cgcx: cgcx,
374+
};
375+
if !cgcx.remark.is_empty() {
376+
llvm::LLVMContextSetDiagnosticHandler(llcx, diagnostic_handler,
377+
&fv as *const DiagHandlerFreeVars
378+
as *mut c_void);
379+
}
380+
341381
if config.emit_no_opt_bc {
342382
let ext = format!("{}.no-opt.bc", name_extra);
343383
output_names.with_extension(ext.as_slice()).with_c_str(|buf| {
@@ -785,13 +825,18 @@ fn run_work_multithreaded(sess: &Session,
785825
for i in range(0, num_workers) {
786826
let work_items_arc = work_items_arc.clone();
787827
let diag_emitter = diag_emitter.clone();
828+
let remark = sess.opts.cg.remark.clone();
788829

789830
let future = TaskBuilder::new().named(format!("codegen-{}", i)).try_future(proc() {
790831
let diag_handler = mk_handler(box diag_emitter);
791832

792833
// Must construct cgcx inside the proc because it has non-Send
793834
// fields.
794-
let cgcx = CodegenContext::new(&diag_handler);
835+
let cgcx = CodegenContext {
836+
lto_ctxt: None,
837+
handler: &diag_handler,
838+
remark: remark,
839+
};
795840

796841
loop {
797842
// Avoid holding the lock for the entire duration of the match.

branches/try2/src/librustc/driver/config.rs

Lines changed: 40 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -235,6 +235,21 @@ pub fn debugging_opts_map() -> Vec<(&'static str, &'static str, u64)> {
235235
--pretty flowgraph output", FLOWGRAPH_PRINT_ALL))
236236
}
237237

238+
#[deriving(Clone)]
239+
pub enum Passes {
240+
Passes(Vec<String>),
241+
AllPasses,
242+
}
243+
244+
impl Passes {
245+
pub fn is_empty(&self) -> bool {
246+
match *self {
247+
Passes(ref v) => v.is_empty(),
248+
AllPasses => false,
249+
}
250+
}
251+
}
252+
238253
/// Declare a macro that will define all CodegenOptions fields and parsers all
239254
/// at once. The goal of this macro is to define an interface that can be
240255
/// programmatically used by the option parser in order to initialize the struct
@@ -261,7 +276,7 @@ macro_rules! cgoptions(
261276
&[ $( (stringify!($opt), cgsetters::$opt, $desc) ),* ];
262277

263278
mod cgsetters {
264-
use super::CodegenOptions;
279+
use super::{CodegenOptions, Passes, AllPasses};
265280

266281
$(
267282
pub fn $opt(cg: &mut CodegenOptions, v: Option<&str>) -> bool {
@@ -310,6 +325,24 @@ macro_rules! cgoptions(
310325
None => false
311326
}
312327
}
328+
329+
fn parse_passes(slot: &mut Passes, v: Option<&str>) -> bool {
330+
match v {
331+
Some("all") => {
332+
*slot = AllPasses;
333+
true
334+
}
335+
v => {
336+
let mut passes = vec!();
337+
if parse_list(&mut passes, v) {
338+
*slot = Passes(passes);
339+
true
340+
} else {
341+
false
342+
}
343+
}
344+
}
345+
}
313346
}
314347
) )
315348

@@ -356,6 +389,8 @@ cgoptions!(
356389
"extra data to put in each output filename"),
357390
codegen_units: uint = (1, parse_uint,
358391
"divide crate into N units to optimize in parallel"),
392+
remark: Passes = (Passes(Vec::new()), parse_passes,
393+
"print remarks for these optimization passes (space separated, or \"all\")"),
359394
)
360395

361396
pub fn build_codegen_options(matches: &getopts::Matches) -> CodegenOptions
@@ -744,6 +779,10 @@ pub fn build_session_options(matches: &getopts::Matches) -> Options {
744779
}
745780
let cg = build_codegen_options(matches);
746781

782+
if !cg.remark.is_empty() && debuginfo == NoDebugInfo {
783+
early_warn("-C remark will not show source locations without --debuginfo");
784+
}
785+
747786
let color = match matches.opt_str("color").as_ref().map(|s| s.as_slice()) {
748787
Some("auto") => Auto,
749788
Some("always") => Always,
Lines changed: 92 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,92 @@
1+
// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
2+
// file at the top-level directory of this distribution and at
3+
// http://rust-lang.org/COPYRIGHT.
4+
//
5+
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6+
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7+
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8+
// option. This file may not be copied, modified, or distributed
9+
// except according to those terms.
10+
11+
//! LLVM diagnostic reports.
12+
13+
use libc::c_char;
14+
15+
use {ValueRef, TwineRef, DebugLocRef, DiagnosticInfoRef};
16+
17+
pub enum OptimizationDiagnosticKind {
18+
OptimizationRemark,
19+
OptimizationMissed,
20+
OptimizationAnalysis,
21+
OptimizationFailure,
22+
}
23+
24+
impl OptimizationDiagnosticKind {
25+
pub fn describe(self) -> &'static str {
26+
match self {
27+
OptimizationRemark => "remark",
28+
OptimizationMissed => "missed",
29+
OptimizationAnalysis => "analysis",
30+
OptimizationFailure => "failure",
31+
}
32+
}
33+
}
34+
35+
pub struct OptimizationDiagnostic {
36+
pub kind: OptimizationDiagnosticKind,
37+
pub pass_name: *const c_char,
38+
pub function: ValueRef,
39+
pub debug_loc: DebugLocRef,
40+
pub message: TwineRef,
41+
}
42+
43+
impl OptimizationDiagnostic {
44+
unsafe fn unpack(kind: OptimizationDiagnosticKind, di: DiagnosticInfoRef)
45+
-> OptimizationDiagnostic {
46+
47+
let mut opt = OptimizationDiagnostic {
48+
kind: kind,
49+
pass_name: 0 as *const c_char,
50+
function: 0 as ValueRef,
51+
debug_loc: 0 as DebugLocRef,
52+
message: 0 as TwineRef,
53+
};
54+
55+
super::LLVMUnpackOptimizationDiagnostic(di,
56+
&mut opt.pass_name,
57+
&mut opt.function,
58+
&mut opt.debug_loc,
59+
&mut opt.message);
60+
61+
opt
62+
}
63+
}
64+
65+
pub enum Diagnostic {
66+
Optimization(OptimizationDiagnostic),
67+
68+
/// LLVM has other types that we do not wrap here.
69+
UnknownDiagnostic(DiagnosticInfoRef),
70+
}
71+
72+
impl Diagnostic {
73+
pub unsafe fn unpack(di: DiagnosticInfoRef) -> Diagnostic {
74+
let kind = super::LLVMGetDiagInfoKind(di);
75+
76+
match kind {
77+
super::DK_OptimizationRemark
78+
=> Optimization(OptimizationDiagnostic::unpack(OptimizationRemark, di)),
79+
80+
super::DK_OptimizationRemarkMissed
81+
=> Optimization(OptimizationDiagnostic::unpack(OptimizationMissed, di)),
82+
83+
super::DK_OptimizationRemarkAnalysis
84+
=> Optimization(OptimizationDiagnostic::unpack(OptimizationAnalysis, di)),
85+
86+
super::DK_OptimizationFailure
87+
=> Optimization(OptimizationDiagnostic::unpack(OptimizationFailure, di)),
88+
89+
_ => UnknownDiagnostic(di)
90+
}
91+
}
92+
}

0 commit comments

Comments
 (0)