aboutsummaryrefslogtreecommitdiff
path: root/src/comp
diff options
context:
space:
mode:
authorGraydon Hoare <[email protected]>2011-01-05 15:31:35 -0800
committerGraydon Hoare <[email protected]>2011-01-05 15:31:35 -0800
commit5d2a6c73ca5b0e082c3fb2a3eee40e18029355f9 (patch)
tree6318714f17b5298e3c81729dc988b028f928c7e9 /src/comp
parentFix Yet Another Horrid Makefile Bug that was causing the run-fail tests to si... (diff)
downloadrust-5d2a6c73ca5b0e082c3fb2a3eee40e18029355f9.tar.xz
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 792642ad..624c56f9 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 99ce2dff..75a75b3f 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);