@@ -959,10 +959,42 @@ pub fn need_invoke(bcx: &Block) -> bool {
959959
960960pub fn load_if_immediate ( cx : & Block , v : ValueRef , t : ty:: t ) -> ValueRef {
961961 let _icx = push_ctxt ( "load_if_immediate" ) ;
962- if type_is_immediate ( cx. ccx ( ) , t) { return Load ( cx, v) ; }
962+ if type_is_immediate ( cx. ccx ( ) , t) { return load_ty ( cx, v, t ) ; }
963963 return v;
964964}
965965
966+ pub fn load_ty ( cx : & Block , ptr : ValueRef , t : ty:: t ) -> ValueRef {
967+ /*!
968+ * Helper for loading values from memory. Does the necessary conversion if
969+ * the in-memory type differs from the type used for SSA values. Also
970+ * handles various special cases where the type gives us better information
971+ * about what we are loading.
972+ */
973+ if type_is_zero_size ( cx. ccx ( ) , t) {
974+ C_undef ( type_of:: type_of ( cx. ccx ( ) , t) )
975+ } else if ty:: type_is_bool ( t) {
976+ Trunc ( cx, LoadRangeAssert ( cx, ptr, 0 , 2 , lib:: llvm:: False ) , Type :: i1 ( cx. ccx ( ) ) )
977+ } else if ty:: type_is_char ( t) {
978+ // a char is a unicode codepoint, and so takes values from 0
979+ // to 0x10FFFF inclusive only.
980+ LoadRangeAssert ( cx, ptr, 0 , 0x10FFFF + 1 , lib:: llvm:: False )
981+ } else {
982+ Load ( cx, ptr)
983+ }
984+ }
985+
986+ pub fn store_ty ( cx : & Block , v : ValueRef , dst : ValueRef , t : ty:: t ) {
987+ /*!
988+ * Helper for storing values in memory. Does the necessary conversion if
989+ * the in-memory type differs from the type used for SSA values.
990+ */
991+ if ty:: type_is_bool ( t) {
992+ Store ( cx, ZExt ( cx, v, Type :: i8 ( cx. ccx ( ) ) ) , dst) ;
993+ } else {
994+ Store ( cx, v, dst) ;
995+ } ;
996+ }
997+
966998pub fn ignore_lhs ( _bcx : & Block , local : & ast:: Local ) -> bool {
967999 match local. pat . node {
9681000 ast:: PatWild => true , _ => false
@@ -1285,9 +1317,14 @@ fn copy_args_to_allocas<'a>(fcx: &FunctionContext<'a>,
12851317// Ties up the llstaticallocas -> llloadenv -> lltop edges,
12861318// and builds the return block.
12871319pub fn finish_fn < ' a > ( fcx : & ' a FunctionContext < ' a > ,
1288- last_bcx : & ' a Block < ' a > ) {
1320+ last_bcx : & ' a Block < ' a > ,
1321+ retty : ty:: t ) {
12891322 let _icx = push_ctxt ( "finish_fn" ) ;
12901323
1324+ // This shouldn't need to recompute the return type,
1325+ // as new_fn_ctxt did it already.
1326+ let substd_retty = retty. substp ( fcx. ccx . tcx ( ) , fcx. param_substs ) ;
1327+
12911328 let ret_cx = match fcx. llreturn . get ( ) {
12921329 Some ( llreturn) => {
12931330 if !last_bcx. terminated . get ( ) {
@@ -1297,13 +1334,13 @@ pub fn finish_fn<'a>(fcx: &'a FunctionContext<'a>,
12971334 }
12981335 None => last_bcx
12991336 } ;
1300- build_return_block ( fcx, ret_cx) ;
1337+ build_return_block ( fcx, ret_cx, substd_retty ) ;
13011338 debuginfo:: clear_source_location ( fcx) ;
13021339 fcx. cleanup ( ) ;
13031340}
13041341
13051342// Builds the return block for a function.
1306- pub fn build_return_block ( fcx : & FunctionContext , ret_cx : & Block ) {
1343+ pub fn build_return_block ( fcx : & FunctionContext , ret_cx : & Block , retty : ty :: t ) {
13071344 // Return the value if this function immediate; otherwise, return void.
13081345 if fcx. llretptr . get ( ) . is_none ( ) || fcx. caller_expects_out_pointer {
13091346 return RetVoid ( ret_cx) ;
@@ -1321,13 +1358,16 @@ pub fn build_return_block(fcx: &FunctionContext, ret_cx: &Block) {
13211358 retptr. erase_from_parent ( ) ;
13221359 }
13231360
1324- retval
1361+ if ty:: type_is_bool ( retty) {
1362+ Trunc ( ret_cx, retval, Type :: i1 ( fcx. ccx ) )
1363+ } else {
1364+ retval
1365+ }
13251366 }
13261367 // Otherwise, load the return value from the ret slot
1327- None => Load ( ret_cx, fcx. llretptr . get ( ) . unwrap ( ) )
1368+ None => load_ty ( ret_cx, fcx. llretptr . get ( ) . unwrap ( ) , retty )
13281369 } ;
13291370
1330-
13311371 Ret ( ret_cx, retval) ;
13321372}
13331373
@@ -1429,7 +1469,7 @@ pub fn trans_closure(ccx: &CrateContext,
14291469 }
14301470
14311471 // Insert the mandatory first few basic blocks before lltop.
1432- finish_fn( & fcx, bcx) ;
1472+ finish_fn( & fcx, bcx, output_type ) ;
14331473}
14341474
14351475// trans_fn: creates an LLVM function corresponding to a source language
@@ -1521,7 +1561,7 @@ fn trans_enum_variant_or_tuple_like_struct(ccx: &CrateContext,
15211561 }
15221562 }
15231563
1524- finish_fn( & fcx, bcx) ;
1564+ finish_fn( & fcx, bcx, result_ty ) ;
15251565}
15261566
15271567fn trans_enum_def( ccx: & CrateContext , enum_definition: & ast:: EnumDef ,
0 commit comments