diff --git a/src/rustc/back/link.rs b/src/rustc/back/link.rs index 5a05bc7c124..57a03a5c64c 100644 --- a/src/rustc/back/link.rs +++ b/src/rustc/back/link.rs @@ -505,6 +505,34 @@ fn get_symbol_hash(ccx: @crate_ctxt, t: ty::t) -> str { ret hash; } + +// Name sanitation. LLVM will happily accept identifiers with weird names, but +// gas doesn't! +fn sanitize(s: str) -> str { + let result = ""; + str::chars_iter(s) {|c| + alt c { + '@' { result += "_sbox_"; } + '~' { result += "_ubox_"; } + '*' { result += "_ptr_"; } + '&' { result += "_ref_"; } + ',' { result += "_"; } + + '{' | '(' { result += "_of_"; } + 'a' to 'z' + | 'A' to 'Z' + | '0' to '9' + | '_' { str::push_char(result,c); } + _ { + if c > 'z' && char::is_XID_continue(c) { + str::push_char(result,c); + } + } + } + } + ret result; +} + fn mangle(ss: path) -> str { // Follow C++ namespace-mangling style @@ -512,7 +540,8 @@ fn mangle(ss: path) -> str { for s in ss { alt s { path_name(s) | path_mod(s) { - n += #fmt["%u%s", str::len(s), s]; + let sani = sanitize(s); + n += #fmt["%u%s", str::len(sani), sani]; } } } n += "E"; // End name-sequence. diff --git a/src/rustc/middle/trans/base.rs b/src/rustc/middle/trans/base.rs index a69ba168fe3..0863d93acfc 100644 --- a/src/rustc/middle/trans/base.rs +++ b/src/rustc/middle/trans/base.rs @@ -128,34 +128,6 @@ fn get_dest_addr(dest: dest) -> ValueRef { } } -// Name sanitation. LLVM will happily accept identifiers with weird names, but -// gas doesn't! -fn sanitize(s: str) -> str { - let result = ""; - for c: u8 in s { - if c == '@' as u8 { - result += "boxed_"; - } else { - if c == ',' as u8 { - result += "_"; - } else { - if c == '{' as u8 || c == '(' as u8 { - result += "_of_"; - } else { - if c != 10u8 && c != '}' as u8 && c != ')' as u8 && - c != ' ' as u8 && c != '\t' as u8 && c != ';' as u8 - { - let v = [c]; - result += str::from_bytes(v); - } - } - } - } - } - ret result; -} - - fn log_fn_time(ccx: @crate_ctxt, name: str, start: time::timeval, end: time::timeval) { let elapsed = 1000 * ((end.sec - start.sec) as int) + @@ -412,6 +384,14 @@ fn set_glue_inlining(f: ValueRef, t: ty::t) { } else { set_always_inline(f); } } +// Double-check that we never ask LLVM to declare the same symbol twice. It +// silently mangles such symbols, breaking our linkage model. +fn note_unique_llvm_symbol(ccx: @crate_ctxt, sym: str) { + if ccx.all_llvm_symbols.contains_key(sym) { + ccx.sess.bug("duplicate LLVM symbol: " + sym); + } + ccx.all_llvm_symbols.insert(sym, ()); +} // Generates the declaration for (but doesn't emit) a type descriptor. fn declare_tydesc(ccx: @crate_ctxt, t: ty::t) -> @tydesc_info { @@ -424,8 +404,8 @@ fn declare_tydesc(ccx: @crate_ctxt, t: ty::t) -> @tydesc_info { let name; if ccx.sess.opts.debuginfo { name = mangle_internal_name_by_type_only(ccx, t, "tydesc"); - name = sanitize(name); } else { name = mangle_internal_name_by_seq(ccx, "tydesc"); } + note_unique_llvm_symbol(ccx, name); let gvar = str::as_c_str(name, {|buf| llvm::LLVMAddGlobal(ccx.llmod, ccx.tydesc_type, buf) }); @@ -449,8 +429,10 @@ fn declare_generic_glue(ccx: @crate_ctxt, t: ty::t, llfnty: TypeRef, let fn_nm; if ccx.sess.opts.debuginfo { fn_nm = mangle_internal_name_by_type_only(ccx, t, "glue_" + name); - fn_nm = sanitize(fn_nm); - } else { fn_nm = mangle_internal_name_by_seq(ccx, "glue_" + name); } + } else { + fn_nm = mangle_internal_name_by_seq(ccx, "glue_" + name); + } + note_unique_llvm_symbol(ccx, fn_nm); let llfn = decl_cdecl_fn(ccx.llmod, fn_nm, llfnty); set_glue_inlining(llfn, t); ret llfn; @@ -4414,6 +4396,7 @@ fn trans_constant(ccx: @crate_ctxt, it: @ast::item) { path_name("discrim")]; let s = mangle_exported_name(ccx, p, ty::mk_int(ccx.tcx)); let disr_val = vi[i].disr_val; + note_unique_llvm_symbol(ccx, s); let discrim_gvar = str::as_c_str(s, {|buf| llvm::LLVMAddGlobal(ccx.llmod, ccx.int_type, buf) }); @@ -4669,6 +4652,7 @@ fn trans_crate(sess: session::session, crate: @ast::crate, tcx: ty::ctxt, sha: sha, type_sha1s: ty::new_ty_hash(), type_short_names: ty::new_ty_hash(), + all_llvm_symbols: str_hash::<()>(), tcx: tcx, maps: maps, stats: diff --git a/src/rustc/middle/trans/common.rs b/src/rustc/middle/trans/common.rs index 940a1848821..df5f03e9922 100644 --- a/src/rustc/middle/trans/common.rs +++ b/src/rustc/middle/trans/common.rs @@ -5,7 +5,7 @@ import libc::c_uint; import vec::unsafe::to_ptr; -import std::map::hashmap; +import std::map::{hashmap,set}; import syntax::ast; import driver::session; import session::session; @@ -101,6 +101,7 @@ type crate_ctxt = { sha: std::sha1::sha1, type_sha1s: hashmap, type_short_names: hashmap, + all_llvm_symbols: set, tcx: ty::ctxt, maps: maps, stats: stats,