From: Eduard Burtescu Date: Wed, 9 Mar 2016 20:17:02 +0000 (+0200) Subject: hir, mir: Separate HIR expressions / MIR operands from InlineAsm. X-Git-Url: https://git.lizzy.rs/?a=commitdiff_plain;h=856185dbb2f4a57dc865c6dc3c856268c7efa79a;p=rust.git hir, mir: Separate HIR expressions / MIR operands from InlineAsm. --- diff --git a/src/librustc/middle/cfg/construct.rs b/src/librustc/middle/cfg/construct.rs index 1fb27261c4d..dcfa8d1e36a 100644 --- a/src/librustc/middle/cfg/construct.rs +++ b/src/librustc/middle/cfg/construct.rs @@ -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(..) | diff --git a/src/librustc/middle/expr_use_visitor.rs b/src/librustc/middle/expr_use_visitor.rs index a87ce1206b4..91ffef2aa59 100644 --- a/src/librustc/middle/expr_use_visitor.rs +++ b/src/librustc/middle/expr_use_visitor.rs @@ -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(..) | diff --git a/src/librustc/middle/liveness.rs b/src/librustc/middle/liveness.rs index 0bfb830efc1..d78e0ca79aa 100644 --- a/src/librustc/middle/liveness.rs +++ b/src/librustc/middle/liveness.rs @@ -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); diff --git a/src/librustc/mir/repr.rs b/src/librustc/mir/repr.rs index 84187d941a6..06d68af8838 100644 --- a/src/librustc/mir/repr.rs +++ b/src/librustc/mir/repr.rs @@ -680,7 +680,11 @@ pub enum Rvalue<'tcx> { from_end: usize, }, - InlineAsm(InlineAsm), + InlineAsm { + asm: InlineAsm, + outputs: Vec>, + inputs: Vec> + } } #[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), diff --git a/src/librustc/mir/tcx.rs b/src/librustc/mir/tcx.rs index d7848e60e4e..c8a2bc440ce 100644 --- a/src/librustc/mir/tcx.rs +++ b/src/librustc/mir/tcx.rs @@ -220,7 +220,7 @@ pub fn rvalue_ty(&self, } } Rvalue::Slice { .. } => None, - Rvalue::InlineAsm(..) => None + Rvalue::InlineAsm { .. } => None } } } diff --git a/src/librustc/mir/visit.rs b/src/librustc/mir/visit.rs index 5e3c6e028a3..36d45f0a51e 100644 --- a/src/librustc/mir/visit.rs +++ b/src/librustc/mir/visit.rs @@ -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); + } } } } diff --git a/src/librustc_back/svh.rs b/src/librustc_back/svh.rs index b01b80b8133..3507a119e54 100644 --- a/src/librustc_back/svh.rs +++ b/src/librustc_back/svh.rs @@ -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, } diff --git a/src/librustc_front/fold.rs b/src/librustc_front/fold.rs index 6ae59122f71..e65f2fc37de 100644 --- a/src/librustc_front/fold.rs +++ b/src/librustc_front/fold.rs @@ -1107,34 +1107,11 @@ pub fn noop_fold_expr(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)), diff --git a/src/librustc_front/hir.rs b/src/librustc_front/hir.rs index 0b1418fc878..43a9ac23a95 100644 --- a/src/librustc_front/hir.rs +++ b/src/librustc_front/hir.rs @@ -793,8 +793,8 @@ pub enum Expr_ { /// A `return`, with an optional value to be returned ExprRet(Option>), - /// Output of the `asm!()` macro - ExprInlineAsm(InlineAsm), + /// Inline assembly (from `asm!`), with its outputs and inputs. + ExprInlineAsm(InlineAsm, Vec>, Vec>), /// 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, 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, - pub inputs: HirVec<(InternedString, P)>, + pub inputs: HirVec, pub clobbers: HirVec, pub volatile: bool, pub alignstack: bool, diff --git a/src/librustc_front/intravisit.rs b/src/librustc_front/intravisit.rs index d71e392f521..e031dfc5b16 100644 --- a/src/librustc_front/intravisit.rs +++ b/src/librustc_front/intravisit.rs @@ -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) } } } diff --git a/src/librustc_front/lowering.rs b/src/librustc_front/lowering.rs index 825ab3fbd4c..8aac6356f9d 100644 --- a/src/librustc_front/lowering.rs +++ b/src/librustc_front/lowering.rs @@ -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(), diff --git a/src/librustc_front/print/pprust.rs b/src/librustc_front/print/pprust.rs index 1100f084454..1ebbbb73e8c 100644 --- a/src/librustc_front/print/pprust.rs +++ b/src/librustc_front/print/pprust.rs @@ -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)); diff --git a/src/librustc_mir/build/expr/as_rvalue.rs b/src/librustc_mir/build/expr/as_rvalue.rs index db94035e5ce..4c0e9b98d9a 100644 --- a/src/librustc_mir/build/expr/as_rvalue.rs +++ b/src/librustc_mir/build/expr/as_rvalue.rs @@ -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)); diff --git a/src/librustc_mir/hair/cx/expr.rs b/src/librustc_mir/hair/cx/expr.rs index e1962eb076b..204b1c1d1e0 100644 --- a/src/librustc_mir/hair/cx/expr.rs +++ b/src/librustc_mir/hair/cx/expr.rs @@ -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: diff --git a/src/librustc_mir/hair/mod.rs b/src/librustc_mir/hair/mod.rs index 6a22dce7af9..78c438df6f8 100644 --- a/src/librustc_mir/hair/mod.rs +++ b/src/librustc_mir/hair/mod.rs @@ -230,6 +230,8 @@ pub enum ExprKind<'tcx> { }, InlineAsm { asm: &'tcx hir::InlineAsm, + outputs: Vec>, + inputs: Vec> }, } diff --git a/src/librustc_mir/transform/erase_regions.rs b/src/librustc_mir/transform/erase_regions.rs index 1920bd552ec..9ac3749589e 100644 --- a/src/librustc_mir/transform/erase_regions.rs +++ b/src/librustc_mir/transform/erase_regions.rs @@ -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, diff --git a/src/librustc_passes/consts.rs b/src/librustc_passes/consts.rs index 6be7f6c2002..74ede89be55 100644 --- a/src/librustc_passes/consts.rs +++ b/src/librustc_passes/consts.rs @@ -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, diff --git a/src/librustc_trans/trans/asm.rs b/src/librustc_trans/trans/asm.rs index 27c3dfc4c97..4d0c55131f7 100644 --- a/src/librustc_trans/trans/asm.rs +++ b/src/librustc_trans/trans/asm.rs @@ -11,12 +11,10 @@ //! # 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; @@ -26,75 +24,35 @@ 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| - -> 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>, + mut inputs: Vec) { + 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::>() - .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::>().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; - } diff --git a/src/librustc_trans/trans/debuginfo/create_scope_map.rs b/src/librustc_trans/trans/debuginfo/create_scope_map.rs index 4ba103c0c0d..41fed12e7bf 100644 --- a/src/librustc_trans/trans/debuginfo/create_scope_map.rs +++ b/src/librustc_trans/trans/debuginfo/create_scope_map.rs @@ -468,16 +468,13 @@ fn walk_expr(cx: &CrateContext, } } - hir::ExprInlineAsm(hir::InlineAsm { ref inputs, - ref outputs, - .. }) => { - // inputs, outputs: Vec<(String, P)> - 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); } } } diff --git a/src/librustc_trans/trans/expr.rs b/src/librustc_trans/trans/expr.rs index 094d530d14c..abcd703f33b 100644 --- a/src/librustc_trans/trans/expr.rs +++ b/src/librustc_trans/trans/expr.rs @@ -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( diff --git a/src/librustc_trans/trans/mir/rvalue.rs b/src/librustc_trans/trans/mir/rvalue.rs index 4b4cf328f63..17c8aef244b 100644 --- a/src/librustc_trans/trans/mir/rvalue.rs +++ b/src/librustc_trans/trans/mir/rvalue.rs @@ -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, } diff --git a/src/librustc_typeck/check/mod.rs b/src/librustc_typeck/check/mod.rs index 0d5e25efd68..903fc458d81 100644 --- a/src/librustc_typeck/check/mod.rs +++ b/src/librustc_typeck/check/mod.rs @@ -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); }