Skip to content

Commit

Permalink
[WIP] Eagerly construct bodies of THIR
Browse files Browse the repository at this point in the history
  • Loading branch information
LeSeulArtichaut committed Mar 9, 2021
1 parent 3a5d45f commit 60def4d
Show file tree
Hide file tree
Showing 18 changed files with 1,315 additions and 1,554 deletions.
65 changes: 33 additions & 32 deletions compiler/rustc_mir_build/src/build/block.rs
Expand Up @@ -2,7 +2,6 @@ use crate::build::matches::ArmHasGuard;
use crate::build::ForGuard::OutsideGuard;
use crate::build::{BlockAnd, BlockAndExtension, BlockFrame, Builder};
use crate::thir::*;
use rustc_hir as hir;
use rustc_middle::mir::*;
use rustc_session::lint::builtin::UNSAFE_OP_IN_UNSAFE_FN;
use rustc_session::lint::Level;
Expand All @@ -13,7 +12,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
&mut self,
destination: Place<'tcx>,
block: BasicBlock,
ast_block: &'tcx hir::Block<'tcx>,
ast_block: &Block<'tcx>,
source_info: SourceInfo,
) -> BlockAnd<()> {
let Block {
Expand All @@ -24,22 +23,29 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
expr,
targeted_by_break,
safety_mode,
} = self.hir.mirror(ast_block);
} = ast_block;
self.in_opt_scope(opt_destruction_scope.map(|de| (de, source_info)), move |this| {
this.in_scope((region_scope, source_info), LintLevel::Inherited, move |this| {
if targeted_by_break {
this.in_breakable_scope(None, destination, span, |this| {
this.in_scope((*region_scope, source_info), LintLevel::Inherited, move |this| {
if *targeted_by_break {
this.in_breakable_scope(None, destination, *span, |this| {
Some(this.ast_block_stmts(
destination,
block,
span,
stmts,
expr,
safety_mode,
*span,
&stmts,
expr.as_deref(),
*safety_mode,
))
})
} else {
this.ast_block_stmts(destination, block, span, stmts, expr, safety_mode)
this.ast_block_stmts(
destination,
block,
*span,
&stmts,
expr.as_deref(),
*safety_mode,
)
}
})
})
Expand All @@ -50,8 +56,8 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
destination: Place<'tcx>,
mut block: BasicBlock,
span: Span,
stmts: Vec<StmtRef<'tcx>>,
expr: Option<ExprRef<'tcx>>,
stmts: &[Stmt<'tcx>],
expr: Option<&Expr<'tcx>>,
safety_mode: BlockSafety,
) -> BlockAnd<()> {
let this = self;
Expand Down Expand Up @@ -79,19 +85,17 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
this.update_source_scope_for_safety_mode(span, safety_mode);

let source_info = this.source_info(span);
for stmt in stmts {
let Stmt { kind, opt_destruction_scope } = this.hir.mirror(stmt);
for Stmt { kind, opt_destruction_scope } in stmts {
match kind {
StmtKind::Expr { scope, expr } => {
this.block_context.push(BlockFrame::Statement { ignores_expr_result: true });
unpack!(
block = this.in_opt_scope(
opt_destruction_scope.map(|de| (de, source_info)),
|this| {
let si = (scope, source_info);
let si = (*scope, source_info);
this.in_scope(si, LintLevel::Inherited, |this| {
let expr = this.hir.mirror(expr);
this.stmt_expr(block, expr, Some(scope))
this.stmt_expr(block, &expr, Some(*scope))
})
}
)
Expand All @@ -102,7 +106,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
this.block_context.push(BlockFrame::Statement { ignores_expr_result });

// Enter the remainder scope, i.e., the bindings' destruction scope.
this.push_scope((remainder_scope, source_info));
this.push_scope((*remainder_scope, source_info));
let_scope_stack.push(remainder_scope);

// Declare the bindings, which may create a source scope.
Expand All @@ -114,29 +118,29 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {

// Evaluate the initializer, if present.
if let Some(init) = initializer {
let initializer_span = init.span();
let initializer_span = init.span;

unpack!(
block = this.in_opt_scope(
opt_destruction_scope.map(|de| (de, source_info)),
|this| {
let scope = (init_scope, source_info);
this.in_scope(scope, lint_level, |this| {
let scope = (*init_scope, source_info);
this.in_scope(scope, *lint_level, |this| {
this.declare_bindings(
visibility_scope,
remainder_span,
&pattern,
ArmHasGuard(false),
Some((None, initializer_span)),
);
this.expr_into_pattern(block, pattern, init)
this.expr_into_pattern(block, pattern.clone(), &init)
})
}
)
);
} else {
let scope = (init_scope, source_info);
unpack!(this.in_scope(scope, lint_level, |this| {
let scope = (*init_scope, source_info);
unpack!(this.in_scope(scope, *lint_level, |this| {
this.declare_bindings(
visibility_scope,
remainder_span,
Expand Down Expand Up @@ -176,13 +180,10 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
if let Some(expr) = expr {
let tail_result_is_ignored =
destination_ty.is_unit() || this.block_context.currently_ignores_tail_results();
let span = match expr {
ExprRef::Thir(expr) => expr.span,
ExprRef::Mirror(ref expr) => expr.span,
};
this.block_context.push(BlockFrame::TailExpr { tail_result_is_ignored, span });
this.block_context
.push(BlockFrame::TailExpr { tail_result_is_ignored, span: expr.span });

unpack!(block = this.into(destination, block, expr));
unpack!(block = this.expr_into_dest(destination, block, expr));
let popped = this.block_context.pop();

assert!(popped.map_or(false, |bf| bf.is_tail_expr()));
Expand All @@ -200,7 +201,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
// Finally, we pop all the let scopes before exiting out from the scope of block
// itself.
for scope in let_scope_stack.into_iter().rev() {
unpack!(block = this.pop_scope((scope, source_info), block));
unpack!(block = this.pop_scope((*scope, source_info), block));
}
// Restore the original source scope.
this.source_scope = outer_source_scope;
Expand Down
26 changes: 10 additions & 16 deletions compiler/rustc_mir_build/src/build/expr/as_constant.rs
Expand Up @@ -8,33 +8,27 @@ use rustc_middle::ty::CanonicalUserTypeAnnotation;
impl<'a, 'tcx> Builder<'a, 'tcx> {
/// Compile `expr`, yielding a compile-time constant. Assumes that
/// `expr` is a valid compile-time constant!
crate fn as_constant<M>(&mut self, expr: M) -> Constant<'tcx>
where
M: Mirror<'tcx, Output = Expr<'tcx>>,
{
let expr = self.hir.mirror(expr);
self.expr_as_constant(expr)
}

fn expr_as_constant(&mut self, expr: Expr<'tcx>) -> Constant<'tcx> {
crate fn as_constant(&mut self, expr: &Expr<'tcx>) -> Constant<'tcx> {
let this = self;
let Expr { ty, temp_lifetime: _, span, kind } = expr;
match kind {
ExprKind::Scope { region_scope: _, lint_level: _, value } => this.as_constant(value),
ExprKind::Scope { region_scope: _, lint_level: _, value } => this.as_constant(&value),
ExprKind::Literal { literal, user_ty, const_id: _ } => {
let user_ty = user_ty.map(|user_ty| {
this.canonical_user_type_annotations.push(CanonicalUserTypeAnnotation {
span,
span: *span,
user_ty,
inferred_ty: ty,
})
});
assert_eq!(literal.ty, ty);
Constant { span, user_ty, literal }
assert_eq!(literal.ty, *ty);
Constant { span: *span, user_ty, literal }
}
ExprKind::StaticRef { literal, .. } => Constant { span: *span, user_ty: None, literal },
ExprKind::ConstBlock { value } => {
Constant { span: *span, user_ty: None, literal: value }
}
ExprKind::StaticRef { literal, .. } => Constant { span, user_ty: None, literal },
ExprKind::ConstBlock { value } => Constant { span, user_ty: None, literal: value },
_ => span_bug!(span, "expression is not a valid constant {:?}", kind),
_ => span_bug!(*span, "expression is not a valid constant {:?}", kind),
}
}
}
77 changes: 24 additions & 53 deletions compiler/rustc_mir_build/src/build/expr/as_operand.rs
Expand Up @@ -14,10 +14,11 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
/// after the current enclosing `ExprKind::Scope` has ended, so
/// please do *not* return it from functions to avoid bad
/// miscompiles.
crate fn as_local_operand<M>(&mut self, block: BasicBlock, expr: M) -> BlockAnd<Operand<'tcx>>
where
M: Mirror<'tcx, Output = Expr<'tcx>>,
{
crate fn as_local_operand(
&mut self,
block: BasicBlock,
expr: &Expr<'tcx>,
) -> BlockAnd<Operand<'tcx>> {
let local_scope = self.local_scope();
self.as_operand(block, Some(local_scope), expr)
}
Expand Down Expand Up @@ -70,14 +71,11 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
/// value to the stack.
///
/// See #68034 for more details.
crate fn as_local_call_operand<M>(
crate fn as_local_call_operand(
&mut self,
block: BasicBlock,
expr: M,
) -> BlockAnd<Operand<'tcx>>
where
M: Mirror<'tcx, Output = Expr<'tcx>>,
{
expr: &Expr<'tcx>,
) -> BlockAnd<Operand<'tcx>> {
let local_scope = self.local_scope();
self.as_call_operand(block, Some(local_scope), expr)
}
Expand All @@ -88,52 +86,27 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
/// this time.
///
/// The operand is known to be live until the end of `scope`.
crate fn as_operand<M>(
&mut self,
block: BasicBlock,
scope: Option<region::Scope>,
expr: M,
) -> BlockAnd<Operand<'tcx>>
where
M: Mirror<'tcx, Output = Expr<'tcx>>,
{
let expr = self.hir.mirror(expr);
self.expr_as_operand(block, scope, expr)
}

///
/// Like `as_local_call_operand`, except that the argument will
/// not be valid once `scope` ends.
fn as_call_operand<M>(
&mut self,
block: BasicBlock,
scope: Option<region::Scope>,
expr: M,
) -> BlockAnd<Operand<'tcx>>
where
M: Mirror<'tcx, Output = Expr<'tcx>>,
{
let expr = self.hir.mirror(expr);
self.expr_as_call_operand(block, scope, expr)
}

fn expr_as_operand(
crate fn as_operand(
&mut self,
mut block: BasicBlock,
scope: Option<region::Scope>,
expr: Expr<'tcx>,
expr: &Expr<'tcx>,
) -> BlockAnd<Operand<'tcx>> {
debug!("expr_as_operand(block={:?}, expr={:?})", block, expr);
debug!("as_operand(block={:?}, expr={:?})", block, expr);
let this = self;

if let ExprKind::Scope { region_scope, lint_level, value } = expr.kind {
if let ExprKind::Scope { region_scope, lint_level, value } = &expr.kind {
let source_info = this.source_info(expr.span);
let region_scope = (region_scope, source_info);
let region_scope = (*region_scope, source_info);
return this
.in_scope(region_scope, lint_level, |this| this.as_operand(block, scope, value));
.in_scope(region_scope, *lint_level, |this| this.as_operand(block, scope, &value));
}

let category = Category::of(&expr.kind).unwrap();
debug!("expr_as_operand: category={:?} for={:?}", category, expr.kind);
debug!("as_operand: category={:?} for={:?}", category, expr.kind);
match category {
Category::Constant => {
let constant = this.as_constant(expr);
Expand All @@ -146,20 +119,20 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
}
}

fn expr_as_call_operand(
crate fn as_call_operand(
&mut self,
mut block: BasicBlock,
scope: Option<region::Scope>,
expr: Expr<'tcx>,
expr: &Expr<'tcx>,
) -> BlockAnd<Operand<'tcx>> {
debug!("expr_as_call_operand(block={:?}, expr={:?})", block, expr);
debug!("as_call_operand(block={:?}, expr={:?})", block, expr);
let this = self;

if let ExprKind::Scope { region_scope, lint_level, value } = expr.kind {
if let ExprKind::Scope { region_scope, lint_level, value } = &expr.kind {
let source_info = this.source_info(expr.span);
let region_scope = (region_scope, source_info);
return this.in_scope(region_scope, lint_level, |this| {
this.as_call_operand(block, scope, value)
let region_scope = (*region_scope, source_info);
return this.in_scope(region_scope, *lint_level, |this| {
this.as_call_operand(block, scope, &value)
});
}

Expand All @@ -177,8 +150,6 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
// As described above, detect the case where we are passing a value of unsized
// type, and that value is coming from the deref of a box.
if let ExprKind::Deref { ref arg } = expr.kind {
let arg = this.hir.mirror(arg.clone());

// Generate let tmp0 = arg0
let operand = unpack!(block = this.as_temp(block, scope, arg, Mutability::Mut));

Expand All @@ -193,6 +164,6 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
}
}

this.expr_as_operand(block, scope, expr)
this.as_operand(block, scope, expr)
}
}

0 comments on commit 60def4d

Please sign in to comment.