]> git.lizzy.rs Git - rust.git/commitdiff
hir, mir: Separate HIR expressions / MIR operands from InlineAsm.
authorEduard Burtescu <edy.burt@gmail.com>
Wed, 9 Mar 2016 20:17:02 +0000 (22:17 +0200)
committerEduard Burtescu <edy.burt@gmail.com>
Thu, 17 Mar 2016 19:51:55 +0000 (21:51 +0200)
22 files changed:
src/librustc/middle/cfg/construct.rs
src/librustc/middle/expr_use_visitor.rs
src/librustc/middle/liveness.rs
src/librustc/mir/repr.rs
src/librustc/mir/tcx.rs
src/librustc/mir/visit.rs
src/librustc_back/svh.rs
src/librustc_front/fold.rs
src/librustc_front/hir.rs
src/librustc_front/intravisit.rs
src/librustc_front/lowering.rs
src/librustc_front/print/pprust.rs
src/librustc_mir/build/expr/as_rvalue.rs
src/librustc_mir/hair/cx/expr.rs
src/librustc_mir/hair/mod.rs
src/librustc_mir/transform/erase_regions.rs
src/librustc_passes/consts.rs
src/librustc_trans/trans/asm.rs
src/librustc_trans/trans/debuginfo/create_scope_map.rs
src/librustc_trans/trans/expr.rs
src/librustc_trans/trans/mir/rvalue.rs
src/librustc_typeck/check/mod.rs

index 1fb27261c4dbf6de87a6e577443a9b7c825366e8..dcfa8d1e36a21f39aaac5069bf282f28b074dde8 100644 (file)
@@ -354,19 +354,10 @@ fn expr(&mut self, expr: &hir::Expr, pred: CFGIndex) -> CFGIndex {
                 self.straightline(expr, pred, Some(&**e).into_iter())
             }
 
-            hir::ExprInlineAsm(ref inline_asm) => {
-                let inputs = inline_asm.inputs.iter();
-                let outputs = inline_asm.outputs.iter();
-                let post_inputs = self.exprs(inputs.map(|a| {
-                    debug!("cfg::construct InlineAsm id:{} input:{:?}", expr.id, a);
-                    let &(_, ref expr) = a;
-                    &**expr
-                }), pred);
-                let post_outputs = self.exprs(outputs.map(|a| {
-                    debug!("cfg::construct InlineAsm id:{} output:{:?}", expr.id, a);
-                    &*a.expr
-                }), post_inputs);
-                self.add_ast_node(expr.id, &[post_outputs])
+            hir::ExprInlineAsm(_, ref outputs, ref inputs) => {
+                let post_outputs = self.exprs(outputs.iter().map(|e| &**e), pred);
+                let post_inputs = self.exprs(inputs.iter().map(|e| &**e), post_outputs);
+                self.add_ast_node(expr.id, &[post_inputs])
             }
 
             hir::ExprClosure(..) |
index a87ce1206b408f2217782d52cf772476d2238954..91ffef2aa599d97c4c342b2834c20df87b0e38f1 100644 (file)
@@ -449,23 +449,20 @@ pub fn walk_expr(&mut self, expr: &hir::Expr) {
                 }
             }
 
-            hir::ExprInlineAsm(ref ia) => {
-                for &(_, ref input) in &ia.inputs {
-                    self.consume_expr(&input);
-                }
-
-                for output in &ia.outputs {
-                    if output.is_indirect {
-                        self.consume_expr(&output.expr);
+            hir::ExprInlineAsm(ref ia, ref outputs, ref inputs) => {
+                for (o, output) in ia.outputs.iter().zip(outputs) {
+                    if o.is_indirect {
+                        self.consume_expr(output);
                     } else {
-                        self.mutate_expr(expr, &output.expr,
-                                         if output.is_rw {
+                        self.mutate_expr(expr, output,
+                                         if o.is_rw {
                                              MutateMode::WriteAndRead
                                          } else {
                                              MutateMode::JustWrite
                                          });
                     }
                 }
+                self.consume_exprs(inputs);
             }
 
             hir::ExprBreak(..) |
index 0bfb830efc1e77b4c17112118cb38ccdbe5701ea..d78e0ca79aa82650790190b79a4ae7da37a2dfea 100644 (file)
@@ -1170,25 +1170,21 @@ fn propagate_through_expr(&mut self, expr: &Expr, succ: LiveNode)
             self.propagate_through_expr(&e, succ)
           }
 
-          hir::ExprInlineAsm(ref ia) => {
-
-            let succ = ia.outputs.iter().rev().fold(succ,
-                |succ, out| {
-                    // see comment on lvalues
-                    // in propagate_through_lvalue_components()
-                    if out.is_indirect {
-                        self.propagate_through_expr(&out.expr, succ)
-                    } else {
-                        let acc = if out.is_rw { ACC_WRITE|ACC_READ } else { ACC_WRITE };
-                        let succ = self.write_lvalue(&out.expr, succ, acc);
-                        self.propagate_through_lvalue_components(&out.expr, succ)
-                    }
+          hir::ExprInlineAsm(ref ia, ref outputs, ref inputs) => {
+            let succ = ia.outputs.iter().zip(outputs).rev().fold(succ, |succ, (o, output)| {
+                // see comment on lvalues
+                // in propagate_through_lvalue_components()
+                if o.is_indirect {
+                    self.propagate_through_expr(output, succ)
+                } else {
+                    let acc = if o.is_rw { ACC_WRITE|ACC_READ } else { ACC_WRITE };
+                    let succ = self.write_lvalue(output, succ, acc);
+                    self.propagate_through_lvalue_components(output, succ)
                 }
-            );
+            });
+
             // Inputs are executed first. Propagate last because of rev order
-            ia.inputs.iter().rev().fold(succ, |succ, &(_, ref expr)| {
-                self.propagate_through_expr(&expr, succ)
-            })
+            self.propagate_through_exprs(inputs, succ)
           }
 
           hir::ExprLit(..) => {
@@ -1425,17 +1421,17 @@ fn check_expr(this: &mut Liveness, expr: &Expr) {
         intravisit::walk_expr(this, expr);
       }
 
-      hir::ExprInlineAsm(ref ia) => {
-        for &(_, ref input) in &ia.inputs {
-          this.visit_expr(&input);
+      hir::ExprInlineAsm(ref ia, ref outputs, ref inputs) => {
+        for input in inputs {
+          this.visit_expr(input);
         }
 
         // Output operands must be lvalues
-        for out in &ia.outputs {
-          if !out.is_indirect {
-            this.check_lvalue(&out.expr);
+        for (o, output) in ia.outputs.iter().zip(outputs) {
+          if !o.is_indirect {
+            this.check_lvalue(output);
           }
-          this.visit_expr(&out.expr);
+          this.visit_expr(output);
         }
 
         intravisit::walk_expr(this, expr);
index 84187d941a6b08b9722405a9e442ce5184875ba0..06d68af8838994aec797c5d3efca6aef22797f68 100644 (file)
@@ -680,7 +680,11 @@ pub enum Rvalue<'tcx> {
         from_end: usize,
     },
 
-    InlineAsm(InlineAsm),
+    InlineAsm {
+        asm: InlineAsm,
+        outputs: Vec<Lvalue<'tcx>>,
+        inputs: Vec<Operand<'tcx>>
+    }
 }
 
 #[derive(Clone, Copy, Debug, PartialEq, Eq, RustcEncodable, RustcDecodable)]
@@ -765,7 +769,9 @@ fn fmt(&self, fmt: &mut Formatter) -> fmt::Result {
             BinaryOp(ref op, ref a, ref b) => write!(fmt, "{:?}({:?}, {:?})", op, a, b),
             UnaryOp(ref op, ref a) => write!(fmt, "{:?}({:?})", op, a),
             Box(ref t) => write!(fmt, "Box({:?})", t),
-            InlineAsm(ref asm) => write!(fmt, "InlineAsm({:?})", asm),
+            InlineAsm { ref asm, ref outputs, ref inputs } => {
+                write!(fmt, "asm!({:?} : {:?} : {:?})", asm, outputs, inputs)
+            }
             Slice { ref input, from_start, from_end } =>
                 write!(fmt, "{:?}[{:?}..-{:?}]", input, from_start, from_end),
 
index d7848e60e4ecedeca8d9086ade7ac1a04ede2154..c8a2bc440ce1d79ae5cda6de1021bfcf94c8b35f 100644 (file)
@@ -220,7 +220,7 @@ pub fn rvalue_ty(&self,
                 }
             }
             Rvalue::Slice { .. } => None,
-            Rvalue::InlineAsm(..) => None
+            Rvalue::InlineAsm { .. } => None
         }
     }
 }
index 5e3c6e028a32524159aad94610b58b2494561767..36d45f0a51ec22fda19aa31c8ef09a9a0d1e5913 100644 (file)
@@ -261,7 +261,14 @@ fn super_rvalue(&mut self,
                         });
                     }
 
-                    Rvalue::InlineAsm(_) => {
+                    Rvalue::InlineAsm { ref $($mutability)* outputs,
+                                        ref $($mutability)* inputs, .. } => {
+                        for output in & $($mutability)* outputs[..] {
+                            self.visit_lvalue(output, LvalueContext::Store);
+                        }
+                        for input in & $($mutability)* inputs[..] {
+                            self.visit_operand(input);
+                        }
                     }
                 }
             }
index b01b80b813399048d30ff41b2313d7113f198af1..3507a119e5455ebbf12dc79509b01b063001b170 100644 (file)
@@ -279,7 +279,7 @@ fn saw_expr<'a>(node: &'a Expr_) -> SawExprComponent<'a> {
             ExprBreak(id)            => SawExprBreak(id.map(|id| id.node.name.as_str())),
             ExprAgain(id)            => SawExprAgain(id.map(|id| id.node.name.as_str())),
             ExprRet(..)              => SawExprRet,
-            ExprInlineAsm(ref asm)   => SawExprInlineAsm(asm),
+            ExprInlineAsm(ref a,_,_) => SawExprInlineAsm(a),
             ExprStruct(..)           => SawExprStruct,
             ExprRepeat(..)           => SawExprRepeat,
         }
index 6ae59122f71c49a85525eb8534972ecfa41eca3c..e65f2fc37debfa813c63f982711ffd7236d4b9e7 100644 (file)
@@ -1107,34 +1107,11 @@ pub fn noop_fold_expr<T: Folder>(Expr { id, node, span, attrs }: Expr, folder: &
                 respan(folder.new_span(label.span), folder.fold_ident(label.node))
             })),
             ExprRet(e) => ExprRet(e.map(|x| folder.fold_expr(x))),
-            ExprInlineAsm(InlineAsm {
-                inputs,
-                outputs,
-                asm,
-                asm_str_style,
-                clobbers,
-                volatile,
-                alignstack,
-                dialect,
-                expn_id,
-            }) => ExprInlineAsm(InlineAsm {
-                inputs: inputs.move_map(|(c, input)| (c, folder.fold_expr(input))),
-                outputs: outputs.move_map(|out| {
-                    InlineAsmOutput {
-                        constraint: out.constraint,
-                        expr: folder.fold_expr(out.expr),
-                        is_rw: out.is_rw,
-                        is_indirect: out.is_indirect,
-                    }
-                }),
-                asm: asm,
-                asm_str_style: asm_str_style,
-                clobbers: clobbers,
-                volatile: volatile,
-                alignstack: alignstack,
-                dialect: dialect,
-                expn_id: expn_id,
-            }),
+            ExprInlineAsm(asm, outputs, inputs) => {
+                ExprInlineAsm(asm,
+                              outputs.move_map(|x| folder.fold_expr(x)),
+                              inputs.move_map(|x| folder.fold_expr(x)))
+            }
             ExprStruct(path, fields, maybe_expr) => {
                 ExprStruct(folder.fold_path(path),
                            fields.move_map(|x| folder.fold_field(x)),
index 0b1418fc878452b83ecb51a054e6a3f47abe1b7e..43a9ac23a95ed2f0ebb8333150b92d0b2ab6692a 100644 (file)
@@ -793,8 +793,8 @@ pub enum Expr_ {
     /// A `return`, with an optional value to be returned
     ExprRet(Option<P<Expr>>),
 
-    /// Output of the `asm!()` macro
-    ExprInlineAsm(InlineAsm),
+    /// Inline assembly (from `asm!`), with its outputs and inputs.
+    ExprInlineAsm(InlineAsm, Vec<P<Expr>>, Vec<P<Expr>>),
 
     /// A struct literal expression.
     ///
@@ -978,7 +978,6 @@ pub enum Ty_ {
 #[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug)]
 pub struct InlineAsmOutput {
     pub constraint: InternedString,
-    pub expr: P<Expr>,
     pub is_rw: bool,
     pub is_indirect: bool,
 }
@@ -988,7 +987,7 @@ pub struct InlineAsm {
     pub asm: InternedString,
     pub asm_str_style: StrStyle,
     pub outputs: HirVec<InlineAsmOutput>,
-    pub inputs: HirVec<(InternedString, P<Expr>)>,
+    pub inputs: HirVec<InternedString>,
     pub clobbers: HirVec<InternedString>,
     pub volatile: bool,
     pub alignstack: bool,
index d71e392f521e7795cf44f64029bcd1454dc14950..e031dfc5b161dd9e4c564350fea5329f20b8542f 100644 (file)
@@ -798,12 +798,12 @@ pub fn walk_expr<'v, V: Visitor<'v>>(visitor: &mut V, expression: &'v Expr) {
         ExprRet(ref optional_expression) => {
             walk_list!(visitor, visit_expr, optional_expression);
         }
-        ExprInlineAsm(ref ia) => {
-            for &(_, ref input) in &ia.inputs {
-                visitor.visit_expr(&input)
+        ExprInlineAsm(_, ref outputs, ref inputs) => {
+            for output in outputs {
+                visitor.visit_expr(output)
             }
-            for output in &ia.outputs {
-                visitor.visit_expr(&output.expr)
+            for input in inputs {
+                visitor.visit_expr(input)
             }
         }
     }
index 825ab3fbd4c8227107c4c71846e79b5bb3972b5d..8aac6356f9d3bf0f30ffceb50a7493012997e2ea 100644 (file)
@@ -1320,14 +1320,11 @@ fn make_struct(lctx: &LoweringContext,
                     dialect,
                     expn_id,
                 }) => hir::ExprInlineAsm(hir::InlineAsm {
-                inputs: inputs.iter()
-                              .map(|&(ref c, ref input)| (c.clone(), lower_expr(lctx, input)))
-                              .collect(),
+                inputs: inputs.iter().map(|&(ref c, _)| c.clone()).collect(),
                 outputs: outputs.iter()
                                 .map(|out| {
                                     hir::InlineAsmOutput {
                                         constraint: out.constraint.clone(),
-                                        expr: lower_expr(lctx, &out.expr),
                                         is_rw: out.is_rw,
                                         is_indirect: out.is_indirect,
                                     }
@@ -1340,7 +1337,8 @@ fn make_struct(lctx: &LoweringContext,
                 alignstack: alignstack,
                 dialect: dialect,
                 expn_id: expn_id,
-            }),
+            }, outputs.iter().map(|out| lower_expr(lctx, &out.expr)).collect(),
+               inputs.iter().map(|&(_, ref input)| lower_expr(lctx, input)).collect()),
             ExprKind::Struct(ref path, ref fields, ref maybe_expr) => {
                 hir::ExprStruct(lower_path(lctx, path),
                                 fields.iter().map(|x| lower_field(lctx, x)).collect(),
index 1100f084454c729747c50c057819d5e80acbecda..1ebbbb73e8c994897c2ef09c697341abfd0f03d6 100644 (file)
@@ -1486,12 +1486,13 @@ pub fn print_expr(&mut self, expr: &hir::Expr) -> io::Result<()> {
                     _ => (),
                 }
             }
-            hir::ExprInlineAsm(ref a) => {
+            hir::ExprInlineAsm(ref a, ref outputs, ref inputs) => {
                 try!(word(&mut self.s, "asm!"));
                 try!(self.popen());
                 try!(self.print_string(&a.asm, a.asm_str_style));
                 try!(self.word_space(":"));
 
+                let mut out_idx = 0;
                 try!(self.commasep(Inconsistent, &a.outputs, |s, out| {
                     match out.constraint.slice_shift_char() {
                         Some(('=', operand)) if out.is_rw => {
@@ -1500,18 +1501,21 @@ pub fn print_expr(&mut self, expr: &hir::Expr) -> io::Result<()> {
                         _ => try!(s.print_string(&out.constraint, ast::StrStyle::Cooked)),
                     }
                     try!(s.popen());
-                    try!(s.print_expr(&out.expr));
+                    try!(s.print_expr(&outputs[out_idx]));
                     try!(s.pclose());
+                    out_idx += 1;
                     Ok(())
                 }));
                 try!(space(&mut self.s));
                 try!(self.word_space(":"));
 
-                try!(self.commasep(Inconsistent, &a.inputs, |s, &(ref co, ref o)| {
+                let mut in_idx = 0;
+                try!(self.commasep(Inconsistent, &a.inputs, |s, co| {
                     try!(s.print_string(&co, ast::StrStyle::Cooked));
                     try!(s.popen());
-                    try!(s.print_expr(&o));
+                    try!(s.print_expr(&inputs[in_idx]));
                     try!(s.pclose());
+                    in_idx += 1;
                     Ok(())
                 }));
                 try!(space(&mut self.s));
index db94035e5ce5a7d84a5474c2c029e2f587d734ca..4c0e9b98d9a6e324bebd8e4f9de0a90d0a9a2107 100644 (file)
@@ -39,8 +39,20 @@ fn expr_as_rvalue(&mut self,
             ExprKind::Scope { extent, value } => {
                 this.in_scope(extent, block, |this| this.as_rvalue(block, value))
             }
-            ExprKind::InlineAsm { asm } => {
-                block.and(Rvalue::InlineAsm(asm.clone()))
+            ExprKind::InlineAsm { asm, outputs, inputs } => {
+                let outputs = outputs.into_iter().map(|output| {
+                    unpack!(block = this.as_lvalue(block, output))
+                }).collect();
+
+                let inputs = inputs.into_iter().map(|input| {
+                    unpack!(block = this.as_operand(block, input))
+                }).collect();
+
+                block.and(Rvalue::InlineAsm {
+                    asm: asm.clone(),
+                    outputs: outputs,
+                    inputs: inputs
+                })
             }
             ExprKind::Repeat { value, count } => {
                 let value_operand = unpack!(block = this.as_operand(block, value));
index e1962eb076be53383bf3f1c8485f17aa5465c716..204b1c1d1e0c043ba7c3869d6c8653f12891567c 100644 (file)
@@ -337,8 +337,12 @@ fn make_mirror<'a>(self, cx: &mut Cx<'a, 'tcx>) -> Expr<'tcx> {
                 convert_path_expr(cx, self)
             }
 
-            hir::ExprInlineAsm(ref asm) => {
-                ExprKind::InlineAsm { asm: asm }
+            hir::ExprInlineAsm(ref asm, ref outputs, ref inputs) => {
+                ExprKind::InlineAsm {
+                    asm: asm,
+                    outputs: outputs.to_ref(),
+                    inputs: inputs.to_ref()
+                }
             }
 
             // Now comes the rote stuff:
index 6a22dce7af9d262f985ac78fe03e4681e0c9673d..78c438df6f87adac858c6e0d93e6c69d3aff42b4 100644 (file)
@@ -230,6 +230,8 @@ pub enum ExprKind<'tcx> {
     },
     InlineAsm {
         asm: &'tcx hir::InlineAsm,
+        outputs: Vec<ExprRef<'tcx>>,
+        inputs: Vec<ExprRef<'tcx>>
     },
 }
 
index 1920bd552ec3e5a3dc6821f97b4f221d29cdf3a8..9ac3749589e90df0a9989ea73ea918afa9524551 100644 (file)
@@ -82,7 +82,7 @@ fn visit_rvalue(&mut self, rvalue: &mut Rvalue<'tcx>) {
             Rvalue::BinaryOp(_, _, _) |
             Rvalue::UnaryOp(_, _) |
             Rvalue::Slice { input: _, from_start: _, from_end: _ } |
-            Rvalue::InlineAsm(_) => {},
+            Rvalue::InlineAsm {..} => {},
 
             Rvalue::Repeat(_, ref mut value) => value.ty = self.tcx.erase_regions(&value.ty),
             Rvalue::Ref(ref mut region, _, _) => *region = ty::ReStatic,
index 6be7f6c200247a01abd0fefdb2bd35d62a5cefe5..74ede89be556221ede4dbcffb2a34483823b90cc 100644 (file)
@@ -756,7 +756,7 @@ struct and enum constructors",
         // Expressions with side-effects.
         hir::ExprAssign(..) |
         hir::ExprAssignOp(..) |
-        hir::ExprInlineAsm(_) => {
+        hir::ExprInlineAsm(..) => {
             v.add_qualif(ConstQualif::NOT_CONST);
             if v.mode != Mode::Var {
                 span_err!(v.tcx.sess, e.span, E0019,
index 27c3dfc4c974d0987ffb33b7f3d94856804e2e38..4d0c55131f765c2a26e7f971d5ba82c4536798ef 100644 (file)
 //! # Translation of inline assembly.
 
 use llvm::{self, ValueRef};
+use trans::base;
 use trans::build::*;
 use trans::common::*;
-use trans::cleanup;
-use trans::cleanup::CleanupMethods;
-use trans::datum::{Datum, Expr};
-use trans::expr;
+use trans::datum::{Datum, Lvalue};
 use trans::type_of;
 use trans::type_::Type;
 
 use libc::{c_uint, c_char};
 
 // Take an inline assembly expression and splat it out via LLVM
-pub fn trans_inline_asm<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, ia: &ast::InlineAsm)
-                                    -> Block<'blk, 'tcx> {
-    let fcx = bcx.fcx;
-    let mut bcx = bcx;
-    let mut constraints = Vec::new();
-    let mut output_types = Vec::new();
-
-    let temp_scope = fcx.push_custom_cleanup_scope();
-
-    let take_datum = |mut bcx: Block<'blk, 'tcx>,
-                      arg_datum: Datum<'tcx, Expr>,
-                      llargs: &mut Vec<ValueRef>|
-                      -> Block<'blk, 'tcx> {
-        // Make this an rvalue, since we are going to be
-        // passing ownership.
-        let arg_datum = unpack_datum!(
-            bcx, arg_datum.to_rvalue_datum(bcx, "arg"));
-
-        // Now that arg_datum is owned, get it into the appropriate
-        // mode (ref vs value).
-        let arg_datum = unpack_datum!(
-            bcx, arg_datum.to_appropriate_datum(bcx));
-
-        // Technically, ownership of val passes to the callee.
-        // However, we must cleanup should we panic before the
-        // callee is actually invoked.
-        let val = arg_datum.add_clean(bcx.fcx,
-            cleanup::CustomScope(temp_scope));
-        llargs.push(val);
-        bcx
-    };
-
-    let mut ext_inputs = Vec::new();
-    let mut ext_constraints = Vec::new();
+pub fn trans_inline_asm<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
+                                    ia: &ast::InlineAsm,
+                                    outputs: Vec<Datum<'tcx, Lvalue>>,
+                                    mut inputs: Vec<ValueRef>) {
+    let mut ext_constraints = vec![];
+    let mut output_types = vec![];
 
     // Prepare the output operands
-    let mut outputs = Vec::new();
-    let mut inputs = Vec::new();
-    for (i, out) in ia.outputs.iter().enumerate() {
-        constraints.push(out.constraint.clone());
-
-        let out_datum = unpack_datum!(bcx, expr::trans(bcx, &out.expr));
+    let mut indirect_outputs = vec![];
+    for (i, (out, out_datum)) in ia.outputs.iter().zip(&outputs).enumerate() {
+        let val = if out.is_rw || out.is_indirect {
+            Some(base::load_ty(bcx, out_datum.val, out_datum.ty))
+        } else {
+            None
+        };
+        if out.is_rw {
+            inputs.push(val.unwrap());
+            ext_constraints.push(i.to_string());
+        }
         if out.is_indirect {
-            bcx = take_datum(bcx, out_datum, &mut inputs);
-            if out.is_rw {
-                ext_inputs.push(*inputs.last().unwrap());
-                ext_constraints.push(i.to_string());
-            }
+            indirect_outputs.push(val.unwrap());
         } else {
             output_types.push(type_of::type_of(bcx.ccx(), out_datum.ty));
-            outputs.push(out_datum.val);
-            if out.is_rw {
-                bcx = take_datum(bcx, out_datum, &mut ext_inputs);
-                ext_constraints.push(i.to_string());
-            }
         }
     }
-
-    // Now the input operands
-    for &(ref c, ref input) in &ia.inputs {
-        constraints.push((*c).clone());
-
-        let in_datum = unpack_datum!(bcx, expr::trans(bcx, &input));
-        bcx = take_datum(bcx, in_datum, &mut inputs);
+    if !indirect_outputs.is_empty() {
+        indirect_outputs.extend_from_slice(&inputs);
+        inputs = indirect_outputs;
     }
-    inputs.extend_from_slice(&ext_inputs[..]);
-
-    // no failure occurred preparing operands, no need to cleanup
-    fcx.pop_custom_cleanup_scope(temp_scope);
 
     let clobbers = ia.clobbers.iter()
                               .map(|s| format!("~{{{}}}", &s));
@@ -106,19 +64,18 @@ pub fn trans_inline_asm<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, ia: &ast::InlineAsm)
         _                => Vec::new()
     };
 
-    let all_constraints= constraints.iter()
-                                    .map(|s| s.to_string())
-                                    .chain(ext_constraints)
-                                    .chain(clobbers)
-                                    .chain(arch_clobbers.iter()
-                                               .map(|s| s.to_string()))
-                                    .collect::<Vec<String>>()
-                                    .join(",");
+    let all_constraints =
+        ia.outputs.iter().map(|out| out.constraint.to_string())
+          .chain(ia.inputs.iter().map(|s| s.to_string()))
+          .chain(ext_constraints)
+          .chain(clobbers)
+          .chain(arch_clobbers.iter().map(|s| s.to_string()))
+          .collect::<Vec<String>>().join(",");
 
     debug!("Asm Constraints: {}", &all_constraints[..]);
 
     // Depending on how many outputs we have, the return type is different
-    let num_outputs = outputs.len();
+    let num_outputs = output_types.len();
     let output_type = match num_outputs {
         0 => Type::void(bcx.ccx()),
         1 => output_types[0],
@@ -142,13 +99,10 @@ pub fn trans_inline_asm<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, ia: &ast::InlineAsm)
                           dialect);
 
     // Again, based on how many outputs we have
-    if num_outputs == 1 {
-        Store(bcx, r, outputs[0]);
-    } else {
-        for (i, o) in outputs.iter().enumerate() {
-            let v = ExtractValue(bcx, r, i);
-            Store(bcx, v, *o);
-        }
+    let outputs = ia.outputs.iter().zip(&outputs).filter(|&(ref o, _)| !o.is_indirect);
+    for (i, (_, datum)) in outputs.enumerate() {
+        let v = if num_outputs == 1 { r } else { ExtractValue(bcx, r, i) };
+        Store(bcx, v, datum.val);
     }
 
     // Store expn_id in a metadata node so we can map LLVM errors
@@ -163,7 +117,4 @@ pub fn trans_inline_asm<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, ia: &ast::InlineAsm)
         llvm::LLVMSetMetadata(r, kind,
             llvm::LLVMMDNodeInContext(bcx.ccx().llcx(), &val, 1));
     }
-
-    return bcx;
-
 }
index 4ba103c0c0d08c7991aa24c9ec8a135407f43736..41fed12e7bf3cc7bd847434ab206041f5875c5fe 100644 (file)
@@ -468,16 +468,13 @@ fn walk_expr(cx: &CrateContext,
             }
         }
 
-        hir::ExprInlineAsm(hir::InlineAsm { ref inputs,
-                                            ref outputs,
-                                            .. }) => {
-            // inputs, outputs: Vec<(String, P<Expr>)>
-            for &(_, ref exp) in inputs {
-                walk_expr(cx, &exp, scope_stack, scope_map);
+        hir::ExprInlineAsm(_, ref outputs, ref inputs) => {
+            for output in outputs {
+                walk_expr(cx, output, scope_stack, scope_map);
             }
 
-            for out in outputs {
-                walk_expr(cx, &out.expr, scope_stack, scope_map);
+            for input in inputs {
+                walk_expr(cx, input, scope_stack, scope_map);
             }
         }
     }
index 094d530d14cbae113a43c9da81f89de72c5a4d95..abcd703f33ba39f626de0e780e328c899e5dc96b 100644 (file)
@@ -1037,8 +1037,18 @@ fn trans_rvalue_stmt_unadjusted<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
                 trans_assign_op(bcx, expr, op, &dst, &src)
             }
         }
-        hir::ExprInlineAsm(ref a) => {
-            asm::trans_inline_asm(bcx, a)
+        hir::ExprInlineAsm(ref a, ref outputs, ref inputs) => {
+            let outputs = outputs.iter().map(|output| {
+                let out_datum = unpack_datum!(bcx, trans(bcx, output));
+                unpack_datum!(bcx, out_datum.to_lvalue_datum(bcx, "out", expr.id))
+            }).collect();
+            let inputs = inputs.iter().map(|input| {
+                let input = unpack_datum!(bcx, trans(bcx, input));
+                let input = unpack_datum!(bcx, input.to_rvalue_datum(bcx, "in"));
+                input.to_llscalarish(bcx)
+            }).collect();
+            asm::trans_inline_asm(bcx, a, outputs, inputs);
+            bcx
         }
         _ => {
             bcx.tcx().sess.span_bug(
index 4b4cf328f638e8261fe0047a26f7b6f5a5a9b804..17c8aef244bb95c04a8c6d2d3505864698bda25d 100644 (file)
@@ -19,6 +19,7 @@
 use trans::base;
 use trans::callee::Callee;
 use trans::common::{self, C_uint, BlockAndBuilder, Result};
+use trans::datum::{Datum, Lvalue};
 use trans::debuginfo::DebugLoc;
 use trans::declare;
 use trans::adt;
@@ -193,10 +194,25 @@ pub fn trans_rvalue(&mut self,
                 bcx
             }
 
-            mir::Rvalue::InlineAsm(ref inline_asm) => {
-                bcx.map_block(|bcx| {
-                    asm::trans_inline_asm(bcx, inline_asm)
-                })
+            mir::Rvalue::InlineAsm { ref asm, ref outputs, ref inputs } => {
+                let outputs = outputs.iter().map(|output| {
+                    let lvalue = self.trans_lvalue(&bcx, output);
+                    Datum::new(lvalue.llval, lvalue.ty.to_ty(bcx.tcx()),
+                               Lvalue::new("out"))
+                }).collect();
+
+                let input_vals = inputs.iter().map(|input| {
+                    self.trans_operand(&bcx, input).immediate()
+                }).collect();
+
+                bcx.with_block(|bcx| {
+                    asm::trans_inline_asm(bcx, asm, outputs, input_vals);
+                });
+
+                for input in inputs {
+                    self.set_operand_dropped(&bcx, input);
+                }
+                bcx
             }
 
             _ => {
@@ -472,7 +488,7 @@ pub fn trans_rvalue_operand(&mut self,
             mir::Rvalue::Repeat(..) |
             mir::Rvalue::Aggregate(..) |
             mir::Rvalue::Slice { .. } |
-            mir::Rvalue::InlineAsm(..) => {
+            mir::Rvalue::InlineAsm { .. } => {
                 bcx.tcx().sess.bug(&format!("cannot generate operand from rvalue {:?}", rvalue));
             }
         }
@@ -596,7 +612,7 @@ pub fn rvalue_creates_operand<'tcx>(rvalue: &mir::Rvalue<'tcx>) -> bool {
         mir::Rvalue::Repeat(..) |
         mir::Rvalue::Aggregate(..) |
         mir::Rvalue::Slice { .. } |
-        mir::Rvalue::InlineAsm(..) =>
+        mir::Rvalue::InlineAsm { .. } =>
             false,
     }
 
index 0d5e25efd68c91b93f88f37c0ba5c03d4e470e55..903fc458d818564c891688938095021698c30b94 100644 (file)
@@ -3416,12 +3416,12 @@ fn check_expr_struct<'a, 'tcx>(fcx: &FnCtxt<'a,'tcx>,
               fcx.add_wf_bounds(&item_substs.substs, expr);
           });
       }
-      hir::ExprInlineAsm(ref ia) => {
-          for &(_, ref input) in &ia.inputs {
-              check_expr(fcx, &input);
+      hir::ExprInlineAsm(_, ref outputs, ref inputs) => {
+          for output in outputs {
+              check_expr(fcx, output);
           }
-          for out in &ia.outputs {
-              check_expr(fcx, &out.expr);
+          for input in inputs {
+              check_expr(fcx, input);
           }
           fcx.write_nil(id);
       }