]> git.proxmox.com Git - rustc.git/blame - compiler/rustc_mir_build/src/build/mod.rs
New upstream version 1.71.1+dfsg1
[rustc.git] / compiler / rustc_mir_build / src / build / mod.rs
CommitLineData
923072b8 1pub(crate) use crate::build::expr::as_constant::lit_to_mir_constant;
6a06907d 2use crate::build::expr::as_place::PlaceBuilder;
dc9dc135 3use crate::build::scope::DropKind;
923072b8
FG
4use rustc_apfloat::ieee::{Double, Single};
5use rustc_apfloat::Float;
353b0b11 6use rustc_ast::attr;
923072b8 7use rustc_data_structures::fx::FxHashMap;
f2b60f7d 8use rustc_data_structures::sorted_map::SortedIndexMultiMap;
5e7ed085 9use rustc_errors::ErrorGuaranteed;
dfeec247 10use rustc_hir as hir;
f2b60f7d 11use rustc_hir::def::DefKind;
f9f354fc 12use rustc_hir::def_id::{DefId, LocalDefId};
923072b8 13use rustc_hir::{GeneratorKind, Node};
49aad941 14use rustc_index::{Idx, IndexSlice, IndexVec};
6a06907d 15use rustc_infer::infer::{InferCtxt, TyCtxtInferExt};
fc512014 16use rustc_middle::hir::place::PlaceBase as HirPlaceBase;
ba9703b0 17use rustc_middle::middle::region;
923072b8
FG
18use rustc_middle::mir::interpret::ConstValue;
19use rustc_middle::mir::interpret::Scalar;
ba9703b0 20use rustc_middle::mir::*;
f2b60f7d
FG
21use rustc_middle::thir::{
22 self, BindingMode, Expr, ExprId, LintLevel, LocalVarId, Param, ParamId, PatKind, Thir,
23};
9ffffee4 24use rustc_middle::ty::{self, Ty, TyCtxt, TypeVisitableExt};
94222f64 25use rustc_span::symbol::sym;
dfeec247 26use rustc_span::Span;
923072b8 27use rustc_span::Symbol;
353b0b11 28use rustc_target::abi::FieldIdx;
dfeec247 29use rustc_target::spec::abi::Abi;
3157f602 30
0bf4aa26
XL
31use super::lints;
32
9c376795
FG
33pub(crate) fn mir_built(
34 tcx: TyCtxt<'_>,
49aad941 35 def: LocalDefId,
9c376795 36) -> &rustc_data_structures::steal::Steal<Body<'_>> {
49aad941 37 tcx.alloc_steal_mir(mir_build(tcx, def))
dfeec247
XL
38}
39
9fa01778 40/// Construct the MIR for a given `DefId`.
49aad941 41fn mir_build(tcx: TyCtxt<'_>, def: LocalDefId) -> Body<'_> {
c295e0f8 42 // Ensure unsafeck and abstract const building is ran before we steal the THIR.
49aad941
FG
43 tcx.ensure_with_value().thir_check_unsafety(def);
44 tcx.ensure_with_value().thir_abstract_const(def);
45 if let Err(e) = tcx.check_match(def) {
46 return construct_error(tcx, def, e);
17df50a5
XL
47 }
48
f2b60f7d 49 let body = match tcx.thir_body(def) {
49aad941 50 Err(error_reported) => construct_error(tcx, def, error_reported),
f2b60f7d 51 Ok((thir, expr)) => {
17df50a5
XL
52 // We ran all queries that depended on THIR at the beginning
53 // of `mir_build`, so now we can steal it
54 let thir = thir.steal();
ea8adc8c 55
49aad941
FG
56 tcx.ensure().check_match(def);
57 // this must run before MIR dump, because
58 // "not all control paths return a value" is reported here.
59 //
60 // maybe move the check to a MIR pass?
61 tcx.ensure().check_liveness(def);
62
9ffffee4
FG
63 match thir.body_type {
64 thir::BodyTy::Fn(fn_sig) => construct_fn(tcx, def, &thir, expr, fn_sig),
65 thir::BodyTy::Const(ty) => construct_const(tcx, def, &thir, expr, ty),
6a06907d 66 }
f2b60f7d
FG
67 }
68 };
7cac9316 69
f2b60f7d
FG
70 lints::check(tcx, &body);
71
72 // The borrow checker will replace all the regions here with its own
73 // inference variables. There's no point having non-erased regions here.
74 // The exception is `body.user_type_annotations`, which is used unmodified
75 // by borrow checking.
76 debug_assert!(
77 !(body.local_decls.has_free_regions()
78 || body.basic_blocks.has_free_regions()
79 || body.var_debug_info.has_free_regions()
80 || body.yield_ty().has_free_regions()),
81 "Unexpected free regions in MIR: {:?}",
82 body,
83 );
ba9703b0 84
f2b60f7d 85 body
7cac9316
XL
86}
87
7cac9316
XL
88///////////////////////////////////////////////////////////////////////////
89// BuildMir -- walks a crate, looking for fn items and methods to build MIR from
90
0bf4aa26 91#[derive(Debug, PartialEq, Eq)]
dfeec247 92enum BlockFrame {
0bf4aa26
XL
93 /// Evaluation is currently within a statement.
94 ///
95 /// Examples include:
dc9dc135
XL
96 /// 1. `EXPR;`
97 /// 2. `let _ = EXPR;`
98 /// 3. `let x = EXPR;`
0bf4aa26
XL
99 Statement {
100 /// If true, then statement discards result from evaluating
101 /// the expression (such as examples 1 and 2 above).
dfeec247 102 ignores_expr_result: bool,
0bf4aa26
XL
103 },
104
105 /// Evaluation is currently within the tail expression of a block.
106 ///
107 /// Example: `{ STMT_1; STMT_2; EXPR }`
108 TailExpr {
109 /// If true, then the surrounding context of the block ignores
110 /// the result of evaluating the block's tail expression.
111 ///
112 /// Example: `let _ = { STMT_1; EXPR };`
dfeec247 113 tail_result_is_ignored: bool,
f9f354fc
XL
114
115 /// `Span` of the tail expression.
116 span: Span,
0bf4aa26
XL
117 },
118
119 /// Generic mark meaning that the block occurred as a subexpression
120 /// where the result might be used.
121 ///
122 /// Examples: `foo(EXPR)`, `match EXPR { ... }`
123 SubExpr,
124}
125
126impl BlockFrame {
127 fn is_tail_expr(&self) -> bool {
128 match *self {
129 BlockFrame::TailExpr { .. } => true,
130
dfeec247 131 BlockFrame::Statement { .. } | BlockFrame::SubExpr => false,
0bf4aa26
XL
132 }
133 }
134 fn is_statement(&self) -> bool {
135 match *self {
136 BlockFrame::Statement { .. } => true,
137
dfeec247 138 BlockFrame::TailExpr { .. } | BlockFrame::SubExpr => false,
0bf4aa26
XL
139 }
140 }
dfeec247 141}
0bf4aa26 142
a1dfa0c6
XL
143#[derive(Debug)]
144struct BlockContext(Vec<BlockFrame>);
145
dc9dc135 146struct Builder<'a, 'tcx> {
6a06907d 147 tcx: TyCtxt<'tcx>,
2b03887a 148 infcx: InferCtxt<'tcx>,
6a06907d
XL
149 region_scope_tree: &'tcx region::ScopeTree,
150 param_env: ty::ParamEnv<'tcx>,
151
17df50a5 152 thir: &'a Thir<'tcx>,
b039eaaf 153 cfg: CFG<'tcx>,
54a0048b 154
49aad941 155 def_id: LocalDefId,
6a06907d 156 hir_id: hir::HirId,
04454e1e 157 parent_module: DefId,
6a06907d 158 check_overflow: bool,
54a0048b 159 fn_span: Span,
c30ab7b3 160 arg_count: usize,
60c5eb7d 161 generator_kind: Option<GeneratorKind>,
54a0048b 162
9fa01778
XL
163 /// The current set of scopes, updated as we traverse;
164 /// see the `scope` module for more details.
dc9dc135 165 scopes: scope::Scopes<'tcx>,
54a0048b 166
3dfed10e 167 /// The block-context: each time we build the code within an thir::Block,
0bf4aa26
XL
168 /// we push a frame here tracking whether we are building a statement or
169 /// if we are pushing the tail expression of the block. This is used to
170 /// embed information in generated temps about whether they were created
171 /// for a block tail expression or not.
172 ///
173 /// It would be great if we could fold this into `self.scopes`
9fa01778 174 /// somehow, but right now I think that is very tightly tied to
0bf4aa26
XL
175 /// the code generation in ways that we cannot (or should not)
176 /// start just throwing new entries onto that vector in order to
177 /// distinguish the context of EXPR1 from the context of EXPR2 in
9fa01778 178 /// `{ STMTS; EXPR1 } + EXPR2`.
a1dfa0c6 179 block_context: BlockContext,
0bf4aa26 180
136023e0
XL
181 /// The current unsafe block in scope
182 in_scope_unsafe: Safety,
ea8adc8c 183
9fa01778
XL
184 /// The vector of all scopes that we have created thus far;
185 /// we track this for debuginfo later.
29967ef6 186 source_scopes: IndexVec<SourceScope, SourceScopeData<'tcx>>,
94b46f34 187 source_scope: SourceScope,
54a0048b 188
9fa01778 189 /// The guard-context: each time we build the guard expression for
83c7162d
XL
190 /// a match arm, we push onto this stack, and then pop when we
191 /// finish building it.
192 guard_context: Vec<GuardFrame>,
193
532ac7d7 194 /// Maps `HirId`s of variable bindings to the `Local`s created for them.
83c7162d 195 /// (A match binding can have two locals; the 2nd is for the arm's guard.)
923072b8 196 var_indices: FxHashMap<LocalVarId, LocalsForNode>,
c30ab7b3 197 local_decls: IndexVec<Local, LocalDecl<'tcx>>,
0731742a 198 canonical_user_type_annotations: ty::CanonicalUserTypeAnnotations<'tcx>,
f2b60f7d 199 upvars: CaptureMap<'tcx>,
ff7c6d11 200 unit_temp: Option<Place<'tcx>>,
54a0048b 201
60c5eb7d 202 var_debug_info: Vec<VarDebugInfo<'tcx>>,
e9174d1e
SL
203}
204
f2b60f7d
FG
205type CaptureMap<'tcx> = SortedIndexMultiMap<usize, hir::HirId, Capture<'tcx>>;
206
207#[derive(Debug)]
208struct Capture<'tcx> {
209 captured_place: &'tcx ty::CapturedPlace<'tcx>,
210 use_place: Place<'tcx>,
211 mutability: Mutability,
212}
213
dc9dc135 214impl<'a, 'tcx> Builder<'a, 'tcx> {
923072b8 215 fn is_bound_var_in_guard(&self, id: LocalVarId) -> bool {
83c7162d
XL
216 self.guard_context.iter().any(|frame| frame.locals.iter().any(|local| local.id == id))
217 }
218
923072b8 219 fn var_local_id(&self, id: LocalVarId, for_guard: ForGuard) -> Local {
83c7162d
XL
220 self.var_indices[&id].local_id(for_guard)
221 }
222}
223
a1dfa0c6 224impl BlockContext {
dfeec247
XL
225 fn new() -> Self {
226 BlockContext(vec![])
227 }
228 fn push(&mut self, bf: BlockFrame) {
229 self.0.push(bf);
230 }
231 fn pop(&mut self) -> Option<BlockFrame> {
232 self.0.pop()
233 }
a1dfa0c6 234
9fa01778 235 /// Traverses the frames on the `BlockContext`, searching for either
a1dfa0c6
XL
236 /// the first block-tail expression frame with no intervening
237 /// statement frame.
238 ///
239 /// Notably, this skips over `SubExpr` frames; this method is
240 /// meant to be used in the context of understanding the
241 /// relationship of a temp (created within some complicated
242 /// expression) with its containing expression, and whether the
243 /// value of that *containing expression* (not the temp!) is
244 /// ignored.
245 fn currently_in_block_tail(&self) -> Option<BlockTailInfo> {
246 for bf in self.0.iter().rev() {
247 match bf {
248 BlockFrame::SubExpr => continue,
249 BlockFrame::Statement { .. } => break,
f9f354fc
XL
250 &BlockFrame::TailExpr { tail_result_is_ignored, span } => {
251 return Some(BlockTailInfo { tail_result_is_ignored, span });
dfeec247 252 }
a1dfa0c6
XL
253 }
254 }
255
ba9703b0 256 None
a1dfa0c6
XL
257 }
258
259 /// Looks at the topmost frame on the BlockContext and reports
260 /// whether its one that would discard a block tail result.
261 ///
262 /// Unlike `currently_within_ignored_tail_expression`, this does
263 /// *not* skip over `SubExpr` frames: here, we want to know
264 /// whether the block result itself is discarded.
265 fn currently_ignores_tail_results(&self) -> bool {
266 match self.0.last() {
267 // no context: conservatively assume result is read
268 None => false,
269
270 // sub-expression: block result feeds into some computation
271 Some(BlockFrame::SubExpr) => false,
272
273 // otherwise: use accumulated is_ignored state.
ba9703b0 274 Some(
f9f354fc 275 BlockFrame::TailExpr { tail_result_is_ignored: ignored, .. }
ba9703b0
XL
276 | BlockFrame::Statement { ignores_expr_result: ignored },
277 ) => *ignored,
a1dfa0c6
XL
278 }
279 }
280}
281
83c7162d
XL
282#[derive(Debug)]
283enum LocalsForNode {
532ac7d7 284 /// In the usual case, a `HirId` for an identifier maps to at most
9fa01778 285 /// one `Local` declaration.
83c7162d 286 One(Local),
8faf50e0
XL
287
288 /// The exceptional case is identifiers in a match arm's pattern
289 /// that are referenced in a guard of that match arm. For these,
9fa01778 290 /// we have `2` Locals.
8faf50e0
XL
291 ///
292 /// * `for_arm_body` is the Local used in the arm body (which is
293 /// just like the `One` case above),
294 ///
295 /// * `ref_for_guard` is the Local used in the arm's guard (which
296 /// is a reference to a temp that is an alias of
297 /// `for_arm_body`).
9fa01778 298 ForGuard { ref_for_guard: Local, for_arm_body: Local },
83c7162d
XL
299}
300
301#[derive(Debug)]
302struct GuardFrameLocal {
923072b8 303 id: LocalVarId,
83c7162d
XL
304}
305
306impl GuardFrameLocal {
923072b8 307 fn new(id: LocalVarId, _binding_mode: BindingMode) -> Self {
74b04a01 308 GuardFrameLocal { id }
83c7162d
XL
309 }
310}
311
312#[derive(Debug)]
313struct GuardFrame {
314 /// These are the id's of names that are bound by patterns of the
315 /// arm of *this* guard.
316 ///
317 /// (Frames higher up the stack will have the id's bound in arms
318 /// further out, such as in a case like:
319 ///
320 /// match E1 {
321 /// P1(id1) if (... (match E2 { P2(id2) if ... => B2 })) => B1,
322 /// }
323 ///
9fa01778 324 /// here, when building for FIXME.
83c7162d
XL
325 locals: Vec<GuardFrameLocal>,
326}
327
9fa01778
XL
328/// `ForGuard` indicates whether we are talking about:
329/// 1. The variable for use outside of guard expressions, or
330/// 2. The temp that holds reference to (1.), which is actually what the
331/// guard expressions see.
83c7162d
XL
332#[derive(Copy, Clone, Debug, PartialEq, Eq)]
333enum ForGuard {
94b46f34 334 RefWithinGuard,
83c7162d
XL
335 OutsideGuard,
336}
337
338impl LocalsForNode {
339 fn local_id(&self, for_guard: ForGuard) -> Local {
340 match (self, for_guard) {
dfeec247
XL
341 (&LocalsForNode::One(local_id), ForGuard::OutsideGuard)
342 | (
343 &LocalsForNode::ForGuard { ref_for_guard: local_id, .. },
344 ForGuard::RefWithinGuard,
345 )
346 | (&LocalsForNode::ForGuard { for_arm_body: local_id, .. }, ForGuard::OutsideGuard) => {
347 local_id
348 }
83c7162d 349
dfeec247
XL
350 (&LocalsForNode::One(_), ForGuard::RefWithinGuard) => {
351 bug!("anything with one local should never be within a guard.")
352 }
83c7162d
XL
353 }
354 }
355}
356
b039eaaf 357struct CFG<'tcx> {
3157f602
XL
358 basic_blocks: IndexVec<BasicBlock, BasicBlockData<'tcx>>,
359}
360
e74abb32 361rustc_index::newtype_index! {
9c376795 362 struct ScopeId {}
b7449926 363}
e9174d1e 364
04454e1e
FG
365#[derive(Debug)]
366enum NeedsTemporary {
367 /// Use this variant when whatever you are converting with `as_operand`
368 /// is the last thing you are converting. This means that if we introduced
369 /// an intermediate temporary, we'd only read it immediately after, so we can
370 /// also avoid it.
371 No,
372 /// For all cases where you aren't sure or that are too expensive to compute
373 /// for now. It is always safe to fall back to this.
374 Maybe,
375}
376
e9174d1e 377///////////////////////////////////////////////////////////////////////////
7453a54e
SL
378/// The `BlockAnd` "monad" packages up the new basic block along with a
379/// produced value (sometimes just unit, of course). The `unpack!`
380/// macro (and methods below) makes working with `BlockAnd` much more
381/// convenient.
e9174d1e 382
83c7162d 383#[must_use = "if you don't use one of these results, you're leaving a dangling edge"]
7cac9316 384struct BlockAnd<T>(BasicBlock, T);
e9174d1e 385
92a42be0
SL
386trait BlockAndExtension {
387 fn and<T>(self, v: T) -> BlockAnd<T>;
388 fn unit(self) -> BlockAnd<()>;
389}
390
391impl BlockAndExtension for BasicBlock {
e9174d1e
SL
392 fn and<T>(self, v: T) -> BlockAnd<T> {
393 BlockAnd(self, v)
394 }
395
396 fn unit(self) -> BlockAnd<()> {
397 BlockAnd(self, ())
398 }
399}
400
401/// Update a block pointer and return the value.
402/// Use it like `let x = unpack!(block = self.foo(block, foo))`.
403macro_rules! unpack {
dfeec247
XL
404 ($x:ident = $c:expr) => {{
405 let BlockAnd(b, v) = $c;
406 $x = b;
407 v
408 }};
409
410 ($c:expr) => {{
411 let BlockAnd(b, ()) = $c;
412 b
413 }};
e9174d1e
SL
414}
415
416///////////////////////////////////////////////////////////////////////////
7453a54e 417/// the main entry point for building MIR for a function
e9174d1e 418
f2b60f7d
FG
419fn construct_fn<'tcx>(
420 tcx: TyCtxt<'tcx>,
49aad941 421 fn_def: LocalDefId,
f2b60f7d 422 thir: &Thir<'tcx>,
17df50a5 423 expr: ExprId,
9ffffee4 424 fn_sig: ty::FnSig<'tcx>,
f2b60f7d 425) -> Body<'tcx> {
49aad941
FG
426 let span = tcx.def_span(fn_def);
427 let fn_id = tcx.hir().local_def_id_to_hir_id(fn_def);
428 let generator_kind = tcx.generator_kind(fn_def);
ea8adc8c 429
9ffffee4
FG
430 // The representation of thir for `-Zunpretty=thir-tree` relies on
431 // the entry expression being the last element of `thir.exprs`.
432 assert_eq!(expr.as_usize(), thir.exprs.len() - 1);
433
f2b60f7d 434 // Figure out what primary body this item has.
49aad941 435 let body_id = tcx.hir().body_owned_by(fn_def);
f2b60f7d
FG
436 let span_with_body = tcx.hir().span_with_body(fn_id);
437 let return_ty_span = tcx
438 .hir()
439 .fn_decl_by_hir_id(fn_id)
49aad941 440 .unwrap_or_else(|| span_bug!(span, "can't build MIR for {:?}", fn_def))
f2b60f7d
FG
441 .output
442 .span();
443
f2b60f7d
FG
444 let safety = match fn_sig.unsafety {
445 hir::Unsafety::Normal => Safety::Safe,
446 hir::Unsafety::Unsafe => Safety::FnUnsafe,
447 };
448
449 let mut abi = fn_sig.abi;
49aad941 450 if let DefKind::Closure = tcx.def_kind(fn_def) {
f2b60f7d
FG
451 // HACK(eddyb) Avoid having RustCall on closures,
452 // as it adds unnecessary (and wrong) auto-tupling.
453 abi = Abi::Rust;
454 }
455
456 let arguments = &thir.params;
457
458 let (yield_ty, return_ty) = if generator_kind.is_some() {
459 let gen_ty = arguments[thir::UPVAR_ENV_PARAM].ty;
460 let gen_sig = match gen_ty.kind() {
461 ty::Generator(_, gen_substs, ..) => gen_substs.as_generator().sig(),
462 _ => {
463 span_bug!(span, "generator w/o generator type: {:?}", gen_ty)
464 }
465 };
466 (Some(gen_sig.yield_ty), gen_sig.return_ty)
467 } else {
468 (None, fn_sig.output())
469 };
a7813a04 470
487cf647
FG
471 if let Some(custom_mir_attr) =
472 tcx.hir().attrs(fn_id).iter().find(|attr| attr.name_or_empty() == sym::custom_mir)
473 {
474 return custom::build_custom_mir(
475 tcx,
49aad941 476 fn_def.to_def_id(),
9c376795 477 fn_id,
487cf647
FG
478 thir,
479 expr,
480 arguments,
481 return_ty,
482 return_ty_span,
483 span_with_body,
484 custom_mir_attr,
485 );
486 }
487
2b03887a
FG
488 let infcx = tcx.infer_ctxt().build();
489 let mut builder = Builder::new(
490 thir,
491 infcx,
492 fn_def,
493 fn_id,
494 span_with_body,
495 arguments.len(),
496 safety,
497 return_ty,
498 return_ty_span,
499 generator_kind,
500 );
501
502 let call_site_scope =
503 region::Scope { id: body_id.hir_id.local_id, data: region::ScopeData::CallSite };
504 let arg_scope =
505 region::Scope { id: body_id.hir_id.local_id, data: region::ScopeData::Arguments };
506 let source_info = builder.source_info(span);
507 let call_site_s = (call_site_scope, source_info);
508 unpack!(builder.in_scope(call_site_s, LintLevel::Inherited, |builder| {
509 let arg_scope_s = (arg_scope, source_info);
510 // Attribute epilogue to function's closing brace
511 let fn_end = span_with_body.shrink_to_hi();
512 let return_block =
513 unpack!(builder.in_breakable_scope(None, Place::return_place(), fn_end, |builder| {
514 Some(builder.in_scope(arg_scope_s, LintLevel::Inherited, |builder| {
9ffffee4 515 builder.args_and_body(START_BLOCK, arguments, arg_scope, &thir[expr])
2b03887a
FG
516 }))
517 }));
518 let source_info = builder.source_info(fn_end);
519 builder.cfg.terminate(return_block, source_info, TerminatorKind::Return);
520 builder.build_drop_trees();
521 return_block.unit()
522 }));
523
524 let mut body = builder.finish();
f2b60f7d
FG
525
526 body.spread_arg = if abi == Abi::RustCall {
476ff2be 527 // RustCall pseudo-ABI untuples the last argument.
ba9703b0
XL
528 Some(Local::new(arguments.len()))
529 } else {
530 None
531 };
f2b60f7d
FG
532 if yield_ty.is_some() {
533 body.generator.as_mut().unwrap().yield_ty = yield_ty;
534 }
dc9dc135 535 body
a7813a04
XL
536}
537
dc9dc135 538fn construct_const<'a, 'tcx>(
f2b60f7d 539 tcx: TyCtxt<'tcx>,
49aad941 540 def: LocalDefId,
17df50a5 541 thir: &'a Thir<'tcx>,
17df50a5 542 expr: ExprId,
9ffffee4 543 const_ty: Ty<'tcx>,
dc9dc135 544) -> Body<'tcx> {
49aad941 545 let hir_id = tcx.hir().local_def_id_to_hir_id(def);
a7813a04 546
f2b60f7d
FG
547 // Figure out what primary body this item has.
548 let (span, const_ty_span) = match tcx.hir().get(hir_id) {
549 Node::Item(hir::Item {
550 kind: hir::ItemKind::Static(ty, _, _) | hir::ItemKind::Const(ty, _),
551 span,
552 ..
553 })
554 | Node::ImplItem(hir::ImplItem { kind: hir::ImplItemKind::Const(ty, _), span, .. })
555 | Node::TraitItem(hir::TraitItem {
556 kind: hir::TraitItemKind::Const(ty, Some(_)),
557 span,
558 ..
559 }) => (*span, ty.span),
560 Node::AnonConst(_) => {
49aad941 561 let span = tcx.def_span(def);
f2b60f7d
FG
562 (span, span)
563 }
49aad941 564 _ => span_bug!(tcx.def_span(def), "can't build MIR for {:?}", def),
f2b60f7d 565 };
a7813a04 566
2b03887a
FG
567 let infcx = tcx.infer_ctxt().build();
568 let mut builder = Builder::new(
569 thir,
570 infcx,
571 def,
572 hir_id,
573 span,
574 0,
575 Safety::Safe,
576 const_ty,
577 const_ty_span,
578 None,
579 );
f2b60f7d 580
2b03887a
FG
581 let mut block = START_BLOCK;
582 unpack!(block = builder.expr_into_dest(Place::return_place(), block, &thir[expr]));
f2b60f7d 583
2b03887a
FG
584 let source_info = builder.source_info(span);
585 builder.cfg.terminate(block, source_info, TerminatorKind::Return);
f2b60f7d 586
2b03887a 587 builder.build_drop_trees();
ff7c6d11 588
2b03887a 589 builder.finish()
e9174d1e
SL
590}
591
94222f64 592/// Construct MIR for an item that has had errors in type checking.
74b04a01
XL
593///
594/// This is required because we may still want to run MIR passes on an item
595/// with type errors, but normal MIR construction can't handle that in general.
9ffffee4 596fn construct_error(tcx: TyCtxt<'_>, def: LocalDefId, err: ErrorGuaranteed) -> Body<'_> {
f2b60f7d
FG
597 let span = tcx.def_span(def);
598 let hir_id = tcx.hir().local_def_id_to_hir_id(def);
599 let generator_kind = tcx.generator_kind(def);
9ffffee4 600 let body_owner_kind = tcx.hir().body_owner_kind(def);
f2b60f7d 601
9ffffee4 602 let ty = tcx.ty_error(err);
6a06907d 603 let num_params = match body_owner_kind {
9ffffee4 604 hir::BodyOwnerKind::Fn => tcx.fn_sig(def).skip_binder().inputs().skip_binder().len(),
74b04a01 605 hir::BodyOwnerKind::Closure => {
9ffffee4 606 let ty = tcx.type_of(def).subst_identity();
f2b60f7d
FG
607 match ty.kind() {
608 ty::Closure(_, substs) => {
609 1 + substs.as_closure().sig().inputs().skip_binder().len()
610 }
611 ty::Generator(..) => 2,
612 _ => bug!("expected closure or generator, found {ty:?}"),
74b04a01
XL
613 }
614 }
615 hir::BodyOwnerKind::Const => 0,
616 hir::BodyOwnerKind::Static(_) => 0,
617 };
17df50a5
XL
618 let mut cfg = CFG { basic_blocks: IndexVec::new() };
619 let mut source_scopes = IndexVec::new();
620 let mut local_decls = IndexVec::from_elem_n(LocalDecl::new(ty, span), 1);
621
622 cfg.start_new_block();
623 source_scopes.push(SourceScopeData {
624 span,
625 parent_scope: None,
626 inlined: None,
627 inlined_parent_scope: None,
628 local_data: ClearCrossCrate::Set(SourceScopeLocalData {
629 lint_root: hir_id,
630 safety: Safety::Safe,
631 }),
632 });
633 let source_info = SourceInfo { span, scope: OUTERMOST_SOURCE_SCOPE };
634
74b04a01
XL
635 // Some MIR passes will expect the number of parameters to match the
636 // function declaration.
637 for _ in 0..num_params {
17df50a5 638 local_decls.push(LocalDecl::with_source_info(ty, source_info));
74b04a01 639 }
17df50a5
XL
640 cfg.terminate(START_BLOCK, source_info, TerminatorKind::Unreachable);
641
642 let mut body = Body::new(
f2b60f7d 643 MirSource::item(def.to_def_id()),
17df50a5
XL
644 cfg.basic_blocks,
645 source_scopes,
646 local_decls,
647 IndexVec::new(),
648 num_params,
649 vec![],
650 span,
651 generator_kind,
5099ac24 652 Some(err),
17df50a5 653 );
6a06907d 654 body.generator.as_mut().map(|gen| gen.yield_ty = Some(ty));
74b04a01 655 body
8bb4bdeb
XL
656}
657
dc9dc135 658impl<'a, 'tcx> Builder<'a, 'tcx> {
dfeec247 659 fn new(
17df50a5 660 thir: &'a Thir<'tcx>,
2b03887a 661 infcx: InferCtxt<'tcx>,
49aad941 662 def: LocalDefId,
6a06907d 663 hir_id: hir::HirId,
dfeec247
XL
664 span: Span,
665 arg_count: usize,
666 safety: Safety,
667 return_ty: Ty<'tcx>,
668 return_span: Span,
669 generator_kind: Option<GeneratorKind>,
670 ) -> Builder<'a, 'tcx> {
6a06907d
XL
671 let tcx = infcx.tcx;
672 let attrs = tcx.hir().attrs(hir_id);
673 // Some functions always have overflow checks enabled,
674 // however, they may not get codegen'd, depending on
675 // the settings for the crate they are codegened in.
353b0b11 676 let mut check_overflow = attr::contains_name(attrs, sym::rustc_inherit_overflow_checks);
6a06907d
XL
677 // Respect -C overflow-checks.
678 check_overflow |= tcx.sess.overflow_checks();
679 // Constants always need overflow checks.
680 check_overflow |= matches!(
49aad941 681 tcx.hir().body_owner_kind(def),
6a06907d
XL
682 hir::BodyOwnerKind::Const | hir::BodyOwnerKind::Static(_)
683 );
684
685 let lint_level = LintLevel::Explicit(hir_id);
49aad941 686 let param_env = tcx.param_env(def);
a7813a04 687 let mut builder = Builder {
17df50a5 688 thir,
6a06907d
XL
689 tcx,
690 infcx,
49aad941 691 region_scope_tree: tcx.region_scope_tree(def),
04454e1e 692 param_env,
49aad941 693 def_id: def,
6a06907d 694 hir_id,
04454e1e 695 parent_module: tcx.parent_module(hir_id).to_def_id(),
6a06907d 696 check_overflow,
3157f602 697 cfg: CFG { basic_blocks: IndexVec::new() },
a7813a04 698 fn_span: span,
3b2f2976 699 arg_count,
60c5eb7d 700 generator_kind,
29967ef6 701 scopes: scope::Scopes::new(),
a1dfa0c6 702 block_context: BlockContext::new(),
94b46f34
XL
703 source_scopes: IndexVec::new(),
704 source_scope: OUTERMOST_SOURCE_SCOPE,
83c7162d 705 guard_context: vec![],
136023e0 706 in_scope_unsafe: safety,
f9f354fc 707 local_decls: IndexVec::from_elem_n(LocalDecl::new(return_ty, return_span), 1),
0731742a 708 canonical_user_type_annotations: IndexVec::new(),
f2b60f7d 709 upvars: CaptureMap::new(),
a1dfa0c6 710 var_indices: Default::default(),
a7813a04 711 unit_temp: None,
60c5eb7d 712 var_debug_info: vec![],
a7813a04
XL
713 };
714
715 assert_eq!(builder.cfg.start_new_block(), START_BLOCK);
ea8adc8c 716 assert_eq!(
94b46f34 717 builder.new_source_scope(span, lint_level, Some(safety)),
dfeec247
XL
718 OUTERMOST_SOURCE_SCOPE
719 );
94b46f34 720 builder.source_scopes[OUTERMOST_SOURCE_SCOPE].parent_scope = None;
a7813a04
XL
721
722 builder
723 }
724
60c5eb7d 725 fn finish(self) -> Body<'tcx> {
a7813a04
XL
726 for (index, block) in self.cfg.basic_blocks.iter().enumerate() {
727 if block.terminator.is_none() {
728 span_bug!(self.fn_span, "no terminator on block {:?}", index);
729 }
730 }
731
dc9dc135 732 Body::new(
49aad941 733 MirSource::item(self.def_id.to_def_id()),
0731742a
XL
734 self.cfg.basic_blocks,
735 self.source_scopes,
0731742a
XL
736 self.local_decls,
737 self.canonical_user_type_annotations,
738 self.arg_count,
60c5eb7d 739 self.var_debug_info,
0731742a 740 self.fn_span,
dfeec247 741 self.generator_kind,
9ffffee4 742 None,
476ff2be 743 )
a7813a04
XL
744 }
745
9ffffee4
FG
746 fn insert_upvar_arg(&mut self) {
747 let Some(closure_arg) = self.local_decls.get(ty::CAPTURE_STRUCT_LOCAL) else { return };
748
749 let mut closure_ty = closure_arg.ty;
750 let mut closure_env_projs = vec![];
751 if let ty::Ref(_, ty, _) = closure_ty.kind() {
752 closure_env_projs.push(ProjectionElem::Deref);
753 closure_ty = *ty;
754 }
755
756 let upvar_substs = match closure_ty.kind() {
757 ty::Closure(_, substs) => ty::UpvarSubsts::Closure(substs),
758 ty::Generator(_, substs, _) => ty::UpvarSubsts::Generator(substs),
759 _ => return,
760 };
761
762 // In analyze_closure() in upvar.rs we gathered a list of upvars used by an
763 // indexed closure and we stored in a map called closure_min_captures in TypeckResults
764 // with the closure's DefId. Here, we run through that vec of UpvarIds for
765 // the given closure and use the necessary information to create upvar
766 // debuginfo and to fill `self.upvars`.
767 let capture_tys = upvar_substs.upvar_tys();
768
769 let tcx = self.tcx;
770 self.upvars = tcx
49aad941 771 .closure_captures(self.def_id)
9ffffee4
FG
772 .iter()
773 .zip(capture_tys)
774 .enumerate()
775 .map(|(i, (captured_place, ty))| {
776 let name = captured_place.to_symbol();
777
778 let capture = captured_place.info.capture_kind;
779 let var_id = match captured_place.place.base {
780 HirPlaceBase::Upvar(upvar_id) => upvar_id.var_path.hir_id,
781 _ => bug!("Expected an upvar"),
782 };
783
784 let mutability = captured_place.mutability;
785
786 let mut projs = closure_env_projs.clone();
353b0b11 787 projs.push(ProjectionElem::Field(FieldIdx::new(i), ty));
9ffffee4
FG
788 match capture {
789 ty::UpvarCapture::ByValue => {}
790 ty::UpvarCapture::ByRef(..) => {
791 projs.push(ProjectionElem::Deref);
792 }
793 };
794
795 let use_place = Place {
796 local: ty::CAPTURE_STRUCT_LOCAL,
797 projection: tcx.mk_place_elems(&projs),
798 };
799 self.var_debug_info.push(VarDebugInfo {
800 name,
49aad941 801 references: 0,
9ffffee4
FG
802 source_info: SourceInfo::outermost(captured_place.var_ident.span),
803 value: VarDebugInfoContents::Place(use_place),
353b0b11 804 argument_index: None,
9ffffee4
FG
805 });
806
807 let capture = Capture { captured_place, use_place, mutability };
808 (var_id, capture)
809 })
810 .collect();
811 }
812
dfeec247
XL
813 fn args_and_body(
814 &mut self,
815 mut block: BasicBlock,
353b0b11 816 arguments: &IndexSlice<ParamId, Param<'tcx>>,
dfeec247 817 argument_scope: region::Scope,
17df50a5 818 expr: &Expr<'tcx>,
dfeec247 819 ) -> BlockAnd<()> {
c30ab7b3 820 // Allocate locals for the function arguments
353b0b11 821 for (argument_index, param) in arguments.iter().enumerate() {
f9f354fc 822 let source_info =
f2b60f7d
FG
823 SourceInfo::outermost(param.pat.as_ref().map_or(self.fn_span, |pat| pat.span));
824 let arg_local =
825 self.local_decls.push(LocalDecl::with_source_info(param.ty, source_info));
60c5eb7d
XL
826
827 // If this is a simple binding pattern, give debuginfo a nice name.
f2b60f7d 828 if let Some(ref pat) = param.pat && let Some(name) = pat.simple_ident() {
5e7ed085 829 self.var_debug_info.push(VarDebugInfo {
f2b60f7d 830 name,
5e7ed085 831 source_info,
49aad941 832 references: 0,
5e7ed085 833 value: VarDebugInfoContents::Place(arg_local.into()),
353b0b11 834 argument_index: Some(argument_index as u16 + 1),
5e7ed085 835 });
60c5eb7d
XL
836 }
837 }
838
9ffffee4 839 self.insert_upvar_arg();
c30ab7b3 840
3157f602 841 let mut scope = None;
c30ab7b3 842 // Bind the argument patterns
f2b60f7d 843 for (index, param) in arguments.iter().enumerate() {
ff7c6d11 844 // Function arguments always get the first Local indices after the return place
abe05a73 845 let local = Local::new(index + 1);
dc9dc135 846 let place = Place::from(local);
c30ab7b3 847
0731742a
XL
848 // Make sure we drop (parts of) the argument even when not matched on.
849 self.schedule_drop(
f2b60f7d 850 param.pat.as_ref().map_or(expr.span, |pat| pat.span),
dfeec247
XL
851 argument_scope,
852 local,
853 DropKind::Value,
0731742a
XL
854 );
855
f2b60f7d 856 let Some(ref pat) = param.pat else {
3c0e092e
XL
857 continue;
858 };
3c0e092e 859 let original_source_scope = self.source_scope;
f2b60f7d
FG
860 let span = pat.span;
861 if let Some(arg_hir_id) = param.hir_id {
862 self.set_correct_source_scope_for_arg(arg_hir_id, original_source_scope, span);
863 }
864 match pat.kind {
3c0e092e
XL
865 // Don't introduce extra copies for simple bindings
866 PatKind::Binding {
867 mutability,
868 var,
869 mode: BindingMode::ByValue,
870 subpattern: None,
871 ..
872 } => {
873 self.local_decls[local].mutability = mutability;
874 self.local_decls[local].source_info.scope = self.source_scope;
353b0b11
FG
875 **self.local_decls[local].local_info.as_mut().assert_crate_local() =
876 if let Some(kind) = param.self_kind {
877 LocalInfo::User(BindingForm::ImplicitSelf(kind))
878 } else {
879 let binding_mode = ty::BindingMode::BindByValue(mutability);
880 LocalInfo::User(BindingForm::Var(VarBindingForm {
3c0e092e 881 binding_mode,
f2b60f7d
FG
882 opt_ty_info: param.ty_span,
883 opt_match_place: Some((None, span)),
3c0e092e 884 pat_span: span,
353b0b11
FG
885 }))
886 };
3c0e092e
XL
887 self.var_indices.insert(var, LocalsForNode::One(local));
888 }
889 _ => {
890 scope = self.declare_bindings(
891 scope,
892 expr.span,
f2b60f7d 893 &pat,
487cf647 894 None,
3c0e092e
XL
895 Some((Some(&place), span)),
896 );
897 let place_builder = PlaceBuilder::from(local);
f2b60f7d 898 unpack!(block = self.place_into_pattern(block, &pat, place_builder, false));
abe05a73 899 }
a7813a04 900 }
3c0e092e 901 self.source_scope = original_source_scope;
c30ab7b3 902 }
a7813a04 903
94b46f34
XL
904 // Enter the argument pattern bindings source scope, if it exists.
905 if let Some(source_scope) = scope {
906 self.source_scope = source_scope;
3157f602
XL
907 }
908
6a06907d 909 self.expr_into_dest(Place::return_place(), block, &expr)
416331ca
XL
910 }
911
912 fn set_correct_source_scope_for_arg(
913 &mut self,
914 arg_hir_id: hir::HirId,
915 original_source_scope: SourceScope,
dfeec247 916 pattern_span: Span,
416331ca 917 ) {
487cf647
FG
918 let parent_id = self.source_scopes[original_source_scope]
919 .local_data
920 .as_ref()
921 .assert_crate_local()
922 .lint_root;
923 self.maybe_new_source_scope(pattern_span, None, arg_hir_id, parent_id);
e9174d1e 924 }
7453a54e 925
ff7c6d11 926 fn get_unit_temp(&mut self) -> Place<'tcx> {
7453a54e 927 match self.unit_temp {
dfeec247 928 Some(tmp) => tmp,
7453a54e 929 None => {
6a06907d 930 let ty = self.tcx.mk_unit();
cc61c64b
XL
931 let fn_span = self.fn_span;
932 let tmp = self.temp(ty, fn_span);
dfeec247 933 self.unit_temp = Some(tmp);
7453a54e
SL
934 tmp
935 }
936 }
937 }
e9174d1e
SL
938}
939
923072b8
FG
940fn parse_float_into_constval<'tcx>(
941 num: Symbol,
942 float_ty: ty::FloatTy,
943 neg: bool,
944) -> Option<ConstValue<'tcx>> {
945 parse_float_into_scalar(num, float_ty, neg).map(ConstValue::Scalar)
946}
947
948pub(crate) fn parse_float_into_scalar(
949 num: Symbol,
950 float_ty: ty::FloatTy,
951 neg: bool,
952) -> Option<Scalar> {
953 let num = num.as_str();
954 match float_ty {
955 ty::FloatTy::F32 => {
956 let Ok(rust_f) = num.parse::<f32>() else { return None };
957 let mut f = num.parse::<Single>().unwrap_or_else(|e| {
958 panic!("apfloat::ieee::Single failed to parse `{}`: {:?}", num, e)
959 });
960
961 assert!(
962 u128::from(rust_f.to_bits()) == f.to_bits(),
963 "apfloat::ieee::Single gave different result for `{}`: \
964 {}({:#x}) vs Rust's {}({:#x})",
965 rust_f,
966 f,
967 f.to_bits(),
968 Single::from_bits(rust_f.to_bits().into()),
969 rust_f.to_bits()
970 );
971
972 if neg {
973 f = -f;
974 }
975
976 Some(Scalar::from_f32(f))
977 }
978 ty::FloatTy::F64 => {
979 let Ok(rust_f) = num.parse::<f64>() else { return None };
980 let mut f = num.parse::<Double>().unwrap_or_else(|e| {
981 panic!("apfloat::ieee::Double failed to parse `{}`: {:?}", num, e)
982 });
983
984 assert!(
985 u128::from(rust_f.to_bits()) == f.to_bits(),
986 "apfloat::ieee::Double gave different result for `{}`: \
987 {}({:#x}) vs Rust's {}({:#x})",
988 rust_f,
989 f,
990 f.to_bits(),
991 Double::from_bits(rust_f.to_bits().into()),
992 rust_f.to_bits()
993 );
994
995 if neg {
996 f = -f;
997 }
998
999 Some(Scalar::from_f64(f))
1000 }
1001 }
1002}
1003
e9174d1e
SL
1004///////////////////////////////////////////////////////////////////////////
1005// Builder methods are broken up into modules, depending on what kind
94b46f34 1006// of thing is being lowered. Note that they use the `unpack` macro
e9174d1e
SL
1007// above extensively.
1008
1009mod block;
1010mod cfg;
487cf647 1011mod custom;
e9174d1e 1012mod expr;
e9174d1e
SL
1013mod matches;
1014mod misc;
1015mod scope;
136023e0
XL
1016
1017pub(crate) use expr::category::Category as ExprCategory;