2018-06-17 11:05:11 -05:00
use prelude ::* ;
2018-06-30 09:37:02 -05:00
pub fn trans_mono_item < ' a , ' tcx : ' a > ( cx : & mut CodegenCx < ' a , ' tcx , CurrentBackend > , context : & mut Context , mono_item : MonoItem < ' tcx > ) {
let tcx = cx . tcx ;
match mono_item {
MonoItem ::Fn ( inst ) = > match inst {
Instance {
def : InstanceDef ::Item ( def_id ) ,
substs ,
} = > {
2018-06-30 11:54:08 -05:00
let mut mir = ::std ::io ::Cursor ::new ( Vec ::new ( ) ) ;
::rustc_mir ::util ::write_mir_pretty ( tcx , Some ( def_id ) , & mut mir ) . unwrap ( ) ;
tcx . sess . warn ( & format! ( " {:?} : \n \n {} " , def_id , String ::from_utf8_lossy ( & mir . into_inner ( ) ) ) ) ;
2018-07-20 06:36:53 -05:00
let fn_ty = inst . ty ( tcx ) ;
let fn_ty = tcx . subst_and_normalize_erasing_regions (
substs ,
ty ::ParamEnv ::reveal_all ( ) ,
& fn_ty ,
) ;
let sig = cton_sig_from_fn_ty ( tcx , fn_ty ) ;
2018-06-30 09:37:02 -05:00
let func_id = {
let module = & mut cx . module ;
* cx . def_id_fn_id_map . entry ( inst ) . or_insert_with ( | | {
2018-06-30 11:22:20 -05:00
let def_path_based_names = ::rustc_mir ::monomorphize ::item ::DefPathBasedNames ::new ( tcx , false , false ) ;
let mut name = String ::new ( ) ;
def_path_based_names . push_instance_as_string ( inst , & mut name ) ;
module . declare_function ( & name , Linkage ::Local , & sig ) . unwrap ( )
2018-06-30 09:37:02 -05:00
} )
} ;
let mut f = Function ::with_name_signature ( ExternalName ::user ( 0 , func_id . index ( ) as u32 ) , sig ) ;
2018-07-14 09:39:49 -05:00
let comments = match ::base ::trans_fn ( cx , & mut f , inst ) {
Ok ( comments ) = > comments ,
Err ( err ) = > {
tcx . sess . err ( & err ) ;
return ;
}
} ;
2018-06-30 09:37:02 -05:00
2018-07-14 05:21:45 -05:00
let mut writer = ::pretty_clif ::CommentWriter ( comments ) ;
2018-06-30 09:37:02 -05:00
let mut cton = String ::new ( ) ;
2018-07-14 05:21:45 -05:00
::cranelift ::codegen ::write ::decorate_function ( & mut writer , & mut cton , & f , None ) . unwrap ( ) ;
2018-06-30 09:37:02 -05:00
tcx . sess . warn ( & cton ) ;
let flags = settings ::Flags ::new ( settings ::builder ( ) ) ;
2018-07-14 04:59:42 -05:00
match ::cranelift ::codegen ::verify_function ( & f , & flags ) {
2018-06-30 09:37:02 -05:00
Ok ( _ ) = > { }
Err ( err ) = > {
2018-07-20 06:36:53 -05:00
tcx . sess . err ( & format! ( " {:?} " , err ) ) ;
2018-07-14 04:59:42 -05:00
let pretty_error = ::cranelift ::codegen ::print_errors ::pretty_verifier_error ( & f , None , Some ( Box ::new ( writer ) ) , & err ) ;
2018-06-30 09:37:02 -05:00
tcx . sess . fatal ( & format! ( " cretonne verify error: \n {} " , pretty_error ) ) ;
2018-06-22 12:08:59 -05:00
}
2018-06-19 12:51:29 -05:00
}
2018-06-23 11:26:54 -05:00
2018-06-30 09:37:02 -05:00
context . func = f ;
2018-07-18 06:43:17 -05:00
// TODO: cranelift doesn't yet support some of the things needed
// cx.module.define_function(func_id, context).unwrap();
2018-06-30 09:37:02 -05:00
context . clear ( ) ;
}
2018-06-30 11:56:29 -05:00
inst = > cx . tcx . sess . warn ( & format! ( " Unimplemented instance {:?} " , inst ) ) ,
2018-06-22 12:08:59 -05:00
}
2018-07-18 04:55:32 -05:00
MonoItem ::Static ( def_id ) = > cx . tcx . sess . err ( & format! ( " Unimplemented static mono item {:?} " , def_id ) ) ,
MonoItem ::GlobalAsm ( node_id ) = > cx . tcx . sess . err ( & format! ( " Unimplemented global asm mono item {:?} " , node_id ) ) ,
2018-06-22 12:08:59 -05:00
}
2018-06-19 12:51:29 -05:00
}
2018-07-14 09:39:49 -05:00
pub fn trans_fn < ' a , ' tcx : ' a > ( cx : & mut CodegenCx < ' a , ' tcx , CurrentBackend > , f : & mut Function , instance : Instance < ' tcx > ) -> Result < HashMap < Inst , String > , String > {
2018-06-23 11:54:15 -05:00
let mir = cx . tcx . optimized_mir ( instance . def_id ( ) ) ;
2018-06-17 11:05:11 -05:00
let mut func_ctx = FunctionBuilderContext ::new ( ) ;
let mut bcx : FunctionBuilder < Variable > = FunctionBuilder ::new ( f , & mut func_ctx ) ;
let start_ebb = bcx . create_ebb ( ) ;
bcx . switch_to_block ( start_ebb ) ;
let mut ebb_map : HashMap < BasicBlock , Ebb > = HashMap ::new ( ) ;
for ( bb , _bb_data ) in mir . basic_blocks ( ) . iter_enumerated ( ) {
ebb_map . insert ( bb , bcx . create_ebb ( ) ) ;
}
2018-06-20 08:15:28 -05:00
let mut fx = FunctionCx {
tcx : cx . tcx ,
module : & mut cx . module ,
def_id_fn_id_map : & mut cx . def_id_fn_id_map ,
2018-06-23 11:54:15 -05:00
instance ,
2018-06-20 08:15:28 -05:00
mir ,
2018-06-23 11:54:15 -05:00
bcx ,
param_substs : {
assert! ( ! instance . substs . needs_infer ( ) ) ;
instance . substs
} ,
2018-06-20 08:15:28 -05:00
ebb_map ,
local_map : HashMap ::new ( ) ,
2018-07-14 04:59:42 -05:00
comments : HashMap ::new ( ) ,
2018-07-16 08:13:37 -05:00
constants : & mut cx . constants ,
2018-06-20 08:15:28 -05:00
} ;
let fx = & mut fx ;
2018-07-19 12:33:42 -05:00
::abi ::codegen_fn_prelude ( fx , start_ebb ) ;
2018-06-17 11:05:11 -05:00
2018-06-20 08:15:28 -05:00
fx . bcx . ins ( ) . jump ( * fx . ebb_map . get ( & START_BLOCK ) . unwrap ( ) , & [ ] ) ;
2018-06-17 11:05:11 -05:00
for ( bb , bb_data ) in mir . basic_blocks ( ) . iter_enumerated ( ) {
2018-06-19 12:51:29 -05:00
let ebb = fx . get_ebb ( bb ) ;
fx . bcx . switch_to_block ( ebb ) ;
2018-06-17 11:05:11 -05:00
for stmt in & bb_data . statements {
2018-07-14 09:39:49 -05:00
trans_stmt ( fx , stmt ) ? ;
2018-06-17 11:05:11 -05:00
}
2018-06-30 09:27:11 -05:00
let inst = match & bb_data . terminator ( ) . kind {
2018-06-17 11:05:11 -05:00
TerminatorKind ::Goto { target } = > {
2018-06-19 12:51:29 -05:00
let ebb = fx . get_ebb ( * target ) ;
2018-06-30 09:27:11 -05:00
fx . bcx . ins ( ) . jump ( ebb , & [ ] )
2018-06-17 11:05:11 -05:00
}
TerminatorKind ::Return = > {
2018-06-30 09:27:11 -05:00
fx . bcx . ins ( ) . return_ ( & [ ] )
2018-06-17 11:05:11 -05:00
}
2018-06-18 11:39:07 -05:00
TerminatorKind ::Assert { cond , expected , msg : _ , target , cleanup : _ } = > {
2018-06-26 12:44:19 -05:00
let cond = trans_operand ( fx , cond ) . load_value ( fx ) ;
2018-06-19 12:51:29 -05:00
let target = fx . get_ebb ( * target ) ;
2018-06-30 09:27:11 -05:00
let inst = if * expected {
fx . bcx . ins ( ) . brz ( cond , target , & [ ] )
2018-06-17 11:05:11 -05:00
} else {
2018-06-30 09:27:11 -05:00
fx . bcx . ins ( ) . brnz ( cond , target , & [ ] )
} ;
2018-06-19 12:51:29 -05:00
fx . bcx . ins ( ) . trap ( TrapCode ::User ( ! 0 ) ) ;
2018-06-30 09:27:11 -05:00
inst
2018-06-17 11:05:11 -05:00
}
2018-06-30 09:38:49 -05:00
TerminatorKind ::SwitchInt { discr , switch_ty : _ , values , targets } = > {
2018-06-26 12:44:19 -05:00
let discr = trans_operand ( fx , discr ) . load_value ( fx ) ;
2018-06-17 11:05:11 -05:00
let mut jt_data = JumpTableData ::new ( ) ;
for ( i , value ) in values . iter ( ) . enumerate ( ) {
2018-06-19 12:51:29 -05:00
let ebb = fx . get_ebb ( targets [ i ] ) ;
2018-06-17 11:05:11 -05:00
jt_data . set_entry ( * value as usize , ebb ) ;
}
2018-06-19 12:51:29 -05:00
let mut jump_table = fx . bcx . create_jump_table ( jt_data ) ;
2018-06-30 09:27:11 -05:00
let inst = fx . bcx . ins ( ) . br_table ( discr , jump_table ) ;
2018-06-19 12:51:29 -05:00
let otherwise_ebb = fx . get_ebb ( targets [ targets . len ( ) - 1 ] ) ;
fx . bcx . ins ( ) . jump ( otherwise_ebb , & [ ] ) ;
2018-06-30 09:27:11 -05:00
inst
2018-06-17 11:05:11 -05:00
}
2018-06-17 12:10:00 -05:00
TerminatorKind ::Call { func , args , destination , cleanup : _ } = > {
2018-07-19 12:33:42 -05:00
::abi ::codegen_call ( fx , func , args , destination )
2018-06-17 11:05:11 -05:00
}
2018-06-17 12:10:00 -05:00
TerminatorKind ::Resume | TerminatorKind ::Abort | TerminatorKind ::Unreachable = > {
2018-06-30 09:27:11 -05:00
fx . bcx . ins ( ) . trap ( TrapCode ::User ( ! 0 ) )
2018-06-17 12:10:00 -05:00
}
2018-06-18 11:39:07 -05:00
TerminatorKind ::Yield { .. } |
TerminatorKind ::FalseEdges { .. } |
TerminatorKind ::FalseUnwind { .. } = > {
bug! ( " shouldn't exist at trans {:?} " , bb_data . terminator ( ) ) ;
}
2018-06-28 13:27:43 -05:00
TerminatorKind ::Drop { target , .. } | TerminatorKind ::DropAndReplace { target , .. } = > {
// TODO call drop impl
// unimplemented!("terminator {:?}", bb_data.terminator());
let target_ebb = fx . get_ebb ( * target ) ;
2018-06-30 09:27:11 -05:00
fx . bcx . ins ( ) . jump ( target_ebb , & [ ] )
2018-06-28 13:27:43 -05:00
}
TerminatorKind ::GeneratorDrop = > {
unimplemented! ( " terminator GeneratorDrop " ) ;
2018-06-18 11:39:07 -05:00
}
2018-06-30 09:27:11 -05:00
} ;
let mut terminator_head = " \n " . to_string ( ) ;
bb_data . terminator ( ) . kind . fmt_head ( & mut terminator_head ) . unwrap ( ) ;
2018-07-14 04:59:42 -05:00
fx . add_comment ( inst , terminator_head ) ;
2018-06-17 11:05:11 -05:00
}
2018-06-19 12:51:29 -05:00
fx . bcx . seal_all_blocks ( ) ;
fx . bcx . finalize ( ) ;
2018-07-14 04:59:42 -05:00
2018-07-14 09:39:49 -05:00
Ok ( fx . comments . clone ( ) )
2018-06-17 11:05:11 -05:00
}
2018-07-14 09:39:49 -05:00
fn trans_stmt < ' a , ' tcx : ' a > ( fx : & mut FunctionCx < ' a , ' tcx > , stmt : & Statement < ' tcx > ) -> Result < ( ) , String > {
fx . tcx . sess . warn ( & format! ( " stmt {:?} " , stmt ) ) ;
2018-06-30 09:27:11 -05:00
let nop_inst = fx . bcx . ins ( ) . nop ( ) ;
2018-06-17 11:05:11 -05:00
match & stmt . kind {
2018-06-24 07:29:56 -05:00
StatementKind ::SetDiscriminant { place , variant_index } = > {
let place = trans_place ( fx , place ) ;
2018-06-26 12:44:19 -05:00
let layout = place . layout ( ) ;
2018-06-24 07:29:56 -05:00
if layout . for_variant ( & * fx , * variant_index ) . abi = = layout ::Abi ::Uninhabited {
2018-07-14 09:39:49 -05:00
return Ok ( ( ) ) ;
2018-06-23 11:54:15 -05:00
}
2018-06-24 07:29:56 -05:00
match layout . variants {
2018-06-23 11:54:15 -05:00
layout ::Variants ::Single { index } = > {
2018-06-24 07:29:56 -05:00
assert_eq! ( index , * variant_index ) ;
2018-07-19 12:42:07 -05:00
fx . bcx . ins ( ) . nop ( ) ;
2018-06-23 11:54:15 -05:00
}
layout ::Variants ::Tagged { .. } = > {
2018-06-26 12:44:19 -05:00
let ptr = place . place_field ( fx , mir ::Field ::new ( 0 ) ) ;
2018-06-24 07:29:56 -05:00
let to = layout . ty . ty_adt_def ( ) . unwrap ( )
. discriminant_for_variant ( fx . tcx , * variant_index )
2018-06-23 11:54:15 -05:00
. val ;
2018-06-26 12:44:19 -05:00
let discr = CValue ::const_val ( fx , ptr . layout ( ) . ty , to as u64 as i64 ) ;
ptr . write_cvalue ( fx , discr ) ;
2018-06-23 11:54:15 -05:00
}
layout ::Variants ::NicheFilling {
dataful_variant ,
ref niche_variants ,
niche_start ,
..
} = > {
2018-06-24 07:29:56 -05:00
if * variant_index ! = dataful_variant {
2018-06-26 12:44:19 -05:00
let niche = place . place_field ( fx , mir ::Field ::new ( 0 ) ) ;
2018-06-24 07:29:56 -05:00
//let niche_llty = niche.layout.immediate_llvm_type(bx.cx);
2018-06-23 11:54:15 -05:00
let niche_value = ( ( variant_index - * niche_variants . start ( ) ) as u128 )
. wrapping_add ( niche_start ) ;
// FIXME(eddyb) Check the actual primitive type here.
let niche_llval = if niche_value = = 0 {
2018-06-26 12:44:19 -05:00
CValue ::const_val ( fx , niche . layout ( ) . ty , 0 )
2018-06-23 11:54:15 -05:00
} else {
2018-06-26 12:44:19 -05:00
CValue ::const_val ( fx , niche . layout ( ) . ty , niche_value as u64 as i64 )
2018-06-23 11:54:15 -05:00
} ;
2018-06-26 12:44:19 -05:00
niche . write_cvalue ( fx , niche_llval ) ;
2018-07-19 12:42:07 -05:00
} else {
fx . bcx . ins ( ) . nop ( ) ;
2018-06-23 11:54:15 -05:00
}
}
}
2018-06-24 07:29:56 -05:00
}
2018-06-23 11:26:54 -05:00
StatementKind ::Assign ( to_place , rval ) = > {
let lval = trans_place ( fx , to_place ) ;
2018-06-26 12:44:19 -05:00
let dest_layout = lval . layout ( ) ;
2018-06-20 08:29:50 -05:00
match rval {
Rvalue ::Use ( operand ) = > {
let val = trans_operand ( fx , operand ) ;
2018-06-26 12:44:19 -05:00
lval . write_cvalue ( fx , val ) ;
2018-06-27 09:01:30 -05:00
}
Rvalue ::Ref ( _ , _ , place ) = > {
let place = trans_place ( fx , place ) ;
let addr = place . expect_addr ( ) ;
lval . write_cvalue ( fx , CValue ::ByVal ( addr , dest_layout ) ) ;
}
2018-06-23 11:26:54 -05:00
Rvalue ::BinaryOp ( bin_op , lhs , rhs ) = > {
2018-06-23 11:54:15 -05:00
let ty = fx . monomorphize ( & lhs . ty ( & fx . mir . local_decls , fx . tcx ) ) ;
2018-06-26 12:44:19 -05:00
let lhs = trans_operand ( fx , lhs ) . load_value ( fx ) ;
let rhs = trans_operand ( fx , rhs ) . load_value ( fx ) ;
2018-06-23 11:26:54 -05:00
let res = match ty . sty {
TypeVariants ::TyUint ( _ ) = > {
2018-07-14 09:39:49 -05:00
trans_int_binop ( fx , * bin_op , lhs , rhs , lval . layout ( ) . ty , false , false )
2018-06-23 11:26:54 -05:00
}
2018-06-23 11:54:15 -05:00
TypeVariants ::TyInt ( _ ) = > {
2018-07-14 09:39:49 -05:00
trans_int_binop ( fx , * bin_op , lhs , rhs , lval . layout ( ) . ty , true , false )
2018-06-23 11:54:15 -05:00
}
2018-07-18 08:17:22 -05:00
TypeVariants ::TyRawPtr ( .. ) = > {
trans_ptr_binop ( fx , * bin_op , lhs , rhs , lval . layout ( ) . ty , false )
}
2018-06-27 08:57:52 -05:00
_ = > unimplemented! ( " bin op {:?} for {:?} " , bin_op , ty ) ,
2018-06-23 11:26:54 -05:00
} ;
2018-06-27 08:47:58 -05:00
lval . write_cvalue ( fx , res ) ;
2018-06-23 11:26:54 -05:00
}
2018-06-20 08:29:50 -05:00
Rvalue ::CheckedBinaryOp ( bin_op , lhs , rhs ) = > {
2018-06-23 11:54:15 -05:00
let ty = fx . monomorphize ( & lhs . ty ( & fx . mir . local_decls , fx . tcx ) ) ;
2018-06-26 12:44:19 -05:00
let lhs = trans_operand ( fx , lhs ) . load_value ( fx ) ;
let rhs = trans_operand ( fx , rhs ) . load_value ( fx ) ;
2018-06-20 08:29:50 -05:00
let res = match ty . sty {
TypeVariants ::TyUint ( _ ) = > {
2018-06-27 08:47:58 -05:00
trans_int_binop ( fx , * bin_op , lhs , rhs , ty , false , true )
2018-06-20 08:29:50 -05:00
}
2018-06-24 07:29:56 -05:00
TypeVariants ::TyInt ( _ ) = > {
2018-06-27 08:47:58 -05:00
trans_int_binop ( fx , * bin_op , lhs , rhs , ty , true , true )
2018-06-24 07:29:56 -05:00
}
2018-06-27 08:57:52 -05:00
_ = > unimplemented! ( " checked bin op {:?} for {:?} " , bin_op , ty ) ,
2018-06-20 08:29:50 -05:00
} ;
2018-07-14 09:39:49 -05:00
return Err ( format! ( " checked bin op {:?} " , bin_op ) ) ;
2018-06-28 13:13:51 -05:00
lval . write_cvalue ( fx , res ) ;
2018-06-20 08:29:50 -05:00
}
2018-06-27 08:57:52 -05:00
Rvalue ::UnaryOp ( un_op , operand ) = > {
let ty = fx . monomorphize ( & operand . ty ( & fx . mir . local_decls , fx . tcx ) ) ;
let layout = fx . layout_of ( ty ) ;
let val = trans_operand ( fx , operand ) . load_value ( fx ) ;
let res = match un_op {
UnOp ::Not = > fx . bcx . ins ( ) . bnot ( val ) ,
UnOp ::Neg = > match ty . sty {
TypeVariants ::TyFloat ( _ ) = > fx . bcx . ins ( ) . fneg ( val ) ,
2018-06-27 09:01:30 -05:00
_ = > unimplemented! ( " un op Neg for {:?} " , ty ) ,
2018-06-27 08:57:52 -05:00
}
} ;
lval . write_cvalue ( fx , CValue ::ByVal ( res , layout ) ) ;
}
2018-06-20 08:29:50 -05:00
Rvalue ::Cast ( CastKind ::ReifyFnPointer , operand , ty ) = > {
let operand = trans_operand ( fx , operand ) ;
2018-06-26 12:44:19 -05:00
let layout = fx . layout_of ( ty ) ;
lval . write_cvalue ( fx , operand . unchecked_cast_to ( layout ) ) ;
2018-06-20 08:29:50 -05:00
}
Rvalue ::Cast ( CastKind ::UnsafeFnPointer , operand , ty ) = > {
let operand = trans_operand ( fx , operand ) ;
2018-06-26 12:44:19 -05:00
let layout = fx . layout_of ( ty ) ;
lval . write_cvalue ( fx , operand . unchecked_cast_to ( layout ) ) ;
2018-06-23 11:26:54 -05:00
}
2018-07-18 09:22:29 -05:00
Rvalue ::Cast ( CastKind ::Misc , operand , to_ty ) = > {
2018-07-18 07:21:13 -05:00
let operand = trans_operand ( fx , operand ) ;
2018-07-18 09:22:29 -05:00
let from_ty = operand . layout ( ) . ty ;
match ( & from_ty . sty , & to_ty . sty ) {
2018-07-18 07:21:13 -05:00
( TypeVariants ::TyRef ( .. ) , TypeVariants ::TyRef ( .. ) ) |
( TypeVariants ::TyRef ( .. ) , TypeVariants ::TyRawPtr ( .. ) ) |
( TypeVariants ::TyRawPtr ( .. ) , TypeVariants ::TyRef ( .. ) ) |
( TypeVariants ::TyRawPtr ( .. ) , TypeVariants ::TyRawPtr ( .. ) ) = > {
2018-07-18 09:22:29 -05:00
lval . write_cvalue ( fx , operand . unchecked_cast_to ( dest_layout ) ) ;
2018-07-18 07:21:13 -05:00
}
2018-07-19 12:37:34 -05:00
( TypeVariants ::TyChar , TypeVariants ::TyUint ( _ ) ) |
2018-07-18 09:22:29 -05:00
( TypeVariants ::TyUint ( _ ) , TypeVariants ::TyInt ( _ ) ) |
( TypeVariants ::TyUint ( _ ) , TypeVariants ::TyUint ( _ ) ) = > {
let from = operand . load_value ( fx ) ;
let res = ::common ::cton_intcast ( fx , from , from_ty , to_ty , false ) ;
lval . write_cvalue ( fx , CValue ::ByVal ( res , dest_layout ) ) ;
}
( TypeVariants ::TyInt ( _ ) , TypeVariants ::TyInt ( _ ) ) |
( TypeVariants ::TyInt ( _ ) , TypeVariants ::TyUint ( _ ) ) = > {
let from = operand . load_value ( fx ) ;
let res = ::common ::cton_intcast ( fx , from , from_ty , to_ty , true ) ;
lval . write_cvalue ( fx , CValue ::ByVal ( res , dest_layout ) ) ;
}
_ = > unimplemented! ( " rval misc {:?} {:?} " , operand , to_ty ) ,
2018-07-18 07:21:13 -05:00
}
} ,
2018-07-18 04:55:32 -05:00
Rvalue ::Cast ( CastKind ::ClosureFnPointer , operand , ty ) = > unimplemented! ( " rval closure_fn_ptr {:?} {:?} " , operand , ty ) ,
Rvalue ::Cast ( CastKind ::Unsize , operand , ty ) = > unimplemented! ( " rval unsize {:?} {:?} " , operand , ty ) ,
2018-06-23 11:26:54 -05:00
Rvalue ::Discriminant ( place ) = > {
2018-06-26 13:29:32 -05:00
let place = trans_place ( fx , place ) ;
2018-06-26 12:44:19 -05:00
let dest_cton_ty = fx . cton_type ( dest_layout . ty ) . unwrap ( ) ;
let layout = lval . layout ( ) ;
2018-06-23 11:26:54 -05:00
if layout . abi = = layout ::Abi ::Uninhabited {
fx . bcx . ins ( ) . trap ( TrapCode ::User ( ! 0 ) ) ;
}
match layout . variants {
layout ::Variants ::Single { index } = > {
let discr_val = layout . ty . ty_adt_def ( ) . map_or (
index as u128 ,
| def | def . discriminant_for_variant ( fx . tcx , index ) . val ) ;
2018-06-26 12:44:19 -05:00
let val = CValue ::const_val ( fx , dest_layout . ty , discr_val as u64 as i64 ) ;
lval . write_cvalue ( fx , val ) ;
2018-07-14 09:39:49 -05:00
return Ok ( ( ) ) ;
2018-06-23 11:26:54 -05:00
}
layout ::Variants ::Tagged { .. } |
layout ::Variants ::NicheFilling { .. } = > { } ,
}
2018-06-26 13:29:32 -05:00
let discr = place . to_cvalue ( fx ) . value_field ( fx , mir ::Field ::new ( 0 ) ) ;
let discr_ty = discr . layout ( ) . ty ;
2018-06-26 12:44:19 -05:00
let lldiscr = discr . load_value ( fx ) ;
2018-06-23 11:26:54 -05:00
match layout . variants {
layout ::Variants ::Single { .. } = > bug! ( ) ,
layout ::Variants ::Tagged { ref tag , .. } = > {
let signed = match tag . value {
layout ::Int ( _ , signed ) = > signed ,
_ = > false
} ;
2018-06-26 12:44:19 -05:00
let val = cton_intcast ( fx , lldiscr , discr_ty , dest_layout . ty , signed ) ;
lval . write_cvalue ( fx , CValue ::ByVal ( val , dest_layout ) ) ;
2018-06-23 11:26:54 -05:00
}
layout ::Variants ::NicheFilling {
dataful_variant ,
ref niche_variants ,
niche_start ,
..
} = > {
2018-06-24 07:01:41 -05:00
let niche_llty = fx . cton_type ( discr_ty ) . unwrap ( ) ;
2018-06-23 11:26:54 -05:00
if niche_variants . start ( ) = = niche_variants . end ( ) {
let b = fx . bcx . ins ( ) . icmp_imm ( IntCC ::Equal , lldiscr , niche_start as u64 as i64 ) ;
2018-06-24 07:01:41 -05:00
let if_true = fx . bcx . ins ( ) . iconst ( dest_cton_ty , * niche_variants . start ( ) as u64 as i64 ) ;
let if_false = fx . bcx . ins ( ) . iconst ( dest_cton_ty , dataful_variant as u64 as i64 ) ;
2018-06-23 11:26:54 -05:00
let val = fx . bcx . ins ( ) . select ( b , if_true , if_false ) ;
2018-06-26 12:44:19 -05:00
lval . write_cvalue ( fx , CValue ::ByVal ( val , dest_layout ) ) ;
2018-06-23 11:26:54 -05:00
} else {
// Rebase from niche values to discriminant values.
let delta = niche_start . wrapping_sub ( * niche_variants . start ( ) as u128 ) ;
let delta = fx . bcx . ins ( ) . iconst ( niche_llty , delta as u64 as i64 ) ;
let lldiscr = fx . bcx . ins ( ) . isub ( lldiscr , delta ) ;
let b = fx . bcx . ins ( ) . icmp_imm ( IntCC ::UnsignedLessThanOrEqual , lldiscr , * niche_variants . end ( ) as u64 as i64 ) ;
2018-06-26 12:44:19 -05:00
let if_true = cton_intcast ( fx , lldiscr , discr_ty , dest_layout . ty , false ) ;
2018-06-23 11:26:54 -05:00
let if_false = fx . bcx . ins ( ) . iconst ( niche_llty , dataful_variant as u64 as i64 ) ;
let val = fx . bcx . ins ( ) . select ( b , if_true , if_false ) ;
2018-06-26 12:44:19 -05:00
lval . write_cvalue ( fx , CValue ::ByVal ( val , dest_layout ) ) ;
2018-06-23 11:26:54 -05:00
}
}
}
2018-06-20 08:29:50 -05:00
}
2018-07-18 04:55:32 -05:00
Rvalue ::Repeat ( operand , times ) = > unimplemented! ( " rval repeat {:?} {:?} " , operand , times ) ,
2018-07-18 07:21:13 -05:00
Rvalue ::Len ( lval ) = > return Err ( format! ( " rval len {:?} " , lval ) ) ,
2018-07-18 04:55:32 -05:00
Rvalue ::NullaryOp ( NullOp ::Box , ty ) = > unimplemented! ( " rval box {:?} " , ty ) ,
Rvalue ::NullaryOp ( NullOp ::SizeOf , ty ) = > unimplemented! ( " rval size_of {:?} " , ty ) ,
Rvalue ::Aggregate ( _ , _ ) = > bug! ( " shouldn't exist at trans {:?} " , rval ) ,
2018-06-20 08:29:50 -05:00
}
2018-06-17 11:05:11 -05:00
}
2018-07-18 04:55:32 -05:00
StatementKind ::StorageLive ( _ ) | StatementKind ::StorageDead ( _ ) | StatementKind ::Nop | StatementKind ::ReadForMatch ( _ ) | StatementKind ::Validate ( _ , _ ) | StatementKind ::EndRegion ( _ ) | StatementKind ::UserAssertTy ( _ , _ ) = > {
2018-06-30 09:27:11 -05:00
fx . bcx . ins ( ) . nop ( ) ;
}
2018-07-18 04:55:32 -05:00
StatementKind ::InlineAsm { .. } = > fx . tcx . sess . fatal ( " Inline assembly is not supported " ) ,
2018-06-17 11:05:11 -05:00
}
2018-06-30 09:27:11 -05:00
let inst = fx . bcx . func . layout . next_inst ( nop_inst ) . unwrap ( ) ;
fx . bcx . func . layout . remove_inst ( nop_inst ) ;
2018-07-14 04:59:42 -05:00
fx . add_comment ( inst , format! ( " {:?} " , stmt ) ) ;
2018-07-14 09:39:49 -05:00
Ok ( ( ) )
2018-06-17 11:05:11 -05:00
}
2018-07-18 08:17:22 -05:00
macro_rules ! binop_match {
( @ single $fx :expr , $bug_fmt :expr , $var :expr , $lhs :expr , $rhs :expr , bug ) = > {
bug! ( " bin op {} on {} lhs: {:?} rhs: {:?} " , stringify! ( $var ) , $bug_fmt , $lhs , $rhs )
} ;
( @ single $fx :expr , $bug_fmt :expr , $var :expr , $lhs :expr , $rhs :expr , icmp ( $cc :ident ) ) = > { {
let b = $fx . bcx . ins ( ) . icmp ( IntCC ::$cc , $lhs , $rhs ) ;
$fx . bcx . ins ( ) . bint ( types ::I8 , b )
} } ;
( @ single $fx :expr , $bug_fmt :expr , $var :expr , $lhs :expr , $rhs :expr , $name :ident ) = > {
$fx . bcx . ins ( ) . $name ( $lhs , $rhs )
} ;
(
$fx :expr , $bin_op :expr , $signed :expr , $lhs :expr , $rhs :expr , $bug_fmt :expr ;
$(
$var :ident ( $sign :pat ) $name :tt $( ( $next :tt ) ) ? ;
) *
) = > {
match ( $bin_op , $signed ) {
$(
( BinOp ::$var , $sign ) = > binop_match! ( @ single $fx , $bug_fmt , $var , $lhs , $rhs , $name $( ( $next ) ) ? ) ,
) *
}
}
}
2018-06-30 09:38:49 -05:00
fn trans_int_binop < ' a , ' tcx : ' a > ( fx : & mut FunctionCx < ' a , ' tcx > , bin_op : BinOp , lhs : Value , rhs : Value , ty : Ty < ' tcx > , signed : bool , _checked : bool ) -> CValue < ' tcx > {
2018-07-18 08:17:22 -05:00
let res = binop_match! {
fx , bin_op , signed , lhs , rhs , " non ptr " ;
Add ( _ ) iadd ;
Sub ( _ ) isub ;
Mul ( _ ) imul ;
Div ( false ) udiv ;
Div ( true ) sdiv ;
Rem ( false ) urem ;
Rem ( true ) srem ;
BitXor ( _ ) bxor ;
BitAnd ( _ ) band ;
BitOr ( _ ) bor ;
Shl ( _ ) ishl ;
Shr ( false ) ushr ;
Shr ( true ) sshr ;
Eq ( _ ) icmp ( Equal ) ;
Lt ( false ) icmp ( UnsignedLessThan ) ;
Lt ( true ) icmp ( SignedLessThan ) ;
Le ( false ) icmp ( UnsignedLessThanOrEqual ) ;
Le ( true ) icmp ( SignedLessThanOrEqual ) ;
Ne ( _ ) icmp ( NotEqual ) ;
Ge ( false ) icmp ( UnsignedGreaterThanOrEqual ) ;
Ge ( true ) icmp ( SignedGreaterThanOrEqual ) ;
Gt ( false ) icmp ( UnsignedGreaterThan ) ;
Gt ( true ) icmp ( SignedGreaterThan ) ;
Offset ( _ ) bug ;
2018-06-27 08:47:58 -05:00
} ;
2018-07-18 08:17:22 -05:00
// TODO: return correct value for checked binops
CValue ::ByVal ( res , fx . layout_of ( ty ) )
}
fn trans_ptr_binop < ' a , ' tcx : ' a > ( fx : & mut FunctionCx < ' a , ' tcx > , bin_op : BinOp , lhs : Value , rhs : Value , ty : Ty < ' tcx > , _checked : bool ) -> CValue < ' tcx > {
let res = binop_match! {
fx , bin_op , false , lhs , rhs , " ptr " ;
Add ( _ ) bug ;
Sub ( _ ) bug ;
Mul ( _ ) bug ;
Div ( _ ) bug ;
Rem ( _ ) bug ;
BitXor ( _ ) bug ;
BitAnd ( _ ) bug ;
BitOr ( _ ) bug ;
Shl ( _ ) bug ;
Shr ( _ ) bug ;
Eq ( _ ) icmp ( Equal ) ;
Lt ( _ ) icmp ( UnsignedLessThan ) ;
Le ( _ ) icmp ( UnsignedLessThanOrEqual ) ;
Ne ( _ ) icmp ( NotEqual ) ;
Ge ( _ ) icmp ( UnsignedGreaterThanOrEqual ) ;
Gt ( _ ) icmp ( UnsignedGreaterThan ) ;
Offset ( _ ) iadd ;
} ;
2018-06-27 08:47:58 -05:00
// TODO: return correct value for checked binops
CValue ::ByVal ( res , fx . layout_of ( ty ) )
}
2018-07-19 12:33:42 -05:00
pub fn trans_place < ' a , ' tcx : ' a > ( fx : & mut FunctionCx < ' a , ' tcx > , place : & Place < ' tcx > ) -> CPlace < ' tcx > {
2018-06-17 11:05:11 -05:00
match place {
2018-06-20 08:15:28 -05:00
Place ::Local ( local ) = > fx . get_local_place ( * local ) ,
2018-07-18 04:55:32 -05:00
Place ::Static ( static_ ) = > unimplemented! ( " static place {:?} ty {:?} " , static_ . def_id , static_ . ty ) ,
2018-06-17 11:05:11 -05:00
Place ::Projection ( projection ) = > {
2018-06-23 11:26:54 -05:00
let base = trans_place ( fx , & projection . base ) ;
2018-06-17 11:05:11 -05:00
match projection . elem {
2018-06-23 11:54:15 -05:00
ProjectionElem ::Deref = > {
2018-06-26 12:44:19 -05:00
CPlace ::Addr ( base . to_cvalue ( fx ) . load_value ( fx ) , fx . layout_of ( place . ty ( & * fx . mir , fx . tcx ) . to_ty ( fx . tcx ) ) )
2018-06-23 11:54:15 -05:00
}
2018-06-30 09:38:49 -05:00
ProjectionElem ::Field ( field , _ty ) = > {
2018-06-26 12:44:19 -05:00
base . place_field ( fx , field )
2018-06-23 11:26:54 -05:00
}
2018-07-18 04:55:32 -05:00
ProjectionElem ::Index ( local ) = > unimplemented! ( " projection index {:?} {:?} " , projection . base , local ) ,
ProjectionElem ::ConstantIndex { offset , min_length : _ , from_end : false } = > unimplemented! ( " projection const index {:?} offset {:?} not from end " , projection . base , offset ) ,
ProjectionElem ::ConstantIndex { offset , min_length : _ , from_end : true } = > unimplemented! ( " projection const index {:?} offset {:?} from end " , projection . base , offset ) ,
ProjectionElem ::Subslice { from , to } = > unimplemented! ( " projection subslice {:?} from {} to {} " , projection . base , from , to ) ,
2018-06-30 09:38:49 -05:00
ProjectionElem ::Downcast ( _adt_def , variant ) = > {
2018-06-26 12:44:19 -05:00
base . downcast_variant ( fx , variant )
2018-06-17 11:05:11 -05:00
}
}
}
}
}
2018-07-19 12:33:42 -05:00
pub fn trans_operand < ' a , ' tcx > ( fx : & mut FunctionCx < ' a , ' tcx > , operand : & Operand < ' tcx > ) -> CValue < ' tcx > {
2018-06-17 11:05:11 -05:00
match operand {
2018-06-18 11:39:07 -05:00
Operand ::Move ( place ) |
2018-06-20 08:15:28 -05:00
Operand ::Copy ( place ) = > {
let cplace = trans_place ( fx , place ) ;
cplace . to_cvalue ( fx )
} ,
2018-06-17 11:05:11 -05:00
Operand ::Constant ( const_ ) = > {
2018-07-14 09:45:20 -05:00
::constant ::trans_constant ( fx , const_ )
2018-06-17 11:05:11 -05:00
}
}
}