diff --git a/src/librustc/middle/trans/base.rs b/src/librustc/middle/trans/base.rs index a65f6668cd3..d0ce66da43f 100644 --- a/src/librustc/middle/trans/base.rs +++ b/src/librustc/middle/trans/base.rs @@ -2396,6 +2396,30 @@ fn declare_intrinsics(llmod: ModuleRef) -> HashMap<~str, ValueRef> { T_fn(~[T_f32()], T_f32())); let truncf64 = decl_cdecl_fn(llmod, ~"llvm.trunc.f64", T_fn(~[T_f64()], T_f64())); + let ctpop8 = decl_cdecl_fn(llmod, ~"llvm.ctpop.i8", + T_fn(~[T_i8()], T_i8())); + let ctpop16 = decl_cdecl_fn(llmod, ~"llvm.ctpop.i16", + T_fn(~[T_i16()], T_i16())); + let ctpop32 = decl_cdecl_fn(llmod, ~"llvm.ctpop.i32", + T_fn(~[T_i32()], T_i32())); + let ctpop64 = decl_cdecl_fn(llmod, ~"llvm.ctpop.i64", + T_fn(~[T_i64()], T_i64())); + let ctlz8 = decl_cdecl_fn(llmod, ~"llvm.ctlz.i8", + T_fn(~[T_i8(), T_i1()], T_i8())); + let ctlz16 = decl_cdecl_fn(llmod, ~"llvm.ctlz.i16", + T_fn(~[T_i16(), T_i1()], T_i16())); + let ctlz32 = decl_cdecl_fn(llmod, ~"llvm.ctlz.i32", + T_fn(~[T_i32(), T_i1()], T_i32())); + let ctlz64 = decl_cdecl_fn(llmod, ~"llvm.ctlz.i64", + T_fn(~[T_i64(), T_i1()], T_i64())); + let cttz8 = decl_cdecl_fn(llmod, ~"llvm.cttz.i8", + T_fn(~[T_i8(), T_i1()], T_i8())); + let cttz16 = decl_cdecl_fn(llmod, ~"llvm.cttz.i16", + T_fn(~[T_i16(), T_i1()], T_i16())); + let cttz32 = decl_cdecl_fn(llmod, ~"llvm.cttz.i32", + T_fn(~[T_i32(), T_i1()], T_i32())); + let cttz64 = decl_cdecl_fn(llmod, ~"llvm.cttz.i64", + T_fn(~[T_i64(), T_i1()], T_i64())); let intrinsics = HashMap(); intrinsics.insert(~"llvm.gcroot", gcroot); @@ -2436,6 +2460,18 @@ fn declare_intrinsics(llmod: ModuleRef) -> HashMap<~str, ValueRef> { intrinsics.insert(~"llvm.ceil.f64", ceilf64); intrinsics.insert(~"llvm.trunc.f32", truncf32); intrinsics.insert(~"llvm.trunc.f64", truncf64); + intrinsics.insert(~"llvm.ctpop.i8", ctpop8); + intrinsics.insert(~"llvm.ctpop.i16", ctpop16); + intrinsics.insert(~"llvm.ctpop.i32", ctpop32); + intrinsics.insert(~"llvm.ctpop.i64", ctpop64); + intrinsics.insert(~"llvm.ctlz.i8", ctlz8); + intrinsics.insert(~"llvm.ctlz.i16", ctlz16); + intrinsics.insert(~"llvm.ctlz.i32", ctlz32); + intrinsics.insert(~"llvm.ctlz.i64", ctlz64); + intrinsics.insert(~"llvm.cttz.i8", cttz8); + intrinsics.insert(~"llvm.cttz.i16", cttz16); + intrinsics.insert(~"llvm.cttz.i32", cttz32); + intrinsics.insert(~"llvm.cttz.i64", cttz64); return intrinsics; } diff --git a/src/librustc/middle/trans/foreign.rs b/src/librustc/middle/trans/foreign.rs index 38c3a4f7cb3..e7cdf82fd15 100644 --- a/src/librustc/middle/trans/foreign.rs +++ b/src/librustc/middle/trans/foreign.rs @@ -1194,6 +1194,74 @@ fn trans_intrinsic(ccx: @crate_ctxt, decl: ValueRef, item: @ast::foreign_item, let truncf = ccx.intrinsics.get(~"llvm.trunc.f64"); Store(bcx, Call(bcx, truncf, ~[x]), fcx.llretptr); } + ~"ctpop8" => { + let x = get_param(decl, first_real_arg); + let ctpop = ccx.intrinsics.get(~"llvm.ctpop.i8"); + Store(bcx, Call(bcx, ctpop, ~[x]), fcx.llretptr) + } + ~"ctpop16" => { + let x = get_param(decl, first_real_arg); + let ctpop = ccx.intrinsics.get(~"llvm.ctpop.i16"); + Store(bcx, Call(bcx, ctpop, ~[x]), fcx.llretptr) + } + ~"ctpop32" => { + let x = get_param(decl, first_real_arg); + let ctpop = ccx.intrinsics.get(~"llvm.ctpop.i32"); + Store(bcx, Call(bcx, ctpop, ~[x]), fcx.llretptr) + } + ~"ctpop64" => { + let x = get_param(decl, first_real_arg); + let ctpop = ccx.intrinsics.get(~"llvm.ctpop.i64"); + Store(bcx, Call(bcx, ctpop, ~[x]), fcx.llretptr) + } + ~"ctlz8" => { + let x = get_param(decl, first_real_arg); + let y = C_bool(false); + let ctlz = ccx.intrinsics.get(~"llvm.ctlz.i8"); + Store(bcx, Call(bcx, ctlz, ~[x, y]), fcx.llretptr) + } + ~"ctlz16" => { + let x = get_param(decl, first_real_arg); + let y = C_bool(false); + let ctlz = ccx.intrinsics.get(~"llvm.ctlz.i16"); + Store(bcx, Call(bcx, ctlz, ~[x, y]), fcx.llretptr) + } + ~"ctlz32" => { + let x = get_param(decl, first_real_arg); + let y = C_bool(false); + let ctlz = ccx.intrinsics.get(~"llvm.ctlz.i32"); + Store(bcx, Call(bcx, ctlz, ~[x, y]), fcx.llretptr) + } + ~"ctlz64" => { + let x = get_param(decl, first_real_arg); + let y = C_bool(false); + let ctlz = ccx.intrinsics.get(~"llvm.ctlz.i64"); + Store(bcx, Call(bcx, ctlz, ~[x, y]), fcx.llretptr) + } + ~"cttz8" => { + let x = get_param(decl, first_real_arg); + let y = C_bool(false); + let cttz = ccx.intrinsics.get(~"llvm.cttz.i8"); + Store(bcx, Call(bcx, cttz, ~[x, y]), fcx.llretptr) + } + ~"cttz16" => { + let x = get_param(decl, first_real_arg); + let y = C_bool(false); + let cttz = ccx.intrinsics.get(~"llvm.cttz.i16"); + Store(bcx, Call(bcx, cttz, ~[x, y]), fcx.llretptr) + } + ~"cttz32" => { + let x = get_param(decl, first_real_arg); + let y = C_bool(false); + let cttz = ccx.intrinsics.get(~"llvm.cttz.i32"); + Store(bcx, Call(bcx, cttz, ~[x, y]), fcx.llretptr) + } + ~"cttz64" => { + let x = get_param(decl, first_real_arg); + let y = C_bool(false); + let cttz = ccx.intrinsics.get(~"llvm.cttz.i64"); + Store(bcx, Call(bcx, cttz, ~[x, y]), fcx.llretptr) + } _ => { // Could we make this an enum rather than a string? does it get // checked earlier? diff --git a/src/librustc/middle/trans/type_use.rs b/src/librustc/middle/trans/type_use.rs index 08ee59f5d89..7f3b78359fe 100644 --- a/src/librustc/middle/trans/type_use.rs +++ b/src/librustc/middle/trans/type_use.rs @@ -130,6 +130,11 @@ fn type_uses_for(ccx: @crate_ctxt, fn_id: def_id, n_tps: uint) ~"floorf32"| ~"floorf64"| ~"ceilf32" | ~"ceilf64" | ~"truncf32"| ~"truncf64" => 0, + ~"ctpop8" | ~"ctpop16" | ~"ctpop32" | ~"ctpop64" => 0, + + ~"ctlz8" | ~"ctlz16" | ~"ctlz32" | ~"ctlz64" => 0, + ~"cttz8" | ~"cttz16" | ~"cttz32" | ~"cttz64" => 0, + // would be cool to make these an enum instead of strings! _ => fail ~"unknown intrinsic in type_use" }; diff --git a/src/librustc/middle/typeck/check/mod.rs b/src/librustc/middle/typeck/check/mod.rs index 8af091fdb9a..93bdfd5ccda 100644 --- a/src/librustc/middle/typeck/check/mod.rs +++ b/src/librustc/middle/typeck/check/mod.rs @@ -3156,7 +3156,55 @@ fn check_intrinsic_type(ccx: @crate_ctxt, it: @ast::foreign_item) { (0u, ~[arg(ast::by_copy, ty::mk_f64(tcx))], ty::mk_f64(tcx)) } - ref other => { + ~"ctpop8" => { + (0u, ~[arg(ast::by_copy, ty::mk_i8(tcx))], + ty::mk_i8(tcx)) + } + ~"ctpop16" => { + (0u, ~[arg(ast::by_copy, ty::mk_i16(tcx))], + ty::mk_i16(tcx)) + } + ~"ctpop32" => { + (0u, ~[arg(ast::by_copy, ty::mk_i32(tcx))], + ty::mk_i32(tcx)) + } + ~"ctpop64" => { + (0u, ~[arg(ast::by_copy, ty::mk_i64(tcx))], + ty::mk_i64(tcx)) + } + ~"ctlz8" => { + (0u, ~[arg(ast::by_copy, ty::mk_i8(tcx))], + ty::mk_i8(tcx)) + } + ~"ctlz16" => { + (0u, ~[arg(ast::by_copy, ty::mk_i16(tcx))], + ty::mk_i16(tcx)) + } + ~"ctlz32" => { + (0u, ~[arg(ast::by_copy, ty::mk_i32(tcx))], + ty::mk_i32(tcx)) + } + ~"ctlz64" => { + (0u, ~[arg(ast::by_copy, ty::mk_i64(tcx))], + ty::mk_i64(tcx)) + } + ~"cttz8" => { + (0u, ~[arg(ast::by_copy, ty::mk_i8(tcx))], + ty::mk_i8(tcx)) + } + ~"cttz16" => { + (0u, ~[arg(ast::by_copy, ty::mk_i16(tcx))], + ty::mk_i16(tcx)) + } + ~"cttz32" => { + (0u, ~[arg(ast::by_copy, ty::mk_i32(tcx))], + ty::mk_i32(tcx)) + } + ~"cttz64" => { + (0u, ~[arg(ast::by_copy, ty::mk_i64(tcx))], + ty::mk_i64(tcx)) + } + ref other => { tcx.sess.span_err(it.span, ~"unrecognized intrinsic function: `" + (*other) + ~"`"); return; diff --git a/src/test/run-pass/intrinsics-integer.rs b/src/test/run-pass/intrinsics-integer.rs new file mode 100644 index 00000000000..588cc496b28 --- /dev/null +++ b/src/test/run-pass/intrinsics-integer.rs @@ -0,0 +1,112 @@ +// xfail-fast + +// Copyright 2012 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +extern mod std; + +#[abi = "rust-intrinsic"] +extern mod rusti { + fn ctpop8(x: i8) -> i8; + fn ctpop16(x: i16) -> i16; + fn ctpop32(x: i32) -> i32; + fn ctpop64(x: i64) -> i64; + + fn ctlz8(x: i8) -> i8; + fn ctlz16(x: i16) -> i16; + fn ctlz32(x: i32) -> i32; + fn ctlz64(x: i64) -> i64; + + fn cttz8(x: i8) -> i8; + fn cttz16(x: i16) -> i16; + fn cttz32(x: i32) -> i32; + fn cttz64(x: i64) -> i64; +} + +fn main() { + + use rusti::*; + + assert(ctpop8(0i8) == 0i8); + assert(ctpop16(0i16) == 0i16); + assert(ctpop32(0i32) == 0i32); + assert(ctpop64(0i64) == 0i64); + + assert(ctpop8(1i8) == 1i8); + assert(ctpop16(1i16) == 1i16); + assert(ctpop32(1i32) == 1i32); + assert(ctpop64(1i64) == 1i64); + + assert(ctpop8(10i8) == 2i8); + assert(ctpop16(10i16) == 2i16); + assert(ctpop32(10i32) == 2i32); + assert(ctpop64(10i64) == 2i64); + + assert(ctpop8(100i8) == 3i8); + assert(ctpop16(100i16) == 3i16); + assert(ctpop32(100i32) == 3i32); + assert(ctpop64(100i64) == 3i64); + + assert(ctpop8(-1i8) == 8i8); + assert(ctpop16(-1i16) == 16i16); + assert(ctpop32(-1i32) == 32i32); + assert(ctpop64(-1i64) == 64i64); + + assert(ctlz8(0i8) == 8i8); + assert(ctlz16(0i16) == 16i16); + assert(ctlz32(0i32) == 32i32); + assert(ctlz64(0i64) == 64i64); + + assert(ctlz8(1i8) == 7i8); + assert(ctlz16(1i16) == 15i16); + assert(ctlz32(1i32) == 31i32); + assert(ctlz64(1i64) == 63i64); + + assert(ctlz8(10i8) == 4i8); + assert(ctlz16(10i16) == 12i16); + assert(ctlz32(10i32) == 28i32); + assert(ctlz64(10i64) == 60i64); + + assert(ctlz8(100i8) == 1i8); + assert(ctlz16(100i16) == 9i16); + assert(ctlz32(100i32) == 25i32); + assert(ctlz64(100i64) == 57i64); + + assert(cttz8(-1i8) == 0i8); + assert(cttz16(-1i16) == 0i16); + assert(cttz32(-1i32) == 0i32); + assert(cttz64(-1i64) == 0i64); + + assert(cttz8(0i8) == 8i8); + assert(cttz16(0i16) == 16i16); + assert(cttz32(0i32) == 32i32); + assert(cttz64(0i64) == 64i64); + + assert(cttz8(1i8) == 0i8); + assert(cttz16(1i16) == 0i16); + assert(cttz32(1i32) == 0i32); + assert(cttz64(1i64) == 0i64); + + assert(cttz8(10i8) == 1i8); + assert(cttz16(10i16) == 1i16); + assert(cttz32(10i32) == 1i32); + assert(cttz64(10i64) == 1i64); + + assert(cttz8(100i8) == 2i8); + assert(cttz16(100i16) == 2i16); + assert(cttz32(100i32) == 2i32); + assert(cttz64(100i64) == 2i64); + + assert(cttz8(-1i8) == 0i8); + assert(cttz16(-1i16) == 0i16); + assert(cttz32(-1i32) == 0i32); + assert(cttz64(-1i64) == 0i64); + +}