From e42fcb958cd89d11dbe8f493cfac0a1fca4b1bb1 Mon Sep 17 00:00:00 2001 From: Corey Richardson Date: Sun, 19 May 2013 16:03:52 -0400 Subject: [PATCH 1/3] Implement unimplemented const binops --- src/librustc/lib/llvm.rs | 5 ++ src/librustc/middle/trans/consts.rs | 56 +++++++++++--- src/test/run-pass/const-binops.rs | 116 ++++++++++++++++++++++++++++ 3 files changed, 165 insertions(+), 12 deletions(-) create mode 100644 src/test/run-pass/const-binops.rs diff --git a/src/librustc/lib/llvm.rs b/src/librustc/lib/llvm.rs index d06bf1480c989..cdc128c6eeb61 100644 --- a/src/librustc/lib/llvm.rs +++ b/src/librustc/lib/llvm.rs @@ -220,6 +220,7 @@ pub mod llvm { use super::{ObjectFileRef, Opcode, PassManagerRef, PassManagerBuilderRef}; use super::{SectionIteratorRef, TargetDataRef, TypeKind, TypeRef, UseRef}; use super::{ValueRef}; + use super::{IntPredicate, RealPredicate}; use core::libc::{c_char, c_int, c_longlong, c_uint, c_ulonglong}; @@ -451,6 +452,10 @@ pub mod llvm { /* all zeroes */ #[fast_ffi] pub unsafe fn LLVMConstAllOnes(Ty: TypeRef) -> ValueRef; + #[fast_ffi] + pub unsafe fn LLVMConstICmp(Pred: IntPredicate, V1: ValueRef, V2: ValueRef) -> ValueRef; + #[fast_ffi] + pub unsafe fn LLVMConstFCmp(Pred: RealPredicate, V1: ValueRef, V2: ValueRef) -> ValueRef; /* only for int/vector */ #[fast_ffi] pub unsafe fn LLVMGetUndef(Ty: TypeRef) -> ValueRef; diff --git a/src/librustc/middle/trans/consts.rs b/src/librustc/middle/trans/consts.rs index e08cc536a701f..6df523976f2b0 100644 --- a/src/librustc/middle/trans/consts.rs +++ b/src/librustc/middle/trans/consts.rs @@ -9,8 +9,10 @@ // except according to those terms. use back::abi; -use lib::llvm::{llvm, SetLinkage, PrivateLinkage, - ValueRef, TypeRef, Bool, True, False}; +use lib::llvm::{llvm, 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 +282,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 +292,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 { llvm::LLVMConstFCmp(RealOEQ, te1, te2) } + else { llvm::LLVMConstICmp(IntEQ, te1, te2) } + }, + ast::lt => { + if is_float { llvm::LLVMConstFCmp(RealOLT, te1, te2) } + else { + if signed { llvm::LLVMConstICmp(IntSLT, te1, te2) } + else { llvm::LLVMConstICmp(IntULT, te1, te2) } + } + }, + ast::le => { + if is_float { llvm::LLVMConstFCmp(RealOLE, te1, te2) } + else { + if signed { llvm::LLVMConstICmp(IntSLE, te1, te2) } + else { llvm::LLVMConstICmp(IntULE, te1, te2) } + } + }, + ast::ne => { + if is_float { llvm::LLVMConstFCmp(RealONE, te1, te2) } + else { llvm::LLVMConstICmp(IntNE, te1, te2) } + }, + ast::ge => { + if is_float { llvm::LLVMConstFCmp(RealOGE, te1, te2) } + else { + if signed { llvm::LLVMConstICmp(IntSGE, te1, te2) } + else { llvm::LLVMConstICmp(IntUGE, te1, te2) } + } + }, + ast::gt => { + if is_float { llvm::LLVMConstFCmp(RealOGT, te1, te2) } + else { + if signed { llvm::LLVMConstICmp(IntSGT, te1, te2) } + else { llvm::LLVMConstICmp(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 0000000000000..507f68dc3a146 --- /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; + +static ad: bool = 1 < 2; +static ae: bool = -1 < 2; +static af: bool = 1.0 < 2; + +static ag: bool = 1 != 2; +static ah: bool = -1 != 2; +static ai: bool = 1.0 != 2; + +static aj: bool = 2 >= 1; +static ak: bool = 2 >= -2; +static al: bool = 1.0 >= -2; + +static am: bool = 2 > 1; +static an: bool = 2 > -2; +static ao: bool = 1.0 > -2; + +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); +} From b97642758fb2c060ec689c540576d308fc081f1e Mon Sep 17 00:00:00 2001 From: Corey Richardson Date: Sun, 19 May 2013 20:18:56 -0400 Subject: [PATCH 2/3] Fix LLVMConst{I,F}Cmp --- src/librustc/lib/llvm.rs | 15 ++++++++++--- src/librustc/middle/trans/consts.rs | 35 +++++++++++++++-------------- 2 files changed, 30 insertions(+), 20 deletions(-) diff --git a/src/librustc/lib/llvm.rs b/src/librustc/lib/llvm.rs index cdc128c6eeb61..bf3d09d848dad 100644 --- a/src/librustc/lib/llvm.rs +++ b/src/librustc/lib/llvm.rs @@ -220,7 +220,6 @@ pub mod llvm { use super::{ObjectFileRef, Opcode, PassManagerRef, PassManagerBuilderRef}; use super::{SectionIteratorRef, TargetDataRef, TypeKind, TypeRef, UseRef}; use super::{ValueRef}; - use super::{IntPredicate, RealPredicate}; use core::libc::{c_char, c_int, c_longlong, c_uint, c_ulonglong}; @@ -453,9 +452,9 @@ pub mod llvm { #[fast_ffi] pub unsafe fn LLVMConstAllOnes(Ty: TypeRef) -> ValueRef; #[fast_ffi] - pub unsafe fn LLVMConstICmp(Pred: IntPredicate, V1: ValueRef, V2: ValueRef) -> ValueRef; + pub unsafe fn LLVMConstICmp(Pred: c_uint, V1: ValueRef, V2: ValueRef) -> ValueRef; #[fast_ffi] - pub unsafe fn LLVMConstFCmp(Pred: RealPredicate, V1: ValueRef, V2: ValueRef) -> ValueRef; + pub unsafe fn LLVMConstFCmp(Pred: c_uint, V1: ValueRef, V2: ValueRef) -> ValueRef; /* only for int/vector */ #[fast_ffi] pub unsafe fn LLVMGetUndef(Ty: TypeRef) -> ValueRef; @@ -1919,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_uint, V1, V2) + } +} +pub fn ConstFCmp(Pred: RealPredicate, V1: ValueRef, V2: ValueRef) -> ValueRef { + unsafe { + llvm::LLVMConstICmp(Pred as c_uint, 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 6df523976f2b0..22014fa330414 100644 --- a/src/librustc/middle/trans/consts.rs +++ b/src/librustc/middle/trans/consts.rs @@ -9,7 +9,8 @@ // 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}; @@ -293,39 +294,39 @@ fn const_expr_unadjusted(cx: @CrateContext, e: @ast::expr) -> ValueRef { else { llvm::LLVMConstLShr(te1, te2) } } ast::eq => { - if is_float { llvm::LLVMConstFCmp(RealOEQ, te1, te2) } - else { llvm::LLVMConstICmp(IntEQ, te1, te2) } + if is_float { ConstFCmp(RealOEQ, te1, te2) } + else { ConstICmp(IntEQ, te1, te2) } }, ast::lt => { - if is_float { llvm::LLVMConstFCmp(RealOLT, te1, te2) } + if is_float { ConstFCmp(RealOLT, te1, te2) } else { - if signed { llvm::LLVMConstICmp(IntSLT, te1, te2) } - else { llvm::LLVMConstICmp(IntULT, te1, te2) } + if signed { ConstICmp(IntSLT, te1, te2) } + else { ConstICmp(IntULT, te1, te2) } } }, ast::le => { - if is_float { llvm::LLVMConstFCmp(RealOLE, te1, te2) } + if is_float { ConstFCmp(RealOLE, te1, te2) } else { - if signed { llvm::LLVMConstICmp(IntSLE, te1, te2) } - else { llvm::LLVMConstICmp(IntULE, te1, te2) } + if signed { ConstICmp(IntSLE, te1, te2) } + else { ConstICmp(IntULE, te1, te2) } } }, ast::ne => { - if is_float { llvm::LLVMConstFCmp(RealONE, te1, te2) } - else { llvm::LLVMConstICmp(IntNE, te1, te2) } + if is_float { ConstFCmp(RealONE, te1, te2) } + else { ConstICmp(IntNE, te1, te2) } }, ast::ge => { - if is_float { llvm::LLVMConstFCmp(RealOGE, te1, te2) } + if is_float { ConstFCmp(RealOGE, te1, te2) } else { - if signed { llvm::LLVMConstICmp(IntSGE, te1, te2) } - else { llvm::LLVMConstICmp(IntUGE, te1, te2) } + if signed { ConstICmp(IntSGE, te1, te2) } + else { ConstICmp(IntUGE, te1, te2) } } }, ast::gt => { - if is_float { llvm::LLVMConstFCmp(RealOGT, te1, te2) } + if is_float { ConstFCmp(RealOGT, te1, te2) } else { - if signed { llvm::LLVMConstICmp(IntSGT, te1, te2) } - else { llvm::LLVMConstICmp(IntUGT, te1, te2) } + if signed { ConstICmp(IntSGT, te1, te2) } + else { ConstICmp(IntUGT, te1, te2) } } }, }; From 808c5b8d4e479b5e0fd336f8290fda2f0c429257 Mon Sep 17 00:00:00 2001 From: Corey Richardson Date: Sun, 19 May 2013 22:08:59 -0400 Subject: [PATCH 3/3] Test fixes, use LLVMConstFCmp in ConstFCmp --- src/librustc/lib/llvm.rs | 12 ++++++------ src/test/run-pass/const-binops.rs | 12 ++++++------ 2 files changed, 12 insertions(+), 12 deletions(-) diff --git a/src/librustc/lib/llvm.rs b/src/librustc/lib/llvm.rs index bf3d09d848dad..9198991e5360e 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"] @@ -452,9 +452,9 @@ pub mod llvm { #[fast_ffi] pub unsafe fn LLVMConstAllOnes(Ty: TypeRef) -> ValueRef; #[fast_ffi] - pub unsafe fn LLVMConstICmp(Pred: c_uint, V1: ValueRef, V2: ValueRef) -> ValueRef; + pub unsafe fn LLVMConstICmp(Pred: c_ushort, V1: ValueRef, V2: ValueRef) -> ValueRef; #[fast_ffi] - pub unsafe fn LLVMConstFCmp(Pred: c_uint, V1: ValueRef, V2: ValueRef) -> ValueRef; + 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; @@ -1920,12 +1920,12 @@ pub fn SetLinkage(Global: ValueRef, Link: Linkage) { pub fn ConstICmp(Pred: IntPredicate, V1: ValueRef, V2: ValueRef) -> ValueRef { unsafe { - llvm::LLVMConstICmp(Pred as c_uint, V1, V2) + llvm::LLVMConstICmp(Pred as c_ushort, V1, V2) } } pub fn ConstFCmp(Pred: RealPredicate, V1: ValueRef, V2: ValueRef) -> ValueRef { unsafe { - llvm::LLVMConstICmp(Pred as c_uint, V1, V2) + llvm::LLVMConstFCmp(Pred as c_ushort, V1, V2) } } /* Memory-managed object interface to type handles. */ diff --git a/src/test/run-pass/const-binops.rs b/src/test/run-pass/const-binops.rs index 507f68dc3a146..cd87ca3ab537e 100644 --- a/src/test/run-pass/const-binops.rs +++ b/src/test/run-pass/const-binops.rs @@ -38,23 +38,23 @@ static z: bool = 1.0 == 1.0; static aa: bool = 1 <= 2; static ab: bool = -1 <= 2; -static ac: bool = 1.0 <= 2; +static ac: bool = 1.0 <= 2.0; static ad: bool = 1 < 2; static ae: bool = -1 < 2; -static af: bool = 1.0 < 2; +static af: bool = 1.0 < 2.0; static ag: bool = 1 != 2; static ah: bool = -1 != 2; -static ai: bool = 1.0 != 2; +static ai: bool = 1.0 != 2.0; static aj: bool = 2 >= 1; static ak: bool = 2 >= -2; -static al: bool = 1.0 >= -2; +static al: bool = 1.0 >= -2.0; static am: bool = 2 > 1; static an: bool = 2 > -2; -static ao: bool = 1.0 > -2; +static ao: bool = 1.0 > -2.0; fn main() { assert_eq!(a, -1); @@ -63,7 +63,7 @@ fn main() { assert_eq!(c, -1); assert_eq!(d, 0); - assert_approx_eq!(e, -0.3); + assert_approx_eq!(e, 0.3); assert_eq!(e2, -9); assert_eq!(f, 9);