1
Fork 0

auto merge of #9158 : thestinger/rust/extern, r=alexcrichton

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
This commit is contained in:
bors 2013-09-13 14:10:52 -07:00
commit 150b4ffccc
3 changed files with 10 additions and 10 deletions

View file

@ -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], 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); } 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) { pub fn AtomicFence(cx: @mut Block, order: AtomicOrdering) {

View file

@ -13,6 +13,7 @@ use lib::llvm::llvm;
use lib::llvm::{CallConv, AtomicBinOp, AtomicOrdering, AsmDialect}; use lib::llvm::{CallConv, AtomicBinOp, AtomicOrdering, AsmDialect};
use lib::llvm::{Opcode, IntPredicate, RealPredicate, False}; use lib::llvm::{Opcode, IntPredicate, RealPredicate, False};
use lib::llvm::{ValueRef, BasicBlockRef, BuilderRef, ModuleRef}; use lib::llvm::{ValueRef, BasicBlockRef, BuilderRef, ModuleRef};
use lib::llvm::{StructRetAttribute};
use middle::trans::base; use middle::trans::base;
use middle::trans::common::*; use middle::trans::common::*;
use middle::trans::machine::llalign_of_min; use middle::trans::machine::llalign_of_min;
@ -778,14 +779,9 @@ impl Builder {
pub fn call(&self, llfn: ValueRef, args: &[ValueRef]) -> ValueRef { pub fn call(&self, llfn: ValueRef, args: &[ValueRef]) -> ValueRef {
self.count_insn("call"); 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| { do args.as_imm_buf |ptr, len| {
unsafe { 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], pub fn call_with_conv(&self, llfn: ValueRef, args: &[ValueRef],
conv: CallConv) -> ValueRef { conv: CallConv, sret: bool) -> ValueRef {
self.count_insn("callwithconv"); self.count_insn("callwithconv");
unsafe { unsafe {
let v = llvm::LLVMBuildCall(self.llbuilder, llfn, vec::raw::to_ptr(args), let v = llvm::LLVMBuildCall(self.llbuilder, llfn, vec::raw::to_ptr(args),
args.len() as c_uint, noname()); args.len() as c_uint, noname());
lib::llvm::SetInstructionCallConv(v, conv); lib::llvm::SetInstructionCallConv(v, conv);
if sret {
let return_slot = 1;
llvm::LLVMAddInstrAttribute(v, return_slot, StructRetAttribute as c_uint);
}
v v
} }
} }

View file

@ -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, // If the function we just called does not use an outpointer,
// store the result into the rust outpointer. Cast the outpointer // store the result into the rust outpointer. Cast the outpointer