Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add noalias and noreturn attributes in more cases. #11538

Merged
merged 1 commit into from
Jan 14, 2014
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
87 changes: 48 additions & 39 deletions src/librustc/middle/trans/base.rs
Original file line number Diff line number Diff line change
Expand Up @@ -177,32 +177,57 @@ impl<'a> Drop for StatRecorder<'a> {
}

// only use this for foreign function ABIs and glue, use `decl_rust_fn` for Rust functions
pub fn decl_fn(llmod: ModuleRef, name: &str, cc: lib::llvm::CallConv, ty: Type) -> ValueRef {
fn decl_fn(llmod: ModuleRef, name: &str, cc: lib::llvm::CallConv,
ty: Type, output: ty::t) -> ValueRef {
let llfn: ValueRef = name.with_c_str(|buf| {
unsafe {
llvm::LLVMGetOrInsertFunction(llmod, buf, ty.to_ref())
}
});

match ty::get(output).sty {
// functions returning bottom may unwind, but can never return normally
ty::ty_bot => {
unsafe {
llvm::LLVMAddFunctionAttr(llfn, lib::llvm::NoReturnAttribute as c_uint)
}
}
// `~` pointer return values never alias because ownership is transferred
// FIXME #6750 ~Trait cannot be directly marked as
// noalias because the actual object pointer is nested.
ty::ty_uniq(..) | // ty::ty_trait(_, _, ty::UniqTraitStore, _, _) |
ty::ty_vec(_, ty::vstore_uniq) | ty::ty_str(ty::vstore_uniq) => {
unsafe {
llvm::LLVMAddReturnAttribute(llfn, lib::llvm::NoAliasAttribute as c_uint);
}
}
_ => {}
}

lib::llvm::SetFunctionCallConv(llfn, cc);
// Function addresses in Rust are never significant, allowing functions to be merged.
lib::llvm::SetUnnamedAddr(llfn, true);
return llfn;

llfn
}

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

// only use this for foreign function ABIs and glue, use `get_extern_rust_fn` for Rust functions
pub fn get_extern_fn(externs: &mut ExternMap, llmod: ModuleRef, name: &str,
cc: lib::llvm::CallConv, ty: Type) -> ValueRef {
pub fn get_extern_fn(externs: &mut ExternMap, llmod: ModuleRef,
name: &str, cc: lib::llvm::CallConv,
ty: Type, output: ty::t) -> ValueRef {
match externs.find_equiv(&name) {
Some(n) => return *n,
None => ()
None => {}
}
let f = decl_fn(llmod, name, cc, ty);
let f = decl_fn(llmod, name, cc, ty, output);
externs.insert(name.to_owned(), f);
f
}
Expand Down Expand Up @@ -233,24 +258,7 @@ fn decl_rust_fn(ccx: &CrateContext,
output: ty::t,
name: &str) -> ValueRef {
let llfty = type_of_rust_fn(ccx, self_ty, inputs, output);
let llfn = decl_cdecl_fn(ccx.llmod, name, llfty);

match ty::get(output).sty {
// functions returning bottom may unwind, but can never return normally
ty::ty_bot => {
unsafe {
llvm::LLVMAddFunctionAttr(llfn, lib::llvm::NoReturnAttribute as c_uint)
}
}
// `~` pointer return values never alias because ownership is transferred
ty::ty_uniq(..) |
ty::ty_vec(_, ty::vstore_uniq) => {
unsafe {
llvm::LLVMAddReturnAttribute(llfn, lib::llvm::NoAliasAttribute as c_uint);
}
}
_ => ()
}
let llfn = decl_cdecl_fn(ccx.llmod, name, llfty, output);

let uses_outptr = type_of::return_uses_outptr(ccx, output);
let offset = if uses_outptr { 2 } else { 1 };
Expand All @@ -259,8 +267,10 @@ fn decl_rust_fn(ccx: &CrateContext,
let llarg = unsafe { llvm::LLVMGetParam(llfn, (offset + i) as c_uint) };
match ty::get(arg_ty).sty {
// `~` pointer parameters never alias because ownership is transferred
ty::ty_uniq(..) |
ty::ty_vec(_, ty::vstore_uniq) |
// FIXME #6750 ~Trait cannot be directly marked as
// noalias because the actual object pointer is nested.
ty::ty_uniq(..) | // ty::ty_trait(_, _, ty::UniqTraitStore, _, _) |
ty::ty_vec(_, ty::vstore_uniq) | ty::ty_str(ty::vstore_uniq) |
ty::ty_closure(ty::ClosureTy {sigil: ast::OwnedSigil, ..}) => {
unsafe {
llvm::LLVMAddAttribute(llarg, lib::llvm::NoAliasAttribute as c_uint);
Expand Down Expand Up @@ -584,11 +594,8 @@ pub fn get_res_dtor(ccx: @CrateContext,

{
let mut externs = ccx.externs.borrow_mut();
get_extern_fn(externs.get(),
ccx.llmod,
name,
lib::llvm::CCallConv,
llty)
get_extern_fn(externs.get(), ccx.llmod, name,
lib::llvm::CCallConv, llty, ty::mk_nil())
}
}
}
Expand Down Expand Up @@ -919,7 +926,8 @@ pub fn trans_external_path(ccx: &CrateContext, did: ast::DefId, t: ty::t) -> Val
let cconv = c.unwrap_or(lib::llvm::CCallConv);
let llty = type_of_fn_from_ty(ccx, None, t);
let mut externs = ccx.externs.borrow_mut();
get_extern_fn(externs.get(), ccx.llmod, name, cconv, llty)
get_extern_fn(externs.get(), ccx.llmod, name,
cconv, llty, fn_ty.sig.output)
}
}
}
Expand Down Expand Up @@ -2535,13 +2543,13 @@ pub fn register_fn_llvmty(ccx: @CrateContext,
sym: ~str,
node_id: ast::NodeId,
cc: lib::llvm::CallConv,
fn_ty: Type)
-> ValueRef {
fn_ty: Type,
output: ty::t) -> ValueRef {
debug!("register_fn_fuller creating fn for item {} with path {}",
node_id,
ast_map::path_to_str(item_path(ccx, &node_id), token::get_ident_interner()));

let llfn = decl_fn(ccx.llmod, sym, cc, fn_ty);
let llfn = decl_fn(ccx.llmod, sym, cc, fn_ty, output);
finish_register_fn(ccx, sp, sym, node_id, llfn);
llfn
}
Expand Down Expand Up @@ -2573,7 +2581,7 @@ pub fn create_entry_wrapper(ccx: @CrateContext,
let llfty = Type::func([ccx.int_type, Type::i8().ptr_to().ptr_to()],
&ccx.int_type);

let llfn = decl_cdecl_fn(ccx.llmod, "main", llfty);
let llfn = decl_cdecl_fn(ccx.llmod, "main", llfty, ty::mk_nil());
let llbb = "top".with_c_str(|buf| {
unsafe {
llvm::LLVMAppendBasicBlockInContext(ccx.llcx, llfn, buf)
Expand Down Expand Up @@ -2977,7 +2985,8 @@ pub fn p2i(ccx: &CrateContext, v: ValueRef) -> ValueRef {
macro_rules! ifn (
($intrinsics:ident, $name:expr, $args:expr, $ret:expr) => ({
let name = $name;
let f = decl_cdecl_fn(llmod, name, Type::func($args, &$ret));
// HACK(eddyb) dummy output type, shouln't affect anything.
let f = decl_cdecl_fn(llmod, name, Type::func($args, &$ret), ty::mk_nil());
$intrinsics.insert(name, f);
})
)
Expand Down
20 changes: 6 additions & 14 deletions src/librustc/middle/trans/foreign.rs
Original file line number Diff line number Diff line change
Expand Up @@ -150,11 +150,8 @@ pub fn register_foreign_item_fn(ccx: @CrateContext,
let llfn;
{
let mut externs = ccx.externs.borrow_mut();
llfn = base::get_extern_fn(externs.get(),
ccx.llmod,
lname,
cc,
llfn_ty);
llfn = base::get_extern_fn(externs.get(), ccx.llmod, lname,
cc, llfn_ty, tys.fn_sig.output);
};
add_argument_attributes(&tys, llfn);

Expand Down Expand Up @@ -417,19 +414,14 @@ pub fn register_rust_fn_with_foreign_abi(ccx: @CrateContext,
let tys = foreign_types_for_id(ccx, node_id);
let llfn_ty = lltype_for_fn_from_foreign_types(&tys);
let t = ty::node_id_to_type(ccx.tcx, node_id);
let cconv = match ty::get(t).sty {
let (cconv, output) = match ty::get(t).sty {
ty::ty_bare_fn(ref fn_ty) => {
let c = llvm_calling_convention(ccx, fn_ty.abis);
c.unwrap_or(lib::llvm::CCallConv)
(c.unwrap_or(lib::llvm::CCallConv), fn_ty.sig.output)
}
_ => lib::llvm::CCallConv
_ => fail!("expected bare fn in register_rust_fn_with_foreign_abi")
};
let llfn = base::register_fn_llvmty(ccx,
sp,
sym,
node_id,
cconv,
llfn_ty);
let llfn = base::register_fn_llvmty(ccx, sp, sym, node_id, cconv, llfn_ty, output);
add_argument_attributes(&tys, llfn);
debug!("register_rust_fn_with_foreign_abi(node_id={:?}, llfn_ty={}, llfn={})",
node_id, ccx.tn.type_to_str(llfn_ty), ccx.tn.val_to_str(llfn));
Expand Down
2 changes: 1 addition & 1 deletion src/librustc/middle/trans/glue.rs
Original file line number Diff line number Diff line change
Expand Up @@ -592,7 +592,7 @@ fn declare_generic_glue(ccx: &CrateContext, t: ty::t, llfnty: Type,
let fn_nm = mangle_internal_name_by_type_and_seq(ccx, t, (~"glue_" + name)).to_managed();
debug!("{} is for type {}", fn_nm, ppaux::ty_to_str(ccx.tcx, t));
note_unique_llvm_symbol(ccx, fn_nm);
let llfn = decl_cdecl_fn(ccx.llmod, fn_nm, llfnty);
let llfn = decl_cdecl_fn(ccx.llmod, fn_nm, llfnty, ty::mk_nil());
return llfn;
}

Expand Down
7 changes: 4 additions & 3 deletions src/librustc/middle/trans/intrinsic.rs
Original file line number Diff line number Diff line change
Expand Up @@ -431,9 +431,10 @@ pub fn trans_intrinsic(ccx: @CrateContext,
// native function. There should be a general in-language
// way to do this
let llfty = type_of_rust_fn(bcx.ccx(), None, [], ty::mk_nil());
let morestack_addr = decl_cdecl_fn(
bcx.ccx().llmod, "__morestack", llfty);
let morestack_addr = PointerCast(bcx, morestack_addr, Type::nil().ptr_to());
let morestack_addr = decl_cdecl_fn(bcx.ccx().llmod, "__morestack",
llfty, ty::mk_nil());
let morestack_addr = PointerCast(bcx, morestack_addr,
Type::nil().ptr_to());
Ret(bcx, morestack_addr);
}
"offset" => {
Expand Down