@@ -538,8 +538,8 @@ pub fn compare_scalar_values<'a>(
538538 // We don't need to do actual comparisons for nil.
539539 // () == () holds but () < () does not.
540540 match op {
541- ast:: BiEq | ast:: BiLe | ast:: BiGe => return C_i1 ( cx. ccx ( ) , true ) ,
542- ast:: BiNe | ast:: BiLt | ast:: BiGt => return C_i1 ( cx. ccx ( ) , false ) ,
541+ ast:: BiEq | ast:: BiLe | ast:: BiGe => return C_bool ( cx. ccx ( ) , true ) ,
542+ ast:: BiNe | ast:: BiLt | ast:: BiGt => return C_bool ( cx. ccx ( ) , false ) ,
543543 // refinements would be nice
544544 _ => die ( cx)
545545 }
@@ -958,10 +958,42 @@ pub fn need_invoke(bcx: &Block) -> bool {
958958
959959pub fn load_if_immediate ( cx : & Block , v : ValueRef , t : ty:: t ) -> ValueRef {
960960 let _icx = push_ctxt ( "load_if_immediate" ) ;
961- if type_is_immediate ( cx. ccx ( ) , t) { return Load ( cx, v) ; }
961+ if type_is_immediate ( cx. ccx ( ) , t) { return load_ty ( cx, v, t ) ; }
962962 return v;
963963}
964964
965+ pub fn load_ty ( cx : & Block , ptr : ValueRef , t : ty:: t ) -> ValueRef {
966+ /*!
967+ * Helper for loading values from memory. Does the necessary conversion if
968+ * the in-memory type differs from the type used for SSA values. Also
969+ * handles various special cases where the type gives us better information
970+ * about what we are loading.
971+ */
972+ if type_is_zero_size ( cx. ccx ( ) , t) {
973+ C_undef ( type_of:: type_of ( cx. ccx ( ) , t) )
974+ } else if ty:: type_is_bool ( t) {
975+ Trunc ( cx, LoadRangeAssert ( cx, ptr, 0 , 2 , lib:: llvm:: False ) , Type :: i1 ( cx. ccx ( ) ) )
976+ } else if ty:: type_is_char ( t) {
977+ // a char is a unicode codepoint, and so takes values from 0
978+ // to 0x10FFFF inclusive only.
979+ LoadRangeAssert ( cx, ptr, 0 , 0x10FFFF + 1 , lib:: llvm:: False )
980+ } else {
981+ Load ( cx, ptr)
982+ }
983+ }
984+
985+ pub fn store_ty ( cx : & Block , v : ValueRef , dst : ValueRef , t : ty:: t ) {
986+ /*!
987+ * Helper for storing values in memory. Does the necessary conversion if
988+ * the in-memory type differs from the type used for SSA values.
989+ */
990+ if ty:: type_is_bool ( t) {
991+ Store ( cx, ZExt ( cx, v, Type :: i8 ( cx. ccx ( ) ) ) , dst) ;
992+ } else {
993+ Store ( cx, v, dst) ;
994+ } ;
995+ }
996+
965997pub fn ignore_lhs ( _bcx : & Block , local : & ast:: Local ) -> bool {
966998 match local. pat . node {
967999 ast:: PatWild => true , _ => false
@@ -1013,7 +1045,7 @@ pub fn call_memcpy(cx: &Block, dst: ValueRef, src: ValueRef, n_bytes: ValueRef,
10131045 let dst_ptr = PointerCast ( cx, dst, Type :: i8p ( ccx) ) ;
10141046 let size = IntCast ( cx, n_bytes, ccx. int_type ) ;
10151047 let align = C_i32 ( ccx, align as i32 ) ;
1016- let volatile = C_i1 ( ccx, false ) ;
1048+ let volatile = C_bool ( ccx, false ) ;
10171049 Call ( cx, memcpy, [ dst_ptr, src_ptr, size, align, volatile] , [ ] ) ;
10181050}
10191051
@@ -1058,7 +1090,7 @@ fn memzero(b: &Builder, llptr: ValueRef, ty: Type) {
10581090 let llzeroval = C_u8 ( ccx, 0 ) ;
10591091 let size = machine:: llsize_of ( ccx, ty) ;
10601092 let align = C_i32 ( ccx, llalign_of_min ( ccx, ty) as i32 ) ;
1061- let volatile = C_i1 ( ccx, false ) ;
1093+ let volatile = C_bool ( ccx, false ) ;
10621094 b. call ( llintrinsicfn, [ llptr, llzeroval, size, align, volatile] , [ ] ) ;
10631095}
10641096
@@ -1282,9 +1314,14 @@ fn copy_args_to_allocas<'a>(fcx: &FunctionContext<'a>,
12821314// Ties up the llstaticallocas -> llloadenv -> lltop edges,
12831315// and builds the return block.
12841316pub fn finish_fn < ' a > ( fcx : & ' a FunctionContext < ' a > ,
1285- last_bcx : & ' a Block < ' a > ) {
1317+ last_bcx : & ' a Block < ' a > ,
1318+ retty : ty:: t ) {
12861319 let _icx = push_ctxt ( "finish_fn" ) ;
12871320
1321+ // This shouldn't need to recompute the return type,
1322+ // as new_fn_ctxt did it already.
1323+ let substd_retty = retty. substp ( fcx. ccx . tcx ( ) , fcx. param_substs ) ;
1324+
12881325 let ret_cx = match fcx. llreturn . get ( ) {
12891326 Some ( llreturn) => {
12901327 if !last_bcx. terminated . get ( ) {
@@ -1294,13 +1331,13 @@ pub fn finish_fn<'a>(fcx: &'a FunctionContext<'a>,
12941331 }
12951332 None => last_bcx
12961333 } ;
1297- build_return_block ( fcx, ret_cx) ;
1334+ build_return_block ( fcx, ret_cx, substd_retty ) ;
12981335 debuginfo:: clear_source_location ( fcx) ;
12991336 fcx. cleanup ( ) ;
13001337}
13011338
13021339// Builds the return block for a function.
1303- pub fn build_return_block ( fcx : & FunctionContext , ret_cx : & Block ) {
1340+ pub fn build_return_block ( fcx : & FunctionContext , ret_cx : & Block , retty : ty :: t ) {
13041341 // Return the value if this function immediate; otherwise, return void.
13051342 if fcx. llretptr . get ( ) . is_none ( ) || fcx. caller_expects_out_pointer {
13061343 return RetVoid ( ret_cx) ;
@@ -1318,13 +1355,16 @@ pub fn build_return_block(fcx: &FunctionContext, ret_cx: &Block) {
13181355 retptr. erase_from_parent ( ) ;
13191356 }
13201357
1321- retval
1358+ if ty:: type_is_bool ( retty) {
1359+ Trunc ( ret_cx, retval, Type :: i1 ( fcx. ccx ) )
1360+ } else {
1361+ retval
1362+ }
13221363 }
13231364 // Otherwise, load the return value from the ret slot
1324- None => Load ( ret_cx, fcx. llretptr . get ( ) . unwrap ( ) )
1365+ None => load_ty ( ret_cx, fcx. llretptr . get ( ) . unwrap ( ) , retty )
13251366 } ;
13261367
1327-
13281368 Ret ( ret_cx, retval) ;
13291369}
13301370
@@ -1422,7 +1462,7 @@ pub fn trans_closure(ccx: &CrateContext,
14221462 }
14231463
14241464 // Insert the mandatory first few basic blocks before lltop.
1425- finish_fn( & fcx, bcx) ;
1465+ finish_fn( & fcx, bcx, output_type ) ;
14261466}
14271467
14281468// trans_fn: creates an LLVM function corresponding to a source language
@@ -1512,7 +1552,7 @@ fn trans_enum_variant_or_tuple_like_struct(ccx: &CrateContext,
15121552 }
15131553 }
15141554
1515- finish_fn( & fcx, bcx) ;
1555+ finish_fn( & fcx, bcx, result_ty ) ;
15161556}
15171557
15181558fn trans_enum_def( ccx: & CrateContext , enum_definition: & ast:: EnumDef ,
0 commit comments