about summary refs log tree commit diff
path: root/src
diff options
context:
space:
mode:
authorGraydon Hoare <graydon@mozilla.com>2011-01-21 12:09:25 -0800
committerGraydon Hoare <graydon@mozilla.com>2011-01-21 12:09:25 -0800
commit90e329da6b263cde1fc286e2c4aa6d062a6acf8a (patch)
tree55b7a7b571be8752612e8eaaac69d07e34d03bef /src
parentc72d6a3e7a605d67ceff701465eff77b95dc2d32 (diff)
downloadrust-90e329da6b263cde1fc286e2c4aa6d062a6acf8a.tar.gz
rust-90e329da6b263cde1fc286e2c4aa6d062a6acf8a.zip
First cut at translating const items. Support the literal forms at least. Un-XFAIL const.rs.
Diffstat (limited to 'src')
-rw-r--r--src/Makefile1
-rw-r--r--src/comp/middle/trans.rs100
2 files changed, 75 insertions, 26 deletions
diff --git a/src/Makefile b/src/Makefile
index 4f27b434abf..385558b6062 100644
--- a/src/Makefile
+++ b/src/Makefile
@@ -432,6 +432,7 @@ TEST_XFAILS_RUSTC := $(filter-out \
                         cast.rs \
                         char.rs \
                         complex.rs \
+                        const.rs \
                         dead-code-one-arm-if.rs \
                         deep.rs \
                         deref.rs \
diff --git a/src/comp/middle/trans.rs b/src/comp/middle/trans.rs
index 57f5b002b65..49d8a7caeef 100644
--- a/src/comp/middle/trans.rs
+++ b/src/comp/middle/trans.rs
@@ -70,6 +70,7 @@ state type crate_ctxt = rec(session.session sess,
                             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, ValueRef] consts,
                             hashmap[ast.def_id,()] obj_methods,
                             hashmap[@ty.t, ValueRef] tydescs,
                             vec[ast.obj_field] obj_fields,
@@ -527,7 +528,9 @@ fn C_int(int i) -> ValueRef {
     ret C_integral(i, T_int());
 }
 
-fn C_str(@crate_ctxt cx, str s) -> ValueRef {
+// This is a 'c-like' raw string, which differs from
+// our boxed-and-length-annotated strings.
+fn C_cstr(@crate_ctxt cx, str s) -> ValueRef {
     auto sc = llvm.LLVMConstString(_str.buf(s), _str.byte_len(s), False);
     auto g = llvm.LLVMAddGlobal(cx.llmod, val_ty(sc),
                                 _str.buf(cx.names.next("str")));
@@ -538,6 +541,23 @@ fn C_str(@crate_ctxt cx, str s) -> ValueRef {
     ret g;
 }
 
+// A rust boxed-and-length-annotated string.
+fn C_str(@crate_ctxt cx, str s) -> ValueRef {
+    auto len = _str.byte_len(s);
+    auto box = C_struct(vec(C_int(abi.const_refcount as int),
+                            C_int(len + 1u as int), // 'alloc'
+                            C_int(len + 1u as int), // 'fill'
+                            llvm.LLVMConstString(_str.buf(s),
+                                                 len, False)));
+    auto g = llvm.LLVMAddGlobal(cx.llmod, val_ty(box),
+                                _str.buf(cx.names.next("str")));
+    llvm.LLVMSetInitializer(g, box);
+    llvm.LLVMSetGlobalConstant(g, True);
+    llvm.LLVMSetLinkage(g, lib.llvm.LLVMPrivateLinkage
+                        as llvm.Linkage);
+    ret llvm.LLVMConstPointerCast(g, T_ptr(T_str()));
+}
+
 fn C_zero_byte_arr(uint size) -> ValueRef {
     auto i = 0u;
     let vec[ValueRef] elts = vec();
@@ -1504,13 +1524,13 @@ fn copy_ty(@block_ctxt cx,
     fail;
 }
 
-fn trans_lit(@block_ctxt cx, &ast.lit lit, &ast.ann ann) -> result {
+fn trans_lit(@crate_ctxt cx, &ast.lit lit, &ast.ann ann) -> ValueRef {
     alt (lit.node) {
         case (ast.lit_int(?i)) {
-            ret res(cx, C_int(i));
+            ret C_int(i);
         }
         case (ast.lit_uint(?u)) {
-            ret res(cx, C_int(u as int));
+            ret C_int(u as int);
         }
         case (ast.lit_mach_int(?tm, ?i)) {
             // FIXME: the entire handling of mach types falls apart
@@ -1527,32 +1547,20 @@ fn trans_lit(@block_ctxt cx, &ast.lit lit, &ast.ann ann) -> result {
                 case (common.ty_i16) { t = T_i16(); }
                 case (common.ty_i32) { t = T_i32(); }
                 case (common.ty_i64) { t = T_i64(); }
-                case (_) {
-                    cx.fcx.ccx.sess.bug("bad mach int literal type");
-                }
             }
-            ret res(cx, C_integral(i, t));
+            ret C_integral(i, t);
         }
         case (ast.lit_char(?c)) {
-            ret res(cx, C_integral(c as int, T_char()));
+            ret C_integral(c as int, T_char());
         }
         case (ast.lit_bool(?b)) {
-            ret res(cx, C_bool(b));
+            ret C_bool(b);
         }
         case (ast.lit_nil) {
-            ret res(cx, C_nil());
+            ret C_nil();
         }
         case (ast.lit_str(?s)) {
-            auto len = (_str.byte_len(s) as int) + 1;
-            auto sub = trans_upcall(cx, "upcall_new_str",
-                                    vec(p2i(C_str(cx.fcx.ccx, s)),
-                                        C_int(len)));
-            auto val = sub.bcx.build.IntToPtr(sub.val,
-                                              T_ptr(T_str()));
-            auto t = node_ann_type(cx.fcx.ccx, ann);
-            find_scope_cx(cx).cleanups +=
-                clean(bind drop_ty(_, val, t));
-            ret res(sub.bcx, val);
+            ret C_str(cx, s);
         }
     }
 }
@@ -2087,6 +2095,10 @@ fn trans_path(@block_ctxt cx, &ast.path p, &option.t[ast.def] dopt,
                         ret lval_val(cx, cx.fcx.ccx.item_ids.get(vid));
                     }
                 }
+                case (ast.def_const(?did)) {
+                    check (cx.fcx.ccx.consts.contains_key(did));
+                    ret lval_mem(cx, cx.fcx.ccx.consts.get(did));
+                }
                 case (_) {
                     cx.fcx.ccx.sess.unimpl("def variant in trans");
                 }
@@ -2155,8 +2167,8 @@ fn trans_index(@block_ctxt cx, &ast.span sp, @ast.expr base,
     ix.bcx.build.CondBr(bounds_check, next_cx.llbb, fail_cx.llbb);
 
     // fail: bad bounds check.
-    auto V_expr_str = p2i(C_str(cx.fcx.ccx, "out-of-bounds access"));
-    auto V_filename = p2i(C_str(cx.fcx.ccx, sp.filename));
+    auto V_expr_str = p2i(C_cstr(cx.fcx.ccx, "out-of-bounds access"));
+    auto V_filename = p2i(C_cstr(cx.fcx.ccx, sp.filename));
     auto V_line = sp.lo.line as int;
     auto args = vec(V_expr_str, V_filename, C_int(V_line));
     auto fail_res = trans_upcall(fail_cx, "upcall_fail", args);
@@ -2667,7 +2679,7 @@ fn trans_rec(@block_ctxt cx, vec[ast.field] fields,
 fn trans_expr(@block_ctxt cx, @ast.expr e) -> result {
     alt (e.node) {
         case (ast.expr_lit(?lit, ?ann)) {
-            ret trans_lit(cx, *lit, ann);
+            ret res(cx, trans_lit(cx.fcx.ccx, *lit, ann));
         }
 
         case (ast.expr_unary(?op, ?x, ?ann)) {
@@ -2806,8 +2818,8 @@ fn trans_check_expr(@block_ctxt cx, @ast.expr e) -> result {
     auto cond_res = trans_expr(cx, e);
 
     // FIXME: need pretty-printer.
-    auto V_expr_str = p2i(C_str(cx.fcx.ccx, "<expr>"));
-    auto V_filename = p2i(C_str(cx.fcx.ccx, e.span.filename));
+    auto V_expr_str = p2i(C_cstr(cx.fcx.ccx, "<expr>"));
+    auto V_filename = p2i(C_cstr(cx.fcx.ccx, e.span.filename));
     auto V_line = e.span.lo.line as int;
     auto args = vec(V_expr_str, V_filename, C_int(V_line));
 
@@ -3495,6 +3507,37 @@ fn trans_tag_variant(@crate_ctxt cx, ast.def_id tag_id,
     bcx.build.Ret(lltagval);
 }
 
+// FIXME: this should do some structural hash-consing to avoid
+// duplicate constants. I think. Maybe LLVM has a magical mode
+// that does so later on?
+
+fn trans_const_expr(@crate_ctxt cx, @ast.expr e) -> ValueRef {
+    alt (e.node) {
+        case (ast.expr_lit(?lit, ?ann)) {
+            ret trans_lit(cx, *lit, ann);
+        }
+    }
+}
+
+fn trans_const(@crate_ctxt cx, @ast.expr e,
+               &ast.def_id cid, &ast.ann ann) {
+    auto t = node_ann_type(cx, ann);
+    auto v = trans_const_expr(cx, e);
+    if (ty.type_is_scalar(t)) {
+        // The scalars come back as 1st class LLVM vals
+        // which we have to stick into global constants.
+        auto g = llvm.LLVMAddGlobal(cx.llmod, val_ty(v),
+                                    _str.buf(cx.names.next(cx.path)));
+        llvm.LLVMSetInitializer(g, v);
+        llvm.LLVMSetGlobalConstant(g, True);
+        llvm.LLVMSetLinkage(g, lib.llvm.LLVMPrivateLinkage
+                            as llvm.Linkage);
+        cx.consts.insert(cid, g);
+    } else {
+        cx.consts.insert(cid, v);
+    }
+}
+
 fn trans_item(@crate_ctxt cx, &ast.item item) {
     alt (item.node) {
         case (ast.item_fn(?name, ?f, ?tps, ?fid, ?ann)) {
@@ -3518,6 +3561,10 @@ fn trans_item(@crate_ctxt cx, &ast.item item) {
                 i += 1;
             }
         }
+        case (ast.item_const(?name, _, ?expr, ?cid, ?ann)) {
+            auto sub_cx = @rec(path=cx.path + "." + name with *cx);
+            trans_const(sub_cx, expr, cid, ann);
+        }
         case (_) { /* fall through */ }
     }
 }
@@ -4055,6 +4102,7 @@ fn trans_crate(session.session sess, @ast.crate crate, str output,
                    items = new_def_hash[@ast.item](),
                    tags = new_def_hash[@tag_info](),
                    fn_pairs = new_def_hash[ValueRef](),
+                   consts = new_def_hash[ValueRef](),
                    obj_methods = new_def_hash[()](),
                    tydescs = tydescs,
                    obj_fields = obj_fields,