From e82394013d90f1dfe8f3f990809c74e3f149e23e Mon Sep 17 00:00:00 2001 From: Luqman Aden Date: Fri, 26 Jul 2013 23:19:58 -0400 Subject: [PATCH 1/2] librustc: Respect no_mangle attribute on statics. --- src/librustc/middle/trans/base.rs | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/src/librustc/middle/trans/base.rs b/src/librustc/middle/trans/base.rs index 50ea6537544..1ab6233e939 100644 --- a/src/librustc/middle/trans/base.rs +++ b/src/librustc/middle/trans/base.rs @@ -2453,7 +2453,12 @@ pub fn get_item_val(ccx: @mut CrateContext, id: ast::node_id) -> ValueRef { let v = match i.node { ast::item_static(_, m, expr) => { let typ = ty::node_id_to_type(ccx.tcx, i.id); - let s = mangle_exported_name(ccx, my_path, typ); + let s = + if attr::contains_name(i.attrs, "no_mangle") { + path_elt_to_str(*my_path.last(), token::get_ident_interner()) + } else { + mangle_exported_name(ccx, my_path, typ) + }; // We need the translated value here, because for enums the // LLVM type is not fully determined by the Rust type. let v = consts::const_expr(ccx, expr); From c32b26be1000673e06ef2e5d114e39a28a5d6cd5 Mon Sep 17 00:00:00 2001 From: Luqman Aden Date: Sat, 27 Jul 2013 01:50:20 -0400 Subject: [PATCH 2/2] librustc: Unify name mangling for functions and statics. --- src/librustc/middle/trans/base.rs | 338 ++++++++++++++------------- src/librustc/middle/trans/foreign.rs | 11 +- 2 files changed, 178 insertions(+), 171 deletions(-) diff --git a/src/librustc/middle/trans/base.rs b/src/librustc/middle/trans/base.rs index 1ab6233e939..b0aa35c272b 100644 --- a/src/librustc/middle/trans/base.rs +++ b/src/librustc/middle/trans/base.rs @@ -2244,47 +2244,38 @@ pub fn trans_mod(ccx: @mut CrateContext, m: &ast::_mod) { pub fn register_fn(ccx: @mut CrateContext, sp: span, - path: path, - node_id: ast::node_id, - attrs: &[ast::Attribute]) + sym: ~str, + node_id: ast::node_id) -> ValueRef { 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, sp: span, - path: path, + sym: ~str, 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, attrs, node_type, + register_fn_fuller(ccx, sp, sym, node_id, node_type, lib::llvm::CCallConv, llfty) } pub fn register_fn_fuller(ccx: @mut CrateContext, sp: span, - path: path, + sym: ~str, node_id: ast::node_id, - attrs: &[ast::Attribute], node_type: ty::t, cc: lib::llvm::CallConv, fn_ty: Type) -> ValueRef { debug!("register_fn_fuller creating fn for item %d with path %s", 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") { - path_elt_to_str(*path.last(), token::get_ident_interner()) - } 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); + let llfn = decl_fn(ccx.llmod, sym, cc, fn_ty); + ccx.item_symbols.insert(node_id, sym); // FIXME #4404 android JNI hacks 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); } -pub fn item_path(ccx: &CrateContext, i: &ast::item) -> path { - let base = match ccx.tcx.items.get_copy(&i.id) { - ast_map::node_item(_, p) => p, - // separate map for paths? +pub fn item_path(ccx: &CrateContext, id: &ast::node_id) -> path { + match ccx.tcx.items.get_copy(id) { + ast_map::node_item(i, p) => + vec::append((*p).clone(), [path_name(i.ident)]), + // separate map for paths? _ => 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 { debug!("get_item_val(id=`%?`)", id); + let val = ccx.item_vals.find_copy(&id); match val { - Some(v) => v, - None => { - let mut exprt = false; - let item = ccx.tcx.items.get_copy(&id); - let val = match item { - ast_map::node_item(i, pth) => { - let my_path = vec::append((*pth).clone(), [path_name(i.ident)]); - let v = match i.node { - ast::item_static(_, m, expr) => { - let typ = ty::node_id_to_type(ccx.tcx, i.id); - let s = - if attr::contains_name(i.attrs, "no_mangle") { - path_elt_to_str(*my_path.last(), token::get_ident_interner()) - } else { - mangle_exported_name(ccx, my_path, typ) - }; - // We need the translated value here, because for enums the - // LLVM type is not fully determined by the Rust type. - let v = consts::const_expr(ccx, expr); - ccx.const_values.insert(id, v); - exprt = m == ast::m_mutbl; - unsafe { - let llty = llvm::LLVMTypeOf(v); - let g = do s.as_c_str |buf| { - llvm::LLVMAddGlobal(ccx.llmod, llty, buf) - }; - ccx.item_symbols.insert(i.id, s); - 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) + Some(v) => v, + None => { + let mut exprt = false; + let item = ccx.tcx.items.get_copy(&id); + let val = match item { + ast_map::node_item(i, pth) => { + + let my_path = vec::append((*pth).clone(), [path_name(i.ident)]); + let ty = ty::node_id_to_type(ccx.tcx, i.id); + let sym = exported_name(ccx, my_path, ty, i.attrs); + + let v = match i.node { + ast::item_static(_, m, expr) => { + // We need the translated value here, because for enums the + // LLVM type is not fully determined by the Rust type. + let v = consts::const_expr(ccx, expr); + ccx.const_values.insert(id, v); + exprt = m == ast::m_mutbl; + + unsafe { + let llty = llvm::LLVMTypeOf(v); + let g = do sym.as_c_str |buf| { + llvm::LLVMAddGlobal(ccx.llmod, llty, buf) + }; + + ccx.item_symbols.insert(i.id, sym); + g + } } - }; - 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)]); - 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::item_fn(_, purity, _, _, _) => { + let llfn = if purity != ast::extern_fn { + register_fn_full(ccx, i.span, sym, i.id, ty) + } else { + foreign::register_foreign_fn(ccx, i.span, sym, i.id) + }; + set_inline_hint_if_appr(i.attrs, llfn); + llfn + } - ast_map::node_struct_ctor(struct_def, struct_item, struct_path) => { - // Only register the constructor if this is a tuple-like struct. - match struct_def.ctor_id { - None => { - ccx.tcx.sess.bug("attempt to register a constructor of \ - a non-tuple-like struct") + _ => 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 } - Some(ctor_id) => { - let llfn = register_fn(ccx, - struct_item.span, - (*struct_path).clone(), - ctor_id, - struct_item.attrs); + + 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) => { + 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); 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); + ast_map::node_struct_ctor(struct_def, struct_item, struct_path) => { + // Only register the constructor if this is a tuple-like struct. + match struct_def.ctor_id { + None => { + ccx.tcx.sess.bug("attempt to register a constructor of \ + a non-tuple-like struct") + } + 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(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); llfn } @@ -2618,7 +2626,7 @@ pub fn trans_constant(ccx: &mut CrateContext, it: @ast::item) { ast::def_id { crate: ast::local_crate, node: it.id }); let mut i = 0; - let path = item_path(ccx, it); + let path = item_path(ccx, &it.id); for (*enum_definition).variants.iter().advance |variant| { let p = vec::append(path.clone(), [ path_name(variant.node.name), diff --git a/src/librustc/middle/trans/foreign.rs b/src/librustc/middle/trans/foreign.rs index 372d24e664c..6e198af448b 100644 --- a/src/librustc/middle/trans/foreign.rs +++ b/src/librustc/middle/trans/foreign.rs @@ -32,6 +32,7 @@ use middle::ty; use middle::ty::FnSig; use util::ppaux::ty_to_str; +use std::cell::Cell; use std::uint; use std::vec; use syntax::codemap::span; @@ -1139,22 +1140,20 @@ pub fn trans_foreign_fn(ccx: @mut CrateContext, pub fn register_foreign_fn(ccx: @mut CrateContext, sp: span, - path: ast_map::path, - node_id: ast::node_id, - attrs: &[ast::Attribute]) + sym: ~str, + node_id: ast::node_id) -> ValueRef { let _icx = push_ctxt("foreign::register_foreign_fn"); let t = ty::node_id_to_type(ccx.tcx, node_id); + let sym = Cell::new(sym); let tys = shim_types(ccx, node_id); do tys.fn_ty.decl_fn |fnty| { - // XXX(pcwalton): We should not copy the path. register_fn_fuller(ccx, sp, - path.clone(), + sym.take(), node_id, - attrs, t, lib::llvm::CCallConv, fnty)