summary refs log tree commit diff
path: root/src
diff options
context:
space:
mode:
authorJoshua Wise <joshua@joshuawise.com>2011-11-09 01:42:30 -0800
committerBrian Anderson <banderson@mozilla.com>2011-11-09 14:33:06 -0800
commitc8fae5dc75b8a5d1538e3c17ae34d087546da1f5 (patch)
tree8dc577ea73c5b74c3092a8b32fe6954c94645ec8 /src
parente674a7e99f6dacd5a743e8255f2014321f88ccc1 (diff)
downloadrust-c8fae5dc75b8a5d1538e3c17ae34d087546da1f5.tar.gz
rust-c8fae5dc75b8a5d1538e3c17ae34d087546da1f5.zip
trans: Add binops (except for logic and comparators) and unops to trans_const_expr. Working towards issue #570.
Diffstat (limited to 'src')
-rw-r--r--src/comp/middle/check_const.rs14
-rw-r--r--src/comp/middle/trans.rs66
2 files changed, 78 insertions, 2 deletions
diff --git a/src/comp/middle/check_const.rs b/src/comp/middle/check_const.rs
index db6094abbdc..59bfdadf62f 100644
--- a/src/comp/middle/check_const.rs
+++ b/src/comp/middle/check_const.rs
@@ -27,8 +27,20 @@ fn check_const_expr(tcx: ty::ctxt, ex: @expr, &&s: (), v: visit::vt<()>) {
     visit::visit_expr(ex, s, v);
     alt ex.node {
       expr_lit(_) { }
+      expr_binary(_, _, _) { /* subexps covered by visit */ }
+      expr_unary(u, _) {
+        alt u {
+          box(_)  |
+          uniq(_) |
+          deref.  {
+            tcx.sess.span_err(ex.span,
+                              "disallowed operator in constant expression");
+          }
+          _ { }
+        }
+      }
       _ { tcx.sess.span_err(ex.span,
-          "constant contains unimplemented expression type"); }
+            "constant contains unimplemented expression type"); }
     }
 }
 
diff --git a/src/comp/middle/trans.rs b/src/comp/middle/trans.rs
index e054d359bb9..5e25d53e810 100644
--- a/src/comp/middle/trans.rs
+++ b/src/comp/middle/trans.rs
@@ -5290,7 +5290,71 @@ fn trans_tag_variant(cx: @local_ctxt, tag_id: ast::node_id,
 fn trans_const_expr(cx: @crate_ctxt, e: @ast::expr) -> ValueRef {
     alt e.node {
       ast::expr_lit(lit) { ret trans_crate_lit(cx, *lit); }
-      _ { cx.sess.span_unimpl(e.span, "consts that's not a plain literal"); }
+      ast::expr_binary(b, e1, e2) {
+        let te1 = trans_const_expr(cx, e1);
+        let te2 = trans_const_expr(cx, e2);
+        /* Neither type is bottom, and we expect them to be unified already,
+         * so the following is safe. */
+        let ty = ty::expr_ty(ccx_tcx(cx), e1);
+        let is_float = ty::type_is_fp(ccx_tcx(cx), ty);
+        let signed = ty::type_is_signed(ccx_tcx(cx), ty);
+        ret alt b {
+          ast::add.    {
+            if is_float { llvm::LLVMConstFAdd(te1, te2) }
+            else        { llvm::LLVMConstAdd(te1, te2) }
+          }
+          ast::sub.    {
+            if is_float { llvm::LLVMConstFSub(te1, te2) }
+            else        { llvm::LLVMConstSub(te1, te2) }
+          }
+          ast::mul.    {
+            if is_float { llvm::LLVMConstFMul(te1, te2) }
+            else        { llvm::LLVMConstMul(te1, te2) }
+          }
+          ast::div.    {
+            if is_float    { llvm::LLVMConstFDiv(te1, te2) }
+            else if signed { llvm::LLVMConstSDiv(te1, te2) }
+            else           { llvm::LLVMConstUDiv(te1, te2) }
+          }
+          ast::rem.    {
+            if is_float    { llvm::LLVMConstFRem(te1, te2) }
+            else if signed { llvm::LLVMConstSRem(te1, te2) }
+            else           { llvm::LLVMConstURem(te1, te2) }
+          }
+          ast::and.    |
+          ast::or.     { cx.sess.span_unimpl(e.span, "binop logic"); }
+          ast::bitxor. { llvm::LLVMConstXor(te1, te2) }
+          ast::bitand. { llvm::LLVMConstAnd(te1, te2) }
+          ast::bitor.  { llvm::LLVMConstOr(te1, te2) }
+          ast::lsl.    { llvm::LLVMConstShl(te1, te2) }
+          ast::lsr.    { llvm::LLVMConstLShr(te1, te2) }
+          ast::asr.    { llvm::LLVMConstAShr(te1, te2) }
+          ast::eq.     |
+          ast::lt.     |
+          ast::le.     |
+          ast::ne.     |
+          ast::ge.     |
+          ast::gt.     { cx.sess.span_unimpl(e.span, "binop comparator"); }
+        }
+      }
+      ast::expr_unary(u, e) {
+        let te = trans_const_expr(cx, e);
+        let ty = ty::expr_ty(ccx_tcx(cx), e);
+        let is_float = ty::type_is_fp(ccx_tcx(cx), ty);
+        ret alt u {
+          ast::box(_)  |
+          ast::uniq(_) |
+          ast::deref.  { cx.sess.span_bug(e.span,
+                           "bad unop type in trans_const_expr"); }
+          ast::not.    { llvm::LLVMConstNot(te) }
+          ast::neg.    {
+            if is_float { llvm::LLVMConstFNeg(te) }
+            else        { llvm::LLVMConstNeg(te) }
+          }
+        }
+      }
+      _ { cx.sess.span_bug(e.span,
+            "bad constant expression type in trans_const_expr"); }
     }
 }