diff --git a/src/Cargo.lock b/src/Cargo.lock
index 569a24055bb..db896b59ba4 100644
--- a/src/Cargo.lock
+++ b/src/Cargo.lock
@@ -444,6 +444,7 @@ dependencies = [
name = "core"
version = "0.0.0"
dependencies = [
+ "cc 1.0.25 (registry+https://github.com/rust-lang/crates.io-index)",
"rand 0.5.5 (registry+https://github.com/rust-lang/crates.io-index)",
]
diff --git a/src/libcore/Cargo.toml b/src/libcore/Cargo.toml
index 0b01cfc488b..2de1fa521e8 100644
--- a/src/libcore/Cargo.toml
+++ b/src/libcore/Cargo.toml
@@ -21,3 +21,6 @@ path = "../libcore/benches/lib.rs"
[dev-dependencies]
rand = "0.5"
+
+[build-dependencies]
+cc = "1.0"
diff --git a/src/libcore/build.rs b/src/libcore/build.rs
new file mode 100644
index 00000000000..beca373d397
--- /dev/null
+++ b/src/libcore/build.rs
@@ -0,0 +1,22 @@
+// Copyright 2019 King's College London.
+// Created by the Software Development Team .
+//
+// Licensed under the Apache License, Version 2.0 or the MIT license
+// , at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+extern crate cc;
+
+fn main() {
+ let mut c_build = cc::Build::new();
+
+ c_build.file("yk_swt_impl.c");
+ c_build.compile("yk_swt_impl");
+ c_build.flag("-std=c11");
+ c_build.warnings(true);
+ c_build.extra_warnings(true);
+
+ println!("cargo:rerun-if-changed=yk_swt_impl.c");
+}
diff --git a/src/libcore/lib.rs b/src/libcore/lib.rs
index 6da694209a0..1fa82178705 100644
--- a/src/libcore/lib.rs
+++ b/src/libcore/lib.rs
@@ -229,7 +229,9 @@ mod nonzero;
mod tuple;
mod unit;
-mod yk_swt;
+/// Yorick software tracing.
+#[unstable(feature = "yk_swt", issue = "0")]
+pub mod yk_swt;
// Pull in the `coresimd` crate directly into libcore. This is where all the
// architecture-specific (and vendor-specific) intrinsics are defined. AKA
diff --git a/src/libcore/yk_swt.rs b/src/libcore/yk_swt.rs
index 8e80965c447..36a17930254 100644
--- a/src/libcore/yk_swt.rs
+++ b/src/libcore/yk_swt.rs
@@ -7,20 +7,91 @@
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-/// The software trace recorder function.
-/// This is a weak language item, it actually resides in libstd. It has to be weak to allow libcore
-/// to call up to libstd (libstd is not a dependency of libcore).
-extern "Rust" {
- #[cfg_attr(not(stage0), lang="yk_swt_rec_loc")]
- fn yk_swt_rec_loc(crate_hash: u64, def_idx: u32, bb: u32);
+/// The result of `yk_swt_stop_tracing_impl()` is an array of this C struct.
+#[repr(C)]
+#[derive(Debug)]
+pub struct MirLoc {
+ /// Unique identifier for the crate.
+ pub crate_hash: u64,
+ /// The definition index.
+ pub def_idx: u32,
+ /// The basic block index.
+ pub bb_idx: u32,
+}
+
+/// Wraps the raw C trace buffer and exposes a more "Rusty" interface to it.
+#[derive(Debug)]
+#[allow(dead_code)]
+pub struct SWTrace {
+ /// A heap allocated array of `MirLoc` structs, which the consumer must free. Ideally we'd
+ /// have this struct implement `std::ops::Drop` or at least provide a method to do the freeing,
+ /// but we can do neither due to libcore restrictions.
+ buf: *mut MirLoc,
+ /// The number of items in the above array.
+ len: usize,
}
-/// Wrapper lang item to call the above wrapper function.
-/// This has to be a lang item too, as a MIR terminator cannot call a weak language item directly.
+impl SWTrace {
+ /// Returns the number of MIR locations recorded in the trace.
+ pub fn len(&self) -> usize {
+ self.len
+ }
+
+ /// Return a pointer to the raw trace buffer. The consumer *must* free this pointer.
+ pub fn buf(self) -> *mut MirLoc {
+ self.buf
+ }
+
+ /// Returns the location at index `idx` or `None` if the index is out of bounds.
+ pub fn loc<'a>(&'a self, idx: usize) -> &'a MirLoc {
+ if idx >= self.len {
+ panic!("software trace index out of bounds: len={}, idx={}", self.len, idx);
+ } else {
+ if idx > isize::max_value() as usize {
+ panic!("index too large for ptr arithmetic");
+ }
+ unsafe { &*self.buf.offset(idx as isize) }
+ }
+ }
+}
+
+/// The software trace recorder function.
+/// This is implemented in C so that: the `yk_swt_calls` MIR pass doesn't see inside.
#[allow(dead_code)] // Used only indirectly in a MIR pass.
-#[cfg_attr(not(stage0), lang="yk_swt_rec_loc_wrap")]
+#[cfg_attr(not(stage0), lang="yk_swt_rec_loc")]
+#[cfg_attr(not(stage0), no_trace)]
+#[cfg(not(test))]
+fn yk_swt_rec_loc(crate_hash: u64, def_idx: u32, bb_idx: u32) {
+ extern "C" { fn yk_swt_rec_loc_impl(crate_hash: u64, def_idx: u32, bb_idx: u32); }
+ unsafe { yk_swt_rec_loc_impl(crate_hash, def_idx, bb_idx); }
+}
+
+/// Start software tracing on the current thread. The current thread must not already be tracing.
#[cfg_attr(not(stage0), no_trace)]
-fn yk_swt_rec_loc_wrap(crate_hash: u64, def_idx: u32, bb: u32) {
- unsafe { yk_swt_rec_loc(crate_hash, def_idx, bb) };
+pub fn start_tracing() {
+ extern "C" { fn yk_swt_start_tracing_impl(); }
+ unsafe { yk_swt_start_tracing_impl(); }
}
+/// Stop software tracing and return the trace, or `None` if the trace was invalidated.
+/// The current thread must already be tracing.
+#[cfg_attr(not(stage0), no_trace)]
+pub fn stop_tracing() -> Option {
+ let len: usize = 0;
+
+ extern "C" { fn yk_swt_stop_tracing_impl(ret_len: &usize) -> *mut MirLoc; }
+ let buf = unsafe { yk_swt_stop_tracing_impl(&len) };
+
+ if buf.is_null() {
+ None
+ } else {
+ Some(SWTrace { buf, len })
+ }
+}
+
+/// Invalidate the software trace, if one is being collected.
+#[cfg_attr(not(stage0), no_trace)]
+pub fn invalidate_trace() {
+ extern "C" { fn yk_swt_invalidate_trace_impl(); }
+ unsafe { yk_swt_invalidate_trace_impl(); }
+}
diff --git a/src/libcore/yk_swt_impl.c b/src/libcore/yk_swt_impl.c
new file mode 100644
index 00000000000..85b025e0bcb
--- /dev/null
+++ b/src/libcore/yk_swt_impl.c
@@ -0,0 +1,130 @@
+// Copyright 2019 King's College London.
+// Created by the Software Development Team .
+//
+// Licensed under the Apache License, Version 2.0 or the MIT license
+// , at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+#include
+#include
+#include
+#include
+#include
+
+struct mir_loc {
+ uint64_t crate_hash;
+ uint32_t def_idx;
+ uint32_t bb_idx;
+};
+
+#define TL_TRACE_INIT_CAP 1024
+#define TL_TRACE_REALLOC_CAP 1024
+
+void yk_swt_start_tracing_impl(void);
+void yk_swt_rec_loc_impl(uint64_t crate_hash, uint32_t def_idx, uint32_t bb_idx);
+struct mir_loc *yk_swt_stop_tracing_impl(size_t *ret_trace_len);
+void yk_swt_invalidate_trace_impl(void);
+
+// The trace buffer.
+static __thread struct mir_loc *trace_buf = NULL;
+// The number of elements in the trace buffer.
+static __thread size_t trace_buf_len = 0;
+// The allocation capacity of the trace buffer (in elements).
+static __thread size_t trace_buf_cap = 0;
+// Is the current thread tracing?
+// true = we are tracing, false = we are not tracing or an error occurred.
+static __thread volatile atomic_bool tracing = false;
+
+// Start tracing on the current thread.
+// A new trace buffer is allocated and MIR locations will be written into it on
+// subsequent calls to `yk_swt_rec_loc_impl`. If the current thread is already
+// tracing, calling this will lead to undefined behaviour.
+void
+yk_swt_start_tracing_impl(void) {
+ trace_buf = calloc(TL_TRACE_INIT_CAP, sizeof(struct mir_loc));
+ if (trace_buf == NULL) {
+ err(EXIT_FAILURE, "%s: calloc: ", __func__);
+ }
+
+ trace_buf_cap = TL_TRACE_INIT_CAP;
+ atomic_store_explicit(&tracing, true, memory_order_relaxed);
+}
+
+// Record a location into the trace buffer if tracing is enabled on the current thread.
+void
+yk_swt_rec_loc_impl(uint64_t crate_hash, uint32_t def_idx, uint32_t bb_idx)
+{
+ if (!atomic_load_explicit(&tracing, memory_order_relaxed)) {
+ return;
+ }
+
+ // Check if we need more space and reallocate if necessary.
+ if (trace_buf_len == trace_buf_cap) {
+ if (trace_buf_cap >= SIZE_MAX - TL_TRACE_REALLOC_CAP) {
+ // Trace capacity would overflow.
+ atomic_store_explicit(&tracing, false, memory_order_relaxed);
+ return;
+ }
+ size_t new_cap = trace_buf_cap + TL_TRACE_REALLOC_CAP;
+
+ if (new_cap > SIZE_MAX / sizeof(struct mir_loc)) {
+ // New buffer size would overflow.
+ atomic_store_explicit(&tracing, false, memory_order_relaxed);
+ return;
+ }
+ size_t new_size = new_cap * sizeof(struct mir_loc);
+
+ trace_buf = realloc(trace_buf, new_size);
+ if (trace_buf == NULL) {
+ atomic_store_explicit(&tracing, false, memory_order_relaxed);
+ return;
+ }
+
+ trace_buf_cap = new_cap;
+ }
+
+ struct mir_loc loc = { crate_hash, def_idx, bb_idx };
+ trace_buf[trace_buf_len] = loc;
+ trace_buf_len ++;
+}
+
+
+// Stop tracing on the current thread.
+// On success the trace buffer is returned and the number of locations it
+// holds is written to `*ret_trace_len`. It is the responsibility of the caller
+// to free the returned trace buffer. A NULL pointer is returned on error.
+// Calling this function when tracing was not started with
+// `yk_swt_start_tracing_impl()` results in undefined behaviour.
+struct mir_loc *
+yk_swt_stop_tracing_impl(size_t *ret_trace_len) {
+ if (!atomic_load_explicit(&tracing, memory_order_relaxed)) {
+ free(trace_buf);
+ trace_buf = NULL;
+ trace_buf_len = 0;
+ }
+
+ // We hand ownership of the trace to Rust now. Rust is responsible for
+ // freeing the trace.
+ struct mir_loc *ret_trace = trace_buf;
+ *ret_trace_len = trace_buf_len;
+
+ // Now reset all off the recorder's state.
+ // We reset `trace_invalid` when tracing is restarted, because signals
+ // handlers which set this flag may arrive in the meantime.
+ trace_buf = NULL;
+ tracing = false;
+ trace_buf_len = 0;
+ trace_buf_cap = 0;
+
+ return ret_trace;
+}
+
+// Call this to safely mark the trace invalid.
+void
+yk_swt_invalidate_trace_impl(void) {
+ // We don't free the trace buffer here, as this may be called in a signal
+ // handler and thus needs to be reentrant.
+ atomic_store_explicit(&tracing, false, memory_order_relaxed);
+}
diff --git a/src/librustc/middle/lang_items.rs b/src/librustc/middle/lang_items.rs
index 38d131643bd..75e7e999d83 100644
--- a/src/librustc/middle/lang_items.rs
+++ b/src/librustc/middle/lang_items.rs
@@ -377,7 +377,6 @@ language_item_table! {
U128ShroFnLangItem, "u128_shro", u128_shro_fn, Target::Fn;
YkSwtRecLocLangItem, "yk_swt_rec_loc", yk_swt_rec_loc, Target::Fn;
- YkSwtRecLocWrapLangItem, "yk_swt_rec_loc_wrap",yk_swt_rec_loc_wrap, Target::Fn;
// Align offset for stride != 1, must not panic.
AlignOffsetLangItem, "align_offset", align_offset_fn, Target::Fn;
diff --git a/src/librustc/middle/weak_lang_items.rs b/src/librustc/middle/weak_lang_items.rs
index acbb951a453..0d407765c9e 100644
--- a/src/librustc/middle/weak_lang_items.rs
+++ b/src/librustc/middle/weak_lang_items.rs
@@ -168,5 +168,4 @@ weak_lang_items! {
eh_personality, EhPersonalityLangItem, rust_eh_personality;
eh_unwind_resume, EhUnwindResumeLangItem, rust_eh_unwind_resume;
oom, OomLangItem, rust_oom;
- yk_swt_rec_loc, YkSwtRecLocLangItem, rust_yk_swt_rec_loc;
}
diff --git a/src/librustc_mir/transform/add_yk_swt_calls.rs b/src/librustc_mir/transform/add_yk_swt_calls.rs
index e7b3a809f45..cfb9af6011d 100644
--- a/src/librustc_mir/transform/add_yk_swt_calls.rs
+++ b/src/librustc_mir/transform/add_yk_swt_calls.rs
@@ -51,7 +51,7 @@ impl MirPass for AddYkSWTCalls {
return;
}
- let rec_fn_defid = tcx.get_lang_items(LOCAL_CRATE).yk_swt_rec_loc_wrap()
+ let rec_fn_defid = tcx.get_lang_items(LOCAL_CRATE).yk_swt_rec_loc()
.expect("couldn't find software trace recorder function");
let unit_ty = tcx.mk_unit();
diff --git a/src/libstd/lib.rs b/src/libstd/lib.rs
index 2a6691a9712..623cefacc2c 100644
--- a/src/libstd/lib.rs
+++ b/src/libstd/lib.rs
@@ -310,6 +310,7 @@
#![feature(panic_info_message)]
#![feature(non_exhaustive)]
#![feature(alloc_layout_extra)]
+#![feature(yk_swt)]
#![default_lib_allocator]
@@ -518,10 +519,6 @@ mod coresimd {
#[cfg(all(not(stage0), not(test)))]
pub use stdsimd::arch;
-/// Yorick software tracing.
-#[unstable(feature = "yk_swt", issue = "0")]
-pub mod yk_swt;
-
// Include a number of private modules that exist solely to provide
// the rustdoc documentation for primitive types. Using `include!`
// because rustdoc only looks for these modules at the crate level.
diff --git a/src/libstd/sys/unix/stack_overflow.rs b/src/libstd/sys/unix/stack_overflow.rs
index 40453f9b8a1..a4ed53d1c0a 100644
--- a/src/libstd/sys/unix/stack_overflow.rs
+++ b/src/libstd/sys/unix/stack_overflow.rs
@@ -97,6 +97,10 @@ mod imp {
unsafe extern fn signal_handler(signum: libc::c_int,
info: *mut libc::siginfo_t,
_data: *mut libc::c_void) {
+ // A signal handler can corrupt a software trace.
+ use core::yk_swt;
+ yk_swt::invalidate_trace();
+
use sys_common::util::report_overflow;
let guard = thread_info::stack_guard().unwrap_or(0..0);
diff --git a/src/libstd/yk_swt.rs b/src/libstd/yk_swt.rs
deleted file mode 100644
index c5690af2a03..00000000000
--- a/src/libstd/yk_swt.rs
+++ /dev/null
@@ -1,19 +0,0 @@
-// Copyright 2018 King's College London.
-// Created by the Software Development Team .
-//
-// Licensed under the Apache License, Version 2.0 or the MIT license
-// , at your
-// option. This file may not be copied, modified, or distributed
-// except according to those terms.
-
-/// The software trace recorder function.
-/// The `AddYkSWTCalls` MIR pass injects a call this for every MIR block. The call is done
-/// indirectly via a wrapper in libcore.
-#[cfg_attr(not(stage0), lang="yk_swt_rec_loc")]
-#[allow(unused_variables,dead_code)]
-#[cfg_attr(not(stage0), no_trace)]
-#[cfg(not(test))]
-fn rec_loc(crate_hash: u64, def_idx: u32, bb_idx: u32) {
- // Not implemented.
-}
diff --git a/src/test/compile-fail/two-panic-runtimes.rs b/src/test/compile-fail/two-panic-runtimes.rs
index 4809d92f62b..36ed000e344 100644
--- a/src/test/compile-fail/two-panic-runtimes.rs
+++ b/src/test/compile-fail/two-panic-runtimes.rs
@@ -22,6 +22,3 @@ extern crate panic_runtime_unwind2;
extern crate panic_runtime_lang_items;
fn main() {}
-
-#[lang = "yk_swt_rec_loc"]
-fn yk_swt_rec_loc(_crate_hash: u64, _def_idx: u32, _bb: u32) {}
diff --git a/src/test/run-fail/yk_swt/oob-trace-idx.rs b/src/test/run-fail/yk_swt/oob-trace-idx.rs
new file mode 100644
index 00000000000..df1819f472d
--- /dev/null
+++ b/src/test/run-fail/yk_swt/oob-trace-idx.rs
@@ -0,0 +1,39 @@
+// Copyright 2019 King's College London.
+// Created by the Software Development Team .
+//
+// Licensed under the Apache License, Version 2.0 or the MIT license
+// , at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// error-pattern: software trace index out of bounds
+
+#![feature(yk_swt)]
+#![feature(libc)]
+#![feature(test)]
+
+extern crate core;
+extern crate libc;
+extern crate test;
+
+use core::yk_swt::{start_tracing, stop_tracing};
+use test::black_box;
+
+pub fn main() {
+ start_tracing();
+ black_box(work());
+ let trace = stop_tracing().unwrap();
+
+ // By reading one past the end of the trace buffer, we should cause the test to panic.
+ trace.loc(trace.len());
+}
+
+#[inline(never)]
+fn work() -> u64{
+ let mut res = 100;
+ for i in 0..100 {
+ res += res / 2 + i;
+ }
+ res
+}
diff --git a/src/test/run-make-fulldeps/issue-51671/app.rs b/src/test/run-make-fulldeps/issue-51671/app.rs
index 510e4836388..4066214f4b4 100644
--- a/src/test/run-make-fulldeps/issue-51671/app.rs
+++ b/src/test/run-make-fulldeps/issue-51671/app.rs
@@ -16,9 +16,6 @@
use core::alloc::Layout;
use core::panic::PanicInfo;
-#[lang = "yk_swt_rec_loc"]
-fn yk_swt_rec_loc(_crate_hash: u64, _def_idx: u32, _bb: u32) {}
-
#[panic_handler]
fn panic(_: &PanicInfo) -> ! {
loop {}
diff --git a/src/test/run-make-fulldeps/issue-53964/app.rs b/src/test/run-make-fulldeps/issue-53964/app.rs
index f5fa02d35f7..621e7e99263 100644
--- a/src/test/run-make-fulldeps/issue-53964/app.rs
+++ b/src/test/run-make-fulldeps/issue-53964/app.rs
@@ -5,8 +5,5 @@
#![deny(unused_extern_crates)]
#![feature(lang_items)]
-#[lang = "yk_swt_rec_loc"]
-fn yk_swt_rec_loc(_crate_hash: u64, _def_idx: u32, _bb: u32) {}
-
// `panic` provides a `panic_handler` so it shouldn't trip the `unused_extern_crates` lint
extern crate panic;
diff --git a/src/test/run-make-fulldeps/panic-impl-transitive/panic-impl-provider.rs b/src/test/run-make-fulldeps/panic-impl-transitive/panic-impl-provider.rs
index aa4dc8aeb88..0b11df6347c 100644
--- a/src/test/run-make-fulldeps/panic-impl-transitive/panic-impl-provider.rs
+++ b/src/test/run-make-fulldeps/panic-impl-transitive/panic-impl-provider.rs
@@ -12,9 +12,6 @@
#![no_std]
#![feature(lang_items)]
-#[lang = "yk_swt_rec_loc"]
-fn yk_swt_rec_loc(_crate_hash: u64, _def_idx: u32, _bb: u32) {}
-
use core::panic::PanicInfo;
#[panic_handler]
diff --git a/src/test/run-pass/thinlto/thin-lto-inlines2.rs b/src/test/run-pass/thinlto/thin-lto-inlines2.rs
index 84809b09785..33fe3b0c5b4 100644
--- a/src/test/run-pass/thinlto/thin-lto-inlines2.rs
+++ b/src/test/run-pass/thinlto/thin-lto-inlines2.rs
@@ -20,6 +20,8 @@
// praying two functions go into separate codegen units and then assuming that
// if inlining *doesn't* happen the first byte of the functions will differ.
+#![no_trace]
+
extern crate thin_lto_inlines_aux as bar;
pub fn foo() -> u32 {
diff --git a/src/test/run-pass/yk_swt/collect-trace-twice.rs b/src/test/run-pass/yk_swt/collect-trace-twice.rs
new file mode 100644
index 00000000000..ca356afbcb3
--- /dev/null
+++ b/src/test/run-pass/yk_swt/collect-trace-twice.rs
@@ -0,0 +1,53 @@
+// Copyright 2019 King's College London.
+// Created by the Software Development Team .
+//
+// Licensed under the Apache License, Version 2.0 or the MIT license
+// , at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+#![feature(yk_swt)]
+#![feature(libc)]
+#![feature(test)]
+
+extern crate core;
+extern crate libc;
+extern crate test;
+
+use core::yk_swt::{start_tracing, stop_tracing};
+use test::black_box;
+
+// Collect two traces sequentially in the same thread.
+pub fn main() {
+ start_tracing();
+ black_box(work1());
+ let trace1 = stop_tracing().unwrap();
+
+ start_tracing();
+ black_box(work2());
+ let trace2 = stop_tracing().unwrap();
+
+ assert!(trace1.len() > trace2.len());
+
+ unsafe { libc::free(trace1.buf() as *mut libc::c_void) };
+ unsafe { libc::free(trace2.buf() as *mut libc::c_void) };
+}
+
+#[inline(never)]
+fn work1() -> u64{
+ let mut res = 100;
+ for _ in 0..9000 {
+ res += 1;
+ }
+ res
+}
+
+#[inline(never)]
+fn work2() -> u64{
+ let mut res = 6000;
+ for _ in 0..3000 {
+ res -= 1;
+ }
+ res
+}
diff --git a/src/test/run-pass/yk_swt/collect-trace.rs b/src/test/run-pass/yk_swt/collect-trace.rs
new file mode 100644
index 00000000000..4e0e9c9e809
--- /dev/null
+++ b/src/test/run-pass/yk_swt/collect-trace.rs
@@ -0,0 +1,45 @@
+// Copyright 2019 King's College London.
+// Created by the Software Development Team .
+//
+// Licensed under the Apache License, Version 2.0 or the MIT license
+// , at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+#![feature(yk_swt)]
+#![feature(libc)]
+#![feature(test)]
+
+extern crate core;
+extern crate libc;
+extern crate test;
+
+use core::yk_swt::{start_tracing, stop_tracing};
+use test::black_box;
+
+pub fn main() {
+ start_tracing();
+ black_box(work());
+ let trace = stop_tracing().unwrap();
+
+ let len = trace.len();
+ // The default capacity of the trace buffer is 1024. We want to be sure we've tested the case
+ // where it had to be reallocated beyond its starting capacity.
+ assert!(len > 1024);
+
+ for idx in 0..len {
+ trace.loc(idx); // All indices are in bounds, so should not panic.
+ }
+
+ unsafe { libc::free(trace.buf() as *mut libc::c_void) };
+}
+
+#[inline(never)]
+fn work() -> u64{
+ let mut res = 100;
+ for i in 0..3000 {
+ res += res / 2 + i;
+ }
+ res
+}
diff --git a/src/test/run-pass/yk_swt/collect-traces-threaded.rs b/src/test/run-pass/yk_swt/collect-traces-threaded.rs
new file mode 100644
index 00000000000..7f336737501
--- /dev/null
+++ b/src/test/run-pass/yk_swt/collect-traces-threaded.rs
@@ -0,0 +1,70 @@
+// Copyright 2019 King's College London.
+// Created by the Software Development Team .
+//
+// Licensed under the Apache License, Version 2.0 or the MIT license
+// , at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+#![feature(yk_swt)]
+#![feature(libc)]
+#![feature(test)]
+
+extern crate core;
+extern crate libc;
+extern crate test;
+
+use core::yk_swt::{start_tracing, stop_tracing, SWTrace};
+use std::thread;
+use test::black_box;
+
+// Run tracing in two separate threads with different work and check that the traces are different.
+fn main() {
+ let thr2 = thread::spawn(move || {
+ start_tracing();
+ let _ = work2();
+ let raw_trace2 = stop_tracing().unwrap();
+ let trace2 = trace_to_vec(&raw_trace2);
+ unsafe { libc::free(raw_trace2.buf() as *mut libc::c_void) };
+ trace2
+ });
+
+ start_tracing();
+ black_box(work1());
+ let raw_trace1 = stop_tracing().unwrap();
+ let trace1 = trace_to_vec(&raw_trace1);
+ unsafe { libc::free(raw_trace1.buf() as *mut libc::c_void) };
+
+ let trace2 = thr2.join().unwrap();
+
+ assert_ne!(trace1, trace2); // They should have been thread local.
+}
+
+// Copies a trace into a plain Rust Vec of tuples so we can compare them.
+fn trace_to_vec(t: &SWTrace) -> Vec<(u64, u32, u32)> {
+ let mut v = Vec::new();
+ for i in 0..t.len() {
+ let loc = t.loc(i);
+ v.push((loc.crate_hash, loc.def_idx, loc.bb_idx));
+ }
+ v
+}
+
+#[inline(never)]
+fn work1() -> u64{
+ let mut res = 2000;
+ for _ in 0..1000 {
+ res -= 1;
+ }
+ res
+}
+
+#[inline(never)]
+fn work2() -> u64{
+ let mut res = 0;
+ for i in 0..2000 {
+ res += i + 1;
+ }
+ res
+}
diff --git a/src/test/run-pass/yk_swt/invalidate-trace.rs b/src/test/run-pass/yk_swt/invalidate-trace.rs
new file mode 100644
index 00000000000..9fd8a068637
--- /dev/null
+++ b/src/test/run-pass/yk_swt/invalidate-trace.rs
@@ -0,0 +1,36 @@
+// Copyright 2019 King's College London.
+// Created by the Software Development Team .
+//
+// Licensed under the Apache License, Version 2.0 or the MIT license
+// , at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+#![feature(yk_swt)]
+#![feature(libc)]
+#![feature(test)]
+
+extern crate core;
+extern crate libc;
+extern crate test;
+
+use core::yk_swt::{start_tracing, stop_tracing, invalidate_trace};
+use test::black_box;
+
+// Check that invalidating a trace works.
+fn main() {
+ start_tracing();
+ black_box(work());
+ invalidate_trace();
+ assert!(stop_tracing().is_none());
+}
+
+#[inline(never)]
+fn work() -> u64{
+ let mut res = 2000;
+ for _ in 0..100 {
+ res -= 1;
+ }
+ res
+}
diff --git a/src/test/ui/alloc-error/alloc-error-handler-bad-signature-1.rs b/src/test/ui/alloc-error/alloc-error-handler-bad-signature-1.rs
index 4204fe2d6bc..e98f22b301e 100644
--- a/src/test/ui/alloc-error/alloc-error-handler-bad-signature-1.rs
+++ b/src/test/ui/alloc-error/alloc-error-handler-bad-signature-1.rs
@@ -26,6 +26,3 @@ fn oom(
#[panic_handler]
fn panic(_: &core::panic::PanicInfo) -> ! { loop {} }
-
-#[lang = "yk_swt_rec_loc"]
-fn yk_swt_rec_loc(_crate_hash: u64, _def_idx: u32, _bb: u32) {}
diff --git a/src/test/ui/alloc-error/alloc-error-handler-bad-signature-2.rs b/src/test/ui/alloc-error/alloc-error-handler-bad-signature-2.rs
index 4cadf03676d..e2a9a7fd69a 100644
--- a/src/test/ui/alloc-error/alloc-error-handler-bad-signature-2.rs
+++ b/src/test/ui/alloc-error/alloc-error-handler-bad-signature-2.rs
@@ -25,6 +25,3 @@ fn oom(
#[panic_handler]
fn panic(_: &core::panic::PanicInfo) -> ! { loop {} }
-
-#[lang = "yk_swt_rec_loc"]
-fn yk_swt_rec_loc(_crate_hash: u64, _def_idx: u32, _bb: u32) {}
diff --git a/src/test/ui/alloc-error/alloc-error-handler-bad-signature-3.rs b/src/test/ui/alloc-error/alloc-error-handler-bad-signature-3.rs
index 2e465909723..0ab71160852 100644
--- a/src/test/ui/alloc-error/alloc-error-handler-bad-signature-3.rs
+++ b/src/test/ui/alloc-error/alloc-error-handler-bad-signature-3.rs
@@ -23,6 +23,3 @@ fn oom() -> ! { //~ ERROR function should have one argument
#[panic_handler]
fn panic(_: &core::panic::PanicInfo) -> ! { loop {} }
-
-#[lang = "yk_swt_rec_loc"]
-fn yk_swt_rec_loc(_crate_hash: u64, _def_idx: u32, _bb: u32) {}
diff --git a/src/test/ui/consts/const-eval/const_panic_libcore_main.rs b/src/test/ui/consts/const-eval/const_panic_libcore_main.rs
index d8301e11767..03365ae46ab 100644
--- a/src/test/ui/consts/const-eval/const_panic_libcore_main.rs
+++ b/src/test/ui/consts/const-eval/const_panic_libcore_main.rs
@@ -34,6 +34,3 @@ fn eh_unwind_resume() {}
fn panic(_info: &PanicInfo) -> ! {
loop {}
}
-
-#[lang = "yk_swt_rec_loc"]
-fn yk_swt_rec_loc(_crate_hash: u64, _def_idx: u32, _bb: u32) {}
diff --git a/src/test/ui/missing/missing-alloc_error_handler.rs b/src/test/ui/missing/missing-alloc_error_handler.rs
index d4a7feaddd4..89c368456b1 100644
--- a/src/test/ui/missing/missing-alloc_error_handler.rs
+++ b/src/test/ui/missing/missing-alloc_error_handler.rs
@@ -31,6 +31,3 @@ unsafe impl core::alloc::GlobalAlloc for MyAlloc {
unsafe fn alloc(&self, _: core::alloc::Layout) -> *mut u8 { 0 as _ }
unsafe fn dealloc(&self, _: *mut u8, _: core::alloc::Layout) {}
}
-
-#[lang = "yk_swt_rec_loc"]
-fn yk_swt_rec_loc(_crate_hash: u64, _def_idx: u32, _bb: u32) {}
diff --git a/src/test/ui/missing/missing-allocator.rs b/src/test/ui/missing/missing-allocator.rs
index 5650ec5907b..f4405d1f8fb 100644
--- a/src/test/ui/missing/missing-allocator.rs
+++ b/src/test/ui/missing/missing-allocator.rs
@@ -26,6 +26,3 @@ fn oom(_: core::alloc::Layout) -> ! {
}
extern crate alloc;
-
-#[lang = "yk_swt_rec_loc"]
-fn yk_swt_rec_loc(_crate_hash: u64, _def_idx: u32, _bb: u32) {}
diff --git a/src/test/ui/no_owned_box_lang_item.rs b/src/test/ui/no_owned_box_lang_item.rs
index 49546e32bbb..34d1075f9b7 100644
--- a/src/test/ui/no_owned_box_lang_item.rs
+++ b/src/test/ui/no_owned_box_lang_item.rs
@@ -24,4 +24,3 @@ fn main() {
#[lang = "eh_personality"] extern fn eh_personality() {}
#[lang = "eh_unwind_resume"] extern fn eh_unwind_resume() {}
#[lang = "panic_impl"] fn panic_impl(panic: &PanicInfo) -> ! { loop {} }
-#[lang = "yk_swt_rec_loc"] fn yk_swt_rec_loc(_crate_hash: u64, _def_idx: u32, _bb: u32) {}
diff --git a/src/test/ui/panic-handler/panic-handler-bad-signature-1.rs b/src/test/ui/panic-handler/panic-handler-bad-signature-1.rs
index ee2d554a646..b82a2274390 100644
--- a/src/test/ui/panic-handler/panic-handler-bad-signature-1.rs
+++ b/src/test/ui/panic-handler/panic-handler-bad-signature-1.rs
@@ -22,6 +22,3 @@ fn panic(
) -> () //~ ERROR return type should be `!`
{
}
-
-#[lang = "yk_swt_rec_loc"]
-fn yk_swt_rec_loc(_crate_hash: u64, _def_idx: u32, _bb: u32) {}
diff --git a/src/test/ui/panic-handler/panic-handler-bad-signature-2.rs b/src/test/ui/panic-handler/panic-handler-bad-signature-2.rs
index ccb79410aa1..ccc9dfd7aaa 100644
--- a/src/test/ui/panic-handler/panic-handler-bad-signature-2.rs
+++ b/src/test/ui/panic-handler/panic-handler-bad-signature-2.rs
@@ -23,6 +23,3 @@ fn panic(
{
loop {}
}
-
-#[lang = "yk_swt_rec_loc"]
-fn yk_swt_rec_loc(_crate_hash: u64, _def_idx: u32, _bb: u32) {}
diff --git a/src/test/ui/panic-handler/panic-handler-bad-signature-3.rs b/src/test/ui/panic-handler/panic-handler-bad-signature-3.rs
index 041303fca5f..03be5307986 100644
--- a/src/test/ui/panic-handler/panic-handler-bad-signature-3.rs
+++ b/src/test/ui/panic-handler/panic-handler-bad-signature-3.rs
@@ -20,6 +20,3 @@ use core::panic::PanicInfo;
fn panic() -> ! { //~ ERROR function should have one argument
loop {}
}
-
-#[lang = "yk_swt_rec_loc"]
-fn yk_swt_rec_loc(_crate_hash: u64, _def_idx: u32, _bb: u32) {}
diff --git a/src/test/ui/panic-handler/panic-handler-bad-signature-4.rs b/src/test/ui/panic-handler/panic-handler-bad-signature-4.rs
index d21962085b8..ba013b87e37 100644
--- a/src/test/ui/panic-handler/panic-handler-bad-signature-4.rs
+++ b/src/test/ui/panic-handler/panic-handler-bad-signature-4.rs
@@ -21,6 +21,3 @@ fn panic(pi: &PanicInfo) -> ! {
//~^ ERROR should have no type parameters
loop {}
}
-
-#[lang = "yk_swt_rec_loc"]
-fn yk_swt_rec_loc(_crate_hash: u64, _def_idx: u32, _bb: u32) {}
diff --git a/src/test/ui/panic-handler/panic-handler-duplicate.rs b/src/test/ui/panic-handler/panic-handler-duplicate.rs
index 1e45727439c..c4fb4903e00 100644
--- a/src/test/ui/panic-handler/panic-handler-duplicate.rs
+++ b/src/test/ui/panic-handler/panic-handler-duplicate.rs
@@ -25,6 +25,3 @@ fn panic(info: &PanicInfo) -> ! {
fn panic2(info: &PanicInfo) -> ! { //~ ERROR duplicate lang item found: `panic_impl`.
loop {}
}
-
-#[lang = "yk_swt_rec_loc"]
-fn yk_swt_rec_loc(_crate_hash: u64, _def_idx: u32, _bb: u32) {}
diff --git a/src/test/ui/panic-handler/panic-handler-wrong-location.rs b/src/test/ui/panic-handler/panic-handler-wrong-location.rs
index 5434b28795c..8d0b655515d 100644
--- a/src/test/ui/panic-handler/panic-handler-wrong-location.rs
+++ b/src/test/ui/panic-handler/panic-handler-wrong-location.rs
@@ -17,6 +17,3 @@
#[panic_handler]
#[no_mangle]
static X: u32 = 42;
-
-#[lang = "yk_swt_rec_loc"]
-fn yk_swt_rec_loc(_crate_hash: u64, _def_idx: u32, _bb: u32) {}
diff --git a/src/test/ui/panic-runtime/transitive-link-a-bunch.rs b/src/test/ui/panic-runtime/transitive-link-a-bunch.rs
index 2f6af734d22..e40706b7935 100644
--- a/src/test/ui/panic-runtime/transitive-link-a-bunch.rs
+++ b/src/test/ui/panic-runtime/transitive-link-a-bunch.rs
@@ -24,6 +24,3 @@ extern crate wants_panic_runtime_abort;
extern crate panic_runtime_lang_items;
fn main() {}
-
-#[lang = "yk_swt_rec_loc"]
-fn yk_swt_rec_loc(_crate_hash: u64, _def_idx: u32, _bb: u32) {}
diff --git a/src/test/ui/panic-runtime/want-unwind-got-abort.rs b/src/test/ui/panic-runtime/want-unwind-got-abort.rs
index f04e302cbd5..38de5d4407b 100644
--- a/src/test/ui/panic-runtime/want-unwind-got-abort.rs
+++ b/src/test/ui/panic-runtime/want-unwind-got-abort.rs
@@ -20,6 +20,3 @@ extern crate panic_runtime_abort;
extern crate panic_runtime_lang_items;
fn main() {}
-
-#[lang = "yk_swt_rec_loc"]
-fn yk_swt_rec_loc(_crate_hash: u64, _def_idx: u32, _bb: u32) {}
diff --git a/src/test/ui/panic-runtime/want-unwind-got-abort2.rs b/src/test/ui/panic-runtime/want-unwind-got-abort2.rs
index 3dd2501ad54..bb47dc84904 100644
--- a/src/test/ui/panic-runtime/want-unwind-got-abort2.rs
+++ b/src/test/ui/panic-runtime/want-unwind-got-abort2.rs
@@ -21,6 +21,3 @@ extern crate wants_panic_runtime_abort;
extern crate panic_runtime_lang_items;
fn main() {}
-
-#[lang = "yk_swt_rec_loc"]
-fn yk_swt_rec_loc(_crate_hash: u64, _def_idx: u32, _bb: u32) {}
diff --git a/src/test/ui/range/issue-54505-no-std.rs b/src/test/ui/range/issue-54505-no-std.rs
index 4032ebf144d..22cf15fb2e4 100644
--- a/src/test/ui/range/issue-54505-no-std.rs
+++ b/src/test/ui/range/issue-54505-no-std.rs
@@ -55,6 +55,3 @@ fn main() {
//~| HELP consider borrowing here
//~| SUGGESTION &(..=42)
}
-
-#[lang = "yk_swt_rec_loc"]
-fn yk_swt_rec_loc(_crate_hash: u64, _def_idx: u32, _bb: u32) {}