about summary refs log tree commit diff
diff options
context:
space:
mode:
authorDaniel Micay <danielmicay@gmail.com>2013-09-12 23:23:44 -0400
committerDaniel Micay <danielmicay@gmail.com>2013-09-13 12:34:25 -0400
commit1ac37d50c0096f13604c7ca249517b76ff1f1802 (patch)
tree291e2d02b264607b7008179fe0410b6c44290438
parent2bdf4af0120d61b7853eb09c630a01a0596add42 (diff)
downloadrust-1ac37d50c0096f13604c7ca249517b76ff1f1802.tar.gz
rust-1ac37d50c0096f13604c7ca249517b76ff1f1802.zip
set sret attribute as needed on call instructions
Since function pointers do not carry along the function attributes with
them in the type, this needs to be set on the call instruction itself.

Closes #9152
-rw-r--r--src/librustc/middle/trans/build.rs4
-rw-r--r--src/librustc/middle/trans/builder.rs14
-rw-r--r--src/librustc/middle/trans/foreign.rs2
3 files changed, 10 insertions, 10 deletions
diff --git a/src/librustc/middle/trans/build.rs b/src/librustc/middle/trans/build.rs
index acec33f7004..11458eda585 100644
--- a/src/librustc/middle/trans/build.rs
+++ b/src/librustc/middle/trans/build.rs
@@ -655,9 +655,9 @@ pub fn FastCall(cx: @mut Block, Fn: ValueRef, Args: &[ValueRef]) -> ValueRef {
 }
 
 pub fn CallWithConv(cx: @mut Block, Fn: ValueRef, Args: &[ValueRef],
-                    Conv: CallConv) -> ValueRef {
+                    Conv: CallConv, sret: bool) -> ValueRef {
     if cx.unreachable { return _UndefReturn(cx, Fn); }
-    B(cx).call_with_conv(Fn, Args, Conv)
+    B(cx).call_with_conv(Fn, Args, Conv, sret)
 }
 
 pub fn AtomicFence(cx: @mut Block, order: AtomicOrdering) {
diff --git a/src/librustc/middle/trans/builder.rs b/src/librustc/middle/trans/builder.rs
index 6a1acf68efa..349f14aefbc 100644
--- a/src/librustc/middle/trans/builder.rs
+++ b/src/librustc/middle/trans/builder.rs
@@ -13,6 +13,7 @@ use lib::llvm::llvm;
 use lib::llvm::{CallConv, AtomicBinOp, AtomicOrdering, AsmDialect};
 use lib::llvm::{Opcode, IntPredicate, RealPredicate, False};
 use lib::llvm::{ValueRef, BasicBlockRef, BuilderRef, ModuleRef};
+use lib::llvm::{StructRetAttribute};
 use middle::trans::base;
 use middle::trans::common::*;
 use middle::trans::machine::llalign_of_min;
@@ -778,14 +779,9 @@ impl Builder {
 
     pub fn call(&self, llfn: ValueRef, args: &[ValueRef]) -> ValueRef {
         self.count_insn("call");
-
-        debug!("Call(llfn=%s, args=%?)",
-               self.ccx.tn.val_to_str(llfn),
-               args.map(|arg| self.ccx.tn.val_to_str(*arg)));
-
         do args.as_imm_buf |ptr, len| {
             unsafe {
-            llvm::LLVMBuildCall(self.llbuilder, llfn, ptr, len as c_uint, noname())
+                llvm::LLVMBuildCall(self.llbuilder, llfn, ptr, len as c_uint, noname())
             }
         }
     }
@@ -801,12 +797,16 @@ impl Builder {
     }
 
     pub fn call_with_conv(&self, llfn: ValueRef, args: &[ValueRef],
-                        conv: CallConv) -> ValueRef {
+                         conv: CallConv, sret: bool) -> ValueRef {
         self.count_insn("callwithconv");
         unsafe {
             let v = llvm::LLVMBuildCall(self.llbuilder, llfn, vec::raw::to_ptr(args),
                                         args.len() as c_uint, noname());
             lib::llvm::SetInstructionCallConv(v, conv);
+            if sret {
+                let return_slot = 1;
+                llvm::LLVMAddInstrAttribute(v, return_slot, StructRetAttribute as c_uint);
+            }
             v
         }
     }
diff --git a/src/librustc/middle/trans/foreign.rs b/src/librustc/middle/trans/foreign.rs
index 26968ce4881..681852b3bf2 100644
--- a/src/librustc/middle/trans/foreign.rs
+++ b/src/librustc/middle/trans/foreign.rs
@@ -266,7 +266,7 @@ pub fn trans_native_call(bcx: @mut Block,
         }
     };
 
-    let llforeign_retval = CallWithConv(bcx, llfn, llargs_foreign, cc);
+    let llforeign_retval = CallWithConv(bcx, llfn, llargs_foreign, cc, fn_type.sret);
 
     // If the function we just called does not use an outpointer,
     // store the result into the rust outpointer. Cast the outpointer