about summary refs log tree commit diff
diff options
context:
space:
mode:
authorSimonas Kazlauskas <git@kazlauskas.me>2015-12-19 16:51:52 +0200
committerSimonas Kazlauskas <git@kazlauskas.me>2016-01-06 13:57:52 +0200
commit20ec53a0d38588044f32e35074c81e60b8d3a6ad (patch)
tree862a0178669b72c682cacedb1c7a59276c076b0e
parent924bb1e5ebeab4189c3c48dabae4915825b097b0 (diff)
downloadrust-20ec53a0d38588044f32e35074c81e60b8d3a6ad.tar.gz
rust-20ec53a0d38588044f32e35074c81e60b8d3a6ad.zip
Fix ReturnPointer generation for void return types
Fixes #30480
-rw-r--r--src/librustc_trans/trans/mir/lvalue.rs23
1 files changed, 19 insertions, 4 deletions
diff --git a/src/librustc_trans/trans/mir/lvalue.rs b/src/librustc_trans/trans/mir/lvalue.rs
index b167633909a..f7245879e2d 100644
--- a/src/librustc_trans/trans/mir/lvalue.rs
+++ b/src/librustc_trans/trans/mir/lvalue.rs
@@ -18,6 +18,8 @@ use trans::build;
 use trans::common::{self, Block};
 use trans::debuginfo::DebugLoc;
 use trans::machine;
+use trans::type_of;
+use llvm;
 
 use std::ptr;
 
@@ -91,10 +93,23 @@ impl<'bcx, 'tcx> MirContext<'bcx, 'tcx> {
                     const_ty)
             },
             mir::Lvalue::ReturnPointer => {
-                let return_ty = bcx.monomorphize(&self.mir.return_ty);
-                let llval = fcx.get_ret_slot(bcx, return_ty, "return");
-                LvalueRef::new_sized(llval, LvalueTy::from_ty(return_ty.unwrap()))
-            }
+                let fn_return_ty = bcx.monomorphize(&self.mir.return_ty);
+                let return_ty = fn_return_ty.unwrap();
+                let llval = if !common::return_type_is_void(bcx.ccx(), return_ty) {
+                    fcx.get_ret_slot(bcx, fn_return_ty, "")
+                } else {
+                    // This is a void return; that is, there’s no place to store the value and
+                    // there cannot really be one (or storing into it doesn’t make sense, anyway).
+                    // Ergo, we return an undef ValueRef, so we do not have to special-case every
+                    // place using lvalues, and could use it the same way you use a regular
+                    // ReturnPointer LValue (i.e. store into it, load from it etc).
+                    let llty = type_of::type_of(bcx.ccx(), return_ty).ptr_to();
+                    unsafe {
+                        llvm::LLVMGetUndef(llty.to_ref())
+                    }
+                };
+                LvalueRef::new_sized(llval, LvalueTy::from_ty(return_ty))
+            },
             mir::Lvalue::Projection(ref projection) => {
                 let tr_base = self.trans_lvalue(bcx, &projection.base);
                 let projected_ty = tr_base.ty.projection_ty(tcx, &projection.elem);