about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--src/rustc/middle/check_const.rs8
-rw-r--r--src/rustc/middle/trans/consts.rs49
-rw-r--r--src/test/run-pass/const-region-ptrs.rs4
-rw-r--r--src/test/run-pass/const-vecs-and-slices.rs7
4 files changed, 58 insertions, 10 deletions
diff --git a/src/rustc/middle/check_const.rs b/src/rustc/middle/check_const.rs
index dbf60edca8e..3d485338ffb 100644
--- a/src/rustc/middle/check_const.rs
+++ b/src/rustc/middle/check_const.rs
@@ -66,10 +66,7 @@ fn check_expr(sess: session, def_map: resolve3::DefMap,
                           ~"disallowed operator in constant expression");
             return;
           }
-          expr_lit(@{node: lit_str(_), _}) {
-            sess.span_err(e.span,
-                          ~"string constants are not supported");
-          }
+          expr_lit(@{node: lit_str(_), _}) { }
           expr_binary(_, _, _) | expr_unary(_, _) {
             if method_map.contains_key(e.id) {
                 sess.span_err(e.span, ~"user-defined operators are not \
@@ -101,6 +98,9 @@ fn check_expr(sess: session, def_map: resolve3::DefMap,
               }
             }
           }
+          expr_vstore(_, vstore_slice(_)) |
+          expr_vstore(_, vstore_fixed(_)) |
+          expr_vec(_, m_imm) |
           expr_addr_of(m_imm, _) |
           expr_tup(*) |
           expr_rec(*) { }
diff --git a/src/rustc/middle/trans/consts.rs b/src/rustc/middle/trans/consts.rs
index 8a8e284b5c0..03c0b303c09 100644
--- a/src/rustc/middle/trans/consts.rs
+++ b/src/rustc/middle/trans/consts.rs
@@ -25,21 +25,29 @@ fn const_lit(cx: @crate_ctxt, e: @ast::expr, lit: ast::lit)
       ast::lit_float(fs, t) { C_floating(*fs, T_float_ty(cx, t)) }
       ast::lit_bool(b) { C_bool(b) }
       ast::lit_nil { C_nil() }
-      ast::lit_str(s) {
-        cx.sess.span_unimpl(lit.span, ~"unique string in this context");
-      }
+      ast::lit_str(s) { C_estr_slice(cx, *s) }
     }
 }
 
 // FIXME (#2530): 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 const_vec_and_sz(cx: @crate_ctxt, e: @ast::expr, es: &[@ast::expr])
+    -> (ValueRef, ValueRef) {
+    let vec_ty = ty::expr_ty(cx.tcx, e);
+    let unit_ty = ty::sequence_element_type(cx.tcx, vec_ty);
+    let llunitty = type_of::type_of(cx, unit_ty);
+    let v = C_array(llunitty, es.map(|e| const_expr(cx, e)));
+    let unit_sz = shape::llsize_of(cx, llunitty);
+    let sz = llvm::LLVMConstMul(C_uint(cx, es.len()), unit_sz);
+    return (v, sz);
+}
+
 fn const_expr(cx: @crate_ctxt, e: @ast::expr) -> ValueRef {
     let _icx = cx.insn_ctxt(~"const_expr");
     alt e.node {
       ast::expr_lit(lit) { consts::const_lit(cx, e, *lit) }
-      // If we have a vstore, just keep going; it has to be a string
-      ast::expr_vstore(e, _) { const_expr(cx, e) }
       ast::expr_binary(b, e1, e2) {
         let te1 = const_expr(cx, e1);
         let te2 = const_expr(cx, e2);
@@ -147,6 +155,37 @@ fn const_expr(cx: @crate_ctxt, e: @ast::expr) -> ValueRef {
       ast::expr_rec(fs, none) {
         C_struct(fs.map(|f| const_expr(cx, f.node.expr)))
       }
+      ast::expr_vec(es, m_imm) {
+        let (v, _) = const_vec_and_sz(cx, e, es);
+        v
+      }
+      ast::expr_vstore(e, ast::vstore_fixed(_)) {
+        const_expr(cx, e)
+      }
+      ast::expr_vstore(sub, ast::vstore_slice(_)) {
+        alt sub.node {
+          ast::expr_lit(lit) {
+            alt lit.node {
+              ast::lit_str(*) => { const_expr(cx, sub) }
+              _ => { cx.sess.span_bug(e.span,
+                                      ~"bad const-slice lit") }
+            }
+          }
+          ast::expr_vec(es, m_imm) => {
+            let (cv, sz) = const_vec_and_sz(cx, e, es);
+            let subty = ty::expr_ty(cx.tcx, sub),
+            llty = type_of::type_of(cx, subty);
+            let gv = do str::as_c_str("const") |name| {
+                llvm::LLVMAddGlobal(cx.llmod, llty, name)
+            };
+            llvm::LLVMSetInitializer(gv, cv);
+            llvm::LLVMSetGlobalConstant(gv, True);
+            C_struct(~[gv, sz])
+          }
+          _ => cx.sess.span_bug(e.span,
+                                ~"bad const-slice expr")
+        }
+      }
       ast::expr_path(path) {
         alt cx.tcx.def_map.find(e.id) {
           some(ast::def_const(def_id)) {
diff --git a/src/test/run-pass/const-region-ptrs.rs b/src/test/run-pass/const-region-ptrs.rs
index 2ce212c158d..4fb90af66a2 100644
--- a/src/test/run-pass/const-region-ptrs.rs
+++ b/src/test/run-pass/const-region-ptrs.rs
@@ -4,6 +4,8 @@ const x: &int = &10;
 const y: &{a: int, b: &int} = &{a: 15, b: x};
 
 fn main() {
-    io::println(fmt!("x = %?", x));
+    io::println(fmt!("x = %?", *x));
     io::println(fmt!("y = {a: %?, b: %?}", y.a, *(y.b)));
+    assert *x == 10;
+    assert *(y.b) == 10;
 }
diff --git a/src/test/run-pass/const-vecs-and-slices.rs b/src/test/run-pass/const-vecs-and-slices.rs
new file mode 100644
index 00000000000..4e5b7e81e9a
--- /dev/null
+++ b/src/test/run-pass/const-vecs-and-slices.rs
@@ -0,0 +1,7 @@
+const x : [int]/4 = [1,2,3,4];
+
+fn main() {
+    io::println(fmt!("%?", x[1]));
+    assert x[1] == 2;
+    assert x[3] == 4;
+}
\ No newline at end of file