1- // Copyright 2018 King's College London.
21// Created by the Software Development Team <http://soft-dev.org/>.
32//
43// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
@@ -17,7 +16,8 @@ use rustc::ty::TyCtxt;
1716use rustc:: hir:: def_id:: DefId ;
1817use rustc:: mir:: {
1918 Mir , TerminatorKind , Operand , Constant , StatementKind , BasicBlock , BasicBlockData , Terminator ,
20- Place , Rvalue , Statement , Local , PlaceBase
19+ Place , Rvalue , Statement , Local , PlaceBase , BorrowKind , BinOp , UnOp , NullOp , Projection ,
20+ AggregateKind
2121} ;
2222use rustc:: ty:: { TyS , TyKind , Const , LazyConst } ;
2323use rustc:: util:: nodemap:: DefIdSet ;
@@ -29,6 +29,7 @@ use std::io::Write;
2929use std:: error:: Error ;
3030use std:: cell:: { Cell , RefCell } ;
3131use std:: mem:: size_of;
32+ use std:: marker:: PhantomData ;
3233use rustc_data_structures:: bit_set:: BitSet ;
3334use rustc_data_structures:: indexed_vec:: IndexVec ;
3435use ykpack;
@@ -264,6 +265,8 @@ impl<'tcx> ToPack<ykpack::Terminator> for (&ConvCx<'_, 'tcx, '_>, &Terminator<'t
264265 unwind_bb : unwind_bb. map ( |bb| u32:: from ( bb) ) ,
265266 } ,
266267 TerminatorKind :: Call { ref func, cleanup : cleanup_bb, ref destination, .. } => {
268+ // In MIR, a call instruction accepts an arbitrary operand, but in TIR we special
269+ // case the call targets.
267270 let ser_oper = if let Operand :: Constant ( box Constant {
268271 literal : LazyConst :: Evaluated ( Const {
269272 ty : & TyS {
@@ -307,7 +310,7 @@ impl<'tcx> ToPack<ykpack::BasicBlock> for
307310 fn to_pack ( & mut self ) -> ykpack:: BasicBlock {
308311 let ( ccx, bb, bb_data) = self ;
309312 let ser_stmts = bb_data. statements . iter ( ) . map ( |stmt| ( * ccx, * bb, stmt) . to_pack ( ) ) ;
310- ykpack:: BasicBlock :: new ( ser_stmts. collect ( ) ,
313+ ykpack:: BasicBlock :: new ( ser_stmts. filter ( |s| * s != ykpack :: Statement :: Nop ) . collect ( ) ,
311314 ( * ccx, bb_data. terminator . as_ref ( ) . unwrap ( ) ) . to_pack ( ) )
312315 }
313316}
@@ -321,12 +324,23 @@ impl<'tcx> ToPack<ykpack::Statement> for (&ConvCx<'_, 'tcx, '_>, BasicBlock, &St
321324 StatementKind :: Assign ( ref place, ref rval) => {
322325 let lhs = ( * ccx, place) . to_pack ( ) ;
323326 let rhs = ( * ccx, & * * rval) . to_pack ( ) ;
324- if let ykpack:: Place :: Local ( tvar) = lhs {
327+ if let ykpack:: Place :: Base ( ykpack :: PlaceBase :: Local ( tvar) ) = lhs {
325328 ccx. push_def_site ( * bb, tvar) ;
326329 }
327330 ykpack:: Statement :: Assign ( lhs, rhs)
328331 } ,
329- _ => ykpack:: Statement :: Unimplemented ,
332+ StatementKind :: SetDiscriminant { ref place, ref variant_index} =>
333+ ykpack:: Statement :: SetDiscriminant ( ( * ccx, place) . to_pack ( ) , variant_index. as_u32 ( ) ) ,
334+ // StorageLive/Dead not useful to the tracer. Ignore them.
335+ StatementKind :: StorageLive ( ..)
336+ | StatementKind :: StorageDead ( ..) => ykpack:: Statement :: Nop ,
337+ StatementKind :: InlineAsm { ..} => ykpack:: Statement :: Unimplemented ,
338+ // These MIR statements all codegen to nothing, and are thus nops for us too. See
339+ // codegen_statement() in librustc_codegen_ssa for proof.
340+ StatementKind :: Retag ( ..)
341+ | StatementKind :: AscribeUserType ( ..)
342+ | StatementKind :: FakeRead ( ..)
343+ | StatementKind :: Nop => ykpack:: Statement :: Nop ,
330344 }
331345 }
332346}
@@ -337,8 +351,50 @@ impl<'tcx> ToPack<ykpack::Place> for (&ConvCx<'_, 'tcx, '_>, &Place<'tcx>) {
337351 let ( ccx, place) = self ;
338352
339353 match place {
340- Place :: Base ( PlaceBase :: Local ( local) ) => ykpack:: Place :: Local ( ccx. tir_var ( * local) ) ,
341- _ => ykpack:: Place :: Unimplemented , // FIXME
354+ Place :: Base ( pb) => ykpack:: Place :: Base ( ( * ccx, pb) . to_pack ( ) ) ,
355+ Place :: Projection ( pj) => ykpack:: Place :: Projection ( ( * ccx, pj. as_ref ( ) ) . to_pack ( ) ) ,
356+ }
357+ }
358+ }
359+
360+ /// Projection -> Pack
361+ /// In Rust, projections are parameterised, but there is only ever one concrete instantiation, so
362+ /// we lower to a concrete `PlaceProjection`.
363+ impl < ' tcx , T > ToPack < ykpack:: PlaceProjection >
364+ for ( & ConvCx < ' _ , ' tcx , ' _ > , & Projection < ' tcx , Place < ' tcx > , Local , T > )
365+ {
366+ fn to_pack ( & mut self ) -> ykpack:: PlaceProjection {
367+ let ( ccx, pj) = self ;
368+
369+ ykpack:: PlaceProjection {
370+ base : Box :: new ( ( * ccx, & pj. base ) . to_pack ( ) ) ,
371+ elem : ykpack:: ProjectionElem :: Unimplemented ( PhantomData ) , // FIXME
372+ }
373+ }
374+ }
375+
376+ /// PlaceBase -> Pack
377+ impl < ' tcx > ToPack < ykpack:: PlaceBase > for ( & ConvCx < ' _ , ' tcx , ' _ > , & PlaceBase < ' tcx > ) {
378+ fn to_pack ( & mut self ) -> ykpack:: PlaceBase {
379+ let ( ccx, pb) = self ;
380+
381+ match pb {
382+ PlaceBase :: Local ( local) => ykpack:: PlaceBase :: Local ( ccx. tir_var ( * local) ) ,
383+ PlaceBase :: Static ( s) => ykpack:: PlaceBase :: Static ( ( * ccx, & s. as_ref ( ) . def_id ) . to_pack ( ) ) ,
384+ PlaceBase :: Promoted ( bx) => ykpack:: PlaceBase :: Promoted ( bx. 0 . as_u32 ( ) ) ,
385+ }
386+ }
387+ }
388+
389+ /// Operand -> Pack
390+ impl < ' tcx > ToPack < ykpack:: Operand > for ( & ConvCx < ' _ , ' tcx , ' _ > , & Operand < ' tcx > ) {
391+ fn to_pack ( & mut self ) -> ykpack:: Operand {
392+ let ( ccx, op) = self ;
393+
394+ match * op {
395+ Operand :: Move ( place) | Operand :: Copy ( place)
396+ => ykpack:: Operand :: Place ( ( * ccx, place) . to_pack ( ) ) ,
397+ _ => ykpack:: Operand :: Unimplemented , // FIXME
342398 }
343399 }
344400}
@@ -349,8 +405,106 @@ impl<'tcx> ToPack<ykpack::Rvalue> for (&ConvCx<'_, 'tcx, '_>, &Rvalue<'tcx>) {
349405 let ( ccx, rval) = self ;
350406
351407 match * rval {
352- Rvalue :: Use ( Operand :: Move ( place) ) => ykpack:: Rvalue :: Place ( ( * ccx, place) . to_pack ( ) ) ,
353- _ => ykpack:: Rvalue :: Unimplemented , // FIXME
408+ Rvalue :: Use ( oper) => ykpack:: Rvalue :: Use ( ( * ccx, oper) . to_pack ( ) ) ,
409+ Rvalue :: Repeat ( oper, len) => ykpack:: Rvalue :: Repeat ( ( * ccx, oper) . to_pack ( ) , * len) ,
410+ Rvalue :: Ref ( _region, borrow_kind, place) => ykpack:: Rvalue :: Ref (
411+ ( * ccx, borrow_kind) . to_pack ( ) ,
412+ ( * ccx, place) . to_pack ( ) ) ,
413+ Rvalue :: Len ( place) => ykpack:: Rvalue :: Len ( ( * ccx, place) . to_pack ( ) ) ,
414+ // Since TIR is currently untyped we consider a cast as a simple variable use.
415+ Rvalue :: Cast ( _, oper, _) => ykpack:: Rvalue :: Use ( ( * ccx, oper) . to_pack ( ) ) ,
416+ Rvalue :: BinaryOp ( bop, o1, o2) => ykpack:: Rvalue :: BinaryOp (
417+ ( * ccx, bop) . to_pack ( ) ,
418+ ( * ccx, o1) . to_pack ( ) ,
419+ ( * ccx, o2) . to_pack ( ) ) ,
420+ Rvalue :: CheckedBinaryOp ( bop, o1, o2) => ykpack:: Rvalue :: CheckedBinaryOp (
421+ ( * ccx, bop) . to_pack ( ) ,
422+ ( * ccx, o1) . to_pack ( ) ,
423+ ( * ccx, o2) . to_pack ( ) ) ,
424+ Rvalue :: NullaryOp ( null_op, _) => ykpack:: Rvalue :: NullaryOp ( ( * ccx, null_op) . to_pack ( ) ) ,
425+ Rvalue :: UnaryOp ( un_op, op) =>
426+ ykpack:: Rvalue :: UnaryOp ( ( * ccx, un_op) . to_pack ( ) , ( * ccx, op) . to_pack ( ) ) ,
427+ Rvalue :: Discriminant ( place) => ykpack:: Rvalue :: Discriminant ( ( * ccx, place) . to_pack ( ) ) ,
428+ Rvalue :: Aggregate ( ag_kind, ops) => ykpack:: Rvalue :: Aggregate (
429+ ( * ccx, ag_kind. as_ref ( ) ) . to_pack ( ) ,
430+ ops. iter ( ) . map ( |op| ( * ccx, op) . to_pack ( ) ) . collect ( ) ) ,
431+ }
432+ }
433+ }
434+
435+ /// AggregateKind -> Pack
436+ impl < ' tcx > ToPack < ykpack:: AggregateKind > for ( & ConvCx < ' _ , ' tcx , ' _ > , & AggregateKind < ' tcx > ) {
437+ fn to_pack ( & mut self ) -> ykpack:: AggregateKind {
438+ let ( ccx, ak) = self ;
439+ match * ak {
440+ AggregateKind :: Array ( _) => ykpack:: AggregateKind :: Array ,
441+ AggregateKind :: Tuple => ykpack:: AggregateKind :: Tuple ,
442+ AggregateKind :: Adt { ..} => ykpack:: AggregateKind :: Unimplemented ,
443+ AggregateKind :: Closure ( def_id, _) =>
444+ ykpack:: AggregateKind :: Closure ( ( * ccx, def_id) . to_pack ( ) ) ,
445+ AggregateKind :: Generator ( def_id, ..) =>
446+ ykpack:: AggregateKind :: Generator ( ( * ccx, def_id) . to_pack ( ) ) ,
447+ }
448+ }
449+ }
450+
451+ /// BorrowKind -> Pack
452+ impl < ' tcx > ToPack < ykpack:: BorrowKind > for ( & ConvCx < ' _ , ' tcx , ' _ > , & BorrowKind ) {
453+ fn to_pack ( & mut self ) -> ykpack:: BorrowKind {
454+ let ( _ccx, bk) = self ;
455+ match * bk {
456+ BorrowKind :: Shared => ykpack:: BorrowKind :: Shared ,
457+ BorrowKind :: Shallow => ykpack:: BorrowKind :: Shallow ,
458+ BorrowKind :: Unique => ykpack:: BorrowKind :: Unique ,
459+ BorrowKind :: Mut { ..} => ykpack:: BorrowKind :: Mut ,
460+ }
461+ }
462+ }
463+
464+ /// BinOp -> Pack
465+ impl < ' tcx > ToPack < ykpack:: BinOp > for ( & ConvCx < ' _ , ' tcx , ' _ > , & BinOp ) {
466+ fn to_pack ( & mut self ) -> ykpack:: BinOp {
467+ let ( _ccx, op) = self ;
468+ match * op {
469+ BinOp :: Add => ykpack:: BinOp :: Add ,
470+ BinOp :: Sub => ykpack:: BinOp :: Sub ,
471+ BinOp :: Mul => ykpack:: BinOp :: Mul ,
472+ BinOp :: Div => ykpack:: BinOp :: Div ,
473+ BinOp :: Rem => ykpack:: BinOp :: Rem ,
474+ BinOp :: BitXor => ykpack:: BinOp :: BitXor ,
475+ BinOp :: BitAnd => ykpack:: BinOp :: BitAnd ,
476+ BinOp :: BitOr => ykpack:: BinOp :: BitOr ,
477+ BinOp :: Shl => ykpack:: BinOp :: Shl ,
478+ BinOp :: Shr => ykpack:: BinOp :: Shr ,
479+ BinOp :: Eq => ykpack:: BinOp :: Eq ,
480+ BinOp :: Lt => ykpack:: BinOp :: Lt ,
481+ BinOp :: Le => ykpack:: BinOp :: Le ,
482+ BinOp :: Ne => ykpack:: BinOp :: Ne ,
483+ BinOp :: Ge => ykpack:: BinOp :: Ge ,
484+ BinOp :: Gt => ykpack:: BinOp :: Gt ,
485+ BinOp :: Offset => ykpack:: BinOp :: Offset ,
486+ }
487+ }
488+ }
489+
490+ /// NullOp -> Pack
491+ impl < ' tcx > ToPack < ykpack:: NullOp > for ( & ConvCx < ' _ , ' tcx , ' _ > , & NullOp ) {
492+ fn to_pack ( & mut self ) -> ykpack:: NullOp {
493+ let ( _ccx, op) = self ;
494+ match * op {
495+ NullOp :: SizeOf => ykpack:: NullOp :: SizeOf ,
496+ NullOp :: Box => ykpack:: NullOp :: Box ,
497+ }
498+ }
499+ }
500+
501+ /// UnOp -> Pack
502+ impl < ' tcx > ToPack < ykpack:: UnOp > for ( & ConvCx < ' _ , ' tcx , ' _ > , & UnOp ) {
503+ fn to_pack ( & mut self ) -> ykpack:: UnOp {
504+ let ( _ccx, op) = self ;
505+ match * op {
506+ UnOp :: Not => ykpack:: UnOp :: Not ,
507+ UnOp :: Neg => ykpack:: UnOp :: Neg ,
354508 }
355509 }
356510}
0 commit comments