hir, mir: Separate HIR expressions / MIR operands from InlineAsm.

This commit is contained in:
Eduard Burtescu 2016-03-09 22:17:02 +02:00
parent 415d95fbeb
commit 856185dbb2
22 changed files with 176 additions and 209 deletions

View File

@ -354,19 +354,10 @@ impl<'a, 'tcx> CFGBuilder<'a, 'tcx> {
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(..) |

View File

@ -449,23 +449,20 @@ impl<'d,'t,'a,'tcx> ExprUseVisitor<'d,'t,'a,'tcx> {
}
}
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(..) |

View File

@ -1170,25 +1170,21 @@ impl<'a, 'tcx> Liveness<'a, 'tcx> {
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);

View 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 @@ impl<'tcx> Debug for Rvalue<'tcx> {
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),

View File

@ -220,7 +220,7 @@ impl<'tcx> Mir<'tcx> {
}
}
Rvalue::Slice { .. } => None,
Rvalue::InlineAsm(..) => None
Rvalue::InlineAsm { .. } => None
}
}
}

View File

@ -261,7 +261,14 @@ macro_rules! make_mir_visitor {
});
}
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);
}
}
}
}

View File

@ -279,7 +279,7 @@ mod svh_visitor {
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,
}

View 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)),

View 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,

View 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)
}
}
}

View File

@ -1320,14 +1320,11 @@ pub fn lower_expr(lctx: &LoweringContext, e: &Expr) -> P<hir::Expr> {
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 @@ pub fn lower_expr(lctx: &LoweringContext, e: &Expr) -> P<hir::Expr> {
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(),

View File

@ -1486,12 +1486,13 @@ impl<'a> State<'a> {
_ => (),
}
}
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 @@ impl<'a> State<'a> {
_ => 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));

View File

@ -39,8 +39,20 @@ impl<'a,'tcx> Builder<'a,'tcx> {
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));

View File

@ -337,8 +337,12 @@ impl<'tcx> Mirror<'tcx> for &'tcx hir::Expr {
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:

View File

@ -230,6 +230,8 @@ pub enum ExprKind<'tcx> {
},
InlineAsm {
asm: &'tcx hir::InlineAsm,
outputs: Vec<ExprRef<'tcx>>,
inputs: Vec<ExprRef<'tcx>>
},
}

View File

@ -82,7 +82,7 @@ impl<'a, 'tcx> MutVisitor<'tcx> for EraseRegionsVisitor<'a, '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,

View File

@ -756,7 +756,7 @@ fn check_expr<'a, 'tcx>(v: &mut CheckCrateVisitor<'a, 'tcx>,
// 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,

View File

@ -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 syntax::ast::AsmDialect;
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;
}

View 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);
}
}
}

View 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(

View File

@ -19,6 +19,7 @@ use trans::asm;
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 @@ impl<'bcx, 'tcx> MirContext<'bcx, 'tcx> {
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 @@ impl<'bcx, 'tcx> MirContext<'bcx, 'tcx> {
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,
}

View File

@ -3416,12 +3416,12 @@ fn check_expr_with_expectation_and_lvalue_pref<'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);
}