Skip to content

Commit

Permalink
Add noalias and noreturn attributes in more cases.
Browse files Browse the repository at this point in the history
  • Loading branch information
eddyb committed Jan 14, 2014
1 parent 77eedda commit 8e2027a
Show file tree
Hide file tree
Showing 4 changed files with 59 additions and 57 deletions.
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

0 comments on commit 8e2027a

Please sign in to comment.