about summary refs log tree commit diff
path: root/src/rustc
diff options
context:
space:
mode:
authorGraydon Hoare <graydon@mozilla.com>2012-03-20 14:21:02 -0700
committerGraydon Hoare <graydon@mozilla.com>2012-03-20 15:16:12 -0700
commit8e911cbd6565517530a6034aad7b7e49ef50e6a3 (patch)
tree6c0dc499ae72bb2990c8195a242f0ab6c6e467f4 /src/rustc
parent1695148b5de9e801c4fbbbadce2f576e511c1cc2 (diff)
downloadrust-8e911cbd6565517530a6034aad7b7e49ef50e6a3.tar.gz
rust-8e911cbd6565517530a6034aad7b7e49ef50e6a3.zip
Work on fixing name mangling.
Diffstat (limited to 'src/rustc')
-rw-r--r--src/rustc/back/link.rs31
-rw-r--r--src/rustc/middle/trans/base.rs46
-rw-r--r--src/rustc/middle/trans/common.rs3
3 files changed, 47 insertions, 33 deletions
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<ty::t, str>,
      type_short_names: hashmap<ty::t, str>,
+     all_llvm_symbols: set<str>,
      tcx: ty::ctxt,
      maps: maps,
      stats: stats,