about summary refs log tree commit diff
path: root/compiler/rustc_mir_dataflow/src/framework/direction.rs
diff options
context:
space:
mode:
Diffstat (limited to 'compiler/rustc_mir_dataflow/src/framework/direction.rs')
-rw-r--r--compiler/rustc_mir_dataflow/src/framework/direction.rs59
1 files changed, 49 insertions, 10 deletions
diff --git a/compiler/rustc_mir_dataflow/src/framework/direction.rs b/compiler/rustc_mir_dataflow/src/framework/direction.rs
index 8a9ced91eb3..6131ee79818 100644
--- a/compiler/rustc_mir_dataflow/src/framework/direction.rs
+++ b/compiler/rustc_mir_dataflow/src/framework/direction.rs
@@ -4,7 +4,9 @@ use rustc_middle::ty::TyCtxt;
 use std::ops::RangeInclusive;
 
 use super::visitor::{ResultsVisitable, ResultsVisitor};
-use super::{Analysis, Effect, EffectIndex, GenKillAnalysis, GenKillSet, SwitchIntTarget};
+use super::{
+    Analysis, CallReturnPlaces, Effect, EffectIndex, GenKillAnalysis, GenKillSet, SwitchIntTarget,
+};
 
 pub trait Direction {
     fn is_forward() -> bool;
@@ -235,14 +237,26 @@ impl Direction for Backward {
                 // Apply terminator-specific edge effects.
                 //
                 // FIXME(ecstaticmorse): Avoid cloning the exit state unconditionally.
-                mir::TerminatorKind::Call {
-                    destination: Some((return_place, dest)),
-                    ref func,
-                    ref args,
-                    ..
+                mir::TerminatorKind::Call { destination: Some((return_place, dest)), .. }
+                    if dest == bb =>
+                {
+                    let mut tmp = exit_state.clone();
+                    analysis.apply_call_return_effect(
+                        &mut tmp,
+                        pred,
+                        CallReturnPlaces::Call(return_place),
+                    );
+                    propagate(pred, &tmp);
+                }
+                mir::TerminatorKind::InlineAsm {
+                    destination: Some(dest), ref operands, ..
                 } if dest == bb => {
                     let mut tmp = exit_state.clone();
-                    analysis.apply_call_return_effect(&mut tmp, pred, func, args, return_place);
+                    analysis.apply_call_return_effect(
+                        &mut tmp,
+                        pred,
+                        CallReturnPlaces::InlineAsm(operands),
+                    );
                     propagate(pred, &tmp);
                 }
 
@@ -258,6 +272,7 @@ impl Direction for Backward {
                 | mir::TerminatorKind::Drop { unwind: Some(unwind), .. }
                 | mir::TerminatorKind::DropAndReplace { unwind: Some(unwind), .. }
                 | mir::TerminatorKind::FalseUnwind { unwind: Some(unwind), .. }
+                | mir::TerminatorKind::InlineAsm { cleanup: Some(unwind), .. }
                     if unwind == bb =>
                 {
                     if dead_unwinds.map_or(true, |dead| !dead.contains(bb)) {
@@ -467,7 +482,7 @@ impl Direction for Forward {
                 propagate(target, exit_state);
             }
 
-            Call { cleanup, destination, ref func, ref args, from_hir_call: _, fn_span: _ } => {
+            Call { cleanup, destination, func: _, args: _, from_hir_call: _, fn_span: _ } => {
                 if let Some(unwind) = cleanup {
                     if dead_unwinds.map_or(true, |dead| !dead.contains(bb)) {
                         propagate(unwind, exit_state);
@@ -477,13 +492,37 @@ impl Direction for Forward {
                 if let Some((dest_place, target)) = destination {
                     // N.B.: This must be done *last*, otherwise the unwind path will see the call
                     // return effect.
-                    analysis.apply_call_return_effect(exit_state, bb, func, args, dest_place);
+                    analysis.apply_call_return_effect(
+                        exit_state,
+                        bb,
+                        CallReturnPlaces::Call(dest_place),
+                    );
                     propagate(target, exit_state);
                 }
             }
 
-            InlineAsm { template: _, operands: _, options: _, line_spans: _, destination } => {
+            InlineAsm {
+                template: _,
+                ref operands,
+                options: _,
+                line_spans: _,
+                destination,
+                cleanup,
+            } => {
+                if let Some(unwind) = cleanup {
+                    if dead_unwinds.map_or(true, |dead| !dead.contains(bb)) {
+                        propagate(unwind, exit_state);
+                    }
+                }
+
                 if let Some(target) = destination {
+                    // N.B.: This must be done *last*, otherwise the unwind path will see the call
+                    // return effect.
+                    analysis.apply_call_return_effect(
+                        exit_state,
+                        bb,
+                        CallReturnPlaces::InlineAsm(operands),
+                    );
                     propagate(target, exit_state);
                 }
             }