auto merge of #11538 : eddyb/rust/llvm-attributes, r=alexcrichton
This commit is contained in:
commit
faa0b5aa61
@ -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
|
||||
}
|
||||
@ -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 };
|
||||
@ -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);
|
||||
@ -582,11 +592,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())
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -917,7 +924,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)
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -2533,13 +2541,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
|
||||
}
|
||||
@ -2571,7 +2579,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)
|
||||
@ -2975,7 +2983,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);
|
||||
})
|
||||
)
|
||||
|
@ -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);
|
||||
|
||||
@ -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));
|
||||
|
@ -596,7 +596,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;
|
||||
}
|
||||
|
||||
|
@ -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" => {
|
||||
|
Loading…
Reference in New Issue
Block a user