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

Commit 7147033

Browse files
committed
Try #2:
2 parents a9abb9a + 74a44dc commit 7147033

File tree

136 files changed

+438
-14
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

136 files changed

+438
-14
lines changed

.buildbot.toml

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,8 @@
11
# Config file for continuous integration.
22

33
[rust]
4-
# Use threads.
5-
codegen-units = 0
4+
codegen-units = 0 # Use many compilation units.
5+
debug-assertions = true # Turn on assertions in rustc.
6+
7+
[llvm]
8+
assertions = true # Turn on assertions in LLVM.

src/libcore/lib.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -229,6 +229,8 @@ mod nonzero;
229229
mod tuple;
230230
mod unit;
231231

232+
mod yk_swt;
233+
232234
// Pull in the `coresimd` crate directly into libcore. This is where all the
233235
// architecture-specific (and vendor-specific) intrinsics are defined. AKA
234236
// things like SIMD and such. Note that the actual source for all this lies in a

src/libcore/yk_swt.rs

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
// Copyright 2018 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+
/// The software trace recorder function.
11+
/// This is a weak language item, it actually resides in libstd. It has to be weak to allow libcore
12+
/// to call up to libstd (libstd is not a dependency of libcore).
13+
extern "Rust" {
14+
#[cfg_attr(not(stage0), lang="yk_swt_rec_loc")]
15+
fn yk_swt_rec_loc(crate_hash: u64, def_idx: u32, bb: u32);
16+
}
17+
18+
/// Wrapper lang item to call the above wrapper function.
19+
/// This has to be a lang item too, as a MIR terminator cannot call a weak language item directly.
20+
#[allow(dead_code)] // Used only indirectly in a MIR pass.
21+
#[cfg_attr(not(stage0), lang="yk_swt_rec_loc_wrap")]
22+
#[cfg_attr(not(stage0), no_trace)]
23+
fn yk_swt_rec_loc_wrap(crate_hash: u64, def_idx: u32, bb: u32) {
24+
unsafe { yk_swt_rec_loc(crate_hash, def_idx, bb) };
25+
}
26+

src/librustc/middle/lang_items.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -376,6 +376,9 @@ language_item_table! {
376376
I128ShroFnLangItem, "i128_shro", i128_shro_fn, Target::Fn;
377377
U128ShroFnLangItem, "u128_shro", u128_shro_fn, Target::Fn;
378378

379+
YkSwtRecLocLangItem, "yk_swt_rec_loc", yk_swt_rec_loc, Target::Fn;
380+
YkSwtRecLocWrapLangItem, "yk_swt_rec_loc_wrap",yk_swt_rec_loc_wrap, Target::Fn;
381+
379382
// Align offset for stride != 1, must not panic.
380383
AlignOffsetLangItem, "align_offset", align_offset_fn, Target::Fn;
381384

src/librustc/middle/weak_lang_items.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -168,4 +168,5 @@ weak_lang_items! {
168168
eh_personality, EhPersonalityLangItem, rust_eh_personality;
169169
eh_unwind_resume, EhUnwindResumeLangItem, rust_eh_unwind_resume;
170170
oom, OomLangItem, rust_oom;
171+
yk_swt_rec_loc, YkSwtRecLocLangItem, rust_yk_swt_rec_loc;
171172
}

src/librustc/ty/sty.rs

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2035,6 +2035,16 @@ impl<'tcx> Const<'tcx> {
20352035
Self::from_bits(tcx, n as u128, ParamEnv::empty().and(tcx.types.usize))
20362036
}
20372037

2038+
#[inline]
2039+
pub fn from_u32(tcx: TyCtxt<'_, '_, 'tcx>, n: u32) -> &'tcx Self {
2040+
Self::from_bits(tcx, n as u128, ParamEnv::empty().and(tcx.types.u32))
2041+
}
2042+
2043+
#[inline]
2044+
pub fn from_u64(tcx: TyCtxt<'_, '_, 'tcx>, n: u64) -> &'tcx Self {
2045+
Self::from_bits(tcx, n as u128, ParamEnv::empty().and(tcx.types.u64))
2046+
}
2047+
20382048
#[inline]
20392049
pub fn to_bits(
20402050
&self,
Lines changed: 170 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,170 @@
1+
// Copyright 2018 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+
use rustc::ty::{self, TyCtxt, List};
11+
use rustc::mir::{Operand, LocalDecl, Place, SourceInfo, BasicBlock, Local, BasicBlockData,
12+
TerminatorKind, Terminator, OUTERMOST_SOURCE_SCOPE, Constant, Mir};
13+
use rustc_data_structures::indexed_vec::Idx;
14+
use syntax_pos::DUMMY_SP;
15+
use syntax::attr;
16+
use transform::{MirPass, MirSource};
17+
use rustc::hir;
18+
use rustc::hir::def_id::{DefIndex, LOCAL_CRATE};
19+
use rustc::hir::map::blocks::FnLikeNode;
20+
21+
/// A MIR pass which, for each basic block, inserts a call to the software trace recorder.
22+
/// The call arguments passed uniquely identify the MIR location.
23+
pub struct AddYkSWTCalls(pub DefIndex);
24+
25+
impl MirPass for AddYkSWTCalls {
26+
fn run_pass<'a, 'tcx>(&self,
27+
tcx: TyCtxt<'a, 'tcx, 'tcx>,
28+
src: MirSource,
29+
mir: &mut Mir<'tcx>) {
30+
if !should_annotate(tcx, src) {
31+
return;
32+
}
33+
34+
// Find the recorder function to call.
35+
let rec_fn_defid = tcx.get_lang_items(LOCAL_CRATE).yk_swt_rec_loc_wrap()
36+
.expect("couldn't find software trace recorder function");
37+
38+
// Types.
39+
let unit_ty = tcx.mk_unit();
40+
let u32_ty = tcx.types.u32;
41+
let u64_ty = tcx.types.u64;
42+
43+
// Each block is replaced by a new block whose terminator calls the recorder function.
44+
let mut replace_blocks = Vec::new();
45+
46+
// The original blocks are copied and the recorder function returns to a copy.
47+
let mut copied_blocks = Vec::new();
48+
49+
// New local decls are required to accomodate the (unit) return value of the recorder func.
50+
let mut new_local_decls = Vec::new();
51+
52+
let num_orig_blocks = mir.basic_blocks().len();
53+
let num_orig_local_decls = mir.local_decls.len();
54+
let local_crate_hash = tcx.crate_hash(LOCAL_CRATE).as_u64();
55+
56+
for (bb, bb_data) in mir.basic_blocks_mut().iter_enumerated() {
57+
// Copy the original block and compute what its index will be once we have pushed onto
58+
// the end of the MIR's basic block vector.
59+
let new_blk = bb_data.clone();
60+
let new_blk_idx = BasicBlock::new(num_orig_blocks + copied_blocks.len());
61+
copied_blocks.push(new_blk);
62+
63+
// Prepare to call the recorder function.
64+
let ret_val = LocalDecl::new_temp(unit_ty, DUMMY_SP);
65+
let ret_place = Place::Local(Local::new(num_orig_local_decls + new_local_decls.len()));
66+
new_local_decls.push(ret_val);
67+
68+
let crate_hash_oper = Operand::Constant(box Constant {
69+
span: DUMMY_SP,
70+
ty: u64_ty,
71+
user_ty: None,
72+
literal: ty::Const::from_u64(tcx, local_crate_hash),
73+
});
74+
75+
let def_idx_oper = Operand::Constant(box Constant {
76+
span: DUMMY_SP,
77+
ty: u32_ty,
78+
user_ty: None,
79+
literal: ty::Const::from_u32(tcx, self.0.as_raw_u32()),
80+
});
81+
82+
let bb_oper = Operand::Constant(box Constant {
83+
span: DUMMY_SP,
84+
ty: u32_ty,
85+
user_ty: None,
86+
literal: ty::Const::from_u32(tcx, bb.index() as u32),
87+
});
88+
89+
let rec_fn_oper = Operand::function_handle(tcx, rec_fn_defid,
90+
List::empty(), DUMMY_SP);
91+
92+
let term_kind = TerminatorKind::Call {
93+
func: rec_fn_oper,
94+
args: vec![crate_hash_oper, def_idx_oper, bb_oper],
95+
destination: Some((ret_place, new_blk_idx)),
96+
cleanup: None,
97+
from_hir_call: false,
98+
};
99+
100+
// Construct a new block to replace the original one.
101+
let source_info = bb_data.terminator.clone().map(|t| t.source_info)
102+
.or(Some(SourceInfo { span: DUMMY_SP, scope: OUTERMOST_SOURCE_SCOPE })).unwrap();
103+
let replace_block = BasicBlockData {
104+
statements: vec![],
105+
terminator: Some(Terminator {
106+
source_info,
107+
kind: term_kind
108+
}),
109+
is_cleanup: false
110+
};
111+
replace_blocks.push(replace_block);
112+
}
113+
114+
// Finally, commit our transformations.
115+
mir.basic_blocks_mut().extend(copied_blocks);
116+
mir.local_decls.extend(new_local_decls);
117+
for (bb, bb_data) in replace_blocks.drain(..).enumerate() {
118+
mir.basic_blocks_mut()[BasicBlock::new(bb)] = bb_data;
119+
}
120+
}
121+
}
122+
123+
/// Given a `MirSource`, decides if we should annotate the correpsonding MIR.
124+
fn should_annotate(tcx: TyCtxt<'a, 'tcx, 'tcx>, src: MirSource) -> bool {
125+
// Never annotate any MIR-like thing marked `#[no_trace]` or `#[naked]`. The trace record and
126+
// wrapper are also marked `#[no_trace]` to prevent infinite recursion.
127+
for attr in tcx.get_attrs(src.def_id).iter() {
128+
if attr.check_name("no_trace") {
129+
return false;
130+
}
131+
if attr.check_name("naked") {
132+
return false;
133+
}
134+
}
135+
136+
// If there is a crate level `#![no_trace]` attribute, honour that.
137+
for attr in tcx.hir.krate_attrs() {
138+
if attr.check_name("no_trace") {
139+
return false;
140+
}
141+
}
142+
143+
// We can't call the software tracing function if there is no libcore.
144+
if attr::contains_name(tcx.hir.krate_attrs(), "no_core") {
145+
return false;
146+
}
147+
148+
// The libcompiler_builtins crate is special and we can't annotate it.
149+
if tcx.is_compiler_builtins(LOCAL_CRATE) {
150+
return false;
151+
}
152+
153+
// We can't add calls to promoted items.
154+
if let Some(_) = src.promoted {
155+
return false;
156+
}
157+
158+
// We can't add calls to constant functions.
159+
let node_id = tcx.hir.as_local_node_id(src.def_id)
160+
.expect("Failed to get node id");
161+
if let Some(fn_like) = FnLikeNode::from_node(tcx.hir.get(node_id)) {
162+
if fn_like.constness() == hir::Constness::Const {
163+
return false;
164+
}
165+
} else {
166+
return false;
167+
}
168+
169+
true
170+
}

src/librustc_mir/transform/mod.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,7 @@ pub mod generator;
4747
pub mod inline;
4848
pub mod lower_128bit;
4949
pub mod uniform_array_move_out;
50+
pub mod add_yk_swt_calls;
5051

5152
pub(crate) fn provide(providers: &mut Providers) {
5253
self::qualify_consts::provide(providers);
@@ -302,6 +303,7 @@ fn optimized_mir<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId) -> &'tcx
302303
&simplify::SimplifyLocals,
303304

304305
&add_call_guards::CriticalCallEdges,
306+
&add_yk_swt_calls::AddYkSWTCalls(def_id.index),
305307
&dump_mir::Marker("PreCodegen"),
306308
]);
307309
tcx.alloc_mir(mir)

src/libstd/lib.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -518,6 +518,10 @@ mod coresimd {
518518
#[cfg(all(not(stage0), not(test)))]
519519
pub use stdsimd::arch;
520520

521+
/// Yorick software tracing.
522+
#[unstable(feature = "yk_swt", issue = "0")]
523+
pub mod yk_swt;
524+
521525
// Include a number of private modules that exist solely to provide
522526
// the rustdoc documentation for primitive types. Using `include!`
523527
// because rustdoc only looks for these modules at the crate level.

src/libstd/yk_swt.rs

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
// Copyright 2018 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+
/// The software trace recorder function.
11+
/// The `AddYkSWTCalls` MIR pass injects a call this for every MIR block. The call is done
12+
/// indirectly via a wrapper in libcore.
13+
#[cfg_attr(not(stage0), lang="yk_swt_rec_loc")]
14+
#[allow(unused_variables,dead_code)]
15+
#[cfg_attr(not(stage0), no_trace)]
16+
#[cfg(not(test))]
17+
fn rec_loc(crate_hash: u64, def_idx: u32, bb_idx: u32) {
18+
// Not implemented.
19+
}

0 commit comments

Comments
 (0)