about summary refs log tree commit diff
diff options
context:
space:
mode:
authorbors <bors@rust-lang.org>2013-02-19 19:04:28 -0800
committerbors <bors@rust-lang.org>2013-02-19 19:04:28 -0800
commitdb25210244f1eca61c63aff139185812e2da3e9b (patch)
tree2d3f1273725fa8d6e64a8f106243767278c180e8
parentb88e4f3b9f5331a3159c754fa17f906a827ef6fd (diff)
parentfa6e3b49bf74dbfb18c7ac1996c8c054c5673f10 (diff)
downloadrust-db25210244f1eca61c63aff139185812e2da3e9b.tar.gz
rust-db25210244f1eca61c63aff139185812e2da3e9b.zip
auto merge of #5044 : thestinger/rust/range, r=pcwalton
Closes #4924

There are some more `Load` calls that could use this, so it's not completely done yet.
-rw-r--r--src/librustc/lib/llvm.rs9
-rw-r--r--src/librustc/middle/trans/_match.rs20
-rw-r--r--src/librustc/middle/trans/build.rs22
-rw-r--r--src/librustc/middle/trans/datum.rs8
4 files changed, 55 insertions, 4 deletions
diff --git a/src/librustc/lib/llvm.rs b/src/librustc/lib/llvm.rs
index c58ab494ed3..694cfb94e96 100644
--- a/src/librustc/lib/llvm.rs
+++ b/src/librustc/lib/llvm.rs
@@ -184,6 +184,15 @@ pub enum FileType {
     ObjectFile = 1
 }
 
+pub enum Metadata {
+    MD_dbg = 0,
+    MD_tbaa = 1,
+    MD_prof = 2,
+    MD_fpmath = 3,
+    MD_range = 4,
+    MD_tbaa_struct = 5
+}
+
 // Opaque pointer types
 pub enum Module_opaque {}
 pub type ModuleRef = *Module_opaque;
diff --git a/src/librustc/middle/trans/_match.rs b/src/librustc/middle/trans/_match.rs
index a6813997ae8..962d5dbfbf0 100644
--- a/src/librustc/middle/trans/_match.rs
+++ b/src/librustc/middle/trans/_match.rs
@@ -1361,13 +1361,29 @@ pub fn compile_submatch(bcx: block,
     if opts.len() > 0u {
         match opts[0] {
             var(_, vdef) => {
-                if (*ty::enum_variants(tcx, vdef.enm)).len() == 1u {
+                let variants = ty::enum_variants(tcx, vdef.enm);
+                if variants.len() == 1 {
                     kind = single;
                 } else {
                     let enumptr =
                         PointerCast(bcx, val, T_opaque_enum_ptr(ccx));
                     let discrimptr = GEPi(bcx, enumptr, [0u, 0u]);
-                    test_val = Load(bcx, discrimptr);
+
+
+                    assert variants.len() > 1;
+                    let min_discrim = do variants.foldr(0) |&x, y| {
+                        int::min(x.disr_val, y)
+                    };
+                    let max_discrim = do variants.foldr(0) |&x, y| {
+                        int::max(x.disr_val, y)
+                    };
+
+                    test_val = LoadRangeAssert(bcx, discrimptr,
+                                               min_discrim as c_ulonglong,
+                                               (max_discrim + 1)
+                                               as c_ulonglong,
+                                               lib::llvm::True);
+
                     kind = switch;
                 }
             }
diff --git a/src/librustc/middle/trans/build.rs b/src/librustc/middle/trans/build.rs
index da9dcc7c9af..85e8be09878 100644
--- a/src/librustc/middle/trans/build.rs
+++ b/src/librustc/middle/trans/build.rs
@@ -14,8 +14,9 @@ use lib::llvm::llvm;
 use lib::llvm::{CallConv, TypeKind, AtomicBinOp, AtomicOrdering};
 use lib::llvm::{Opcode, IntPredicate, RealPredicate, True, False};
 use lib::llvm::{ValueRef, TypeRef, BasicBlockRef, BuilderRef, ModuleRef};
-use libc::{c_uint, c_int};
+use libc::{c_uint, c_int, c_ulonglong};
 use middle::trans::common::*;
+use middle::trans::machine::llsize_of_real;
 
 use core::cast::transmute;
 use core::cast;
@@ -536,6 +537,25 @@ pub fn Load(cx: block, PointerVal: ValueRef) -> ValueRef {
     }
 }
 
+pub fn LoadRangeAssert(cx: block, PointerVal: ValueRef, lo: c_ulonglong,
+                       hi: c_ulonglong, signed: lib::llvm::Bool) -> ValueRef {
+    let value = Load(cx, PointerVal);
+
+    unsafe {
+        let t = llvm::LLVMGetElementType(llvm::LLVMTypeOf(PointerVal));
+        let min = llvm::LLVMConstInt(t, lo, signed);
+        let max = llvm::LLVMConstInt(t, hi, signed);
+
+
+        do vec::as_imm_buf([min, max]) |ptr, len| {
+            llvm::LLVMSetMetadata(value, lib::llvm::MD_range as c_uint,
+                                  llvm::LLVMMDNode(ptr, len as c_uint));
+        }
+    }
+
+    value
+}
+
 pub fn Store(cx: block, Val: ValueRef, Ptr: ValueRef) {
     unsafe {
         if cx.unreachable { return; }
diff --git a/src/librustc/middle/trans/datum.rs b/src/librustc/middle/trans/datum.rs
index 206ee50111f..9db06cea423 100644
--- a/src/librustc/middle/trans/datum.rs
+++ b/src/librustc/middle/trans/datum.rs
@@ -431,7 +431,13 @@ pub impl Datum {
         } else {
             match self.mode {
                 ByValue => self.val,
-                ByRef => Load(bcx, self.val)
+                ByRef => {
+                    if ty::type_is_bool(self.ty) {
+                        LoadRangeAssert(bcx, self.val, 0, 2, lib::llvm::True)
+                    } else {
+                        Load(bcx, self.val)
+                    }
+                }
             }
         }
     }