]> git.proxmox.com Git - rustc.git/blob - compiler/rustc_mir_build/src/build/custom/parse.rs
New upstream version 1.67.1+dfsg1
[rustc.git] / compiler / rustc_mir_build / src / build / custom / parse.rs
1 use rustc_index::vec::IndexVec;
2 use rustc_middle::{mir::*, thir::*, ty::Ty};
3 use rustc_span::Span;
4
5 use super::{PResult, ParseCtxt, ParseError};
6
7 mod instruction;
8
9 /// Helper macro for parsing custom MIR.
10 ///
11 /// Example usage looks something like:
12 /// ```rust,ignore (incomplete example)
13 /// parse_by_kind!(
14 /// self, // : &ParseCtxt
15 /// expr_id, // what you're matching against
16 /// "assignment", // the thing you're trying to parse
17 /// @call("mir_assign", args) => { args[0] }, // match invocations of the `mir_assign` special function
18 /// ExprKind::Assign { lhs, .. } => { lhs }, // match thir assignment expressions
19 /// // no need for fallthrough case - reasonable error is automatically generated
20 /// )
21 /// ```
22 macro_rules! parse_by_kind {
23 (
24 $self:ident,
25 $expr_id:expr,
26 $expr_name:pat,
27 $expected:literal,
28 $(
29 @call($name:literal, $args:ident) => $call_expr:expr,
30 )*
31 $(
32 $pat:pat => $expr:expr,
33 )*
34 ) => {{
35 let expr_id = $self.preparse($expr_id);
36 let expr = &$self.thir[expr_id];
37 debug!("Trying to parse {:?} as {}", expr.kind, $expected);
38 let $expr_name = expr;
39 match &expr.kind {
40 $(
41 ExprKind::Call { ty, fun: _, args: $args, .. } if {
42 match ty.kind() {
43 ty::FnDef(did, _) => {
44 $self.tcx.is_diagnostic_item(rustc_span::Symbol::intern($name), *did)
45 }
46 _ => false,
47 }
48 } => $call_expr,
49 )*
50 $(
51 $pat => $expr,
52 )*
53 #[allow(unreachable_patterns)]
54 _ => return Err($self.expr_error(expr_id, $expected))
55 }
56 }};
57 }
58 pub(crate) use parse_by_kind;
59
60 impl<'tcx, 'body> ParseCtxt<'tcx, 'body> {
61 /// Expressions should only ever be matched on after preparsing them. This removes extra scopes
62 /// we don't care about.
63 fn preparse(&self, expr_id: ExprId) -> ExprId {
64 let expr = &self.thir[expr_id];
65 match expr.kind {
66 ExprKind::Scope { value, .. } => self.preparse(value),
67 _ => expr_id,
68 }
69 }
70
71 fn statement_as_expr(&self, stmt_id: StmtId) -> PResult<ExprId> {
72 match &self.thir[stmt_id].kind {
73 StmtKind::Expr { expr, .. } => Ok(*expr),
74 kind @ StmtKind::Let { pattern, .. } => {
75 return Err(ParseError {
76 span: pattern.span,
77 item_description: format!("{:?}", kind),
78 expected: "expression".to_string(),
79 });
80 }
81 }
82 }
83
84 pub fn parse_args(&mut self, params: &IndexVec<ParamId, Param<'tcx>>) -> PResult<()> {
85 for param in params.iter() {
86 let (var, span) = {
87 let pat = param.pat.as_ref().unwrap();
88 match &pat.kind {
89 PatKind::Binding { var, .. } => (*var, pat.span),
90 _ => {
91 return Err(ParseError {
92 span: pat.span,
93 item_description: format!("{:?}", pat.kind),
94 expected: "local".to_string(),
95 });
96 }
97 }
98 };
99 let decl = LocalDecl::new(param.ty, span);
100 let local = self.body.local_decls.push(decl);
101 self.local_map.insert(var, local);
102 }
103
104 Ok(())
105 }
106
107 /// Bodies are of the form:
108 ///
109 /// ```text
110 /// {
111 /// let bb1: BasicBlock;
112 /// let bb2: BasicBlock;
113 /// {
114 /// let RET: _;
115 /// let local1;
116 /// let local2;
117 ///
118 /// {
119 /// { // entry block
120 /// statement1;
121 /// terminator1
122 /// };
123 ///
124 /// bb1 = {
125 /// statement2;
126 /// terminator2
127 /// };
128 ///
129 /// bb2 = {
130 /// statement3;
131 /// terminator3
132 /// }
133 ///
134 /// RET
135 /// }
136 /// }
137 /// }
138 /// ```
139 ///
140 /// This allows us to easily parse the basic blocks declarations, local declarations, and
141 /// basic block definitions in order.
142 pub fn parse_body(&mut self, expr_id: ExprId) -> PResult<()> {
143 let body = parse_by_kind!(self, expr_id, _, "whole body",
144 ExprKind::Block { block } => self.thir[*block].expr.unwrap(),
145 );
146 let (block_decls, rest) = parse_by_kind!(self, body, _, "body with block decls",
147 ExprKind::Block { block } => {
148 let block = &self.thir[*block];
149 (&block.stmts, block.expr.unwrap())
150 },
151 );
152 self.parse_block_decls(block_decls.iter().copied())?;
153
154 let (local_decls, rest) = parse_by_kind!(self, rest, _, "body with local decls",
155 ExprKind::Block { block } => {
156 let block = &self.thir[*block];
157 (&block.stmts, block.expr.unwrap())
158 },
159 );
160 self.parse_local_decls(local_decls.iter().copied())?;
161
162 let block_defs = parse_by_kind!(self, rest, _, "body with block defs",
163 ExprKind::Block { block } => &self.thir[*block].stmts,
164 );
165 for (i, block_def) in block_defs.iter().enumerate() {
166 let block = self.parse_block_def(self.statement_as_expr(*block_def)?)?;
167 self.body.basic_blocks_mut()[BasicBlock::from_usize(i)] = block;
168 }
169
170 Ok(())
171 }
172
173 fn parse_block_decls(&mut self, stmts: impl Iterator<Item = StmtId>) -> PResult<()> {
174 for stmt in stmts {
175 let (var, _, _) = self.parse_let_statement(stmt)?;
176 let data = BasicBlockData::new(None);
177 let block = self.body.basic_blocks_mut().push(data);
178 self.block_map.insert(var, block);
179 }
180
181 Ok(())
182 }
183
184 fn parse_local_decls(&mut self, mut stmts: impl Iterator<Item = StmtId>) -> PResult<()> {
185 let (ret_var, ..) = self.parse_let_statement(stmts.next().unwrap())?;
186 self.local_map.insert(ret_var, Local::from_u32(0));
187
188 for stmt in stmts {
189 let (var, ty, span) = self.parse_let_statement(stmt)?;
190 let decl = LocalDecl::new(ty, span);
191 let local = self.body.local_decls.push(decl);
192 self.local_map.insert(var, local);
193 }
194
195 Ok(())
196 }
197
198 fn parse_let_statement(&mut self, stmt_id: StmtId) -> PResult<(LocalVarId, Ty<'tcx>, Span)> {
199 let pattern = match &self.thir[stmt_id].kind {
200 StmtKind::Let { pattern, .. } => pattern,
201 StmtKind::Expr { expr, .. } => {
202 return Err(self.expr_error(*expr, "let statement"));
203 }
204 };
205
206 self.parse_var(pattern)
207 }
208
209 fn parse_var(&mut self, mut pat: &Pat<'tcx>) -> PResult<(LocalVarId, Ty<'tcx>, Span)> {
210 // Make sure we throw out any `AscribeUserType` we find
211 loop {
212 match &pat.kind {
213 PatKind::Binding { var, ty, .. } => break Ok((*var, *ty, pat.span)),
214 PatKind::AscribeUserType { subpattern, .. } => {
215 pat = subpattern;
216 }
217 _ => {
218 break Err(ParseError {
219 span: pat.span,
220 item_description: format!("{:?}", pat.kind),
221 expected: "local".to_string(),
222 });
223 }
224 }
225 }
226 }
227
228 fn parse_block_def(&self, expr_id: ExprId) -> PResult<BasicBlockData<'tcx>> {
229 let block = parse_by_kind!(self, expr_id, _, "basic block",
230 ExprKind::Block { block } => &self.thir[*block],
231 );
232
233 let mut data = BasicBlockData::new(None);
234 for stmt_id in &*block.stmts {
235 let stmt = self.statement_as_expr(*stmt_id)?;
236 let span = self.thir[stmt].span;
237 let statement = self.parse_statement(stmt)?;
238 data.statements.push(Statement {
239 source_info: SourceInfo { span, scope: self.source_scope },
240 kind: statement,
241 });
242 }
243
244 let Some(trailing) = block.expr else {
245 return Err(self.expr_error(expr_id, "terminator"))
246 };
247 let span = self.thir[trailing].span;
248 let terminator = self.parse_terminator(trailing)?;
249 data.terminator = Some(Terminator {
250 source_info: SourceInfo { span, scope: self.source_scope },
251 kind: terminator,
252 });
253
254 Ok(data)
255 }
256 }