]> git.lizzy.rs Git - rust.git/blob - compiler/rustc_codegen_ssa/src/mir/statement.rs
Rollup merge of #82554 - SkiFire13:fix-string-retain-unsoundness, r=m-ou-se
[rust.git] / compiler / rustc_codegen_ssa / src / mir / statement.rs
1 use rustc_errors::struct_span_err;
2 use rustc_middle::mir;
3
4 use super::FunctionCx;
5 use super::LocalRef;
6 use super::OperandValue;
7 use crate::traits::BuilderMethods;
8 use crate::traits::*;
9
10 impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
11     pub fn codegen_statement(&mut self, mut bx: Bx, statement: &mir::Statement<'tcx>) -> Bx {
12         debug!("codegen_statement(statement={:?})", statement);
13
14         self.set_debug_loc(&mut bx, statement.source_info);
15         match statement.kind {
16             mir::StatementKind::Assign(box (ref place, ref rvalue)) => {
17                 if let Some(index) = place.as_local() {
18                     match self.locals[index] {
19                         LocalRef::Place(cg_dest) => self.codegen_rvalue(bx, cg_dest, rvalue),
20                         LocalRef::UnsizedPlace(cg_indirect_dest) => {
21                             self.codegen_rvalue_unsized(bx, cg_indirect_dest, rvalue)
22                         }
23                         LocalRef::Operand(None) => {
24                             let (mut bx, operand) = self.codegen_rvalue_operand(bx, rvalue);
25                             self.locals[index] = LocalRef::Operand(Some(operand));
26                             self.debug_introduce_local(&mut bx, index);
27                             bx
28                         }
29                         LocalRef::Operand(Some(op)) => {
30                             if !op.layout.is_zst() {
31                                 span_bug!(
32                                     statement.source_info.span,
33                                     "operand {:?} already assigned",
34                                     rvalue
35                                 );
36                             }
37
38                             // If the type is zero-sized, it's already been set here,
39                             // but we still need to make sure we codegen the operand
40                             self.codegen_rvalue_operand(bx, rvalue).0
41                         }
42                     }
43                 } else {
44                     let cg_dest = self.codegen_place(&mut bx, place.as_ref());
45                     self.codegen_rvalue(bx, cg_dest, rvalue)
46                 }
47             }
48             mir::StatementKind::SetDiscriminant { box ref place, variant_index } => {
49                 self.codegen_place(&mut bx, place.as_ref())
50                     .codegen_set_discr(&mut bx, variant_index);
51                 bx
52             }
53             mir::StatementKind::StorageLive(local) => {
54                 if let LocalRef::Place(cg_place) = self.locals[local] {
55                     cg_place.storage_live(&mut bx);
56                 } else if let LocalRef::UnsizedPlace(cg_indirect_place) = self.locals[local] {
57                     cg_indirect_place.storage_live(&mut bx);
58                 }
59                 bx
60             }
61             mir::StatementKind::StorageDead(local) => {
62                 if let LocalRef::Place(cg_place) = self.locals[local] {
63                     cg_place.storage_dead(&mut bx);
64                 } else if let LocalRef::UnsizedPlace(cg_indirect_place) = self.locals[local] {
65                     cg_indirect_place.storage_dead(&mut bx);
66                 }
67                 bx
68             }
69             mir::StatementKind::LlvmInlineAsm(ref asm) => {
70                 let outputs = asm
71                     .outputs
72                     .iter()
73                     .map(|output| self.codegen_place(&mut bx, output.as_ref()))
74                     .collect();
75
76                 let input_vals = asm.inputs.iter().fold(
77                     Vec::with_capacity(asm.inputs.len()),
78                     |mut acc, (span, input)| {
79                         let op = self.codegen_operand(&mut bx, input);
80                         if let OperandValue::Immediate(_) = op.val {
81                             acc.push(op.immediate());
82                         } else {
83                             struct_span_err!(
84                                 bx.sess(),
85                                 span.to_owned(),
86                                 E0669,
87                                 "invalid value for constraint in inline assembly"
88                             )
89                             .emit();
90                         }
91                         acc
92                     },
93                 );
94
95                 if input_vals.len() == asm.inputs.len() {
96                     let res = bx.codegen_llvm_inline_asm(
97                         &asm.asm,
98                         outputs,
99                         input_vals,
100                         statement.source_info.span,
101                     );
102                     if !res {
103                         struct_span_err!(
104                             bx.sess(),
105                             statement.source_info.span,
106                             E0668,
107                             "malformed inline assembly"
108                         )
109                         .emit();
110                     }
111                 }
112                 bx
113             }
114             mir::StatementKind::Coverage(box ref coverage) => {
115                 self.codegen_coverage(&mut bx, coverage.clone(), statement.source_info.scope);
116                 bx
117             }
118             mir::StatementKind::CopyNonOverlapping(box mir::CopyNonOverlapping {
119                 ref src,
120                 ref dst,
121                 ref count,
122             }) => {
123                 let dst_val = self.codegen_operand(&mut bx, dst);
124                 let src_val = self.codegen_operand(&mut bx, src);
125                 let count = self.codegen_operand(&mut bx, count).immediate();
126                 let pointee_layout = dst_val
127                     .layout
128                     .pointee_info_at(&mut bx, rustc_target::abi::Size::ZERO)
129                     .expect("Expected pointer");
130                 let bytes = bx.mul(count, bx.const_usize(pointee_layout.size.bytes()));
131
132                 let align = pointee_layout.align;
133                 let dst = dst_val.immediate();
134                 let src = src_val.immediate();
135                 bx.memcpy(dst, align, src, align, bytes, crate::MemFlags::empty());
136                 bx
137             }
138             mir::StatementKind::FakeRead(..)
139             | mir::StatementKind::Retag { .. }
140             | mir::StatementKind::AscribeUserType(..)
141             | mir::StatementKind::Nop => bx,
142         }
143     }
144 }