[MIR] Make InlineAsm a Statement

Previously InlineAsm was an Rvalue, but its semantics doesn’t really match the semantics of an
Rvalue – rather it behaves more like a Statement.
This commit is contained in:
Simonas Kazlauskas 2017-02-15 21:21:36 +02:00
parent 62eb6056d3
commit 4a3c66ad2f
16 changed files with 67 additions and 68 deletions

View File

@ -777,6 +777,12 @@ pub enum StatementKind<'tcx> {
/// End the current live range for the storage of the local.
StorageDead(Lvalue<'tcx>),
InlineAsm {
asm: InlineAsm,
outputs: Vec<Lvalue<'tcx>>,
inputs: Vec<Operand<'tcx>>
},
/// No-op. Useful for deleting instructions without affecting statement indices.
Nop,
}
@ -790,7 +796,10 @@ impl<'tcx> Debug for Statement<'tcx> {
StorageDead(ref lv) => write!(fmt, "StorageDead({:?})", lv),
SetDiscriminant{lvalue: ref lv, variant_index: index} => {
write!(fmt, "discriminant({:?}) = {:?}", lv, index)
}
},
InlineAsm { ref asm, ref outputs, ref inputs } => {
write!(fmt, "asm!({:?} : {:?} : {:?})", asm, outputs, inputs)
},
Nop => write!(fmt, "nop"),
}
}
@ -1004,12 +1013,6 @@ pub enum Rvalue<'tcx> {
/// that `Foo` has a destructor. These rvalues can be optimized
/// away after type-checking and before lowering.
Aggregate(AggregateKind<'tcx>, Vec<Operand<'tcx>>),
InlineAsm {
asm: InlineAsm,
outputs: Vec<Lvalue<'tcx>>,
inputs: Vec<Operand<'tcx>>
}
}
#[derive(Clone, Copy, Debug, PartialEq, Eq, RustcEncodable, RustcDecodable)]
@ -1111,10 +1114,6 @@ impl<'tcx> Debug for Rvalue<'tcx> {
UnaryOp(ref op, ref a) => write!(fmt, "{:?}({:?})", op, a),
Discriminant(ref lval) => write!(fmt, "discriminant({:?})", lval),
Box(ref t) => write!(fmt, "Box({:?})", t),
InlineAsm { ref asm, ref outputs, ref inputs } => {
write!(fmt, "asm!({:?} : {:?} : {:?})", asm, outputs, inputs)
}
Ref(_, borrow_kind, ref lv) => {
let kind_str = match borrow_kind {
BorrowKind::Shared => "",

View File

@ -207,7 +207,6 @@ impl<'tcx> Rvalue<'tcx> {
}
}
}
Rvalue::InlineAsm { .. } => None
}
}
}

View File

@ -333,6 +333,16 @@ macro_rules! make_mir_visitor {
StatementKind::StorageDead(ref $($mutability)* lvalue) => {
self.visit_lvalue(lvalue, LvalueContext::StorageDead, location);
}
StatementKind::InlineAsm { ref $($mutability)* outputs,
ref $($mutability)* inputs,
asm: _ } => {
for output in & $($mutability)* outputs[..] {
self.visit_lvalue(output, LvalueContext::Store, location);
}
for input in & $($mutability)* inputs[..] {
self.visit_operand(input, location);
}
}
StatementKind::Nop => {}
}
}
@ -526,17 +536,6 @@ macro_rules! make_mir_visitor {
self.visit_operand(operand, location);
}
}
Rvalue::InlineAsm { ref $($mutability)* outputs,
ref $($mutability)* inputs,
asm: _ } => {
for output in & $($mutability)* outputs[..] {
self.visit_lvalue(output, LvalueContext::Store, location);
}
for input in & $($mutability)* inputs[..] {
self.visit_operand(input, location);
}
}
}
}

View File

@ -473,6 +473,7 @@ impl<'a, 'tcx> BitDenotation for MovingOutStatements<'a, 'tcx> {
}
mir::StatementKind::StorageLive(_) |
mir::StatementKind::StorageDead(_) |
mir::StatementKind::InlineAsm { .. } |
mir::StatementKind::Nop => {}
}
}

View File

@ -104,6 +104,7 @@ fn each_block<'a, 'tcx, O>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
}
mir::StatementKind::StorageLive(_) |
mir::StatementKind::StorageDead(_) |
mir::StatementKind::InlineAsm { .. } |
mir::StatementKind::Nop => continue,
mir::StatementKind::SetDiscriminant{ .. } =>
span_bug!(stmt.source_info.span,

View File

@ -412,6 +412,7 @@ impl<'a, 'tcx> MoveDataBuilder<'a, 'tcx> {
span_bug!(stmt.source_info.span,
"SetDiscriminant should not exist during borrowck");
}
StatementKind::InlineAsm { .. } |
StatementKind::Nop => {}
}
}
@ -436,8 +437,7 @@ impl<'a, 'tcx> MoveDataBuilder<'a, 'tcx> {
}
Rvalue::Ref(..) |
Rvalue::Discriminant(..) |
Rvalue::Len(..) |
Rvalue::InlineAsm { .. } => {}
Rvalue::Len(..) => {}
Rvalue::Box(..) => {
// This returns an rvalue with uninitialized contents. We can't
// move out of it here because it is an rvalue - assignments always

View File

@ -378,6 +378,7 @@ fn drop_flag_effects_for_location<'a, 'tcx, F>(
}
mir::StatementKind::StorageLive(_) |
mir::StatementKind::StorageDead(_) |
mir::StatementKind::InlineAsm { .. } |
mir::StatementKind::Nop => {}
},
None => {

View File

@ -49,21 +49,6 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
ExprKind::Scope { extent, value } => {
this.in_scope(extent, block, |this| this.as_rvalue(block, value))
}
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));
block.and(Rvalue::Repeat(value_operand, count))
@ -238,6 +223,7 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
ExprKind::Break { .. } |
ExprKind::Continue { .. } |
ExprKind::Return { .. } |
ExprKind::InlineAsm { .. } |
ExprKind::StaticRef { .. } => {
// these do not have corresponding `Rvalue` variants,
// so make an operand and then return that

View File

@ -232,6 +232,7 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
ExprKind::AssignOp { .. } |
ExprKind::Continue { .. } |
ExprKind::Break { .. } |
ExprKind::InlineAsm { .. } |
ExprKind::Return {.. } => {
this.stmt_expr(block, expr)
}
@ -257,7 +258,6 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
ExprKind::Index { .. } |
ExprKind::Deref { .. } |
ExprKind::Literal { .. } |
ExprKind::InlineAsm { .. } |
ExprKind::Field { .. } => {
debug_assert!(match Category::of(&expr.kind).unwrap() {
Category::Rvalue(RvalueFunc::Into) => false,

View File

@ -117,6 +117,23 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
this.exit_scope(expr_span, extent, block, return_block);
this.cfg.start_new_block().unit()
}
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();
this.cfg.push(block, Statement {
source_info: source_info,
kind: StatementKind::InlineAsm {
asm: asm.clone(),
outputs: outputs,
inputs: inputs
},
});
block.unit()
}
_ => {
let expr_ty = expr.ty;
let temp = this.temp(expr.ty.clone());

View File

@ -774,10 +774,6 @@ impl<'a, 'tcx> Visitor<'tcx> for Qualifier<'a, 'tcx, 'tcx> {
}
}
}
Rvalue::InlineAsm {..} => {
self.not_const();
}
}
}
@ -933,6 +929,7 @@ impl<'a, 'tcx> Visitor<'tcx> for Qualifier<'a, 'tcx, 'tcx> {
StatementKind::SetDiscriminant { .. } |
StatementKind::StorageLive(_) |
StatementKind::StorageDead(_) |
StatementKind::InlineAsm {..} |
StatementKind::Nop => {}
}
});

View File

@ -361,9 +361,9 @@ impl<'a, 'gcx, 'tcx> TypeChecker<'a, 'gcx, 'tcx> {
span_mirbug!(self, stmt, "bad assignment ({:?} = {:?}): {:?}",
lv_ty, rv_ty, terr);
}
// FIXME: rvalue with undeterminable type - e.g. inline
// asm.
}
// FIXME: rvalue with undeterminable type - e.g. AggregateKind::Array branch that
// returns `None`.
}
StatementKind::SetDiscriminant{ ref lvalue, variant_index } => {
let lvalue_type = lvalue.ty(mir, tcx).to_ty(tcx);
@ -392,6 +392,7 @@ impl<'a, 'gcx, 'tcx> TypeChecker<'a, 'gcx, 'tcx> {
}
}
}
StatementKind::InlineAsm { .. } |
StatementKind::Nop => {}
}
}

View File

@ -128,6 +128,7 @@ impl<'a, 'tcx> mir_visit::Visitor<'tcx> for StatCollector<'a, 'tcx> {
StatementKind::SetDiscriminant { .. } => "StatementKind::SetDiscriminant",
StatementKind::StorageLive(..) => "StatementKind::StorageLive",
StatementKind::StorageDead(..) => "StatementKind::StorageDead",
StatementKind::InlineAsm { .. } => "StatementKind::InlineAsm",
StatementKind::Nop => "StatementKind::Nop",
}, &statement.kind);
self.super_statement(block, statement, location);
@ -198,7 +199,6 @@ impl<'a, 'tcx> mir_visit::Visitor<'tcx> for StatCollector<'a, 'tcx> {
"Rvalue::Aggregate"
}
Rvalue::InlineAsm { .. } => "Rvalue::InlineAsm",
};
self.record(rvalue_kind, rvalue);
self.super_rvalue(rvalue, location);

View File

@ -287,8 +287,9 @@ impl<'a, 'tcx> MirConstContext<'a, 'tcx> {
mir::StatementKind::StorageLive(_) |
mir::StatementKind::StorageDead(_) |
mir::StatementKind::Nop => {}
mir::StatementKind::InlineAsm { .. } |
mir::StatementKind::SetDiscriminant{ .. } => {
span_bug!(span, "SetDiscriminant should not appear in constants?");
span_bug!(span, "{:?} should not appear in constants?", statement.kind);
}
}
}

View File

@ -16,7 +16,6 @@ use rustc::mir::tcx::LvalueTy;
use rustc::mir;
use middle::lang_items::ExchangeMallocFnLangItem;
use asm;
use base;
use builder::Builder;
use callee::Callee;
@ -156,20 +155,6 @@ impl<'a, 'tcx> MirContext<'a, 'tcx> {
bcx
}
mir::Rvalue::InlineAsm { ref asm, ref outputs, ref inputs } => {
let outputs = outputs.iter().map(|output| {
let lvalue = self.trans_lvalue(&bcx, output);
(lvalue.llval, lvalue.ty.to_ty(bcx.tcx()))
}).collect();
let input_vals = inputs.iter().map(|input| {
self.trans_operand(&bcx, input).immediate()
}).collect();
asm::trans_inline_asm(&bcx, asm, outputs, input_vals);
bcx
}
_ => {
assert!(rvalue_creates_operand(rvalue));
let (bcx, temp) = self.trans_rvalue_operand(bcx, rvalue);
@ -468,8 +453,7 @@ impl<'a, 'tcx> MirContext<'a, 'tcx> {
(bcx, operand)
}
mir::Rvalue::Repeat(..) |
mir::Rvalue::Aggregate(..) |
mir::Rvalue::InlineAsm { .. } => {
mir::Rvalue::Aggregate(..) => {
bug!("cannot generate operand from rvalue {:?}", rvalue);
}
@ -669,8 +653,7 @@ pub fn rvalue_creates_operand(rvalue: &mir::Rvalue) -> bool {
mir::Rvalue::Use(..) =>
true,
mir::Rvalue::Repeat(..) |
mir::Rvalue::Aggregate(..) |
mir::Rvalue::InlineAsm { .. } =>
mir::Rvalue::Aggregate(..) =>
false,
}

View File

@ -11,6 +11,7 @@
use rustc::mir;
use base;
use asm;
use common;
use builder::Builder;
@ -73,6 +74,19 @@ impl<'a, 'tcx> MirContext<'a, 'tcx> {
mir::StatementKind::StorageDead(ref lvalue) => {
self.trans_storage_liveness(bcx, lvalue, base::Lifetime::End)
}
mir::StatementKind::InlineAsm { ref asm, ref outputs, ref inputs } => {
let outputs = outputs.iter().map(|output| {
let lvalue = self.trans_lvalue(&bcx, output);
(lvalue.llval, lvalue.ty.to_ty(bcx.tcx()))
}).collect();
let input_vals = inputs.iter().map(|input| {
self.trans_operand(&bcx, input).immediate()
}).collect();
asm::trans_inline_asm(&bcx, asm, outputs, input_vals);
bcx
}
mir::StatementKind::Nop => bcx,
}
}