From cf693df54760fe4da0dd0e9a4dcbd949c1af5827 Mon Sep 17 00:00:00 2001 From: Edd Barrett Date: Tue, 15 Jan 2019 16:29:23 +0000 Subject: [PATCH 1/2] Implement low-level software trace recording, in C, in libcore. This is implemented in C because if it were implemented in Rust, then the tracer code would trace itself and everything it calls (or we'd end up annotating a lot of the standard library `#[no_trace]`). With each call to the trace recorder, we build a "MIR location" struct from the call arguments and insert this into a thread local trace buffer. A successful tracing session will return the trace buffer to the consumer when we stop tracing. If however something happens which renders the trace data unreliable, we say the trace was "invalidated" and return NULL. For example, a trace is invalidated when the Rust stack overflow detector's signal handler interrupts a trace. A trace is also invalidated when when the trace buffer can't be a allocated or re-allocated. User signal handlers remain an open problem, as we are unable to force code outside of our hands to invalidate a trace. --- src/Cargo.lock | 1 + src/libcore/Cargo.toml | 3 + src/libcore/build.rs | 22 +++ src/libcore/lib.rs | 4 +- src/libcore/yk_swt.rs | 93 +++++++++++-- src/libcore/yk_swt_impl.c | 130 ++++++++++++++++++ src/librustc/middle/lang_items.rs | 1 - src/librustc/middle/weak_lang_items.rs | 1 - .../transform/add_yk_swt_calls.rs | 2 +- src/libstd/lib.rs | 5 +- src/libstd/sys/unix/stack_overflow.rs | 4 + src/libstd/yk_swt.rs | 19 --- src/test/run-fail/yk_swt/oob-trace-idx.rs | 39 ++++++ .../run-pass/thinlto/thin-lto-inlines2.rs | 2 + .../run-pass/yk_swt/collect-trace-twice.rs | 53 +++++++ src/test/run-pass/yk_swt/collect-trace.rs | 45 ++++++ .../yk_swt/collect-traces-threaded.rs | 70 ++++++++++ src/test/run-pass/yk_swt/invalidate-trace.rs | 36 +++++ 18 files changed, 492 insertions(+), 38 deletions(-) create mode 100644 src/libcore/build.rs create mode 100644 src/libcore/yk_swt_impl.c delete mode 100644 src/libstd/yk_swt.rs create mode 100644 src/test/run-fail/yk_swt/oob-trace-idx.rs create mode 100644 src/test/run-pass/yk_swt/collect-trace-twice.rs create mode 100644 src/test/run-pass/yk_swt/collect-trace.rs create mode 100644 src/test/run-pass/yk_swt/collect-traces-threaded.rs create mode 100644 src/test/run-pass/yk_swt/invalidate-trace.rs 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/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-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 +} From 12a2499a7b11591c9aaac1a7639e78ab853ffe43 Mon Sep 17 00:00:00 2001 From: Edd Barrett Date: Thu, 17 Jan 2019 13:40:09 +0000 Subject: [PATCH 2/2] Remove dummy language items impls from tests. No longer needed. Since the software tracing function is now implemented in C, tracing no longer interferes in these tests. --- src/test/compile-fail/two-panic-runtimes.rs | 3 --- src/test/run-make-fulldeps/issue-51671/app.rs | 3 --- src/test/run-make-fulldeps/issue-53964/app.rs | 3 --- .../panic-impl-transitive/panic-impl-provider.rs | 3 --- src/test/ui/alloc-error/alloc-error-handler-bad-signature-1.rs | 3 --- src/test/ui/alloc-error/alloc-error-handler-bad-signature-2.rs | 3 --- src/test/ui/alloc-error/alloc-error-handler-bad-signature-3.rs | 3 --- src/test/ui/consts/const-eval/const_panic_libcore_main.rs | 3 --- src/test/ui/missing/missing-alloc_error_handler.rs | 3 --- src/test/ui/missing/missing-allocator.rs | 3 --- src/test/ui/no_owned_box_lang_item.rs | 1 - src/test/ui/panic-handler/panic-handler-bad-signature-1.rs | 3 --- src/test/ui/panic-handler/panic-handler-bad-signature-2.rs | 3 --- src/test/ui/panic-handler/panic-handler-bad-signature-3.rs | 3 --- src/test/ui/panic-handler/panic-handler-bad-signature-4.rs | 3 --- src/test/ui/panic-handler/panic-handler-duplicate.rs | 3 --- src/test/ui/panic-handler/panic-handler-wrong-location.rs | 3 --- src/test/ui/panic-runtime/transitive-link-a-bunch.rs | 3 --- src/test/ui/panic-runtime/want-unwind-got-abort.rs | 3 --- src/test/ui/panic-runtime/want-unwind-got-abort2.rs | 3 --- src/test/ui/range/issue-54505-no-std.rs | 3 --- 21 files changed, 61 deletions(-) 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-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/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) {}