Skip to content

[MIR] Some initial zeroing implementation work #31430

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 6 commits into from
Mar 2, 2016
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion src/librustc/dep_graph/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -198,8 +198,8 @@ pub fn visit_all_items_in_krate<'tcx,V,F>(tcx: &ty::ctxt<'tcx>,
fn visit_item(&mut self, i: &'tcx hir::Item) {
let item_def_id = self.tcx.map.local_def_id(i.id);
let task_id = (self.dep_node_fn)(item_def_id);
debug!("About to start task {:?}", task_id);
let _task = self.tcx.dep_graph.in_task(task_id);
debug!("Started task {:?}", task_id);
self.tcx.dep_graph.read(DepNode::Hir(item_def_id));
self.visitor.visit_item(i)
}
Expand Down
2 changes: 2 additions & 0 deletions src/librustc_llvm/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2165,6 +2165,8 @@ extern {
NumInputs: c_uint)
-> OperandBundleDefRef;
pub fn LLVMRustFreeOperandBundleDef(Bundle: OperandBundleDefRef);

pub fn LLVMRustPositionBuilderAtStart(B: BuilderRef, BB: BasicBlockRef);
}

// LLVM requires symbols from this library, but apparently they're not printed
Expand Down
62 changes: 56 additions & 6 deletions src/librustc_mir/build/block.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,14 +21,64 @@ impl<'a,'tcx> Builder<'a,'tcx> {
-> BlockAnd<()> {
let Block { extent, span, stmts, expr } = self.hir.mirror(ast_block);
self.in_scope(extent, block, move |this| {
unpack!(block = this.stmts(block, stmts));
match expr {
Some(expr) => this.into(destination, block, expr),
None => {
this.cfg.push_assign_unit(block, span, destination);
block.unit()
// This convoluted structure is to avoid using recursion as we walk down a list
// of statements. Basically, the structure we get back is something like:
//
// let x = <init> in {
// expr1;
// let y = <init> in {
// expr2;
// expr3;
// ...
// }
// }
//
// The let bindings are valid till the end of block so all we have to do is to pop all
// the let-scopes at the end.
//
// First we build all the statements in the block.
let mut let_extent_stack = Vec::with_capacity(8);
for stmt in stmts {
let Stmt { span: _, kind } = this.hir.mirror(stmt);
match kind {
StmtKind::Expr { scope, expr } => {
unpack!(block = this.in_scope(scope, block, |this| {
let expr = this.hir.mirror(expr);
let temp = this.temp(expr.ty.clone());
unpack!(block = this.into(&temp, block, expr));
unpack!(block = this.build_drop(block, temp));
block.unit()
}));
}
StmtKind::Let { remainder_scope, init_scope, pattern, initializer } => {
this.push_scope(remainder_scope);
let_extent_stack.push(remainder_scope);
unpack!(block = this.in_scope(init_scope, block, move |this| {
// FIXME #30046 ^~~~
if let Some(init) = initializer {
this.expr_into_pattern(block, remainder_scope, pattern, init)
} else {
this.declare_bindings(remainder_scope, &pattern);
block.unit()
}
}));
}
}
}
// Then, the block may have an optional trailing expression which is a “return” value
// of the block.
if let Some(expr) = expr {
unpack!(block = this.into(destination, block, expr));
} else {
// FIXME(#31472)
this.cfg.push_assign_unit(block, span, destination);
}
// Finally, we pop all the let scopes before exiting out from the scope of block
// itself.
for extent in let_extent_stack.into_iter().rev() {
unpack!(block = this.pop_scope(extent, block));
}
block.unit()
})
}
}
1 change: 0 additions & 1 deletion src/librustc_mir/build/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -185,4 +185,3 @@ mod into;
mod matches;
mod misc;
mod scope;
mod stmt;
1 change: 1 addition & 0 deletions src/librustc_mir/build/scope.rs
Original file line number Diff line number Diff line change
Expand Up @@ -249,6 +249,7 @@ impl<'a,'tcx> Builder<'a,'tcx> {
extent: CodeExtent,
mut block: BasicBlock,
target: BasicBlock) {
debug!("exit_scope(extent={:?}, block={:?}, target={:?})", extent, block, target);
let scope_count = 1 + self.scopes.iter().rev().position(|scope| scope.extent == extent)
.unwrap_or_else(||{
self.hir.span_bug(span, &format!("extent {:?} does not enclose", extent))
Expand Down
83 changes: 0 additions & 83 deletions src/librustc_mir/build/stmt.rs

This file was deleted.

76 changes: 33 additions & 43 deletions src/librustc_mir/hair/cx/block.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,62 +21,52 @@ impl<'tcx> Mirror<'tcx> for &'tcx hir::Block {
fn make_mirror<'a>(self, cx: &mut Cx<'a, 'tcx>) -> Block<'tcx> {
// We have to eagerly translate the "spine" of the statements
// in order to get the lexical scoping correctly.
let stmts = mirror_stmts(cx, self.id, self.stmts.iter().enumerate());
let stmts = mirror_stmts(cx, self.id, &*self.stmts);
Block {
extent: cx.tcx.region_maps.node_extent(self.id),
span: self.span,
stmts: stmts,
expr: self.expr.to_ref(),
expr: self.expr.to_ref()
}
}
}

fn mirror_stmts<'a,'tcx:'a,STMTS>(cx: &mut Cx<'a,'tcx>,
block_id: ast::NodeId,
mut stmts: STMTS)
-> Vec<StmtRef<'tcx>>
where STMTS: Iterator<Item=(usize, &'tcx hir::Stmt)>
fn mirror_stmts<'a,'tcx:'a>(cx: &mut Cx<'a,'tcx>,
block_id: ast::NodeId,
stmts: &'tcx [hir::Stmt])
-> Vec<StmtRef<'tcx>>
{
let mut result = vec![];
while let Some((index, stmt)) = stmts.next() {
for (index, stmt) in stmts.iter().enumerate() {
match stmt.node {
hir::StmtExpr(ref expr, id) | hir::StmtSemi(ref expr, id) =>
result.push(
StmtRef::Mirror(
Box::new(Stmt { span: stmt.span,
kind: StmtKind::Expr {
scope: cx.tcx.region_maps.node_extent(id),
expr: expr.to_ref() } }))),

hir::StmtDecl(ref decl, id) => {
match decl.node {
hir::DeclItem(..) => { /* ignore for purposes of the MIR */ }
hir::DeclLocal(ref local) => {
let remainder_extent = CodeExtentData::Remainder(BlockRemainder {
block: block_id,
first_statement_index: index as u32,
});
let remainder_extent =
cx.tcx.region_maps.lookup_code_extent(remainder_extent);

// pull in all following statements, since
// they are within the scope of this let:
let following_stmts = mirror_stmts(cx, block_id, stmts);

let pattern = cx.irrefutable_pat(&local.pat);
result.push(StmtRef::Mirror(Box::new(Stmt {
span: stmt.span,
kind: StmtKind::Let {
remainder_scope: remainder_extent,
init_scope: cx.tcx.region_maps.node_extent(id),
pattern: pattern,
initializer: local.init.to_ref(),
stmts: following_stmts,
},
})));

return result;
result.push(StmtRef::Mirror(Box::new(Stmt {
span: stmt.span,
kind: StmtKind::Expr {
scope: cx.tcx.region_maps.node_extent(id),
expr: expr.to_ref()
}
}))),
hir::StmtDecl(ref decl, id) => match decl.node {
hir::DeclItem(..) => { /* ignore for purposes of the MIR */ }
hir::DeclLocal(ref local) => {
let remainder_extent = CodeExtentData::Remainder(BlockRemainder {
block: block_id,
first_statement_index: index as u32,
});
let remainder_extent =
cx.tcx.region_maps.lookup_code_extent(remainder_extent);

let pattern = cx.irrefutable_pat(&local.pat);
result.push(StmtRef::Mirror(Box::new(Stmt {
span: stmt.span,
kind: StmtKind::Let {
remainder_scope: remainder_extent,
init_scope: cx.tcx.region_maps.node_extent(id),
pattern: pattern,
initializer: local.init.to_ref(),
},
})));
}
}
}
Expand Down
5 changes: 1 addition & 4 deletions src/librustc_mir/hair/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -78,10 +78,7 @@ pub enum StmtKind<'tcx> {
pattern: Pattern<'tcx>,

/// let pat = <INIT> ...
initializer: Option<ExprRef<'tcx>>,

/// let pat = init; <STMTS>
stmts: Vec<StmtRef<'tcx>>,
initializer: Option<ExprRef<'tcx>>
},
}

Expand Down
25 changes: 16 additions & 9 deletions src/librustc_trans/trans/base.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1298,22 +1298,29 @@ pub fn init_zero_mem<'blk, 'tcx>(cx: Block<'blk, 'tcx>, llptr: ValueRef, t: Ty<'
fn memfill<'a, 'tcx>(b: &Builder<'a, 'tcx>, llptr: ValueRef, ty: Ty<'tcx>, byte: u8) {
let _icx = push_ctxt("memfill");
let ccx = b.ccx;

let llty = type_of::type_of(ccx, ty);
let ptr_width = &ccx.sess().target.target.target_pointer_width[..];
let intrinsic_key = format!("llvm.memset.p0i8.i{}", ptr_width);

let llintrinsicfn = ccx.get_intrinsic(&intrinsic_key);
let llptr = b.pointercast(llptr, Type::i8(ccx).ptr_to());
let llzeroval = C_u8(ccx, byte);
let size = machine::llsize_of(ccx, llty);
let align = C_i32(ccx, type_of::align_of(ccx, ty) as i32);
let volatile = C_bool(ccx, false);
b.call(llintrinsicfn,
&[llptr, llzeroval, size, align, volatile],
None, None);
call_memset(b, llptr, llzeroval, size, align, false);
}

pub fn call_memset<'bcx, 'tcx>(b: &Builder<'bcx, 'tcx>,
ptr: ValueRef,
fill_byte: ValueRef,
size: ValueRef,
align: ValueRef,
volatile: bool) {
let ccx = b.ccx;
let ptr_width = &ccx.sess().target.target.target_pointer_width[..];
let intrinsic_key = format!("llvm.memset.p0i8.i{}", ptr_width);
let llintrinsicfn = ccx.get_intrinsic(&intrinsic_key);
let volatile = C_bool(ccx, volatile);
b.call(llintrinsicfn, &[ptr, fill_byte, size, align, volatile], None, None);
}


/// In general, when we create an scratch value in an alloca, the
/// creator may not know if the block (that initializes the scratch
/// with the desired value) actually dominates the cleanup associated
Expand Down
6 changes: 6 additions & 0 deletions src/librustc_trans/trans/builder.rs
Original file line number Diff line number Diff line change
Expand Up @@ -104,6 +104,12 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
}
}

pub fn position_at_start(&self, llbb: BasicBlockRef) {
unsafe {
llvm::LLVMRustPositionBuilderAtStart(self.llbuilder, llbb);
}
}

pub fn ret_void(&self) {
self.count_insn("retvoid");
unsafe {
Expand Down
9 changes: 9 additions & 0 deletions src/librustc_trans/trans/common.rs
Original file line number Diff line number Diff line change
Expand Up @@ -735,6 +735,15 @@ impl<'blk, 'tcx> BlockAndBuilder<'blk, 'tcx> {
BlockAndBuilder::new(bcx, owned_builder)
}

pub fn at_start<F, R>(&self, f: F) -> R
where F: FnOnce(&BlockAndBuilder<'blk, 'tcx>) -> R
{
self.position_at_start(self.bcx.llbb);
let r = f(self);
self.position_at_end(self.bcx.llbb);
r
}

// Methods delegated to bcx

pub fn ccx(&self) -> &'blk CrateContext<'blk, 'tcx> {
Expand Down
Loading