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