Skip to content
This repository was archived by the owner on Jan 7, 2022. It is now read-only.

Commit a7a94df

Browse files
committed
Try #3:
2 parents bde262e + f95a776 commit a7a94df

File tree

7 files changed

+141
-1
lines changed

7 files changed

+141
-1
lines changed

src/librustc_mir/transform/add_yk_swt_calls.rs

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,11 @@ use rustc::hir;
1818
use rustc::hir::def_id::{DefIndex, LOCAL_CRATE};
1919
use rustc::hir::map::blocks::FnLikeNode;
2020

21+
// Crates the trace recorder depends upon.
22+
// This is effectively libstd and its dependencies (from its Cargo manifest).
23+
static RECORDER_DEPS: &'static [&'static str] = &["std", "alloc", "panic_unwind",
24+
"panic_abort", "core", "libc", "compiler_builtins", "profiler_builtins", "unwind"];
25+
2126
/// A MIR transformation that, for each basic block, inserts a call to the software trace recorder.
2227
/// The arguments to the calls (crate hash, DefId and block index) identify the position to be
2328
/// inserted into a trace.
@@ -170,6 +175,12 @@ fn is_untraceable(tcx: TyCtxt<'a, 'tcx, 'tcx>, src: MirSource) -> bool {
170175
return true;
171176
}
172177

178+
// FIXME Anything which the trace recorder depends upon cannot be traced or we will get
179+
// infinite recursion at runtime..
180+
if RECORDER_DEPS.contains(&&*tcx.crate_name(LOCAL_CRATE).as_str()) {
181+
return true;
182+
}
183+
173184
// We can't transform promoted items, because they are `const`, and our trace recorder isn't.
174185
if let Some(_) = src.promoted {
175186
return true;

src/libstd/yk_swt.rs

Lines changed: 58 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,45 @@
77
// option. This file may not be copied, modified, or distributed
88
// except according to those terms.
99

10+
use ::cell::RefCell;
11+
use ::fmt;
12+
13+
#[allow(missing_docs)]
14+
/// A block location in the Rust MIR.
15+
pub struct MirLoc {
16+
pub crate_hash: u64,
17+
pub def_idx: u32,
18+
pub bb_idx: u32,
19+
}
20+
21+
impl fmt::Debug for MirLoc {
22+
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
23+
write!(f, "loc<{}, {}, {}>", self.crate_hash, self.def_idx, self.bb_idx)
24+
}
25+
}
26+
27+
thread_local! {
28+
/// The software trace currently being collected (if any).
29+
/// When `Some`, a tracing is enabled, otherwise tracing is disabled.
30+
pub static TRACE: RefCell<Option<Vec<MirLoc>>> = RefCell::new(None);
31+
}
32+
33+
/// Start software tracing.
34+
#[cfg_attr(not(stage0), no_trace)]
35+
pub fn start_tracing() {
36+
TRACE.with(|rc| {
37+
let mut trace_o = rc.borrow_mut();
38+
match *trace_o {
39+
Some(_) => panic!("tracing was already started for this thread!"),
40+
None => *trace_o = Some(Vec::new()),
41+
}
42+
});
43+
}
44+
45+
// FIXME Anything used in `rec_loc` below cannot itself be traced, or we get infinite recursion. To
46+
// work sround this, many crates are ignored by the software tracing MIR pass (see
47+
// librustc_mir/transform/add_yk_swt_calls.rs). Consider re-implementing the trace recorder in C?
48+
1049
/// The software trace recorder function.
1150
/// The `AddYkSWTCalls` MIR pass injects a call this for every MIR block. The call is done
1251
/// indirectly via a wrapper in libcore.
@@ -15,5 +54,23 @@
1554
#[cfg_attr(not(stage0), no_trace)]
1655
#[cfg(not(test))]
1756
fn rec_loc(crate_hash: u64, def_idx: u32, bb_idx: u32) {
18-
// Not implemented.
57+
TRACE.with(|rc| {
58+
let mut trace_o = rc.borrow_mut();
59+
match trace_o.as_mut() {
60+
Some(trace) => trace.push(MirLoc{crate_hash, def_idx, bb_idx}),
61+
None => (), // Tracing is disabled, do nothing.
62+
}
63+
});
64+
}
65+
66+
/// Stop tracing and return the trace.
67+
#[cfg_attr(not(stage0), no_trace)]
68+
pub fn stop_tracing() -> Vec<MirLoc> {
69+
TRACE.with(|rc| {
70+
let trace_o = rc.borrow_mut().take();
71+
if trace_o.is_none() {
72+
panic!("tracing not started on this thread");
73+
}
74+
trace_o.unwrap()
75+
})
1976
}
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
// Copyright 2019 King's College London.
2+
// Created by the Software Development Team <http://soft-dev.org/>.
3+
//
4+
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
5+
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
6+
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
7+
// option. This file may not be copied, modified, or distributed
8+
// except according to those terms.
9+
10+
// error-pattern: thread 'main' panicked at 'tracing was already started for this thread!'
11+
12+
#![feature(yk_swt)]
13+
14+
use std::yk_swt::{start_tracing, stop_tracing};
15+
16+
pub fn main() {
17+
start_tracing();
18+
start_tracing(); // Can't call a second time without a stop_tracing() first.
19+
}
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
// Copyright 2019 King's College London.
2+
// Created by the Software Development Team <http://soft-dev.org/>.
3+
//
4+
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
5+
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
6+
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
7+
// option. This file may not be copied, modified, or distributed
8+
// except according to those terms.
9+
10+
// error-pattern: thread 'main' panicked at 'tracing not started on this thread'
11+
12+
#![feature(yk_swt)]
13+
14+
use std::yk_swt::{start_tracing, stop_tracing};
15+
16+
pub fn main() {
17+
// Missing start_tracing();
18+
let _ = stop_tracing();
19+
}

src/test/run-pass/signal-alternate-stack-cleanup.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,10 @@
1616
// ignore-wasm32-bare no libc
1717
// ignore-windows
1818

19+
// Software tracing breaks this test as the thread local used to record the trace becomes valid at
20+
// atexit() time.
21+
#![no_trace]
22+
1923
#![feature(libc)]
2024
extern crate libc;
2125

src/test/run-pass/thinlto/thin-lto-inlines2.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,8 @@
2020
// praying two functions go into separate codegen units and then assuming that
2121
// if inlining *doesn't* happen the first byte of the functions will differ.
2222

23+
#![no_trace]
24+
2325
extern crate thin_lto_inlines_aux as bar;
2426

2527
pub fn foo() -> u32 {
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
// Copyright 2019 King's College London.
2+
// Created by the Software Development Team <http://soft-dev.org/>.
3+
//
4+
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
5+
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
6+
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
7+
// option. This file may not be copied, modified, or distributed
8+
// except according to those terms.
9+
10+
#![feature(yk_swt)]
11+
12+
use std::yk_swt::{start_tracing, stop_tracing};
13+
14+
pub fn main() {
15+
start_tracing();
16+
let _ = work();
17+
let trace = stop_tracing();
18+
assert!(!trace.is_empty());
19+
}
20+
21+
#[inline(never)]
22+
fn work() -> u64{
23+
let mut res = 47;
24+
for i in 0..10 {
25+
res += res / 2 + i;
26+
}
27+
res
28+
}

0 commit comments

Comments
 (0)