about summary refs log tree commit diff
path: root/src/comp
diff options
context:
space:
mode:
authorGraydon Hoare <graydon@mozilla.com>2011-01-05 15:31:35 -0800
committerGraydon Hoare <graydon@mozilla.com>2011-01-05 15:31:35 -0800
commit5d2a6c73ca5b0e082c3fb2a3eee40e18029355f9 (patch)
tree6318714f17b5298e3c81729dc988b028f928c7e9 /src/comp
parent4fca7d61dd83dbef35f386a96929a6139a0531a8 (diff)
downloadrust-5d2a6c73ca5b0e082c3fb2a3eee40e18029355f9.tar.gz
rust-5d2a6c73ca5b0e082c3fb2a3eee40e18029355f9.zip
Use uniform pair representation of functions everywhere, including static functions.
Diffstat (limited to 'src/comp')
-rw-r--r--src/comp/lib/llvm.rs19
-rw-r--r--src/comp/middle/trans.rs151
2 files changed, 132 insertions, 38 deletions
diff --git a/src/comp/lib/llvm.rs b/src/comp/lib/llvm.rs
index 792642ad855..624c56f93c4 100644
--- a/src/comp/lib/llvm.rs
+++ b/src/comp/lib/llvm.rs
@@ -42,6 +42,25 @@ const uint LLVMColdCallConv = 9u;
 const uint LLVMX86StdcallCallConv = 64u;
 const uint LLVMX86FastcallCallConv = 65u;
 
+
+const uint LLVMExternalLinkage = 0u;
+const uint LLVMAvailableExternallyLinkage = 1u;
+const uint LLVMLinkOnceAnyLinkage = 2u;
+const uint LLVMLinkOnceODRLinkage = 3u;
+const uint LLVMWeakAnyLinkage = 4u;
+const uint LLVMWeakODRLinkage = 5u;
+const uint LLVMAppendingLinkage = 6u;
+const uint LLVMInternalLinkage = 7u;
+const uint LLVMPrivateLinkage = 8u;
+const uint LLVMDLLImportLinkage = 9u;
+const uint LLVMDLLExportLinkage = 10u;
+const uint LLVMExternalWeakLinkage = 11u;
+const uint LLVMGhostLinkage = 12u;
+const uint LLVMCommonLinkage = 13u;
+const uint LLVMLinkerPrivateLinkage = 14u;
+const uint LLVMLinkerPrivateWeakLinkage = 15u;
+
+
 // Consts for the LLVM IntPredicate type, pre-cast to uint.
 // FIXME: as above.
 
diff --git a/src/comp/middle/trans.rs b/src/comp/middle/trans.rs
index 99ce2dff1c3..75a75b3fe6b 100644
--- a/src/comp/middle/trans.rs
+++ b/src/comp/middle/trans.rs
@@ -67,6 +67,8 @@ state type crate_ctxt = rec(session.session sess,
                             hashmap[ast.def_id, ValueRef] item_ids,
                             hashmap[ast.def_id, @ast.item] items,
                             hashmap[ast.def_id, @tag_info] tags,
+                            hashmap[ast.def_id, ValueRef] fn_pairs,
+                            hashmap[ast.def_id,()] obj_methods,
                             hashmap[@ty.t, ValueRef] tydescs,
                             vec[ast.obj_field] obj_fields,
                             @glue_fns glues,
@@ -193,7 +195,7 @@ fn T_fn(vec[TypeRef] inputs, TypeRef output) -> TypeRef {
                               False);
 }
 
-fn T_closure(TypeRef tfn) -> TypeRef {
+fn T_fn_pair(TypeRef tfn) -> TypeRef {
     ret T_struct(vec(T_ptr(tfn),
                      T_ptr(T_box(T_nil()))));
 }
@@ -389,7 +391,7 @@ fn type_of_inner(@crate_ctxt cx, @ty.t t) -> TypeRef {
             ret T_struct(tys);
         }
         case (ty.ty_fn(?args, ?out)) {
-            ret type_of_fn(cx, args, out);
+            ret T_fn_pair(type_of_fn(cx, args, out));
         }
         case (ty.ty_obj(?meths)) {
             auto th = mk_type_handle();
@@ -500,6 +502,8 @@ fn C_str(@crate_ctxt cx, str s) -> ValueRef {
                                 _str.buf(cx.names.next("str")));
     llvm.LLVMSetInitializer(g, sc);
     llvm.LLVMSetGlobalConstant(g, True);
+    llvm.LLVMSetLinkage(g, lib.llvm.LLVMPrivateLinkage
+                        as llvm.Linkage);
     ret g;
 }
 
@@ -679,6 +683,8 @@ fn make_tydesc(@crate_ctxt cx, @ty.t t) {
     auto gvar = llvm.LLVMAddGlobal(cx.llmod, val_ty(tydesc), _str.buf(name));
     llvm.LLVMSetInitializer(gvar, tydesc);
     llvm.LLVMSetGlobalConstant(gvar, True);
+    llvm.LLVMSetLinkage(gvar, lib.llvm.LLVMPrivateLinkage
+                        as llvm.Linkage);
     cx.tydescs.insert(t, gvar);
 }
 
@@ -1725,17 +1731,22 @@ fn trans_name(@block_ctxt cx, &ast.name n, &option.t[ast.def] dopt)
                     ret lval_mem(cx, cx.fcx.llobjfields.get(did));
                 }
                 case (ast.def_fn(?did)) {
-                    check (cx.fcx.ccx.item_ids.contains_key(did));
-                    ret lval_val(cx, cx.fcx.ccx.item_ids.get(did));
+                    check (cx.fcx.ccx.fn_pairs.contains_key(did));
+                    ret lval_val(cx, cx.fcx.ccx.fn_pairs.get(did));
                 }
                 case (ast.def_obj(?did)) {
-                    check (cx.fcx.ccx.item_ids.contains_key(did));
-                    ret lval_val(cx, cx.fcx.ccx.item_ids.get(did));
+                    check (cx.fcx.ccx.fn_pairs.contains_key(did));
+                    ret lval_val(cx, cx.fcx.ccx.fn_pairs.get(did));
                 }
                 case (ast.def_variant(?tid, ?vid)) {
                     check (cx.fcx.ccx.tags.contains_key(tid));
-                    check (cx.fcx.ccx.item_ids.contains_key(vid));
-                    ret lval_val(cx, cx.fcx.ccx.item_ids.get(vid));
+                    if (cx.fcx.ccx.fn_pairs.contains_key(vid)) {
+                        ret lval_val(cx, cx.fcx.ccx.fn_pairs.get(vid));
+                    } else {
+                        // Nullary variants are just scalar constants.
+                        check (cx.fcx.ccx.item_ids.contains_key(vid));
+                        ret lval_val(cx, cx.fcx.ccx.item_ids.get(vid));
+                    }
                 }
                 case (_) {
                     cx.fcx.ccx.sess.unimpl("def variant in trans");
@@ -1942,7 +1953,7 @@ impure fn trans_bind(@block_ctxt cx, @ast.expr f,
                      &ast.ann ann) -> result {
     auto f_res = trans_lval(cx, f);
     auto bcx = f_res.res.bcx;
-    auto pair_t = T_closure(node_type(cx.fcx.ccx, ann));
+    auto pair_t = node_type(cx.fcx.ccx, ann);
     auto pair_v = bcx.build.Alloca(pair_t);
     if (f_res.is_mem) {
         cx.fcx.ccx.sess.unimpl("re-binding existing function");
@@ -1959,19 +1970,18 @@ impure fn trans_call(@block_ctxt cx, @ast.expr f,
                      vec[@ast.expr] args, &ast.ann ann) -> result {
     auto f_res = trans_lval(cx, f);
     auto faddr = f_res.res.val;
-    if (f_res.is_mem) {
-        alt (f_res.llobj) {
-            case (some[ValueRef](_)) {
-                // It's a vtbl entry.
-                faddr = f_res.res.bcx.build.Load(faddr);
-            }
-            case (none[ValueRef]) {
-                // It's a closure.
-                auto bcx = f_res.res.bcx;
-                faddr = bcx.build.GEP(faddr, vec(C_int(0),
-                                                 C_int(abi.fn_field_code)));
-                faddr = bcx.build.Load(faddr);
-            }
+
+    alt (f_res.llobj) {
+        case (some[ValueRef](_)) {
+            // It's a vtbl entry.
+            faddr = f_res.res.bcx.build.Load(faddr);
+        }
+        case (none[ValueRef]) {
+            // It's a closure.
+            auto bcx = f_res.res.bcx;
+            faddr = bcx.build.GEP(faddr, vec(C_int(0),
+                                             C_int(abi.fn_field_code)));
+            faddr = bcx.build.Load(faddr);
         }
     }
     auto fn_ty = ty.expr_ty(f);
@@ -2701,6 +2711,8 @@ impure fn trans_vtbl(@crate_ctxt cx, TypeRef self_ty,
                                    _str.buf("_rust_vtbl" + "." + cx.path));
     llvm.LLVMSetInitializer(gvar, vtbl);
     llvm.LLVMSetGlobalConstant(gvar, True);
+    llvm.LLVMSetLinkage(gvar, lib.llvm.LLVMPrivateLinkage
+                        as llvm.Linkage);
     ret gvar;
 }
 
@@ -2818,15 +2830,8 @@ fn trans_tag_variant(@crate_ctxt cx, ast.def_id tag_id,
                            id=varg.id));
     }
 
-    auto var_ty = ty.ann_to_type(variant.ann);
-    auto llfnty = type_of(cx, var_ty);
-
-    let str s = cx.names.next("_rust_tag") + "." + cx.path;
-    let ValueRef llfn = decl_fastcall_fn(cx.llmod, s, llfnty);
-    cx.item_ids.insert(variant.id, llfn);
-
+    check (cx.item_ids.contains_key(variant.id));
     let ValueRef llfndecl = cx.item_ids.get(variant.id);
-    cx.item_names.insert(cx.path, llfndecl);
 
     auto fcx = new_fn_ctxt(cx, cx.path, llfndecl);
     create_llargs_for_fn_args(fcx, none[TypeRef], ret_ty_of_fn(variant.ann),
@@ -2907,25 +2912,59 @@ impure fn trans_mod(@crate_ctxt cx, &ast._mod m) {
     }
 }
 
+fn decl_fn_and_pair(@crate_ctxt cx,
+                    str kind,
+                    str name,
+                    &ast.ann ann,
+                    ast.def_id id) {
+
+    // Bit of a kludge: pick the fn typeref out of the pair.
+    auto llpairty = node_type(cx, ann);
+    let vec[TypeRef] pair_tys = vec(T_nil(), T_nil());
+    llvm.LLVMGetStructElementTypes(llpairty,
+                                   _vec.buf[TypeRef](pair_tys));
+    auto llfty = llvm.LLVMGetElementType(pair_tys.(0));
+
+    // Declare the function itself.
+    let str s = cx.names.next("_rust_" + kind) + "." + name;
+    let ValueRef llfn = decl_fastcall_fn(cx.llmod, s, llfty);
+
+    // Declare the global constant pair that points to it.
+    let str ps = cx.names.next("_rust_" + kind + "_pair") + "." + name;
+    let ValueRef gvar = llvm.LLVMAddGlobal(cx.llmod, llpairty,
+                                           _str.buf(ps));
+    auto pair = C_struct(vec(llfn,
+                             C_null(T_ptr(T_box(T_nil())))));
+
+    llvm.LLVMSetInitializer(gvar, pair);
+    llvm.LLVMSetGlobalConstant(gvar, True);
+    llvm.LLVMSetLinkage(gvar,
+                        lib.llvm.LLVMPrivateLinkage
+                        as llvm.Linkage);
+
+    cx.item_ids.insert(id, llfn);
+    cx.fn_pairs.insert(id, gvar);
+}
+
 
 fn collect_item(&@crate_ctxt cx, @ast.item i) -> @crate_ctxt {
+
     alt (i.node) {
         case (ast.item_fn(?name, ?f, _, ?fid, ?ann)) {
             // TODO: type-params
             cx.items.insert(fid, i);
-            auto llty = node_type(cx, ann);
-            let str s = cx.names.next("_rust_fn") + "." + name;
-            let ValueRef llfn = decl_fastcall_fn(cx.llmod, s, llty);
-            cx.item_ids.insert(fid, llfn);
+            if (! cx.obj_methods.contains_key(fid)) {
+                decl_fn_and_pair(cx, "fn", name, ann, fid);
+            }
         }
 
         case (ast.item_obj(?name, ?ob, _, ?oid, ?ann)) {
             // TODO: type-params
             cx.items.insert(oid, i);
-            auto llty = node_type(cx, ann);
-            let str s = cx.names.next("_rust_obj_ctor") + "." + name;
-            let ValueRef llfn = decl_fastcall_fn(cx.llmod, s, llty);
-            cx.item_ids.insert(oid, llfn);
+            decl_fn_and_pair(cx, "obj_ctor", name, ann, oid);
+            for (@ast.method m in ob.methods) {
+                cx.obj_methods.insert(m.node.id, ());
+            }
         }
 
         case (ast.item_const(?name, _, _, ?cid, _)) {
@@ -2963,6 +3002,36 @@ fn collect_items(@crate_ctxt cx, @ast.crate crate) {
     fold.fold_crate[@crate_ctxt](cx, fld, crate);
 }
 
+fn collect_tag_ctor(&@crate_ctxt cx, @ast.item i) -> @crate_ctxt {
+
+    alt (i.node) {
+
+        case (ast.item_tag(_, ?variants, _, _)) {
+            for (ast.variant variant in variants) {
+                if (_vec.len[ast.variant_arg](variant.args) != 0u) {
+                    decl_fn_and_pair(cx, "tag", variant.name,
+                                     variant.ann, variant.id);
+                }
+            }
+        }
+
+        case (_) { /* fall through */ }
+    }
+    ret cx;
+}
+
+fn collect_tag_ctors(@crate_ctxt cx, @ast.crate crate) {
+
+    let fold.ast_fold[@crate_ctxt] fld =
+        fold.new_identity_fold[@crate_ctxt]();
+
+    fld = @rec( update_env_for_item = bind collect_tag_ctor(_,_)
+                with *fld );
+
+    fold.fold_crate[@crate_ctxt](cx, fld, crate);
+}
+
+
 // The tag type resolution pass, which determines all the LLVM types that
 // correspond to each tag type in the crate.
 
@@ -3048,6 +3117,9 @@ fn trans_constant(&@crate_ctxt cx, @ast.item it) -> @crate_ctxt {
                                                        _str.buf("tag"));
                         llvm.LLVMSetInitializer(gvar, val);
                         llvm.LLVMSetGlobalConstant(gvar, True);
+                        llvm.LLVMSetLinkage(gvar,
+                                            lib.llvm.LLVMPrivateLinkage
+                                            as llvm.Linkage);
                         cx.item_ids.insert(variant_info._0, gvar);
                     }
                     case (n_ary) {
@@ -3281,6 +3353,8 @@ fn trans_crate(session.session sess, @ast.crate crate, str output,
                    item_ids = new_def_hash[ValueRef](),
                    items = new_def_hash[@ast.item](),
                    tags = new_def_hash[@tag_info](),
+                   fn_pairs = new_def_hash[ValueRef](),
+                   obj_methods = new_def_hash[()](),
                    tydescs = tydescs,
                    obj_fields = obj_fields,
                    glues = glues,
@@ -3291,6 +3365,7 @@ fn trans_crate(session.session sess, @ast.crate crate, str output,
 
     collect_items(cx, crate);
     resolve_tag_types(cx, crate);
+    collect_tag_ctors(cx, crate);
     trans_constants(cx, crate);
 
     trans_mod(cx, crate.node.module);