Skip to content

Commit 3f99540

Browse files
committed
fix handling of function attributes
The `noalias` attributes were being set only on function definitions, not on all declarations. This is harmless for `noalias`, but prevented some optimization opportunities and is *not* harmless for other attributes like `sret` with ABI implications. Closes #9104
1 parent 917d3c2 commit 3f99540

File tree

5 files changed

+119
-75
lines changed

5 files changed

+119
-75
lines changed

src/librustc/middle/trans/base.rs

+96-56
Original file line numberDiff line numberDiff line change
@@ -188,14 +188,6 @@ pub fn decl_cdecl_fn(llmod: ModuleRef, name: &str, ty: Type) -> ValueRef {
188188
return decl_fn(llmod, name, lib::llvm::CCallConv, ty);
189189
}
190190

191-
// Only use this if you are going to actually define the function. It's
192-
// not valid to simply declare a function as internal.
193-
pub fn decl_internal_cdecl_fn(llmod: ModuleRef, name: &str, ty: Type) -> ValueRef {
194-
let llfn = decl_cdecl_fn(llmod, name, ty);
195-
lib::llvm::SetLinkage(llfn, lib::llvm::InternalLinkage);
196-
return llfn;
197-
}
198-
199191
pub fn get_extern_fn(externs: &mut ExternMap, llmod: ModuleRef, name: &str,
200192
cc: lib::llvm::CallConv, ty: Type) -> ValueRef {
201193
match externs.find_equiv(&name) {
@@ -204,7 +196,62 @@ pub fn get_extern_fn(externs: &mut ExternMap, llmod: ModuleRef, name: &str,
204196
}
205197
let f = decl_fn(llmod, name, cc, ty);
206198
externs.insert(name.to_owned(), f);
207-
return f;
199+
f
200+
}
201+
202+
pub fn get_extern_rust_fn(ccx: &mut CrateContext, inputs: &[ty::t], output: ty::t,
203+
name: &str) -> ValueRef {
204+
match ccx.externs.find_equiv(&name) {
205+
Some(n) => return *n,
206+
None => ()
207+
}
208+
let f = decl_rust_fn(ccx, inputs, output, name);
209+
ccx.externs.insert(name.to_owned(), f);
210+
f
211+
}
212+
213+
pub fn decl_rust_fn(ccx: &mut CrateContext, inputs: &[ty::t], output: ty::t,
214+
name: &str) -> ValueRef {
215+
let llfty = type_of_rust_fn(ccx, inputs, output);
216+
let llfn = decl_cdecl_fn(ccx.llmod, name, llfty);
217+
218+
match ty::get(output).sty {
219+
// `~` pointer return values never alias because ownership is transferred
220+
ty::ty_uniq(*) |
221+
ty::ty_evec(_, ty::vstore_uniq) => {
222+
unsafe {
223+
llvm::LLVMAddReturnAttribute(llfn, lib::llvm::NoAliasAttribute as c_uint);
224+
}
225+
}
226+
_ => ()
227+
}
228+
229+
let uses_outptr = type_of::return_uses_outptr(ccx.tcx, output);
230+
let offset = if uses_outptr { 2 } else { 1 };
231+
232+
for (i, &arg_ty) in inputs.iter().enumerate() {
233+
let llarg = unsafe { llvm::LLVMGetParam(llfn, (offset + i) as c_uint) };
234+
match ty::get(arg_ty).sty {
235+
// `~` pointer parameters never alias because ownership is transferred
236+
ty::ty_uniq(*) |
237+
ty::ty_evec(_, ty::vstore_uniq) |
238+
ty::ty_closure(ty::ClosureTy {sigil: ast::OwnedSigil, _}) => {
239+
unsafe {
240+
llvm::LLVMAddAttribute(llarg, lib::llvm::NoAliasAttribute as c_uint);
241+
}
242+
}
243+
_ => ()
244+
}
245+
}
246+
247+
llfn
248+
}
249+
250+
pub fn decl_internal_rust_fn(ccx: &mut CrateContext, inputs: &[ty::t], output: ty::t,
251+
name: &str) -> ValueRef {
252+
let llfn = decl_rust_fn(ccx, inputs, output, name);
253+
lib::llvm::SetLinkage(llfn, lib::llvm::InternalLinkage);
254+
llfn
208255
}
209256

210257
pub fn get_extern_const(externs: &mut ExternMap, llmod: ModuleRef,
@@ -808,19 +855,25 @@ pub fn null_env_ptr(ccx: &CrateContext) -> ValueRef {
808855
C_null(Type::opaque_box(ccx).ptr_to())
809856
}
810857
811-
pub fn trans_external_path(ccx: &mut CrateContext, did: ast::DefId, t: ty::t)
812-
-> ValueRef {
858+
pub fn trans_external_path(ccx: &mut CrateContext, did: ast::DefId, t: ty::t) -> ValueRef {
813859
let name = csearch::get_symbol(ccx.sess.cstore, did);
814860
match ty::get(t).sty {
815-
ty::ty_bare_fn(_) | ty::ty_closure(_) => {
816-
let llty = type_of_fn_from_ty(ccx, t);
817-
return get_extern_fn(&mut ccx.externs, ccx.llmod, name,
818-
lib::llvm::CCallConv, llty);
819-
}
820-
_ => {
821-
let llty = type_of(ccx, t);
822-
return get_extern_const(&mut ccx.externs, ccx.llmod, name, llty);
823-
}
861+
ty::ty_bare_fn(ref f) => {
862+
if f.abis.is_rust() || f.abis.is_intrinsic() {
863+
return get_extern_rust_fn(ccx, f.sig.inputs, f.sig.output, name);
864+
} else {
865+
let llty = type_of_fn_from_ty(ccx, t);
866+
return get_extern_fn(&mut ccx.externs, ccx.llmod, name,
867+
lib::llvm::CCallConv, llty);
868+
}
869+
}
870+
ty::ty_closure(ref f) => {
871+
return get_extern_rust_fn(ccx, f.sig.inputs, f.sig.output, name);
872+
}
873+
_ => {
874+
let llty = type_of(ccx, t);
875+
return get_extern_const(&mut ccx.externs, ccx.llmod, name, llty);
876+
}
824877
};
825878
}
826879
@@ -1692,8 +1745,7 @@ pub fn new_fn_ctxt(ccx: @mut CrateContext,
16921745
// field of the fn_ctxt with
16931746
pub fn create_llargs_for_fn_args(cx: @mut FunctionContext,
16941747
self_arg: self_arg,
1695-
args: &[ast::arg],
1696-
arg_tys: &[ty::t])
1748+
args: &[ast::arg])
16971749
-> ~[ValueRef] {
16981750
let _icx = push_ctxt("create_llargs_for_fn_args");
16991751

@@ -1711,23 +1763,7 @@ pub fn create_llargs_for_fn_args(cx: @mut FunctionContext,
17111763
// Return an array containing the ValueRefs that we get from
17121764
// llvm::LLVMGetParam for each argument.
17131765
do vec::from_fn(args.len()) |i| {
1714-
let arg_n = cx.arg_pos(i);
1715-
let arg_ty = arg_tys[i];
1716-
let llarg = unsafe {llvm::LLVMGetParam(cx.llfn, arg_n as c_uint) };
1717-
1718-
match ty::get(arg_ty).sty {
1719-
// `~` pointer parameters never alias because ownership is transferred
1720-
ty::ty_uniq(*) |
1721-
ty::ty_evec(_, ty::vstore_uniq) |
1722-
ty::ty_closure(ty::ClosureTy {sigil: ast::OwnedSigil, _}) => {
1723-
unsafe {
1724-
llvm::LLVMAddAttribute(llarg, lib::llvm::NoAliasAttribute as c_uint);
1725-
}
1726-
}
1727-
_ => ()
1728-
}
1729-
1730-
llarg
1766+
unsafe { llvm::LLVMGetParam(cx.llfn, cx.arg_pos(i) as c_uint) }
17311767
}
17321768
}
17331769

@@ -1881,8 +1917,7 @@ pub fn trans_closure(ccx: @mut CrateContext,
18811917

18821918
// Set up arguments to the function.
18831919
let arg_tys = ty::ty_fn_args(node_id_type(bcx, id));
1884-
let raw_llargs = create_llargs_for_fn_args(fcx, self_arg,
1885-
decl.inputs, arg_tys);
1920+
let raw_llargs = create_llargs_for_fn_args(fcx, self_arg, decl.inputs);
18861921

18871922
// Set the fixed stack segment flag if necessary.
18881923
if attr::contains_name(attributes, "fixed_stack_segment") {
@@ -1946,18 +1981,6 @@ pub fn trans_fn(ccx: @mut CrateContext,
19461981
param_substs.repr(ccx.tcx));
19471982
let _icx = push_ctxt("trans_fn");
19481983
let output_type = ty::ty_fn_ret(ty::node_id_to_type(ccx.tcx, id));
1949-
1950-
match ty::get(output_type).sty {
1951-
// `~` pointer return values never alias because ownership is transferred
1952-
ty::ty_uniq(*) |
1953-
ty::ty_evec(_, ty::vstore_uniq) => {
1954-
unsafe {
1955-
llvm::LLVMAddReturnAttribute(llfndecl, lib::llvm::NoAliasAttribute as c_uint);
1956-
}
1957-
}
1958-
_ => ()
1959-
}
1960-
19611984
trans_closure(ccx,
19621985
path.clone(),
19631986
decl,
@@ -2105,7 +2128,7 @@ pub fn trans_enum_variant_or_tuple_like_struct<A:IdAndTy>(
21052128

21062129
let arg_tys = ty::ty_fn_args(ctor_ty);
21072130

2108-
let raw_llargs = create_llargs_for_fn_args(fcx, no_self, fn_args, arg_tys);
2131+
let raw_llargs = create_llargs_for_fn_args(fcx, no_self, fn_args);
21092132

21102133
let bcx = fcx.entry_bcx.unwrap();
21112134

@@ -2275,8 +2298,25 @@ pub fn register_fn(ccx: @mut CrateContext,
22752298
node_id: ast::NodeId,
22762299
node_type: ty::t)
22772300
-> ValueRef {
2278-
let llfty = type_of_fn_from_ty(ccx, node_type);
2279-
register_fn_llvmty(ccx, sp, sym, node_id, lib::llvm::CCallConv, llfty)
2301+
let f = match ty::get(node_type).sty {
2302+
ty::ty_bare_fn(ref f) => {
2303+
assert!(f.abis.is_rust() || f.abis.is_intrinsic());
2304+
f
2305+
}
2306+
_ => fail!("expected bare rust fn or an intrinsic")
2307+
};
2308+
2309+
let llfn = decl_rust_fn(ccx, f.sig.inputs, f.sig.output, sym);
2310+
ccx.item_symbols.insert(node_id, sym);
2311+
2312+
// FIXME #4404 android JNI hacks
2313+
let is_entry = is_entry_fn(&ccx.sess, node_id) && (!*ccx.sess.building_library ||
2314+
(*ccx.sess.building_library &&
2315+
ccx.sess.targ_cfg.os == session::OsAndroid));
2316+
if is_entry {
2317+
create_entry_wrapper(ccx, sp, llfn);
2318+
}
2319+
llfn
22802320
}
22812321

22822322
pub fn register_fn_llvmty(ccx: @mut CrateContext,

src/librustc/middle/trans/closure.rs

+5-3
Original file line numberDiff line numberDiff line change
@@ -381,16 +381,18 @@ pub fn trans_expr_fn(bcx: @mut Block,
381381

382382
let ccx = bcx.ccx();
383383
let fty = node_id_type(bcx, outer_id);
384-
385-
let llfnty = type_of_fn_from_ty(ccx, fty);
384+
let f = match ty::get(fty).sty {
385+
ty::ty_closure(ref f) => f,
386+
_ => fail!("expected closure")
387+
};
386388

387389
let sub_path = vec::append_one(bcx.fcx.path.clone(),
388390
path_name(special_idents::anon));
389391
// XXX: Bad copy.
390392
let s = mangle_internal_name_by_path_and_seq(ccx,
391393
sub_path.clone(),
392394
"expr_fn");
393-
let llfn = decl_internal_cdecl_fn(ccx.llmod, s, llfnty);
395+
let llfn = decl_internal_rust_fn(ccx, f.sig.inputs, f.sig.output, s);
394396

395397
// set an inline hint for all closures
396398
set_inline_hint(llfn);

src/librustc/middle/trans/foreign.rs

+7-10
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,6 @@ use middle::trans::cabi;
2121
use middle::trans::build::*;
2222
use middle::trans::builder::noname;
2323
use middle::trans::common::*;
24-
use middle::trans::llrepr::LlvmRepr;
2524
use middle::trans::type_of::*;
2625
use middle::trans::type_of;
2726
use middle::ty;
@@ -401,13 +400,12 @@ pub fn trans_rust_fn_with_foreign_abi(ccx: @mut CrateContext,
401400
special_idents::clownshoe_abi
402401
)));
403402

404-
// Compute the LLVM type that the function would have if it
405-
// were just a normal Rust function. This will be the type of
406-
// the wrappee fn.
407-
let llty = match ty::get(t).sty {
403+
// Compute the type that the function would have if it were just a
404+
// normal Rust function. This will be the type of the wrappee fn.
405+
let f = match ty::get(t).sty {
408406
ty::ty_bare_fn(ref f) => {
409407
assert!(!f.abis.is_rust() && !f.abis.is_intrinsic());
410-
type_of_rust_fn(ccx, f.sig.inputs, f.sig.output)
408+
f
411409
}
412410
_ => {
413411
ccx.sess.bug(fmt!("build_rust_fn: extern fn %s has ty %s, \
@@ -417,13 +415,12 @@ pub fn trans_rust_fn_with_foreign_abi(ccx: @mut CrateContext,
417415
}
418416
};
419417

420-
debug!("build_rust_fn: path=%s id=%? t=%s llty=%s",
418+
debug!("build_rust_fn: path=%s id=%? t=%s",
421419
path.repr(tcx),
422420
id,
423-
t.repr(tcx),
424-
llty.llrepr(ccx));
421+
t.repr(tcx));
425422

426-
let llfndecl = base::decl_internal_cdecl_fn(ccx.llmod, ps, llty);
423+
let llfndecl = base::decl_internal_rust_fn(ccx, f.sig.inputs, f.sig.output, ps);
427424
base::trans_fn(ccx,
428425
(*path).clone(),
429426
decl,

src/librustc/middle/trans/monomorphize.rs

+10-4
Original file line numberDiff line numberDiff line change
@@ -14,14 +14,13 @@ use driver::session;
1414
use lib::llvm::ValueRef;
1515
use middle::trans::base::{set_llvm_fn_attrs, set_inline_hint};
1616
use middle::trans::base::{trans_enum_variant,push_ctxt};
17-
use middle::trans::base::{trans_fn, decl_internal_cdecl_fn};
17+
use middle::trans::base::{trans_fn, decl_internal_rust_fn};
1818
use middle::trans::base::{get_item_val, no_self};
1919
use middle::trans::base;
2020
use middle::trans::common::*;
2121
use middle::trans::datum;
2222
use middle::trans::machine;
2323
use middle::trans::meth;
24-
use middle::trans::type_of::type_of_fn_from_ty;
2524
use middle::trans::type_of;
2625
use middle::trans::type_use;
2726
use middle::trans::intrinsic;
@@ -177,7 +176,14 @@ pub fn monomorphic_fn(ccx: @mut CrateContext,
177176
ty::subst_tps(ccx.tcx, substs, None, llitem_ty)
178177
}
179178
};
180-
let llfty = type_of_fn_from_ty(ccx, mono_ty);
179+
180+
let f = match ty::get(mono_ty).sty {
181+
ty::ty_bare_fn(ref f) => {
182+
assert!(f.abis.is_rust() || f.abis.is_intrinsic());
183+
f
184+
}
185+
_ => fail!("expected bare rust fn or an intrinsic")
186+
};
181187

182188
ccx.stats.n_monos += 1;
183189

@@ -200,7 +206,7 @@ pub fn monomorphic_fn(ccx: @mut CrateContext,
200206
debug!("monomorphize_fn mangled to %s", s);
201207

202208
let mk_lldecl = || {
203-
let lldecl = decl_internal_cdecl_fn(ccx.llmod, s, llfty);
209+
let lldecl = decl_internal_rust_fn(ccx, f.sig.inputs, f.sig.output, s);
204210
ccx.monomorphized.insert(hash_id, lldecl);
205211
lldecl
206212
};

src/librustc/middle/trans/reflect.rs

+1-2
Original file line numberDiff line numberDiff line change
@@ -293,8 +293,7 @@ impl Reflector {
293293
sub_path,
294294
"get_disr");
295295

296-
let llfty = type_of_rust_fn(ccx, [opaqueptrty], ty::mk_int());
297-
let llfdecl = decl_internal_cdecl_fn(ccx.llmod, sym, llfty);
296+
let llfdecl = decl_internal_rust_fn(ccx, [opaqueptrty], ty::mk_int(), sym);
298297
let fcx = new_fn_ctxt(ccx,
299298
~[],
300299
llfdecl,

0 commit comments

Comments
 (0)