about summary refs log tree commit diff
path: root/src
diff options
context:
space:
mode:
authorbors <bors@rust-lang.org>2013-05-19 19:40:39 -0700
committerbors <bors@rust-lang.org>2013-05-19 19:40:39 -0700
commitcab9249c62d5f33b3ae625970c05231341d2f95e (patch)
tree6a0283f033157217e3b2315951562acd70ddc2e5 /src
parent9283dfe0b4dfbad176821ed93df6d519ad58423a (diff)
parent808c5b8d4e479b5e0fd336f8290fda2f0c429257 (diff)
auto merge of #6625 : cmr/rust/constops, r=Aatch
Diffstat (limited to 'src')
-rw-r--r--src/librustc/lib/llvm.rs18
-rw-r--r--src/librustc/middle/trans/consts.rs57
-rw-r--r--src/test/run-pass/const-binops.rs116
3 files changed, 177 insertions, 14 deletions
diff --git a/src/librustc/lib/llvm.rs b/src/librustc/lib/llvm.rs
index d06bf1480c9..9198991e536 100644
--- a/src/librustc/lib/llvm.rs
+++ b/src/librustc/lib/llvm.rs
@@ -9,7 +9,7 @@
 // except according to those terms.
 
 use core::hashmap::HashMap;
-use core::libc::c_uint;
+use core::libc::{c_uint, c_ushort};
 
 pub type Opcode = u32;
 pub type Bool = c_uint;
@@ -221,7 +221,7 @@ pub mod llvm {
     use super::{SectionIteratorRef, TargetDataRef, TypeKind, TypeRef, UseRef};
     use super::{ValueRef};
 
-    use core::libc::{c_char, c_int, c_longlong, c_uint, c_ulonglong};
+    use core::libc::{c_char, c_int, c_longlong, c_ushort, c_uint, c_ulonglong};
 
     #[link_args = "-Lrustllvm -lrustllvm"]
     #[link_name = "rustllvm"]
@@ -451,6 +451,10 @@ pub mod llvm {
         /* all zeroes */
         #[fast_ffi]
         pub unsafe fn LLVMConstAllOnes(Ty: TypeRef) -> ValueRef;
+        #[fast_ffi]
+        pub unsafe fn LLVMConstICmp(Pred: c_ushort, V1: ValueRef, V2: ValueRef) -> ValueRef;
+        #[fast_ffi]
+        pub unsafe fn LLVMConstFCmp(Pred: c_ushort, V1: ValueRef, V2: ValueRef) -> ValueRef;
         /* only for int/vector */
         #[fast_ffi]
         pub unsafe fn LLVMGetUndef(Ty: TypeRef) -> ValueRef;
@@ -1914,6 +1918,16 @@ pub fn SetLinkage(Global: ValueRef, Link: Linkage) {
     }
 }
 
+pub fn ConstICmp(Pred: IntPredicate, V1: ValueRef, V2: ValueRef) -> ValueRef {
+    unsafe {
+        llvm::LLVMConstICmp(Pred as c_ushort, V1, V2)
+    }
+}
+pub fn ConstFCmp(Pred: RealPredicate, V1: ValueRef, V2: ValueRef) -> ValueRef {
+    unsafe {
+        llvm::LLVMConstFCmp(Pred as c_ushort, V1, V2)
+    }
+}
 /* Memory-managed object interface to type handles. */
 
 pub struct TypeNames {
diff --git a/src/librustc/middle/trans/consts.rs b/src/librustc/middle/trans/consts.rs
index e08cc536a70..22014fa3304 100644
--- a/src/librustc/middle/trans/consts.rs
+++ b/src/librustc/middle/trans/consts.rs
@@ -9,8 +9,11 @@
 // except according to those terms.
 
 use back::abi;
-use lib::llvm::{llvm, SetLinkage, PrivateLinkage,
-                ValueRef, TypeRef, Bool, True, False};
+use lib::llvm::{llvm, ConstFCmp, ConstICmp, SetLinkage, PrivateLinkage, ValueRef, TypeRef, Bool,
+    True, False};
+use lib::llvm::{IntEQ, IntNE, IntUGT, IntUGE, IntULT, IntULE, IntSGT, IntSGE, IntSLT, IntSLE,
+    RealOEQ, RealOGT, RealOGE, RealOLT, RealOLE, RealONE};
+
 use metadata::csearch;
 use middle::const_eval;
 use middle::trans::adt;
@@ -280,8 +283,8 @@ fn const_expr_unadjusted(cx: @CrateContext, e: @ast::expr) -> ValueRef {
                 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::and    => llvm::LLVMConstAnd(te1, te2),
+              ast::or     => llvm::LLVMConstOr(te1, te2),
               ast::bitxor => llvm::LLVMConstXor(te1, te2),
               ast::bitand => llvm::LLVMConstAnd(te1, te2),
               ast::bitor  => llvm::LLVMConstOr(te1, te2),
@@ -290,14 +293,44 @@ fn const_expr_unadjusted(cx: @CrateContext, e: @ast::expr) -> ValueRef {
                 if signed { llvm::LLVMConstAShr(te1, te2) }
                 else      { llvm::LLVMConstLShr(te1, te2) }
               }
-              ast::eq     |
-              ast::lt     |
-              ast::le     |
-              ast::ne     |
-              ast::ge     |
-              ast::gt     => cx.sess.span_unimpl(e.span, "binop comparator")
-            }
-          }
+              ast::eq     => {
+                  if is_float { ConstFCmp(RealOEQ, te1, te2) }
+                  else        { ConstICmp(IntEQ, te1, te2)   }
+              },
+              ast::lt     => {
+                  if is_float { ConstFCmp(RealOLT, te1, te2) }
+                  else        {
+                      if signed { ConstICmp(IntSLT, te1, te2) }
+                      else      { ConstICmp(IntULT, te1, te2) }
+                  }
+              },
+              ast::le     => {
+                  if is_float { ConstFCmp(RealOLE, te1, te2) }
+                  else        {
+                      if signed { ConstICmp(IntSLE, te1, te2) }
+                      else      { ConstICmp(IntULE, te1, te2) }
+                  }
+              },
+              ast::ne     => {
+                  if is_float { ConstFCmp(RealONE, te1, te2) }
+                  else        { ConstICmp(IntNE, te1, te2) }
+              },
+              ast::ge     => {
+                  if is_float { ConstFCmp(RealOGE, te1, te2) }
+                  else        {
+                      if signed { ConstICmp(IntSGE, te1, te2) }
+                      else      { ConstICmp(IntUGE, te1, te2) }
+                  }
+              },
+              ast::gt     => {
+                  if is_float { ConstFCmp(RealOGT, te1, te2) }
+                  else        {
+                      if signed { ConstICmp(IntSGT, te1, te2) }
+                      else      { ConstICmp(IntUGT, te1, te2) }
+                  }
+              },
+            };
+          },
           ast::expr_unary(u, e) => {
             let te = const_expr(cx, e);
             let ty = ty::expr_ty(cx.tcx, e);
diff --git a/src/test/run-pass/const-binops.rs b/src/test/run-pass/const-binops.rs
new file mode 100644
index 00000000000..cd87ca3ab53
--- /dev/null
+++ b/src/test/run-pass/const-binops.rs
@@ -0,0 +1,116 @@
+static a: int = -4 + 3;
+static a2: uint = 3 + 3;
+static b: float = 3.0 + 2.7;
+
+static c: int = 3 - 4;
+static d: uint = 3 - 3;
+static e: float = 3.0 - 2.7;
+
+static e2: int = -3 * 3;
+static f: uint = 3 * 3;
+static g: float = 3.3 * 3.3;
+
+static h: int = 3 / -1;
+static i: uint = 3 / 3;
+static j: float = 3.3 / 3.3;
+
+static n: bool = true && false;
+
+static o: bool = true || false;
+
+static p: int = 3 & 1;
+static q: uint = 1 & 3;
+
+static r: int = 3 | 1;
+static s: uint = 1 | 3;
+
+static t: int = 3 ^ 1;
+static u: uint = 1 ^ 3;
+
+static v: int = 1 << 3;
+
+// NOTE: better shr coverage
+static w: int = 1024 >> 4;
+static x: uint = 1024 >> 4;
+
+static y: bool = 1 == 1;
+static z: bool = 1.0 == 1.0;
+
+static aa: bool = 1 <= 2;
+static ab: bool = -1 <= 2;
+static ac: bool = 1.0 <= 2.0;
+
+static ad: bool = 1 < 2;
+static ae: bool = -1 < 2;
+static af: bool = 1.0 < 2.0;
+
+static ag: bool = 1 != 2;
+static ah: bool = -1 != 2;
+static ai: bool = 1.0 != 2.0;
+
+static aj: bool = 2 >= 1;
+static ak: bool = 2 >= -2;
+static al: bool = 1.0 >= -2.0;
+
+static am: bool = 2 > 1;
+static an: bool = 2 > -2;
+static ao: bool = 1.0 > -2.0;
+
+fn main() {
+    assert_eq!(a, -1);
+    assert_eq!(a2, 6);
+    assert_approx_eq!(b, 5.7);
+
+    assert_eq!(c, -1);
+    assert_eq!(d, 0);
+    assert_approx_eq!(e, 0.3);
+
+    assert_eq!(e2, -9);
+    assert_eq!(f, 9);
+    assert_approx_eq!(g, 10.89);
+
+    assert_eq!(h, -3);
+    assert_eq!(i, 1);
+    assert_approx_eq!(j, 1.0);
+
+    assert_eq!(n, false);
+
+    assert_eq!(o, true);
+
+    assert_eq!(p, 1);
+    assert_eq!(q, 1);
+
+    assert_eq!(r, 3);
+    assert_eq!(s, 3);
+
+    assert_eq!(t, 2);
+    assert_eq!(u, 2);
+
+    assert_eq!(v, 8);
+
+    assert_eq!(w, 64);
+    assert_eq!(x, 64);
+
+    assert_eq!(y, true);
+    assert_eq!(z, true);
+
+    assert_eq!(aa, true);
+    assert_eq!(ab, true);
+    assert_eq!(ac, true);
+
+    assert_eq!(ad, true);
+    assert_eq!(ae, true);
+    assert_eq!(af, true);
+
+    assert_eq!(ag, true);
+    assert_eq!(ah, true);
+    assert_eq!(ai, true);
+
+    assert_eq!(aj, true);
+    assert_eq!(ak, true);
+    assert_eq!(al, true);
+
+    assert_eq!(am, true);
+    assert_eq!(an, true);
+    assert_eq!(ao, true);
+}