librustc: Implement a #[no_mangle] attribute to suppress name mangling. r=brson

This is very helpful for SDL, as SDL wants you to define a function named
`SDL_main`.
This commit is contained in:
Patrick Walton 2013-01-09 23:17:57 -08:00
parent 0c05a6c092
commit a0c2a9b743
7 changed files with 59 additions and 31 deletions

View File

@ -171,8 +171,7 @@ fn is_test_fn(i: @ast::item) -> bool {
}
fn is_ignored(cx: test_ctxt, i: @ast::item) -> bool {
let ignoreattrs = attr::find_attrs_by_name(/*bad*/copy i.attrs,
~"ignore");
let ignoreattrs = attr::find_attrs_by_name(i.attrs, "ignore");
let ignoreitems = attr::attr_metas(ignoreattrs);
let cfg_metas = vec::concat(vec::filter_map(ignoreitems,
|i| attr::get_meta_item_list(*i)));

View File

@ -147,8 +147,7 @@ fn visit_item(e: env, i: @ast::item) {
let cstore = e.cstore;
let mut already_added = false;
let link_args = attr::find_attrs_by_name(/*bad*/copy i.attrs,
~"link_args");
let link_args = attr::find_attrs_by_name(i.attrs, "link_args");
match fm.sort {
ast::named => {

View File

@ -329,8 +329,7 @@ impl ctxt {
for [allow, warn, deny, forbid].each |level| {
let level_name = level_to_str(*level);
let metas =
attr::attr_metas(attr::find_attrs_by_name(/*bad*/copy attrs,
level_name));
attr::attr_metas(attr::find_attrs_by_name(attrs, level_name));
for metas.each |meta| {
match /*bad*/copy meta.node {
ast::meta_list(_, metas) => {

View File

@ -76,7 +76,7 @@ use core::uint;
use std::map::HashMap;
use std::smallintmap;
use std::{map, time, list};
use syntax::ast_map::{path, path_mod, path_name};
use syntax::ast_map::{path, path_elt_to_str, path_mod, path_name};
use syntax::ast_util::{def_id_of_def, local_def, path_to_ident};
use syntax::attr;
use syntax::codemap::span;
@ -2086,28 +2086,44 @@ fn get_pair_fn_ty(llpairty: TypeRef) -> TypeRef {
fn register_fn(ccx: @crate_ctxt,
sp: span,
+path: path,
node_id: ast::node_id)
node_id: ast::node_id,
attrs: &[ast::attribute])
-> ValueRef {
let t = ty::node_id_to_type(ccx.tcx, node_id);
register_fn_full(ccx, sp, path, node_id, t)
register_fn_full(ccx, sp, path, node_id, attrs, t)
}
fn register_fn_full(ccx: @crate_ctxt, sp: span, +path: path,
node_id: ast::node_id, node_type: ty::t) -> ValueRef {
fn register_fn_full(ccx: @crate_ctxt,
sp: span,
+path: path,
node_id: ast::node_id,
attrs: &[ast::attribute],
node_type: ty::t)
-> ValueRef {
let llfty = type_of_fn_from_ty(ccx, node_type);
register_fn_fuller(ccx, sp, path, node_id, node_type,
register_fn_fuller(ccx, sp, path, node_id, attrs, node_type,
lib::llvm::CCallConv, llfty)
}
fn register_fn_fuller(ccx: @crate_ctxt, sp: span, +path: path,
node_id: ast::node_id, node_type: ty::t,
cc: lib::llvm::CallConv, llfty: TypeRef) -> ValueRef {
fn register_fn_fuller(ccx: @crate_ctxt,
sp: span,
+path: path,
node_id: ast::node_id,
attrs: &[ast::attribute],
node_type: ty::t,
cc: lib::llvm::CallConv,
llfty: TypeRef)
-> ValueRef {
debug!("register_fn_fuller creating fn for item %d with path %s",
node_id,
ast_map::path_to_str(path, ccx.sess.parse_sess.interner));
// XXX: Bad copy.
let ps: ~str = mangle_exported_name(ccx, copy path, node_type);
let ps = if attr::attrs_contains_name(attrs, "no_mangle") {
path_elt_to_str(path.last(), ccx.sess.parse_sess.interner)
} else {
mangle_exported_name(ccx, /*bad*/copy path, node_type)
};
// XXX: Bad copy.
let llfn: ValueRef = decl_fn(ccx.llmod, copy ps, cc, llfty);
ccx.item_symbols.insert(node_id, ps);
@ -2281,9 +2297,13 @@ fn get_item_val(ccx: @crate_ctxt, id: ast::node_id) -> ValueRef {
}
ast::item_fn(_, purity, _, _) => {
let llfn = if purity != ast::extern_fn {
register_fn(ccx, i.span, my_path, i.id)
register_fn(ccx, i.span, my_path, i.id, i.attrs)
} else {
foreign::register_foreign_fn(ccx, i.span, my_path, i.id)
foreign::register_foreign_fn(ccx,
i.span,
my_path,
i.id,
i.attrs)
};
set_inline_hint_if_appr(/*bad*/copy i.attrs, llfn);
llfn
@ -2315,7 +2335,8 @@ fn get_item_val(ccx: @crate_ctxt, id: ast::node_id) -> ValueRef {
register_fn(ccx, ni.span,
vec::append(/*bad*/copy *pth,
~[path_name(ni.ident)]),
ni.id)
ni.id,
ni.attrs)
}
ast::foreign_item_const(*) => {
let typ = ty::node_id_to_type(ccx.tcx, ni.id);
@ -2366,7 +2387,7 @@ fn get_item_val(ccx: @crate_ctxt, id: ast::node_id) -> ValueRef {
path_name((*v).node.name)]);
llfn = match enm.node {
ast::item_enum(_, _) => {
register_fn(ccx, (*v).span, pth, id)
register_fn(ccx, (*v).span, pth, id, enm.attrs)
}
_ => fail ~"node_variant, shouldn't happen"
};
@ -2390,8 +2411,11 @@ fn get_item_val(ccx: @crate_ctxt, id: ast::node_id) -> ValueRef {
a non-tuple-like struct")
}
Some(ctor_id) => {
let llfn = register_fn(ccx, struct_item.span,
/*bad*/copy *struct_path, ctor_id);
let llfn = register_fn(ccx,
struct_item.span,
/*bad*/copy *struct_path,
ctor_id,
struct_item.attrs);
set_inline_hint(llfn);
llfn
}
@ -2416,7 +2440,7 @@ fn register_method(ccx: @crate_ctxt, id: ast::node_id, pth: @ast_map::path,
let mty = ty::node_id_to_type(ccx.tcx, id);
let pth = vec::append(/*bad*/copy *pth, ~[path_name((ccx.names)(~"meth")),
path_name(m.ident)]);
let llfn = register_fn_full(ccx, m.span, pth, id, mty);
let llfn = register_fn_full(ccx, m.span, pth, id, m.attrs, mty);
set_inline_hint_if_appr(/*bad*/copy m.attrs, llfn);
llfn
}

View File

@ -809,8 +809,7 @@ fn trans_foreign_mod(ccx: @crate_ctxt,
if abi != ast::foreign_abi_rust_intrinsic {
let llwrapfn = get_item_val(ccx, id);
let tys = c_stack_tys(ccx, id);
if attr::attrs_contains_name(/*bad*/copy foreign_item.attrs,
~"rust_stack") {
if attr::attrs_contains_name(foreign_item.attrs, "rust_stack") {
build_direct_fn(ccx, llwrapfn, *foreign_item, tys, cc);
} else {
let llshimfn = build_shim_fn(ccx, *foreign_item, tys, cc);
@ -1479,7 +1478,8 @@ fn trans_foreign_fn(ccx: @crate_ctxt, +path: ast_map::path,
fn register_foreign_fn(ccx: @crate_ctxt,
sp: span,
+path: ast_map::path,
node_id: ast::node_id)
node_id: ast::node_id,
attrs: &[ast::attribute])
-> ValueRef {
let _icx = ccx.insn_ctxt("foreign::register_foreign_fn");
let t = ty::node_id_to_type(ccx.tcx, node_id);
@ -1488,12 +1488,12 @@ fn register_foreign_fn(ccx: @crate_ctxt,
let ret_def = !ty::type_is_bot(ret_ty) && !ty::type_is_nil(ret_ty);
let x86_64 = x86_64_tys(llargtys, llretty, ret_def);
do decl_x86_64_fn(x86_64) |fnty| {
register_fn_fuller(ccx, sp, /*bad*/copy path, node_id,
register_fn_fuller(ccx, sp, /*bad*/copy path, node_id, attrs,
t, lib::llvm::CCallConv, fnty)
}
} else {
let llfty = T_fn(llargtys, llretty);
register_fn_fuller(ccx, sp, path, node_id,
register_fn_fuller(ccx, sp, path, node_id, attrs,
t, lib::llvm::CCallConv, llfty)
}
}

View File

@ -80,6 +80,13 @@ fn path_to_str(p: path, itr: @ident_interner) -> ~str {
path_to_str_with_sep(p, ~"::", itr)
}
fn path_elt_to_str(pe: path_elt, itr: @ident_interner) -> ~str {
match pe {
path_mod(s) => *itr.get(s),
path_name(s) => *itr.get(s)
}
}
enum ast_node {
node_item(@item, @path),
node_foreign_item(@foreign_item, foreign_abi, @path),

View File

@ -180,7 +180,7 @@ fn get_name_value_str_pair(item: @ast::meta_item) -> Option<(~str, ~str)> {
/* Searching */
/// Search a list of attributes and return only those with a specific name
fn find_attrs_by_name(attrs: ~[ast::attribute], name: &str) ->
fn find_attrs_by_name(attrs: &[ast::attribute], name: &str) ->
~[ast::attribute] {
let filter: &fn(a: &ast::attribute) -> Option<ast::attribute> = |a| {
if name == get_attr_name(*a) {
@ -242,7 +242,7 @@ fn contains_name(metas: ~[@ast::meta_item], name: ~str) -> bool {
return vec::len(matches) > 0u;
}
fn attrs_contains_name(attrs: ~[ast::attribute], name: ~str) -> bool {
fn attrs_contains_name(attrs: &[ast::attribute], name: &str) -> bool {
vec::is_not_empty(find_attrs_by_name(attrs, name))
}