1
Fork 0

librustc: Unify name mangling for functions and statics.

This commit is contained in:
Luqman Aden 2013-07-27 01:50:20 -04:00
parent e82394013d
commit c32b26be10
2 changed files with 178 additions and 171 deletions

View file

@ -2244,47 +2244,38 @@ pub fn trans_mod(ccx: @mut CrateContext, m: &ast::_mod) {
pub fn register_fn(ccx: @mut CrateContext, pub fn register_fn(ccx: @mut CrateContext,
sp: span, sp: span,
path: path, sym: ~str,
node_id: ast::node_id, node_id: ast::node_id)
attrs: &[ast::Attribute])
-> ValueRef { -> ValueRef {
let t = ty::node_id_to_type(ccx.tcx, node_id); let t = ty::node_id_to_type(ccx.tcx, node_id);
register_fn_full(ccx, sp, path, node_id, attrs, t) register_fn_full(ccx, sp, sym, node_id, t)
} }
pub fn register_fn_full(ccx: @mut CrateContext, pub fn register_fn_full(ccx: @mut CrateContext,
sp: span, sp: span,
path: path, sym: ~str,
node_id: ast::node_id, node_id: ast::node_id,
attrs: &[ast::Attribute],
node_type: ty::t) node_type: ty::t)
-> ValueRef { -> ValueRef {
let llfty = type_of_fn_from_ty(ccx, node_type); let llfty = type_of_fn_from_ty(ccx, node_type);
register_fn_fuller(ccx, sp, path, node_id, attrs, node_type, register_fn_fuller(ccx, sp, sym, node_id, node_type,
lib::llvm::CCallConv, llfty) lib::llvm::CCallConv, llfty)
} }
pub fn register_fn_fuller(ccx: @mut CrateContext, pub fn register_fn_fuller(ccx: @mut CrateContext,
sp: span, sp: span,
path: path, sym: ~str,
node_id: ast::node_id, node_id: ast::node_id,
attrs: &[ast::Attribute],
node_type: ty::t, node_type: ty::t,
cc: lib::llvm::CallConv, cc: lib::llvm::CallConv,
fn_ty: Type) fn_ty: Type)
-> ValueRef { -> ValueRef {
debug!("register_fn_fuller creating fn for item %d with path %s", debug!("register_fn_fuller creating fn for item %d with path %s",
node_id, node_id,
ast_map::path_to_str(path, token::get_ident_interner())); ast_map::path_to_str(item_path(ccx, &node_id), token::get_ident_interner()));
let ps = if attr::contains_name(attrs, "no_mangle") { let llfn = decl_fn(ccx.llmod, sym, cc, fn_ty);
path_elt_to_str(*path.last(), token::get_ident_interner()) ccx.item_symbols.insert(node_id, sym);
} else {
mangle_exported_name(ccx, path, node_type)
};
let llfn = decl_fn(ccx.llmod, ps, cc, fn_ty);
ccx.item_symbols.insert(node_id, ps);
// FIXME #4404 android JNI hacks // FIXME #4404 android JNI hacks
let is_entry = is_entry_fn(&ccx.sess, node_id) && (!*ccx.sess.building_library || let is_entry = is_entry_fn(&ccx.sess, node_id) && (!*ccx.sess.building_library ||
@ -2430,167 +2421,182 @@ pub fn fill_fn_pair(bcx: @mut Block, pair: ValueRef, llfn: ValueRef,
Store(bcx, llenvblobptr, env_cell); Store(bcx, llenvblobptr, env_cell);
} }
pub fn item_path(ccx: &CrateContext, i: &ast::item) -> path { pub fn item_path(ccx: &CrateContext, id: &ast::node_id) -> path {
let base = match ccx.tcx.items.get_copy(&i.id) { match ccx.tcx.items.get_copy(id) {
ast_map::node_item(_, p) => p, ast_map::node_item(i, p) =>
// separate map for paths? vec::append((*p).clone(), [path_name(i.ident)]),
// separate map for paths?
_ => fail!("item_path") _ => fail!("item_path")
}; }
vec::append((*base).clone(), [path_name(i.ident)]) }
fn exported_name(ccx: @mut CrateContext, path: path, ty: ty::t, attrs: &[ast::Attribute]) -> ~str {
if attr::contains_name(attrs, "no_mangle") {
path_elt_to_str(*path.last(), token::get_ident_interner())
} else {
mangle_exported_name(ccx, path, ty)
}
} }
pub fn get_item_val(ccx: @mut CrateContext, id: ast::node_id) -> ValueRef { pub fn get_item_val(ccx: @mut CrateContext, id: ast::node_id) -> ValueRef {
debug!("get_item_val(id=`%?`)", id); debug!("get_item_val(id=`%?`)", id);
let val = ccx.item_vals.find_copy(&id); let val = ccx.item_vals.find_copy(&id);
match val { match val {
Some(v) => v, Some(v) => v,
None => { None => {
let mut exprt = false; let mut exprt = false;
let item = ccx.tcx.items.get_copy(&id); let item = ccx.tcx.items.get_copy(&id);
let val = match item { let val = match item {
ast_map::node_item(i, pth) => { ast_map::node_item(i, pth) => {
let my_path = vec::append((*pth).clone(), [path_name(i.ident)]);
let v = match i.node { let my_path = vec::append((*pth).clone(), [path_name(i.ident)]);
ast::item_static(_, m, expr) => { let ty = ty::node_id_to_type(ccx.tcx, i.id);
let typ = ty::node_id_to_type(ccx.tcx, i.id); let sym = exported_name(ccx, my_path, ty, i.attrs);
let s =
if attr::contains_name(i.attrs, "no_mangle") { let v = match i.node {
path_elt_to_str(*my_path.last(), token::get_ident_interner()) ast::item_static(_, m, expr) => {
} else { // We need the translated value here, because for enums the
mangle_exported_name(ccx, my_path, typ) // LLVM type is not fully determined by the Rust type.
}; let v = consts::const_expr(ccx, expr);
// We need the translated value here, because for enums the ccx.const_values.insert(id, v);
// LLVM type is not fully determined by the Rust type. exprt = m == ast::m_mutbl;
let v = consts::const_expr(ccx, expr);
ccx.const_values.insert(id, v); unsafe {
exprt = m == ast::m_mutbl; let llty = llvm::LLVMTypeOf(v);
unsafe { let g = do sym.as_c_str |buf| {
let llty = llvm::LLVMTypeOf(v); llvm::LLVMAddGlobal(ccx.llmod, llty, buf)
let g = do s.as_c_str |buf| { };
llvm::LLVMAddGlobal(ccx.llmod, llty, buf)
}; ccx.item_symbols.insert(i.id, sym);
ccx.item_symbols.insert(i.id, s); g
g }
}
}
ast::item_fn(_, purity, _, _, _) => {
let llfn = if purity != ast::extern_fn {
register_fn(ccx, i.span, my_path, i.id, i.attrs)
} else {
foreign::register_foreign_fn(ccx,
i.span,
my_path,
i.id,
i.attrs)
};
set_inline_hint_if_appr(i.attrs, llfn);
llfn
}
_ => fail!("get_item_val: weird result in table")
};
match (attr::first_attr_value_str_by_name(i.attrs, "link_section")) {
Some(sect) => unsafe {
do sect.as_c_str |buf| {
llvm::LLVMSetSection(v, buf);
}
},
None => ()
}
v
}
ast_map::node_trait_method(trait_method, _, pth) => {
debug!("get_item_val(): processing a node_trait_method");
match *trait_method {
ast::required(_) => {
ccx.sess.bug("unexpected variant: required trait method in \
get_item_val()");
}
ast::provided(m) => {
exprt = true;
register_method(ccx, id, pth, m)
}
}
}
ast_map::node_method(m, _, pth) => {
register_method(ccx, id, pth, m)
}
ast_map::node_foreign_item(ni, _, _, pth) => {
exprt = true;
match ni.node {
ast::foreign_item_fn(*) => {
register_fn(ccx, ni.span,
vec::append((*pth).clone(),
[path_name(ni.ident)]),
ni.id,
ni.attrs)
}
ast::foreign_item_static(*) => {
let typ = ty::node_id_to_type(ccx.tcx, ni.id);
let ident = token::ident_to_str(&ni.ident);
let g = do ident.as_c_str |buf| {
unsafe {
let ty = type_of(ccx, typ);
llvm::LLVMAddGlobal(ccx.llmod, ty.to_ref(), buf)
} }
};
g
}
}
}
ast_map::node_variant(ref v, enm, pth) => { ast::item_fn(_, purity, _, _, _) => {
let llfn; let llfn = if purity != ast::extern_fn {
match v.node.kind { register_fn_full(ccx, i.span, sym, i.id, ty)
ast::tuple_variant_kind(ref args) => { } else {
assert!(args.len() != 0u); foreign::register_foreign_fn(ccx, i.span, sym, i.id)
let pth = vec::append((*pth).clone(), };
[path_name(enm.ident), set_inline_hint_if_appr(i.attrs, llfn);
path_name((*v).node.name)]); llfn
llfn = match enm.node { }
ast::item_enum(_, _) => {
register_fn(ccx, (*v).span, pth, id, enm.attrs)
}
_ => fail!("node_variant, shouldn't happen")
};
}
ast::struct_variant_kind(_) => {
fail!("struct variant kind unexpected in get_item_val")
}
}
set_inline_hint(llfn);
llfn
}
ast_map::node_struct_ctor(struct_def, struct_item, struct_path) => { _ => fail!("get_item_val: weird result in table")
// Only register the constructor if this is a tuple-like struct. };
match struct_def.ctor_id {
None => { match (attr::first_attr_value_str_by_name(i.attrs, "link_section")) {
ccx.tcx.sess.bug("attempt to register a constructor of \ Some(sect) => unsafe {
a non-tuple-like struct") do sect.as_c_str |buf| {
llvm::LLVMSetSection(v, buf);
}
},
None => ()
}
v
} }
Some(ctor_id) => {
let llfn = register_fn(ccx, ast_map::node_trait_method(trait_method, _, pth) => {
struct_item.span, debug!("get_item_val(): processing a node_trait_method");
(*struct_path).clone(), match *trait_method {
ctor_id, ast::required(_) => {
struct_item.attrs); ccx.sess.bug("unexpected variant: required trait method in \
get_item_val()");
}
ast::provided(m) => {
exprt = true;
register_method(ccx, id, pth, m)
}
}
}
ast_map::node_method(m, _, pth) => {
register_method(ccx, id, pth, m)
}
ast_map::node_foreign_item(ni, _, _, pth) => {
let ty = ty::node_id_to_type(ccx.tcx, ni.id);
exprt = true;
match ni.node {
ast::foreign_item_fn(*) => {
let path = vec::append((*pth).clone(), [path_name(ni.ident)]);
let sym = exported_name(ccx, path, ty, ni.attrs);
register_fn_full(ccx, ni.span, sym, ni.id, ty)
}
ast::foreign_item_static(*) => {
let ident = token::ident_to_str(&ni.ident);
let g = do ident.as_c_str |buf| {
unsafe {
let ty = type_of(ccx, ty);
llvm::LLVMAddGlobal(ccx.llmod, ty.to_ref(), buf)
}
};
g
}
}
}
ast_map::node_variant(ref v, enm, pth) => {
let llfn;
match v.node.kind {
ast::tuple_variant_kind(ref args) => {
assert!(args.len() != 0u);
let pth = vec::append((*pth).clone(),
[path_name(enm.ident),
path_name((*v).node.name)]);
let ty = ty::node_id_to_type(ccx.tcx, id);
let sym = exported_name(ccx, pth, ty, enm.attrs);
llfn = match enm.node {
ast::item_enum(_, _) => {
register_fn_full(ccx, (*v).span, sym, id, ty)
}
_ => fail!("node_variant, shouldn't happen")
};
}
ast::struct_variant_kind(_) => {
fail!("struct variant kind unexpected in get_item_val")
}
}
set_inline_hint(llfn); set_inline_hint(llfn);
llfn llfn
} }
}
}
ref variant => { ast_map::node_struct_ctor(struct_def, struct_item, struct_path) => {
ccx.sess.bug(fmt!("get_item_val(): unexpected variant: %?", // Only register the constructor if this is a tuple-like struct.
variant)) match struct_def.ctor_id {
} None => {
}; ccx.tcx.sess.bug("attempt to register a constructor of \
if !exprt && !ccx.reachable.contains(&id) { a non-tuple-like struct")
lib::llvm::SetLinkage(val, lib::llvm::InternalLinkage); }
Some(ctor_id) => {
let ty = ty::node_id_to_type(ccx.tcx, ctor_id);
let sym = exported_name(ccx, (*struct_path).clone(), ty,
struct_item.attrs);
let llfn = register_fn_full(ccx, struct_item.span, sym, ctor_id, ty);
set_inline_hint(llfn);
llfn
}
}
}
ref variant => {
ccx.sess.bug(fmt!("get_item_val(): unexpected variant: %?",
variant))
}
};
if !exprt && !ccx.reachable.contains(&id) {
lib::llvm::SetLinkage(val, lib::llvm::InternalLinkage);
}
ccx.item_vals.insert(id, val);
val
} }
ccx.item_vals.insert(id, val);
val
}
} }
} }
@ -2604,7 +2610,9 @@ pub fn register_method(ccx: @mut CrateContext,
path.push(path_name(gensym_name("meth"))); path.push(path_name(gensym_name("meth")));
path.push(path_name(m.ident)); path.push(path_name(m.ident));
let llfn = register_fn_full(ccx, m.span, path, id, m.attrs, mty); let sym = exported_name(ccx, path, mty, m.attrs);
let llfn = register_fn_full(ccx, m.span, sym, id, mty);
set_inline_hint_if_appr(m.attrs, llfn); set_inline_hint_if_appr(m.attrs, llfn);
llfn llfn
} }
@ -2618,7 +2626,7 @@ pub fn trans_constant(ccx: &mut CrateContext, it: @ast::item) {
ast::def_id { crate: ast::local_crate, ast::def_id { crate: ast::local_crate,
node: it.id }); node: it.id });
let mut i = 0; let mut i = 0;
let path = item_path(ccx, it); let path = item_path(ccx, &it.id);
for (*enum_definition).variants.iter().advance |variant| { for (*enum_definition).variants.iter().advance |variant| {
let p = vec::append(path.clone(), [ let p = vec::append(path.clone(), [
path_name(variant.node.name), path_name(variant.node.name),

View file

@ -32,6 +32,7 @@ use middle::ty;
use middle::ty::FnSig; use middle::ty::FnSig;
use util::ppaux::ty_to_str; use util::ppaux::ty_to_str;
use std::cell::Cell;
use std::uint; use std::uint;
use std::vec; use std::vec;
use syntax::codemap::span; use syntax::codemap::span;
@ -1139,22 +1140,20 @@ pub fn trans_foreign_fn(ccx: @mut CrateContext,
pub fn register_foreign_fn(ccx: @mut CrateContext, pub fn register_foreign_fn(ccx: @mut CrateContext,
sp: span, sp: span,
path: ast_map::path, sym: ~str,
node_id: ast::node_id, node_id: ast::node_id)
attrs: &[ast::Attribute])
-> ValueRef { -> ValueRef {
let _icx = push_ctxt("foreign::register_foreign_fn"); let _icx = push_ctxt("foreign::register_foreign_fn");
let t = ty::node_id_to_type(ccx.tcx, node_id); let t = ty::node_id_to_type(ccx.tcx, node_id);
let sym = Cell::new(sym);
let tys = shim_types(ccx, node_id); let tys = shim_types(ccx, node_id);
do tys.fn_ty.decl_fn |fnty| { do tys.fn_ty.decl_fn |fnty| {
// XXX(pcwalton): We should not copy the path.
register_fn_fuller(ccx, register_fn_fuller(ccx,
sp, sp,
path.clone(), sym.take(),
node_id, node_id,
attrs,
t, t,
lib::llvm::CCallConv, lib::llvm::CCallConv,
fnty) fnty)