-
Notifications
You must be signed in to change notification settings - Fork 4
Implement more TIR lowerings. #18
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,4 +1,3 @@ | ||
// Copyright 2018 King's College London. | ||
// Created by the Software Development Team <http://soft-dev.org/>. | ||
// | ||
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or | ||
|
@@ -17,7 +16,8 @@ use rustc::ty::TyCtxt; | |
use rustc::hir::def_id::DefId; | ||
use rustc::mir::{ | ||
Mir, TerminatorKind, Operand, Constant, StatementKind, BasicBlock, BasicBlockData, Terminator, | ||
Place, Rvalue, Statement, Local, PlaceBase | ||
Place, Rvalue, Statement, Local, PlaceBase, BorrowKind, BinOp, UnOp, NullOp, Projection, | ||
AggregateKind | ||
}; | ||
use rustc::ty::{TyS, TyKind, Const, LazyConst}; | ||
use rustc::util::nodemap::DefIdSet; | ||
|
@@ -29,6 +29,7 @@ use std::io::Write; | |
use std::error::Error; | ||
use std::cell::{Cell, RefCell}; | ||
use std::mem::size_of; | ||
use std::marker::PhantomData; | ||
use rustc_data_structures::bit_set::BitSet; | ||
use rustc_data_structures::indexed_vec::IndexVec; | ||
use ykpack; | ||
|
@@ -264,6 +265,8 @@ impl<'tcx> ToPack<ykpack::Terminator> for (&ConvCx<'_, 'tcx, '_>, &Terminator<'t | |
unwind_bb: unwind_bb.map(|bb| u32::from(bb)), | ||
}, | ||
TerminatorKind::Call{ref func, cleanup: cleanup_bb, ref destination, .. } => { | ||
// In MIR, a call instruction accepts an arbitrary operand, but in TIR we special | ||
// case the call targets. | ||
let ser_oper = if let Operand::Constant(box Constant { | ||
literal: LazyConst::Evaluated(Const { | ||
ty: &TyS { | ||
|
@@ -307,7 +310,7 @@ impl<'tcx> ToPack<ykpack::BasicBlock> for | |
fn to_pack(&mut self) -> ykpack::BasicBlock { | ||
let (ccx, bb, bb_data) = self; | ||
let ser_stmts = bb_data.statements.iter().map(|stmt| (*ccx, *bb, stmt).to_pack()); | ||
ykpack::BasicBlock::new(ser_stmts.collect(), | ||
ykpack::BasicBlock::new(ser_stmts.filter(|s| *s != ykpack::Statement::Nop).collect(), | ||
(*ccx, bb_data.terminator.as_ref().unwrap()).to_pack()) | ||
} | ||
} | ||
|
@@ -321,12 +324,23 @@ impl<'tcx> ToPack<ykpack::Statement> for (&ConvCx<'_, 'tcx, '_>, BasicBlock, &St | |
StatementKind::Assign(ref place, ref rval) => { | ||
let lhs = (*ccx, place).to_pack(); | ||
let rhs = (*ccx, &**rval).to_pack(); | ||
if let ykpack::Place::Local(tvar) = lhs { | ||
if let ykpack::Place::Base(ykpack::PlaceBase::Local(tvar)) = lhs { | ||
ccx.push_def_site(*bb, tvar); | ||
} | ||
ykpack::Statement::Assign(lhs, rhs) | ||
}, | ||
_ => ykpack::Statement::Unimplemented, | ||
StatementKind::SetDiscriminant{ref place, ref variant_index} => | ||
ykpack::Statement::SetDiscriminant((*ccx, place).to_pack(), variant_index.as_u32()), | ||
// StorageLive/Dead not useful to the tracer. Ignore them. | ||
StatementKind::StorageLive(..) | ||
| StatementKind::StorageDead(..) => ykpack::Statement::Nop, | ||
StatementKind::InlineAsm{..} => ykpack::Statement::Unimplemented, | ||
// These MIR statements all codegen to nothing, and are thus nops for us too. See | ||
// codegen_statement() in librustc_codegen_ssa for proof. | ||
StatementKind::Retag(..) | ||
| StatementKind::AscribeUserType(..) | ||
| StatementKind::FakeRead(..) | ||
| StatementKind::Nop => ykpack::Statement::Nop, | ||
} | ||
} | ||
} | ||
|
@@ -337,8 +351,50 @@ impl<'tcx> ToPack<ykpack::Place> for (&ConvCx<'_, 'tcx, '_>, &Place<'tcx>) { | |
let (ccx, place) = self; | ||
|
||
match place { | ||
Place::Base(PlaceBase::Local(local)) => ykpack::Place::Local(ccx.tir_var(*local)), | ||
_ => ykpack::Place::Unimplemented, // FIXME | ||
Place::Base(pb) => ykpack::Place::Base((*ccx, pb).to_pack()), | ||
Place::Projection(pj) => ykpack::Place::Projection((*ccx, pj.as_ref()).to_pack()), | ||
} | ||
} | ||
} | ||
|
||
/// Projection -> Pack | ||
/// In Rust, projections are parameterised, but there is only ever one concrete instantiation, so | ||
/// we lower to a concrete `PlaceProjection`. | ||
impl<'tcx, T> ToPack<ykpack::PlaceProjection> | ||
for (&ConvCx<'_, 'tcx, '_>, &Projection<'tcx, Place<'tcx>, Local, T>) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Here we are taking a parameterised MIR There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. OK. |
||
{ | ||
fn to_pack(&mut self) -> ykpack::PlaceProjection { | ||
let (ccx, pj) = self; | ||
|
||
ykpack::PlaceProjection { | ||
base: Box::new((*ccx, &pj.base).to_pack()), | ||
elem: ykpack::ProjectionElem::Unimplemented(PhantomData), // FIXME | ||
} | ||
} | ||
} | ||
|
||
/// PlaceBase -> Pack | ||
impl<'tcx> ToPack<ykpack::PlaceBase> for (&ConvCx<'_, 'tcx, '_>, &PlaceBase<'tcx>) { | ||
fn to_pack(&mut self) -> ykpack::PlaceBase { | ||
let (ccx, pb) = self; | ||
|
||
match pb { | ||
PlaceBase::Local(local) => ykpack::PlaceBase::Local(ccx.tir_var(*local)), | ||
PlaceBase::Static(s) => ykpack::PlaceBase::Static((*ccx, &s.as_ref().def_id).to_pack()), | ||
PlaceBase::Promoted(bx) => ykpack::PlaceBase::Promoted(bx.0.as_u32()), | ||
} | ||
} | ||
} | ||
|
||
/// Operand -> Pack | ||
impl<'tcx> ToPack<ykpack::Operand> for (&ConvCx<'_, 'tcx, '_>, &Operand<'tcx>) { | ||
fn to_pack(&mut self) -> ykpack::Operand { | ||
let (ccx, op) = self; | ||
|
||
match *op { | ||
Operand::Move(place) | Operand::Copy(place) | ||
=> ykpack::Operand::Place((*ccx, place).to_pack()), | ||
_ => ykpack::Operand::Unimplemented, // FIXME | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Bad formatting. Also I think we should make this There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. We don't want to crash, I just want to see an There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. (I have a tool for drawing the cfg from a serialised pack) There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. OK. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. WRT to formatting, how would you have done it? The second line is a continuation of the first, hence the indent. Joining the lines upsets the tidy check. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Ah! Ignore me. |
||
} | ||
} | ||
} | ||
|
@@ -349,8 +405,106 @@ impl<'tcx> ToPack<ykpack::Rvalue> for (&ConvCx<'_, 'tcx, '_>, &Rvalue<'tcx>) { | |
let (ccx, rval) = self; | ||
|
||
match *rval { | ||
Rvalue::Use(Operand::Move(place)) => ykpack::Rvalue::Place((*ccx, place).to_pack()), | ||
_ => ykpack::Rvalue::Unimplemented, // FIXME | ||
Rvalue::Use(oper) => ykpack::Rvalue::Use((*ccx, oper).to_pack()), | ||
Rvalue::Repeat(oper, len) => ykpack::Rvalue::Repeat((*ccx, oper).to_pack(), *len), | ||
Rvalue::Ref(_region, borrow_kind, place) => ykpack::Rvalue::Ref( | ||
(*ccx, borrow_kind).to_pack(), | ||
(*ccx, place).to_pack()), | ||
Rvalue::Len(place) => ykpack::Rvalue::Len((*ccx, place).to_pack()), | ||
// Since TIR is currently untyped we consider a cast as a simple variable use. | ||
Rvalue::Cast(_, oper, _) => ykpack::Rvalue::Use((*ccx, oper).to_pack()), | ||
Rvalue::BinaryOp(bop, o1, o2) => ykpack::Rvalue::BinaryOp( | ||
(*ccx, bop).to_pack(), | ||
(*ccx, o1).to_pack(), | ||
(*ccx, o2).to_pack()), | ||
Rvalue::CheckedBinaryOp(bop, o1, o2) => ykpack::Rvalue::CheckedBinaryOp( | ||
(*ccx, bop).to_pack(), | ||
(*ccx, o1).to_pack(), | ||
(*ccx, o2).to_pack()), | ||
Rvalue::NullaryOp(null_op, _) => ykpack::Rvalue::NullaryOp((*ccx, null_op).to_pack()), | ||
Rvalue::UnaryOp(un_op, op) => | ||
ykpack::Rvalue::UnaryOp((*ccx, un_op).to_pack(), (*ccx, op).to_pack()), | ||
Rvalue::Discriminant(place) => ykpack::Rvalue::Discriminant((*ccx, place).to_pack()), | ||
Rvalue::Aggregate(ag_kind, ops) => ykpack::Rvalue::Aggregate( | ||
(*ccx, ag_kind.as_ref()).to_pack(), | ||
ops.iter().map(|op| (*ccx, op).to_pack()).collect()), | ||
} | ||
} | ||
} | ||
|
||
/// AggregateKind -> Pack | ||
impl<'tcx> ToPack<ykpack::AggregateKind> for (&ConvCx<'_, 'tcx, '_>, &AggregateKind<'tcx>) { | ||
fn to_pack(&mut self) -> ykpack::AggregateKind { | ||
let (ccx, ak) = self; | ||
match *ak { | ||
AggregateKind::Array(_) => ykpack::AggregateKind::Array, | ||
AggregateKind::Tuple => ykpack::AggregateKind::Tuple, | ||
AggregateKind::Adt{..} => ykpack::AggregateKind::Unimplemented, | ||
AggregateKind::Closure(def_id, _) => | ||
ykpack::AggregateKind::Closure((*ccx, def_id).to_pack()), | ||
AggregateKind::Generator(def_id, ..) => | ||
ykpack::AggregateKind::Generator((*ccx, def_id).to_pack()), | ||
} | ||
} | ||
} | ||
|
||
/// BorrowKind -> Pack | ||
impl<'tcx> ToPack<ykpack::BorrowKind> for (&ConvCx<'_, 'tcx, '_>, &BorrowKind) { | ||
fn to_pack(&mut self) -> ykpack::BorrowKind { | ||
let (_ccx, bk) = self; | ||
match *bk { | ||
BorrowKind::Shared => ykpack::BorrowKind::Shared, | ||
BorrowKind::Shallow => ykpack::BorrowKind::Shallow, | ||
BorrowKind::Unique => ykpack::BorrowKind::Unique, | ||
BorrowKind::Mut{..} => ykpack::BorrowKind::Mut, | ||
} | ||
} | ||
} | ||
|
||
/// BinOp -> Pack | ||
impl<'tcx> ToPack<ykpack::BinOp> for (&ConvCx<'_, 'tcx, '_>, &BinOp) { | ||
fn to_pack(&mut self) -> ykpack::BinOp { | ||
let (_ccx, op) = self; | ||
match *op { | ||
BinOp::Add => ykpack::BinOp::Add, | ||
BinOp::Sub => ykpack::BinOp::Sub, | ||
BinOp::Mul => ykpack::BinOp::Mul, | ||
BinOp::Div => ykpack::BinOp::Div, | ||
BinOp::Rem => ykpack::BinOp::Rem, | ||
BinOp::BitXor => ykpack::BinOp::BitXor, | ||
BinOp::BitAnd => ykpack::BinOp::BitAnd, | ||
BinOp::BitOr => ykpack::BinOp::BitOr, | ||
BinOp::Shl => ykpack::BinOp::Shl, | ||
BinOp::Shr => ykpack::BinOp::Shr, | ||
BinOp::Eq => ykpack::BinOp::Eq, | ||
BinOp::Lt => ykpack::BinOp::Lt, | ||
BinOp::Le => ykpack::BinOp::Le, | ||
BinOp::Ne => ykpack::BinOp::Ne, | ||
BinOp::Ge => ykpack::BinOp::Ge, | ||
BinOp::Gt => ykpack::BinOp::Gt, | ||
BinOp::Offset => ykpack::BinOp::Offset, | ||
} | ||
} | ||
} | ||
|
||
/// NullOp -> Pack | ||
impl<'tcx> ToPack<ykpack::NullOp> for (&ConvCx<'_, 'tcx, '_>, &NullOp) { | ||
fn to_pack(&mut self) -> ykpack::NullOp { | ||
let (_ccx, op) = self; | ||
match *op { | ||
NullOp::SizeOf => ykpack::NullOp::SizeOf, | ||
NullOp::Box => ykpack::NullOp::Box, | ||
} | ||
} | ||
} | ||
|
||
/// UnOp -> Pack | ||
impl<'tcx> ToPack<ykpack::UnOp> for (&ConvCx<'_, 'tcx, '_>, &UnOp) { | ||
fn to_pack(&mut self) -> ykpack::UnOp { | ||
let (_ccx, op) = self; | ||
match *op { | ||
UnOp::Not => ykpack::UnOp::Not, | ||
UnOp::Neg => ykpack::UnOp::Neg, | ||
} | ||
} | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Not sure I understand this (I'm not saying it's badly phrased... I just don't understand it!).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
In mir they have
Call(Operand)
whereOperand
is really general. It can express things which I don't think you can even call.There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ah, I see.