about summary refs log tree commit diff
path: root/src
diff options
context:
space:
mode:
authorGraydon Hoare <graydon@mozilla.com>2011-06-06 15:48:36 -0700
committerGraydon Hoare <graydon@mozilla.com>2011-06-06 15:48:47 -0700
commit319156c8d10e34dc9e8f3d243be45595fb55b9fd (patch)
tree061ca797949e75bad556680da1fb286814b995d6 /src
parentee54fa5c7d4c670ee379e75cbd434bd524f8a3cb (diff)
downloadrust-319156c8d10e34dc9e8f3d243be45595fb55b9fd.tar.gz
rust-319156c8d10e34dc9e8f3d243be45595fb55b9fd.zip
Begin tidying up name-mangling rules.
Diffstat (limited to 'src')
-rw-r--r--src/comp/middle/trans.rs124
-rw-r--r--src/lib/vec.rs6
2 files changed, 72 insertions, 58 deletions
diff --git a/src/comp/middle/trans.rs b/src/comp/middle/trans.rs
index 61de9459fac..4230032f7ee 100644
--- a/src/comp/middle/trans.rs
+++ b/src/comp/middle/trans.rs
@@ -118,6 +118,7 @@ state type crate_ctxt = rec(session::session sess,
                             hashmap[ast::def_id,
                                     @ast::native_item] native_items,
                             hashmap[ast::def_id, str] item_symbols,
+                            mutable option::t[ValueRef] main_fn,
                             // TODO: hashmap[tup(tag_id,subtys), @tag_info]
                             hashmap[ty::t, uint] tag_sizes,
                             hashmap[ast::def_id, ValueRef] discrims,
@@ -308,19 +309,10 @@ tag block_parent {
 state type result = rec(@block_ctxt bcx,
                         ValueRef val);
 
-fn sep() -> str {
-    ret "_";
-}
-
 fn extend_path(@local_ctxt cx, &str name) -> @local_ctxt {
   ret @rec(path = cx.path + [name] with *cx);
 }
 
-fn path_name(&vec[str] path) -> str {
-    ret str::connect(path, sep());
-}
-
-
 fn get_type_sha1(&@crate_ctxt ccx, &ty::t t) -> str {
     auto hash = "";
     alt (ccx.type_sha1s.find(t)) {
@@ -336,15 +328,31 @@ fn get_type_sha1(&@crate_ctxt ccx, &ty::t t) -> str {
 
             ccx.sha.input_str(metadata::Encode::ty_str(cx, t));
             hash = str::substr(ccx.sha.result_str(), 0u, 16u);
+            // Prefix with _ so that it never blends into adjacent digits
+            hash = "_" + hash;
             ccx.type_sha1s.insert(t, hash);
         }
     }
     ret hash;
 }
 
+fn mangle(&vec[str] ss) -> str {
+
+    // Follow C++ namespace-mangling style
+
+    auto n = "_ZN"; // Begin name-sequence.
+
+    for (str s in ss) {
+        n += #fmt("%u%s", str::byte_len(s), s);
+    }
+
+    n += "E"; // End name-sequence.
+    ret n;
+}
+
 fn mangle_name_by_type(&@crate_ctxt ccx, &vec[str] path, &ty::t t) -> str {
     auto hash = get_type_sha1(ccx, t);
-    ret sep() + "rust" + sep() + hash + sep() + path_name(path);
+    ret mangle(path + [hash]);
 }
 
 fn mangle_name_by_type_only(&@crate_ctxt ccx, &ty::t t, &str name) -> str {
@@ -353,14 +361,20 @@ fn mangle_name_by_type_only(&@crate_ctxt ccx, &ty::t t, &str name) -> str {
     auto s = ty::ty_to_short_str(ccx.tcx, t);
 
     auto hash = get_type_sha1(ccx, t);
-    ret sep() + "rust" + sep() + hash + sep() + name + "_" + s;
+    ret mangle([name, s, hash]);
+}
+
+fn mangle_name_by_path_and_seq(&@crate_ctxt ccx, &vec[str] path,
+                               &str flav) -> str {
+    ret mangle(path + [ccx.names.next(flav)]);
+}
+
+fn mangle_name_by_path(&@crate_ctxt ccx, &vec[str] path) -> str {
+    ret mangle(path);
 }
 
-fn mangle_name_by_seq(&@crate_ctxt ccx, &vec[str] path,
-                      &str flav) -> str {
-    ret sep() + "rust" + sep()
-        + ccx.names.next(flav) + sep()
-        + path_name(path);
+fn mangle_name_by_seq(&@crate_ctxt ccx, &str flav) -> str {
+    ret ccx.names.next(flav);
 }
 
 fn res(@block_ctxt bcx, ValueRef val) -> result {
@@ -1903,7 +1917,7 @@ fn declare_tydesc(&@local_ctxt cx, &span sp, &ty::t t,
         name = mangle_name_by_type_only(cx.ccx, t, "tydesc");
         name = sanitize(name);
     } else {
-        name = mangle_name_by_seq(cx.ccx, cx.path, "tydesc");
+        name = mangle_name_by_seq(cx.ccx, "tydesc");
     }
 
     auto gvar = llvm::LLVMAddGlobal(ccx.llmod, T_tydesc(ccx.tn),
@@ -1937,7 +1951,7 @@ fn declare_generic_glue(&@local_ctxt cx,
         fn_nm = mangle_name_by_type_only(cx.ccx, t, "glue_" + name);
         fn_nm = sanitize(fn_nm);
     } else {
-        fn_nm = mangle_name_by_seq(cx.ccx, cx.path,  "glue_" + name);
+        fn_nm = mangle_name_by_seq(cx.ccx,  "glue_" + name);
     }
     auto llfn = decl_fastcall_fn(cx.ccx.llmod, fn_nm, llfnty);
     set_glue_inlining(cx, llfn, t);
@@ -4093,7 +4107,7 @@ fn trans_for_each(&@block_ctxt cx,
 
     // Step 2: Declare foreach body function.
 
-    let str s = mangle_name_by_seq(lcx.ccx, lcx.path, "foreach");
+    let str s = mangle_name_by_path_and_seq(lcx.ccx, lcx.path, "foreach");
 
     // The 'env' arg entering the body function is a fake env member (as in
     // the env-part of the normal rust calling convention) that actually
@@ -4792,7 +4806,7 @@ fn trans_bind_thunk(&@local_ctxt cx,
     // Construct a thunk-call with signature incoming_fty, and that copies
     // args forward into a call to outgoing_fty:
 
-    let str s = mangle_name_by_seq(cx.ccx, cx.path, "thunk");
+    let str s = mangle_name_by_path_and_seq(cx.ccx, cx.path, "thunk");
     let TypeRef llthunk_ty = get_pair_fn_ty(type_of(cx.ccx, sp,
                                                     incoming_fty));
     let ValueRef llthunk = decl_internal_fastcall_fn(cx.ccx.llmod,
@@ -6225,9 +6239,10 @@ fn mk_spawn_wrapper(&@block_ctxt cx,
                    0u);
 
     // TODO: construct a name based on tname
-    let str wrap_name = mangle_name_by_seq(cx.fcx.lcx.ccx,
-                                           [""],
-                                           "spawn_wrapper");
+    let str wrap_name =
+        mangle_name_by_path_and_seq(cx.fcx.lcx.ccx,
+                                    cx.fcx.lcx.path,
+                                    "spawn_wrapper");
     auto llfndecl = decl_fastcall_fn(llmod, wrap_name,
                                      wrapper_fn_type);
 
@@ -7078,8 +7093,9 @@ fn create_vtbl(@local_ctxt cx,
             }
         }
 
-        let @local_ctxt mcx = extend_path(cx, m.node.ident);
-        let str s = mangle_name_by_seq(mcx.ccx, mcx.path, "method");
+        let @local_ctxt mcx = @rec(path = cx.path + ["method",
+                                                     m.node.ident] with *cx);
+        let str s = mangle_name_by_path(mcx.ccx, mcx.path);
         let ValueRef llfn = decl_internal_fastcall_fn(cx.ccx.llmod, s,
                                                       llfnty);
         cx.ccx.item_ids.insert(m.node.id, llfn);
@@ -7091,7 +7107,7 @@ fn create_vtbl(@local_ctxt cx,
         methods += [llfn];
     }
     auto vtbl = C_struct(methods);
-    auto vtbl_name = mangle_name_by_seq(cx.ccx, cx.path, "vtbl");
+    auto vtbl_name = mangle_name_by_path(cx.ccx, cx.path + ["vtbl"]);
     auto gvar = llvm::LLVMAddGlobal(cx.ccx.llmod, val_ty(vtbl),
                                    str::buf(vtbl_name));
     llvm::LLVMSetInitializer(gvar, vtbl);
@@ -7108,13 +7124,12 @@ fn trans_dtor(@local_ctxt cx,
               &@ast::method dtor) -> ValueRef {
 
     auto llfnty = T_dtor(cx.ccx, dtor.span, llself_ty);
-    let @local_ctxt dcx = extend_path(cx, "drop");
-    let str s = mangle_name_by_seq(dcx.ccx, dcx.path, "drop");
+    let str s = mangle_name_by_path(cx.ccx, cx.path + ["drop"]);
     let ValueRef llfn = decl_internal_fastcall_fn(cx.ccx.llmod, s, llfnty);
     cx.ccx.item_ids.insert(dtor.node.id, llfn);
     cx.ccx.item_symbols.insert(dtor.node.id, s);
 
-    trans_fn(dcx, dtor.span, dtor.node.meth, dtor.node.id,
+    trans_fn(cx, dtor.span, dtor.node.meth, dtor.node.id,
              some[ty_self_pair](tup(llself_ty, self_ty)),
              ty_params, dtor.node.ann);
 
@@ -7503,13 +7518,22 @@ fn decl_fn_and_pair(&@crate_ctxt ccx, &span sp,
     }
 
     // Declare the function itself.
-    let str s = mangle_name_by_seq(ccx, path, flav);
+    let str s = mangle_name_by_path(ccx, path);
     let ValueRef llfn = decl_internal_fastcall_fn(ccx.llmod, s, llfty);
 
     // Declare the global constant pair that points to it.
     let str ps = mangle_name_by_type(ccx, path, node_ann_type(ccx, ann));
 
     register_fn_pair(ccx, ps, llpairty, llfn, id);
+
+    if (str::eq(vec::top(path), "main") &&
+        !ccx.sess.get_opts().shared) {
+        if (ccx.main_fn != none[ValueRef]) {
+            ccx.sess.span_err(sp, "multiple 'main' functions");
+        }
+        log #fmt("registering %s as main function for crate", ps);
+        ccx.main_fn = some(llfn);
+    }
 }
 
 fn register_fn_pair(&@crate_ctxt cx, str ps, TypeRef llpairty, ValueRef llfn,
@@ -7569,7 +7593,7 @@ fn decl_native_fn_and_pair(&@crate_ctxt ccx,
     // Declare the wrapper.
     auto t = node_ann_type(ccx, ann);
     auto wrapper_type = native_fn_wrapper_type(ccx, sp, num_ty_param, t);
-    let str s = mangle_name_by_seq(ccx, path, "wrapper");
+    let str s = mangle_name_by_path(ccx, path);
     let ValueRef wrapper_fn = decl_internal_fastcall_fn(ccx.llmod, s,
                                                         wrapper_type);
 
@@ -7912,9 +7936,8 @@ fn trans_constant(&@crate_ctxt ccx, @walk_ctxt wcx, &@ast::item it) {
 
                 auto discrim_val = C_int(i as int);
 
-                auto s = mangle_name_by_seq(ccx, wcx.path,
-                                            #fmt("_rust_tag_discrim_%s_%u",
-                                                 ident, i));
+                auto p = wcx.path + [ident, variant.node.name, "discrim"];
+                auto s = mangle_name_by_type(ccx, p, ty::mk_int(ccx.tcx));
                 auto discrim_gvar = llvm::LLVMAddGlobal(ccx.llmod, T_int(),
                                                        str::buf(s));
 
@@ -7973,29 +7996,6 @@ fn create_typedefs(&@crate_ctxt cx) {
     llvm::LLVMAddTypeName(cx.llmod, str::buf("tydesc"), T_tydesc(cx.tn));
 }
 
-fn find_main_fn(&@crate_ctxt cx) -> ValueRef {
-    auto e = sep() + "main";
-    let ValueRef v = C_nil();
-    let uint n = 0u;
-    for each (@tup(ast::def_id, str) i in cx.item_symbols.items()) {
-        if (str::ends_with(i._1, e)) {
-            n += 1u;
-            v = cx.item_ids.get(i._0);
-        }
-    }
-    alt (n) {
-        case (0u) {
-            cx.sess.err("main fn not found");
-        }
-        case (1u) {
-            ret v;
-        }
-        case (_) {
-            cx.sess.err("multiple main fns found");
-        }
-    }
-}
-
 fn trans_main_fn(@local_ctxt cx, ValueRef crate_map) {
     auto T_main_args = [T_int(), T_int()];
     auto T_rust_start_args = [T_int(), T_int(), T_int(), T_int()];
@@ -8015,7 +8015,14 @@ fn trans_main_fn(@local_ctxt cx, ValueRef crate_map) {
 
     auto llargc = llvm::LLVMGetParam(llmain, 0u);
     auto llargv = llvm::LLVMGetParam(llmain, 1u);
-    auto llrust_main = find_main_fn(cx.ccx);
+    auto llrust_main = alt (cx.ccx.main_fn) {
+        case (none) {
+            cx.ccx.sess.err("missing 'main' function");
+            // FIXME: shouldn't sess.err's ! result unify with f?
+            C_nil()
+        }
+        case (some(?f)) { f }
+    };
 
     //
     // Emit the moral equivalent of:
@@ -8283,6 +8290,7 @@ fn trans_crate(&session::session sess, &@ast::crate crate,
                     items = new_def_hash[@ast::item](),
                     native_items = new_def_hash[@ast::native_item](),
                     item_symbols = new_def_hash[str](),
+                    mutable main_fn = none[ValueRef],
                     tag_sizes = tag_sizes,
                     discrims = new_def_hash[ValueRef](),
                     discrim_symbols = new_def_hash[str](),
diff --git a/src/lib/vec.rs b/src/lib/vec.rs
index 8259e494e25..374b55ed9be 100644
--- a/src/lib/vec.rs
+++ b/src/lib/vec.rs
@@ -193,6 +193,12 @@ fn pop[T](&mutable array[T] v) -> T {
     ret e;
 }
 
+fn top[T](&array[T] v) -> T {
+    auto ln = len[T](v);
+    assert (ln > 0u);
+    ret v.(ln-1u);
+}
+
 fn push[T](&mutable array[T] v, &T t) {
     v += [t];
 }