Skip to content

Custom MIR: Support cleanup blocks #117330

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 1 commit into from
Nov 14, 2023
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
13 changes: 13 additions & 0 deletions compiler/rustc_mir_build/src/build/custom/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -162,6 +162,19 @@ impl<'tcx, 'body> ParseCtxt<'tcx, 'body> {
expected: expected.to_string(),
}
}

fn stmt_error(&self, stmt: StmtId, expected: &'static str) -> ParseError {
let stmt = &self.thir[stmt];
let span = match stmt.kind {
StmtKind::Expr { expr, .. } => self.thir[expr].span,
StmtKind::Let { span, .. } => span,
};
ParseError {
span,
item_description: format!("{:?}", stmt.kind),
expected: expected.to_string(),
}
}
}

type PResult<T> = Result<T, ParseError>;
48 changes: 36 additions & 12 deletions compiler/rustc_mir_build/src/build/custom/parse.rs
Original file line number Diff line number Diff line change
Expand Up @@ -27,10 +27,13 @@ macro_rules! parse_by_kind {
$expr_name:pat,
$expected:literal,
$(
@call($name:literal, $args:ident) => $call_expr:expr,
@call($name:ident, $args:ident) => $call_expr:expr,
)*
$(
$pat:pat => $expr:expr,
@variant($adt:ident, $variant:ident) => $variant_expr:expr,
)*
$(
$pat:pat $(if $guard:expr)? => $expr:expr,
)*
) => {{
let expr_id = $self.preparse($expr_id);
Expand All @@ -42,14 +45,20 @@ macro_rules! parse_by_kind {
ExprKind::Call { ty, fun: _, args: $args, .. } if {
match ty.kind() {
ty::FnDef(did, _) => {
$self.tcx.is_diagnostic_item(rustc_span::Symbol::intern($name), *did)
$self.tcx.is_diagnostic_item(rustc_span::sym::$name, *did)
}
_ => false,
}
} => $call_expr,
)*
$(
$pat => $expr,
ExprKind::Adt(box AdtExpr { adt_def, variant_index, .. }) if {
$self.tcx.is_diagnostic_item(rustc_span::sym::$adt, adt_def.did()) &&
adt_def.variants()[*variant_index].name == rustc_span::sym::$variant
} => $variant_expr,
)*
$(
$pat $(if $guard)? => $expr,
)*
#[allow(unreachable_patterns)]
_ => return Err($self.expr_error(expr_id, $expected))
Expand Down Expand Up @@ -172,7 +181,8 @@ impl<'tcx, 'body> ParseCtxt<'tcx, 'body> {
ExprKind::Block { block } => &self.thir[*block].stmts,
);
for (i, block_def) in block_defs.iter().enumerate() {
let block = self.parse_block_def(self.statement_as_expr(*block_def)?)?;
let is_cleanup = self.body.basic_blocks_mut()[BasicBlock::from_usize(i)].is_cleanup;
let block = self.parse_block_def(self.statement_as_expr(*block_def)?, is_cleanup)?;
self.body.basic_blocks_mut()[BasicBlock::from_usize(i)] = block;
}

Expand All @@ -181,15 +191,28 @@ impl<'tcx, 'body> ParseCtxt<'tcx, 'body> {

fn parse_block_decls(&mut self, stmts: impl Iterator<Item = StmtId>) -> PResult<()> {
for stmt in stmts {
let (var, _, _) = self.parse_let_statement(stmt)?;
let data = BasicBlockData::new(None);
let block = self.body.basic_blocks_mut().push(data);
self.block_map.insert(var, block);
self.parse_basic_block_decl(stmt)?;
}

Ok(())
}

fn parse_basic_block_decl(&mut self, stmt: StmtId) -> PResult<()> {
match &self.thir[stmt].kind {
StmtKind::Let { pattern, initializer: Some(initializer), .. } => {
let (var, ..) = self.parse_var(pattern)?;
let mut data = BasicBlockData::new(None);
data.is_cleanup = parse_by_kind!(self, *initializer, _, "basic block declaration",
@variant(mir_basic_block, Normal) => false,
@variant(mir_basic_block, Cleanup) => true,
);
let block = self.body.basic_blocks_mut().push(data);
self.block_map.insert(var, block);
Ok(())
}
_ => Err(self.stmt_error(stmt, "let statement with an initializer")),
}
}

fn parse_local_decls(&mut self, mut stmts: impl Iterator<Item = StmtId>) -> PResult<()> {
let (ret_var, ..) = self.parse_let_statement(stmts.next().unwrap())?;
self.local_map.insert(ret_var, Local::from_u32(0));
Expand Down Expand Up @@ -219,7 +242,7 @@ impl<'tcx, 'body> ParseCtxt<'tcx, 'body> {
};
let span = self.thir[expr].span;
let (name, operand) = parse_by_kind!(self, expr, _, "debuginfo",
@call("mir_debuginfo", args) => {
@call(mir_debuginfo, args) => {
(args[0], args[1])
},
);
Expand Down Expand Up @@ -281,12 +304,13 @@ impl<'tcx, 'body> ParseCtxt<'tcx, 'body> {
}
}

fn parse_block_def(&self, expr_id: ExprId) -> PResult<BasicBlockData<'tcx>> {
fn parse_block_def(&self, expr_id: ExprId, is_cleanup: bool) -> PResult<BasicBlockData<'tcx>> {
let block = parse_by_kind!(self, expr_id, _, "basic block",
ExprKind::Block { block } => &self.thir[*block],
);

let mut data = BasicBlockData::new(None);
data.is_cleanup = is_cleanup;
for stmt_id in &*block.stmts {
let stmt = self.statement_as_expr(*stmt_id)?;
let span = self.thir[stmt].span;
Expand Down
83 changes: 59 additions & 24 deletions compiler/rustc_mir_build/src/build/custom/parse/instruction.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,19 +13,19 @@ use super::{parse_by_kind, PResult, ParseCtxt};
impl<'tcx, 'body> ParseCtxt<'tcx, 'body> {
pub fn parse_statement(&self, expr_id: ExprId) -> PResult<StatementKind<'tcx>> {
parse_by_kind!(self, expr_id, _, "statement",
@call("mir_storage_live", args) => {
@call(mir_storage_live, args) => {
Ok(StatementKind::StorageLive(self.parse_local(args[0])?))
},
@call("mir_storage_dead", args) => {
@call(mir_storage_dead, args) => {
Ok(StatementKind::StorageDead(self.parse_local(args[0])?))
},
@call("mir_deinit", args) => {
@call(mir_deinit, args) => {
Ok(StatementKind::Deinit(Box::new(self.parse_place(args[0])?)))
},
@call("mir_retag", args) => {
@call(mir_retag, args) => {
Ok(StatementKind::Retag(RetagKind::Default, Box::new(self.parse_place(args[0])?)))
},
@call("mir_set_discriminant", args) => {
@call(mir_set_discriminant, args) => {
let place = self.parse_place(args[0])?;
let var = self.parse_integer_literal(args[1])? as u32;
Ok(StatementKind::SetDiscriminant {
Expand All @@ -43,24 +43,30 @@ impl<'tcx, 'body> ParseCtxt<'tcx, 'body> {

pub fn parse_terminator(&self, expr_id: ExprId) -> PResult<TerminatorKind<'tcx>> {
parse_by_kind!(self, expr_id, expr, "terminator",
@call("mir_return", _args) => {
@call(mir_return, _args) => {
Ok(TerminatorKind::Return)
},
@call("mir_goto", args) => {
@call(mir_goto, args) => {
Ok(TerminatorKind::Goto { target: self.parse_block(args[0])? } )
},
@call("mir_unreachable", _args) => {
@call(mir_unreachable, _args) => {
Ok(TerminatorKind::Unreachable)
},
@call("mir_drop", args) => {
@call(mir_unwind_resume, _args) => {
Ok(TerminatorKind::UnwindResume)
},
@call(mir_unwind_terminate, args) => {
Ok(TerminatorKind::UnwindTerminate(self.parse_unwind_terminate_reason(args[0])?))
},
@call(mir_drop, args) => {
Ok(TerminatorKind::Drop {
place: self.parse_place(args[0])?,
target: self.parse_block(args[1])?,
unwind: UnwindAction::Continue,
unwind: self.parse_unwind_action(args[2])?,
replace: false,
})
},
@call("mir_call", args) => {
@call(mir_call, args) => {
self.parse_call(args)
},
ExprKind::Match { scrutinee, arms, .. } => {
Expand All @@ -70,6 +76,34 @@ impl<'tcx, 'body> ParseCtxt<'tcx, 'body> {
)
}

fn parse_unwind_terminate_reason(&self, expr_id: ExprId) -> PResult<UnwindTerminateReason> {
parse_by_kind!(self, expr_id, _, "unwind terminate reason",
@variant(mir_unwind_terminate_reason, Abi) => {
Ok(UnwindTerminateReason::Abi)
},
@variant(mir_unwind_terminate_reason, InCleanup) => {
Ok(UnwindTerminateReason::InCleanup)
},
)
}

fn parse_unwind_action(&self, expr_id: ExprId) -> PResult<UnwindAction> {
parse_by_kind!(self, expr_id, _, "unwind action",
@call(mir_unwind_continue, _args) => {
Ok(UnwindAction::Continue)
},
@call(mir_unwind_unreachable, _args) => {
Ok(UnwindAction::Unreachable)
},
@call(mir_unwind_terminate, args) => {
Ok(UnwindAction::Terminate(self.parse_unwind_terminate_reason(args[0])?))
},
@call(mir_unwind_cleanup, args) => {
Ok(UnwindAction::Cleanup(self.parse_block(args[0])?))
},
)
}

fn parse_match(&self, arms: &[ArmId], span: Span) -> PResult<SwitchTargets> {
let Some((otherwise, rest)) = arms.split_last() else {
return Err(ParseError {
Expand Down Expand Up @@ -113,6 +147,7 @@ impl<'tcx, 'body> ParseCtxt<'tcx, 'body> {
);
let destination = self.parse_place(destination)?;
let target = self.parse_block(args[1])?;
let unwind = self.parse_unwind_action(args[2])?;

parse_by_kind!(self, call, _, "function call",
ExprKind::Call { fun, args, from_hir_call, fn_span, .. } => {
Expand All @@ -126,7 +161,7 @@ impl<'tcx, 'body> ParseCtxt<'tcx, 'body> {
args,
destination,
target: Some(target),
unwind: UnwindAction::Continue,
unwind,
call_source: if *from_hir_call { CallSource::Normal } else {
CallSource::OverloadedOperator
},
Expand All @@ -138,25 +173,25 @@ impl<'tcx, 'body> ParseCtxt<'tcx, 'body> {

fn parse_rvalue(&self, expr_id: ExprId) -> PResult<Rvalue<'tcx>> {
parse_by_kind!(self, expr_id, expr, "rvalue",
@call("mir_discriminant", args) => self.parse_place(args[0]).map(Rvalue::Discriminant),
@call("mir_cast_transmute", args) => {
@call(mir_discriminant, args) => self.parse_place(args[0]).map(Rvalue::Discriminant),
@call(mir_cast_transmute, args) => {
let source = self.parse_operand(args[0])?;
Ok(Rvalue::Cast(CastKind::Transmute, source, expr.ty))
},
@call("mir_checked", args) => {
@call(mir_checked, args) => {
parse_by_kind!(self, args[0], _, "binary op",
ExprKind::Binary { op, lhs, rhs } => Ok(Rvalue::CheckedBinaryOp(
*op, Box::new((self.parse_operand(*lhs)?, self.parse_operand(*rhs)?))
)),
)
},
@call("mir_offset", args) => {
@call(mir_offset, args) => {
let ptr = self.parse_operand(args[0])?;
let offset = self.parse_operand(args[1])?;
Ok(Rvalue::BinaryOp(BinOp::Offset, Box::new((ptr, offset))))
},
@call("mir_len", args) => Ok(Rvalue::Len(self.parse_place(args[0])?)),
@call("mir_copy_for_deref", args) => Ok(Rvalue::CopyForDeref(self.parse_place(args[0])?)),
@call(mir_len, args) => Ok(Rvalue::Len(self.parse_place(args[0])?)),
@call(mir_copy_for_deref, args) => Ok(Rvalue::CopyForDeref(self.parse_place(args[0])?)),
ExprKind::Borrow { borrow_kind, arg } => Ok(
Rvalue::Ref(self.tcx.lifetimes.re_erased, *borrow_kind, self.parse_place(*arg)?)
),
Expand Down Expand Up @@ -206,9 +241,9 @@ impl<'tcx, 'body> ParseCtxt<'tcx, 'body> {

pub fn parse_operand(&self, expr_id: ExprId) -> PResult<Operand<'tcx>> {
parse_by_kind!(self, expr_id, expr, "operand",
@call("mir_move", args) => self.parse_place(args[0]).map(Operand::Move),
@call("mir_static", args) => self.parse_static(args[0]),
@call("mir_static_mut", args) => self.parse_static(args[0]),
@call(mir_move, args) => self.parse_place(args[0]).map(Operand::Move),
@call(mir_static, args) => self.parse_static(args[0]),
@call(mir_static_mut, args) => self.parse_static(args[0]),
ExprKind::Literal { .. }
| ExprKind::NamedConst { .. }
| ExprKind::NonHirLiteral { .. }
Expand All @@ -229,23 +264,23 @@ impl<'tcx, 'body> ParseCtxt<'tcx, 'body> {

fn parse_place_inner(&self, expr_id: ExprId) -> PResult<(Place<'tcx>, PlaceTy<'tcx>)> {
let (parent, proj) = parse_by_kind!(self, expr_id, expr, "place",
@call("mir_field", args) => {
@call(mir_field, args) => {
let (parent, ty) = self.parse_place_inner(args[0])?;
let field = FieldIdx::from_u32(self.parse_integer_literal(args[1])? as u32);
let field_ty = ty.field_ty(self.tcx, field);
let proj = PlaceElem::Field(field, field_ty);
let place = parent.project_deeper(&[proj], self.tcx);
return Ok((place, PlaceTy::from_ty(field_ty)));
},
@call("mir_variant", args) => {
@call(mir_variant, args) => {
(args[0], PlaceElem::Downcast(
None,
VariantIdx::from_u32(self.parse_integer_literal(args[1])? as u32)
))
},
ExprKind::Deref { arg } => {
parse_by_kind!(self, *arg, _, "does not matter",
@call("mir_make_place", args) => return self.parse_place_inner(args[0]),
@call(mir_make_place, args) => return self.parse_place_inner(args[0]),
_ => (*arg, PlaceElem::Deref),
)
},
Expand Down
34 changes: 34 additions & 0 deletions compiler/rustc_span/src/symbol.rs
Original file line number Diff line number Diff line change
Expand Up @@ -124,6 +124,7 @@ symbols! {
// There is currently no checking that all symbols are used; that would be
// nice to have.
Symbols {
Abi,
AcqRel,
Acquire,
AddToDiagnostic,
Expand Down Expand Up @@ -166,6 +167,7 @@ symbols! {
CString,
Capture,
Center,
Cleanup,
Clone,
Command,
ConstParamTy,
Expand Down Expand Up @@ -215,6 +217,7 @@ symbols! {
HashSet,
Hasher,
Implied,
InCleanup,
IndexOutput,
Input,
Instant,
Expand Down Expand Up @@ -258,6 +261,7 @@ symbols! {
NonZeroU8,
NonZeroUsize,
None,
Normal,
Ok,
Option,
Ord,
Expand Down Expand Up @@ -1023,6 +1027,36 @@ symbols! {
minnumf32,
minnumf64,
mips_target_feature,
mir_basic_block,
mir_call,
mir_cast_transmute,
mir_checked,
mir_copy_for_deref,
mir_debuginfo,
mir_deinit,
mir_discriminant,
mir_drop,
mir_field,
mir_goto,
mir_len,
mir_make_place,
mir_move,
mir_offset,
mir_retag,
mir_return,
mir_set_discriminant,
mir_static,
mir_static_mut,
mir_storage_dead,
mir_storage_live,
mir_unreachable,
mir_unwind_cleanup,
mir_unwind_continue,
mir_unwind_resume,
mir_unwind_terminate,
mir_unwind_terminate_reason,
mir_unwind_unreachable,
mir_variant,
miri,
misc,
mmx_reg,
Expand Down
Loading