From a543ed6caa6c35f1ec55ed02256f6c62078a23e8 Mon Sep 17 00:00:00 2001 From: Daniel Micay Date: Tue, 10 Sep 2013 14:28:59 -0400 Subject: [PATCH] add sret + noalias to the out pointer parameter This brings Rust in line with how `clang` handles return pointers. Example: pub fn bar() -> [uint, .. 8] { let a = [0, .. 8]; a } Before: ; Function Attrs: nounwind uwtable define void @_ZN3bar17ha4635c6f704bfa334v0.0E([8 x i64]* nocapture, { i64, %tydesc*, i8*, i8*, i8 }* nocapture readnone) #1 { "function top level": %a = alloca [8 x i64], align 8 %2 = bitcast [8 x i64]* %a to i8* call void @llvm.memset.p0i8.i64(i8* %2, i8 0, i64 64, i32 8, i1 false) %3 = bitcast [8 x i64]* %0 to i8* call void @llvm.memcpy.p0i8.p0i8.i64(i8* %3, i8* %2, i64 64, i32 8, i1 false) ret void } After: ; Function Attrs: nounwind uwtable define void @_ZN3bar17ha4635c6f704bfa334v0.0E([8 x i64]* noalias nocapture sret, { i64, %tydesc*, i8*, i8*, i8 }* nocapture readnone) #1 { "function top level": %2 = bitcast [8 x i64]* %0 to i8* call void @llvm.memset.p0i8.i64(i8* %2, i8 0, i64 64, i32 8, i1 false) ret void } Closes #9072 Closes #7298 --- src/librustc/middle/trans/base.rs | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/src/librustc/middle/trans/base.rs b/src/librustc/middle/trans/base.rs index d964e89ab8e1..5ad2a5ad69e8 100644 --- a/src/librustc/middle/trans/base.rs +++ b/src/librustc/middle/trans/base.rs @@ -1618,6 +1618,18 @@ pub fn new_fn_ctxt_w_id(ccx: @mut CrateContext, } }; let uses_outptr = type_of::return_uses_outptr(ccx.tcx, substd_output_type); + + // The out pointer will never alias with any other pointers, as the object only exists at a + // language level after the call. It can also be tagged with SRet to indicate that it is + // guaranteed to point to a usable block of memory for the type. + if uses_outptr { + unsafe { + let outptr = llvm::LLVMGetParam(llfndecl, 0); + llvm::LLVMAddAttribute(outptr, lib::llvm::StructRetAttribute as c_uint); + llvm::LLVMAddAttribute(outptr, lib::llvm::NoAliasAttribute as c_uint); + } + } + let debug_context = debuginfo::create_function_debug_context(ccx, id, param_substs, llfndecl); let fcx = @mut FunctionContext {