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.
This commit is contained in:
bors 2013-02-19 19:04:28 -08:00
commit db25210244
4 changed files with 55 additions and 4 deletions

View file

@ -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;

View file

@ -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;
}
}

View file

@ -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; }

View file

@ -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)
}
}
}
}
}