mirror of
https://github.com/rust-lang/rust.git
synced 2024-11-22 06:44:35 +00:00
hir, mir: Separate HIR expressions / MIR operands from InlineAsm.
This commit is contained in:
parent
415d95fbeb
commit
856185dbb2
@ -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(..) |
|
||||
|
@ -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(..) |
|
||||
|
@ -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);
|
||||
|
@ -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),
|
||||
|
||||
|
@ -220,7 +220,7 @@ impl<'tcx> Mir<'tcx> {
|
||||
}
|
||||
}
|
||||
Rvalue::Slice { .. } => None,
|
||||
Rvalue::InlineAsm(..) => None
|
||||
Rvalue::InlineAsm { .. } => None
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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,
|
||||
}
|
||||
|
@ -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)),
|
||||
|
@ -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,
|
||||
|
@ -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)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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(),
|
||||
|
@ -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));
|
||||
|
@ -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));
|
||||
|
@ -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:
|
||||
|
@ -230,6 +230,8 @@ pub enum ExprKind<'tcx> {
|
||||
},
|
||||
InlineAsm {
|
||||
asm: &'tcx hir::InlineAsm,
|
||||
outputs: Vec<ExprRef<'tcx>>,
|
||||
inputs: Vec<ExprRef<'tcx>>
|
||||
},
|
||||
}
|
||||
|
||||
|
@ -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,
|
||||
|
@ -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,
|
||||
|
@ -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;
|
||||
|
||||
}
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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(
|
||||
|
@ -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,
|
||||
}
|
||||
|
||||
|
@ -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);
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user