Skip to content

Commit 3c31cf2

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 6bc48b6 commit 3c31cf2

File tree

5 files changed

+119
-80
lines changed

5 files changed

+119
-80
lines changed

src/librustc/middle/trans/base.rs

Lines changed: 96 additions & 61 deletions
Original file line numberDiff line numberDiff line change
@@ -174,6 +174,7 @@ impl<'self> Drop for StatRecorder<'self> {
174174
}
175175
}
176176

177+
// only use this for foreign function ABIs and glue, use `decl_rust_fn` for Rust functions
177178
pub fn decl_fn(llmod: ModuleRef, name: &str, cc: lib::llvm::CallConv, ty: Type) -> ValueRef {
178179
let llfn: ValueRef = do name.with_c_str |buf| {
179180
unsafe {
@@ -185,18 +186,12 @@ pub fn decl_fn(llmod: ModuleRef, name: &str, cc: lib::llvm::CallConv, ty: Type)
185186
return llfn;
186187
}
187188

189+
// only use this for foreign function ABIs and glue, use `decl_rust_fn` for Rust functions
188190
pub fn decl_cdecl_fn(llmod: ModuleRef, name: &str, ty: Type) -> ValueRef {
189191
return decl_fn(llmod, name, lib::llvm::CCallConv, ty);
190192
}
191193

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

211261
pub fn get_extern_const(externs: &mut ExternMap, llmod: ModuleRef,
@@ -809,33 +859,30 @@ pub fn null_env_ptr(ccx: &CrateContext) -> ValueRef {
809859
C_null(Type::opaque_box(ccx).ptr_to())
810860
}
811861
812-
pub fn trans_external_path(ccx: &mut CrateContext, did: ast::DefId, t: ty::t)
813-
-> ValueRef {
862+
pub fn trans_external_path(ccx: &mut CrateContext, did: ast::DefId, t: ty::t) -> ValueRef {
814863
let name = csearch::get_symbol(ccx.sess.cstore, did);
815864
match ty::get(t).sty {
816865
ty::ty_bare_fn(ref fn_ty) => {
817-
// Currently llvm_calling_convention triggers unimpl/bug on
818-
// Rust/RustIntrinsic, so those two are handled specially here.
819-
let cconv = match fn_ty.abis.for_arch(ccx.sess.targ_cfg.arch) {
820-
Some(Rust) | Some(RustIntrinsic) => lib::llvm::CCallConv,
866+
match fn_ty.abis.for_arch(ccx.sess.targ_cfg.arch) {
867+
Some(Rust) | Some(RustIntrinsic) => {
868+
get_extern_rust_fn(ccx, fn_ty.sig.inputs, fn_ty.sig.output, name)
869+
}
821870
Some(*) | None => {
822871
let c = foreign::llvm_calling_convention(ccx, fn_ty.abis);
823-
c.unwrap_or(lib::llvm::CCallConv)
872+
let cconv = c.unwrap_or(lib::llvm::CCallConv);
873+
let llty = type_of_fn_from_ty(ccx, t);
874+
get_extern_fn(&mut ccx.externs, ccx.llmod, name, cconv, llty)
824875
}
825-
};
826-
let llty = type_of_fn_from_ty(ccx, t);
827-
return get_extern_fn(&mut ccx.externs, ccx.llmod, name, cconv, llty);
876+
}
828877
}
829-
ty::ty_closure(_) => {
830-
let llty = type_of_fn_from_ty(ccx, t);
831-
return get_extern_fn(&mut ccx.externs, ccx.llmod, name,
832-
lib::llvm::CCallConv, llty);
878+
ty::ty_closure(ref f) => {
879+
get_extern_rust_fn(ccx, f.sig.inputs, f.sig.output, name)
833880
}
834881
_ => {
835882
let llty = type_of(ccx, t);
836-
return get_extern_const(&mut ccx.externs, ccx.llmod, name, llty);
883+
get_extern_const(&mut ccx.externs, ccx.llmod, name, llty)
837884
}
838-
};
885+
}
839886
}
840887
841888
pub fn invoke(bcx: @mut Block, llfn: ValueRef, llargs: ~[ValueRef],
@@ -1707,8 +1754,7 @@ pub fn new_fn_ctxt(ccx: @mut CrateContext,
17071754
// field of the fn_ctxt with
17081755
pub fn create_llargs_for_fn_args(cx: @mut FunctionContext,
17091756
self_arg: self_arg,
1710-
args: &[ast::arg],
1711-
arg_tys: &[ty::t])
1757+
args: &[ast::arg])
17121758
-> ~[ValueRef] {
17131759
let _icx = push_ctxt("create_llargs_for_fn_args");
17141760

@@ -1726,23 +1772,7 @@ pub fn create_llargs_for_fn_args(cx: @mut FunctionContext,
17261772
// Return an array containing the ValueRefs that we get from
17271773
// llvm::LLVMGetParam for each argument.
17281774
do vec::from_fn(args.len()) |i| {
1729-
let arg_n = cx.arg_pos(i);
1730-
let arg_ty = arg_tys[i];
1731-
let llarg = unsafe {llvm::LLVMGetParam(cx.llfn, arg_n as c_uint) };
1732-
1733-
match ty::get(arg_ty).sty {
1734-
// `~` pointer parameters never alias because ownership is transferred
1735-
ty::ty_uniq(*) |
1736-
ty::ty_evec(_, ty::vstore_uniq) |
1737-
ty::ty_closure(ty::ClosureTy {sigil: ast::OwnedSigil, _}) => {
1738-
unsafe {
1739-
llvm::LLVMAddAttribute(llarg, lib::llvm::NoAliasAttribute as c_uint);
1740-
}
1741-
}
1742-
_ => ()
1743-
}
1744-
1745-
llarg
1775+
unsafe { llvm::LLVMGetParam(cx.llfn, cx.arg_pos(i) as c_uint) }
17461776
}
17471777
}
17481778

@@ -1896,8 +1926,7 @@ pub fn trans_closure(ccx: @mut CrateContext,
18961926

18971927
// Set up arguments to the function.
18981928
let arg_tys = ty::ty_fn_args(node_id_type(bcx, id));
1899-
let raw_llargs = create_llargs_for_fn_args(fcx, self_arg,
1900-
decl.inputs, arg_tys);
1929+
let raw_llargs = create_llargs_for_fn_args(fcx, self_arg, decl.inputs);
19011930

19021931
// Set the fixed stack segment flag if necessary.
19031932
if attr::contains_name(attributes, "fixed_stack_segment") {
@@ -1961,18 +1990,6 @@ pub fn trans_fn(ccx: @mut CrateContext,
19611990
param_substs.repr(ccx.tcx));
19621991
let _icx = push_ctxt("trans_fn");
19631992
let output_type = ty::ty_fn_ret(ty::node_id_to_type(ccx.tcx, id));
1964-
1965-
match ty::get(output_type).sty {
1966-
// `~` pointer return values never alias because ownership is transferred
1967-
ty::ty_uniq(*) |
1968-
ty::ty_evec(_, ty::vstore_uniq) => {
1969-
unsafe {
1970-
llvm::LLVMAddReturnAttribute(llfndecl, lib::llvm::NoAliasAttribute as c_uint);
1971-
}
1972-
}
1973-
_ => ()
1974-
}
1975-
19761993
trans_closure(ccx,
19771994
path.clone(),
19781995
decl,
@@ -2120,7 +2137,7 @@ pub fn trans_enum_variant_or_tuple_like_struct<A:IdAndTy>(
21202137

21212138
let arg_tys = ty::ty_fn_args(ctor_ty);
21222139

2123-
let raw_llargs = create_llargs_for_fn_args(fcx, no_self, fn_args, arg_tys);
2140+
let raw_llargs = create_llargs_for_fn_args(fcx, no_self, fn_args);
21242141

21252142
let bcx = fcx.entry_bcx.unwrap();
21262143

@@ -2298,10 +2315,28 @@ pub fn register_fn(ccx: @mut CrateContext,
22982315
node_id: ast::NodeId,
22992316
node_type: ty::t)
23002317
-> ValueRef {
2301-
let llfty = type_of_fn_from_ty(ccx, node_type);
2302-
register_fn_llvmty(ccx, sp, sym, node_id, lib::llvm::CCallConv, llfty)
2318+
let f = match ty::get(node_type).sty {
2319+
ty::ty_bare_fn(ref f) => {
2320+
assert!(f.abis.is_rust() || f.abis.is_intrinsic());
2321+
f
2322+
}
2323+
_ => fail!("expected bare rust fn or an intrinsic")
2324+
};
2325+
2326+
let llfn = decl_rust_fn(ccx, f.sig.inputs, f.sig.output, sym);
2327+
ccx.item_symbols.insert(node_id, sym);
2328+
2329+
// FIXME #4404 android JNI hacks
2330+
let is_entry = is_entry_fn(&ccx.sess, node_id) && (!*ccx.sess.building_library ||
2331+
(*ccx.sess.building_library &&
2332+
ccx.sess.targ_cfg.os == session::OsAndroid));
2333+
if is_entry {
2334+
create_entry_wrapper(ccx, sp, llfn);
2335+
}
2336+
llfn
23032337
}
23042338

2339+
// only use this for foreign function ABIs and glue, use `register_fn` for Rust functions
23052340
pub fn register_fn_llvmty(ccx: @mut CrateContext,
23062341
sp: Span,
23072342
sym: ~str,

src/librustc/middle/trans/closure.rs

Lines changed: 5 additions & 3 deletions
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

Lines changed: 7 additions & 10 deletions
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;
@@ -406,13 +405,12 @@ pub fn trans_rust_fn_with_foreign_abi(ccx: @mut CrateContext,
406405
special_idents::clownshoe_abi
407406
)));
408407

409-
// Compute the LLVM type that the function would have if it
410-
// were just a normal Rust function. This will be the type of
411-
// the wrappee fn.
412-
let llty = match ty::get(t).sty {
408+
// Compute the type that the function would have if it were just a
409+
// normal Rust function. This will be the type of the wrappee fn.
410+
let f = match ty::get(t).sty {
413411
ty::ty_bare_fn(ref f) => {
414412
assert!(!f.abis.is_rust() && !f.abis.is_intrinsic());
415-
type_of_rust_fn(ccx, f.sig.inputs, f.sig.output)
413+
f
416414
}
417415
_ => {
418416
ccx.sess.bug(fmt!("build_rust_fn: extern fn %s has ty %s, \
@@ -422,13 +420,12 @@ pub fn trans_rust_fn_with_foreign_abi(ccx: @mut CrateContext,
422420
}
423421
};
424422

425-
debug!("build_rust_fn: path=%s id=%? t=%s llty=%s",
423+
debug!("build_rust_fn: path=%s id=%? t=%s",
426424
path.repr(tcx),
427425
id,
428-
t.repr(tcx),
429-
llty.llrepr(ccx));
426+
t.repr(tcx));
430427

431-
let llfndecl = base::decl_internal_cdecl_fn(ccx.llmod, ps, llty);
428+
let llfndecl = base::decl_internal_rust_fn(ccx, f.sig.inputs, f.sig.output, ps);
432429
base::trans_fn(ccx,
433430
(*path).clone(),
434431
decl,

src/librustc/middle/trans/monomorphize.rs

Lines changed: 10 additions & 4 deletions
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

Lines changed: 1 addition & 2 deletions
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)