From 64d98f8ee037282c35007b64c2649055c56af1db Mon Sep 17 00:00:00 2001 From: Daniel Baumann Date: Wed, 17 Apr 2024 14:19:03 +0200 Subject: Merging upstream version 1.68.2+dfsg1. Signed-off-by: Daniel Baumann --- .../src/build/custom/parse/instruction.rs | 170 +++++++++++++++++++-- 1 file changed, 160 insertions(+), 10 deletions(-) (limited to 'compiler/rustc_mir_build/src/build/custom/parse/instruction.rs') diff --git a/compiler/rustc_mir_build/src/build/custom/parse/instruction.rs b/compiler/rustc_mir_build/src/build/custom/parse/instruction.rs index 03206af33..0bca02589 100644 --- a/compiler/rustc_mir_build/src/build/custom/parse/instruction.rs +++ b/compiler/rustc_mir_build/src/build/custom/parse/instruction.rs @@ -1,16 +1,33 @@ use rustc_middle::mir::interpret::{ConstValue, Scalar}; +use rustc_middle::mir::tcx::PlaceTy; use rustc_middle::{mir::*, thir::*, ty}; +use rustc_span::Span; +use rustc_target::abi::VariantIdx; + +use crate::build::custom::ParseError; +use crate::build::expr::as_constant::as_constant_inner; use super::{parse_by_kind, PResult, ParseCtxt}; impl<'tcx, 'body> ParseCtxt<'tcx, 'body> { pub fn parse_statement(&self, expr_id: ExprId) -> PResult> { parse_by_kind!(self, expr_id, _, "statement", + @call("mir_storage_live", args) => { + Ok(StatementKind::StorageLive(self.parse_local(args[0])?)) + }, + @call("mir_storage_dead", args) => { + Ok(StatementKind::StorageDead(self.parse_local(args[0])?)) + }, @call("mir_retag", args) => { Ok(StatementKind::Retag(RetagKind::Default, Box::new(self.parse_place(args[0])?))) }, - @call("mir_retag_raw", args) => { - Ok(StatementKind::Retag(RetagKind::Raw, Box::new(self.parse_place(args[0])?))) + @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 { + place: Box::new(place), + variant_index: VariantIdx::from_u32(var), + }) }, ExprKind::Assign { lhs, rhs } => { let lhs = self.parse_place(*lhs)?; @@ -21,18 +38,109 @@ impl<'tcx, 'body> ParseCtxt<'tcx, 'body> { } pub fn parse_terminator(&self, expr_id: ExprId) -> PResult> { - parse_by_kind!(self, expr_id, _, "terminator", + parse_by_kind!(self, expr_id, expr, "terminator", @call("mir_return", _args) => { Ok(TerminatorKind::Return) }, @call("mir_goto", args) => { Ok(TerminatorKind::Goto { target: self.parse_block(args[0])? } ) }, + @call("mir_unreachable", _args) => { + Ok(TerminatorKind::Unreachable) + }, + @call("mir_drop", args) => { + Ok(TerminatorKind::Drop { + place: self.parse_place(args[0])?, + target: self.parse_block(args[1])?, + unwind: None, + }) + }, + @call("mir_drop_and_replace", args) => { + Ok(TerminatorKind::DropAndReplace { + place: self.parse_place(args[0])?, + value: self.parse_operand(args[1])?, + target: self.parse_block(args[2])?, + unwind: None, + }) + }, + @call("mir_call", args) => { + let destination = self.parse_place(args[0])?; + let target = self.parse_block(args[1])?; + self.parse_call(args[2], destination, target) + }, + ExprKind::Match { scrutinee, arms } => { + let discr = self.parse_operand(*scrutinee)?; + self.parse_match(arms, expr.span).map(|t| TerminatorKind::SwitchInt { discr, targets: t }) + }, + ) + } + + fn parse_match(&self, arms: &[ArmId], span: Span) -> PResult { + let Some((otherwise, rest)) = arms.split_last() else { + return Err(ParseError { + span, + item_description: "no arms".to_string(), + expected: "at least one arm".to_string(), + }) + }; + + let otherwise = &self.thir[*otherwise]; + let PatKind::Wild = otherwise.pattern.kind else { + return Err(ParseError { + span: otherwise.span, + item_description: format!("{:?}", otherwise.pattern.kind), + expected: "wildcard pattern".to_string(), + }) + }; + let otherwise = self.parse_block(otherwise.body)?; + + let mut values = Vec::new(); + let mut targets = Vec::new(); + for arm in rest { + let arm = &self.thir[*arm]; + let PatKind::Constant { value } = arm.pattern.kind else { + return Err(ParseError { + span: arm.pattern.span, + item_description: format!("{:?}", arm.pattern.kind), + expected: "constant pattern".to_string(), + }) + }; + values.push(value.eval_bits(self.tcx, self.param_env, arm.pattern.ty)); + targets.push(self.parse_block(arm.body)?); + } + + Ok(SwitchTargets::new(values.into_iter().zip(targets), otherwise)) + } + + fn parse_call( + &self, + expr_id: ExprId, + destination: Place<'tcx>, + target: BasicBlock, + ) -> PResult> { + parse_by_kind!(self, expr_id, _, "function call", + ExprKind::Call { fun, args, from_hir_call, fn_span, .. } => { + let fun = self.parse_operand(*fun)?; + let args = args + .iter() + .map(|arg| self.parse_operand(*arg)) + .collect::>>()?; + Ok(TerminatorKind::Call { + func: fun, + args, + destination, + target: Some(target), + cleanup: None, + from_hir_call: *from_hir_call, + fn_span: *fn_span, + }) + }, ) } fn parse_rvalue(&self, expr_id: ExprId) -> PResult> { parse_by_kind!(self, expr_id, _, "rvalue", + @call("mir_discriminant", args) => self.parse_place(args[0]).map(Rvalue::Discriminant), ExprKind::Borrow { borrow_kind, arg } => Ok( Rvalue::Ref(self.tcx.lifetimes.re_erased, *borrow_kind, self.parse_place(*arg)?) ), @@ -55,7 +163,7 @@ impl<'tcx, 'body> ParseCtxt<'tcx, 'body> { | ExprKind::ConstParam { .. } | ExprKind::ConstBlock { .. } => { Ok(Operand::Constant(Box::new( - crate::build::expr::as_constant::as_constant_inner(expr, |_| None, self.tcx) + as_constant_inner(expr, |_| None, self.tcx) ))) }, _ => self.parse_place(expr_id).map(Operand::Copy), @@ -63,12 +171,42 @@ impl<'tcx, 'body> ParseCtxt<'tcx, 'body> { } fn parse_place(&self, expr_id: ExprId) -> PResult> { - parse_by_kind!(self, expr_id, _, "place", - ExprKind::Deref { arg } => Ok( - self.parse_place(*arg)?.project_deeper(&[PlaceElem::Deref], self.tcx) - ), - _ => self.parse_local(expr_id).map(Place::from), - ) + self.parse_place_inner(expr_id).map(|(x, _)| x) + } + + 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) => { + let (parent, ty) = self.parse_place_inner(args[0])?; + let field = Field::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) => { + (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]), + _ => (*arg, PlaceElem::Deref), + ) + }, + ExprKind::Index { lhs, index } => (*lhs, PlaceElem::Index(self.parse_local(*index)?)), + ExprKind::Field { lhs, name: field, .. } => (*lhs, PlaceElem::Field(*field, expr.ty)), + _ => { + let place = self.parse_local(expr_id).map(Place::from)?; + return Ok((place, PlaceTy::from_ty(expr.ty))) + }, + ); + let (parent, ty) = self.parse_place_inner(parent)?; + let place = parent.project_deeper(&[proj], self.tcx); + let ty = ty.projection_ty(self.tcx, proj); + Ok((place, ty)) } fn parse_local(&self, expr_id: ExprId) -> PResult { @@ -102,4 +240,16 @@ impl<'tcx, 'body> ParseCtxt<'tcx, 'body> { }, ) } + + fn parse_integer_literal(&self, expr_id: ExprId) -> PResult { + parse_by_kind!(self, expr_id, expr, "constant", + ExprKind::Literal { .. } + | ExprKind::NamedConst { .. } + | ExprKind::NonHirLiteral { .. } + | ExprKind::ConstBlock { .. } => Ok({ + let value = as_constant_inner(expr, |_| None, self.tcx); + value.literal.eval_bits(self.tcx, self.param_env, value.ty()) + }), + ) + } } -- cgit v1.2.3