@@ -41,35 +41,6 @@ pub fn trans_intrinsic(ccx: @mut CrateContext,
ref_id: Option<ast::NodeId>) {
debug!("trans_intrinsic(item.ident=%s)", ccx.sess.str_of(item.ident));

fn simple_llvm_intrinsic(bcx: @mut Block, name: &'static str, num_args: uint) {
assert!(num_args <= 4);
let mut args = [0 as ValueRef, ..4];
let first_real_arg = bcx.fcx.arg_pos(0u);
for i in range(0u, num_args) {
args[i] = get_param(bcx.fcx.llfn, first_real_arg + i);
}
let llfn = bcx.ccx().intrinsics.get_copy(&name);
Ret(bcx, Call(bcx, llfn, args.slice(0, num_args), []));
}

fn with_overflow_instrinsic(bcx: @mut Block, name: &'static str) {
let first_real_arg = bcx.fcx.arg_pos(0u);
let a = get_param(bcx.fcx.llfn, first_real_arg);
let b = get_param(bcx.fcx.llfn, first_real_arg + 1);
let llfn = bcx.ccx().intrinsics.get_copy(&name);

// convert `i1` to a `bool`, and write to the out parameter
let val = Call(bcx, llfn, [a, b], []);
let result = ExtractValue(bcx, val, 0);
let overflow = ZExt(bcx, ExtractValue(bcx, val, 1), Type::bool());
let retptr = get_param(bcx.fcx.llfn, bcx.fcx.out_arg_pos());
let ret = Load(bcx, retptr);
let ret = InsertValue(bcx, ret, result, 0);
let ret = InsertValue(bcx, ret, overflow, 1);
Store(bcx, ret, retptr);
RetVoid(bcx)
}

fn memcpy_intrinsic(bcx: @mut Block, name: &'static str, tp_ty: ty::t, sizebits: u8) {
let ccx = bcx.ccx();
let lltp_ty = type_of::type_of(ccx, tp_ty);
@@ -112,13 +83,6 @@ pub fn trans_intrinsic(ccx: @mut CrateContext,
RetVoid(bcx);
}

fn count_zeros_intrinsic(bcx: @mut Block, name: &'static str) {
let x = get_param(bcx.fcx.llfn, bcx.fcx.arg_pos(0u));
let y = C_i1(false);
let llfn = bcx.ccx().intrinsics.get_copy(&name);
Ret(bcx, Call(bcx, llfn, [x, y], []));
}

let output_type = ty::ty_fn_ret(ty::node_id_to_type(ccx.tcx, item.id));

let fcx = new_fn_ctxt_w_id(ccx,
@@ -406,87 +370,13 @@ pub fn trans_intrinsic(ccx: @mut CrateContext,
let offset = get_param(decl, first_real_arg + 1);
Ret(bcx, InBoundsGEP(bcx, ptr, [offset]));
}

"memcpy32" => memcpy_intrinsic(bcx, "llvm.memcpy.p0i8.p0i8.i32", substs.tys[0], 32),
"memcpy64" => memcpy_intrinsic(bcx, "llvm.memcpy.p0i8.p0i8.i64", substs.tys[0], 64),
"memmove32" => memcpy_intrinsic(bcx, "llvm.memmove.p0i8.p0i8.i32", substs.tys[0], 32),
"memmove64" => memcpy_intrinsic(bcx, "llvm.memmove.p0i8.p0i8.i64", substs.tys[0], 64),
"memset32" => memset_intrinsic(bcx, "llvm.memset.p0i8.i32", substs.tys[0], 32),
"memset64" => memset_intrinsic(bcx, "llvm.memset.p0i8.i64", substs.tys[0], 64),
"sqrtf32" => simple_llvm_intrinsic(bcx, "llvm.sqrt.f32", 1),
"sqrtf64" => simple_llvm_intrinsic(bcx, "llvm.sqrt.f64", 1),
"powif32" => simple_llvm_intrinsic(bcx, "llvm.powi.f32", 2),
"powif64" => simple_llvm_intrinsic(bcx, "llvm.powi.f64", 2),
"sinf32" => simple_llvm_intrinsic(bcx, "llvm.sin.f32", 1),
"sinf64" => simple_llvm_intrinsic(bcx, "llvm.sin.f64", 1),
"cosf32" => simple_llvm_intrinsic(bcx, "llvm.cos.f32", 1),
"cosf64" => simple_llvm_intrinsic(bcx, "llvm.cos.f64", 1),
"powf32" => simple_llvm_intrinsic(bcx, "llvm.pow.f32", 2),
"powf64" => simple_llvm_intrinsic(bcx, "llvm.pow.f64", 2),
"expf32" => simple_llvm_intrinsic(bcx, "llvm.exp.f32", 1),
"expf64" => simple_llvm_intrinsic(bcx, "llvm.exp.f64", 1),
"exp2f32" => simple_llvm_intrinsic(bcx, "llvm.exp2.f32", 1),
"exp2f64" => simple_llvm_intrinsic(bcx, "llvm.exp2.f64", 1),
"logf32" => simple_llvm_intrinsic(bcx, "llvm.log.f32", 1),
"logf64" => simple_llvm_intrinsic(bcx, "llvm.log.f64", 1),
"log10f32" => simple_llvm_intrinsic(bcx, "llvm.log10.f32", 1),
"log10f64" => simple_llvm_intrinsic(bcx, "llvm.log10.f64", 1),
"log2f32" => simple_llvm_intrinsic(bcx, "llvm.log2.f32", 1),
"log2f64" => simple_llvm_intrinsic(bcx, "llvm.log2.f64", 1),
"fmaf32" => simple_llvm_intrinsic(bcx, "llvm.fma.f32", 3),
"fmaf64" => simple_llvm_intrinsic(bcx, "llvm.fma.f64", 3),
"fabsf32" => simple_llvm_intrinsic(bcx, "llvm.fabs.f32", 1),
"fabsf64" => simple_llvm_intrinsic(bcx, "llvm.fabs.f64", 1),
"floorf32" => simple_llvm_intrinsic(bcx, "llvm.floor.f32", 1),
"floorf64" => simple_llvm_intrinsic(bcx, "llvm.floor.f64", 1),
"ceilf32" => simple_llvm_intrinsic(bcx, "llvm.ceil.f32", 1),
"ceilf64" => simple_llvm_intrinsic(bcx, "llvm.ceil.f64", 1),
"truncf32" => simple_llvm_intrinsic(bcx, "llvm.trunc.f32", 1),
"truncf64" => simple_llvm_intrinsic(bcx, "llvm.trunc.f64", 1),
"ctpop8" => simple_llvm_intrinsic(bcx, "llvm.ctpop.i8", 1),
"ctpop16" => simple_llvm_intrinsic(bcx, "llvm.ctpop.i16", 1),
"ctpop32" => simple_llvm_intrinsic(bcx, "llvm.ctpop.i32", 1),
"ctpop64" => simple_llvm_intrinsic(bcx, "llvm.ctpop.i64", 1),
"ctlz8" => count_zeros_intrinsic(bcx, "llvm.ctlz.i8"),
"ctlz16" => count_zeros_intrinsic(bcx, "llvm.ctlz.i16"),
"ctlz32" => count_zeros_intrinsic(bcx, "llvm.ctlz.i32"),
"ctlz64" => count_zeros_intrinsic(bcx, "llvm.ctlz.i64"),
"cttz8" => count_zeros_intrinsic(bcx, "llvm.cttz.i8"),
"cttz16" => count_zeros_intrinsic(bcx, "llvm.cttz.i16"),
"cttz32" => count_zeros_intrinsic(bcx, "llvm.cttz.i32"),
"cttz64" => count_zeros_intrinsic(bcx, "llvm.cttz.i64"),
"bswap16" => simple_llvm_intrinsic(bcx, "llvm.bswap.i16", 1),
"bswap32" => simple_llvm_intrinsic(bcx, "llvm.bswap.i32", 1),
"bswap64" => simple_llvm_intrinsic(bcx, "llvm.bswap.i64", 1),

"i8_add_with_overflow" => with_overflow_instrinsic(bcx, "llvm.sadd.with.overflow.i8"),
"i16_add_with_overflow" => with_overflow_instrinsic(bcx, "llvm.sadd.with.overflow.i16"),
"i32_add_with_overflow" => with_overflow_instrinsic(bcx, "llvm.sadd.with.overflow.i32"),
"i64_add_with_overflow" => with_overflow_instrinsic(bcx, "llvm.sadd.with.overflow.i64"),

"u8_add_with_overflow" => with_overflow_instrinsic(bcx, "llvm.uadd.with.overflow.i8"),
"u16_add_with_overflow" => with_overflow_instrinsic(bcx, "llvm.uadd.with.overflow.i16"),
"u32_add_with_overflow" => with_overflow_instrinsic(bcx, "llvm.uadd.with.overflow.i32"),
"u64_add_with_overflow" => with_overflow_instrinsic(bcx, "llvm.uadd.with.overflow.i64"),

"i8_sub_with_overflow" => with_overflow_instrinsic(bcx, "llvm.ssub.with.overflow.i8"),
"i16_sub_with_overflow" => with_overflow_instrinsic(bcx, "llvm.ssub.with.overflow.i16"),
"i32_sub_with_overflow" => with_overflow_instrinsic(bcx, "llvm.ssub.with.overflow.i32"),
"i64_sub_with_overflow" => with_overflow_instrinsic(bcx, "llvm.ssub.with.overflow.i64"),

"u8_sub_with_overflow" => with_overflow_instrinsic(bcx, "llvm.usub.with.overflow.i8"),
"u16_sub_with_overflow" => with_overflow_instrinsic(bcx, "llvm.usub.with.overflow.i16"),
"u32_sub_with_overflow" => with_overflow_instrinsic(bcx, "llvm.usub.with.overflow.i32"),
"u64_sub_with_overflow" => with_overflow_instrinsic(bcx, "llvm.usub.with.overflow.i64"),

"i8_mul_with_overflow" => with_overflow_instrinsic(bcx, "llvm.smul.with.overflow.i8"),
"i16_mul_with_overflow" => with_overflow_instrinsic(bcx, "llvm.smul.with.overflow.i16"),
"i32_mul_with_overflow" => with_overflow_instrinsic(bcx, "llvm.smul.with.overflow.i32"),
"i64_mul_with_overflow" => with_overflow_instrinsic(bcx, "llvm.smul.with.overflow.i64"),

"u8_mul_with_overflow" => with_overflow_instrinsic(bcx, "llvm.umul.with.overflow.i8"),
"u16_mul_with_overflow" => with_overflow_instrinsic(bcx, "llvm.umul.with.overflow.i16"),
"u32_mul_with_overflow" => with_overflow_instrinsic(bcx, "llvm.umul.with.overflow.i32"),
"u64_mul_with_overflow" => with_overflow_instrinsic(bcx, "llvm.umul.with.overflow.i64"),

_ => {
// Could we make this an enum rather than a string? does it get
@@ -139,6 +139,7 @@ pub fn type_uses_for(ccx: @mut CrateContext, fn_id: DefId, n_tps: uint)
let flags = if name.starts_with("atomic_") {
0
} else {
// would be cool to make these an enum instead of strings!
match name {
"size_of" | "pref_align_of" | "min_align_of" |
"uninit" | "init" | "transmute" | "move_val" |
@@ -153,40 +154,6 @@ pub fn type_uses_for(ccx: @mut CrateContext, fn_id: DefId, n_tps: uint)
"memcpy32" | "memcpy64" | "memmove32" | "memmove64" |
"memset32" | "memset64" => use_repr,

"sqrtf32" | "sqrtf64" | "powif32" | "powif64" |
"sinf32" | "sinf64" | "cosf32" | "cosf64" |
"powf32" | "powf64" | "expf32" | "expf64" |
"exp2f32" | "exp2f64" | "logf32" | "logf64" |
"log10f32"| "log10f64"| "log2f32" | "log2f64" |
"fmaf32" | "fmaf64" | "fabsf32" | "fabsf64" |
"floorf32"| "floorf64"| "ceilf32" | "ceilf64" |
"truncf32"| "truncf64" => 0,

"ctpop8" | "ctpop16" | "ctpop32" | "ctpop64" => 0,

"ctlz8" | "ctlz16" | "ctlz32" | "ctlz64" => 0,
"cttz8" | "cttz16" | "cttz32" | "cttz64" => 0,

"bswap16" | "bswap32" | "bswap64" => 0,


"i8_add_with_overflow" | "u8_add_with_overflow" |
"i16_add_with_overflow" | "u16_add_with_overflow" |
"i32_add_with_overflow" | "u32_add_with_overflow" |
"i64_add_with_overflow" | "u64_add_with_overflow" => 0,

"i8_sub_with_overflow" | "u8_sub_with_overflow" |
"i16_sub_with_overflow" | "u16_sub_with_overflow" |
"i32_sub_with_overflow" | "u32_sub_with_overflow" |
"i64_sub_with_overflow" | "u64_sub_with_overflow" => 0,

"i8_mul_with_overflow" | "u8_mul_with_overflow" |
"i16_mul_with_overflow" | "u16_mul_with_overflow" |
"i32_mul_with_overflow" | "u32_mul_with_overflow" |
"i64_mul_with_overflow" | "u64_mul_with_overflow" => 0,

// would be cool to make these an enum instead of
// strings!
_ => fail!("unknown intrinsic in type_use")
}
};
@@ -3756,108 +3756,6 @@ pub fn check_intrinsic_type(ccx: @mut CrateCtxt, it: @ast::foreign_item) {
],
ty::mk_nil())
}
"sqrtf32" => (0, ~[ ty::mk_f32() ], ty::mk_f32()),
"sqrtf64" => (0, ~[ ty::mk_f64() ], ty::mk_f64()),
"powif32" => {
(0,
~[ ty::mk_f32(), ty::mk_i32() ],
ty::mk_f32())
}
"powif64" => {
(0,
~[ ty::mk_f64(), ty::mk_i32() ],
ty::mk_f64())
}
"sinf32" => (0, ~[ ty::mk_f32() ], ty::mk_f32()),
"sinf64" => (0, ~[ ty::mk_f64() ], ty::mk_f64()),
"cosf32" => (0, ~[ ty::mk_f32() ], ty::mk_f32()),
"cosf64" => (0, ~[ ty::mk_f64() ], ty::mk_f64()),
"powf32" => {
(0,
~[ ty::mk_f32(), ty::mk_f32() ],
ty::mk_f32())
}
"powf64" => {
(0,
~[ ty::mk_f64(), ty::mk_f64() ],
ty::mk_f64())
}
"expf32" => (0, ~[ ty::mk_f32() ], ty::mk_f32()),
"expf64" => (0, ~[ ty::mk_f64() ], ty::mk_f64()),
"exp2f32" => (0, ~[ ty::mk_f32() ], ty::mk_f32()),
"exp2f64" => (0, ~[ ty::mk_f64() ], ty::mk_f64()),
"logf32" => (0, ~[ ty::mk_f32() ], ty::mk_f32()),
"logf64" => (0, ~[ ty::mk_f64() ], ty::mk_f64()),
"log10f32" => (0, ~[ ty::mk_f32() ], ty::mk_f32()),
"log10f64" => (0, ~[ ty::mk_f64() ], ty::mk_f64()),
"log2f32" => (0, ~[ ty::mk_f32() ], ty::mk_f32()),
"log2f64" => (0, ~[ ty::mk_f64() ], ty::mk_f64()),
"fmaf32" => {
(0,
~[ ty::mk_f32(), ty::mk_f32(), ty::mk_f32() ],
ty::mk_f32())
}
"fmaf64" => {
(0,
~[ ty::mk_f64(), ty::mk_f64(), ty::mk_f64() ],
ty::mk_f64())
}
"fabsf32" => (0, ~[ ty::mk_f32() ], ty::mk_f32()),
"fabsf64" => (0, ~[ ty::mk_f64() ], ty::mk_f64()),
"floorf32" => (0, ~[ ty::mk_f32() ], ty::mk_f32()),
"floorf64" => (0, ~[ ty::mk_f64() ], ty::mk_f64()),
"ceilf32" => (0, ~[ ty::mk_f32() ], ty::mk_f32()),
"ceilf64" => (0, ~[ ty::mk_f64() ], ty::mk_f64()),
"truncf32" => (0, ~[ ty::mk_f32() ], ty::mk_f32()),
"truncf64" => (0, ~[ ty::mk_f64() ], ty::mk_f64()),
"ctpop8" => (0, ~[ ty::mk_i8() ], ty::mk_i8()),
"ctpop16" => (0, ~[ ty::mk_i16() ], ty::mk_i16()),
"ctpop32" => (0, ~[ ty::mk_i32() ], ty::mk_i32()),
"ctpop64" => (0, ~[ ty::mk_i64() ], ty::mk_i64()),
"ctlz8" => (0, ~[ ty::mk_i8() ], ty::mk_i8()),
"ctlz16" => (0, ~[ ty::mk_i16() ], ty::mk_i16()),
"ctlz32" => (0, ~[ ty::mk_i32() ], ty::mk_i32()),
"ctlz64" => (0, ~[ ty::mk_i64() ], ty::mk_i64()),
"cttz8" => (0, ~[ ty::mk_i8() ], ty::mk_i8()),
"cttz16" => (0, ~[ ty::mk_i16() ], ty::mk_i16()),
"cttz32" => (0, ~[ ty::mk_i32() ], ty::mk_i32()),
"cttz64" => (0, ~[ ty::mk_i64() ], ty::mk_i64()),
"bswap16" => (0, ~[ ty::mk_i16() ], ty::mk_i16()),
"bswap32" => (0, ~[ ty::mk_i32() ], ty::mk_i32()),
"bswap64" => (0, ~[ ty::mk_i64() ], ty::mk_i64()),

"i8_add_with_overflow" | "i8_sub_with_overflow" | "i8_mul_with_overflow" =>
(0, ~[ty::mk_i8(), ty::mk_i8()],
ty::mk_tup(tcx, ~[ty::mk_i8(), ty::mk_bool()])),

"i16_add_with_overflow" | "i16_sub_with_overflow" | "i16_mul_with_overflow" =>
(0, ~[ty::mk_i16(), ty::mk_i16()],
ty::mk_tup(tcx, ~[ty::mk_i16(), ty::mk_bool()])),

"i32_add_with_overflow" | "i32_sub_with_overflow" | "i32_mul_with_overflow" =>
(0, ~[ty::mk_i32(), ty::mk_i32()],
ty::mk_tup(tcx, ~[ty::mk_i32(), ty::mk_bool()])),

"i64_add_with_overflow" | "i64_sub_with_overflow" | "i64_mul_with_overflow" =>
(0, ~[ty::mk_i64(), ty::mk_i64()],
ty::mk_tup(tcx, ~[ty::mk_i64(), ty::mk_bool()])),

"u8_add_with_overflow" | "u8_sub_with_overflow" | "u8_mul_with_overflow" =>
(0, ~[ty::mk_u8(), ty::mk_u8()],
ty::mk_tup(tcx, ~[ty::mk_u8(), ty::mk_bool()])),

"u16_add_with_overflow" | "u16_sub_with_overflow" | "u16_mul_with_overflow" =>
(0, ~[ty::mk_u16(), ty::mk_u16()],
ty::mk_tup(tcx, ~[ty::mk_u16(), ty::mk_bool()])),

"u32_add_with_overflow" | "u32_sub_with_overflow" | "u32_mul_with_overflow"=>
(0, ~[ty::mk_u32(), ty::mk_u32()],
ty::mk_tup(tcx, ~[ty::mk_u32(), ty::mk_bool()])),

"u64_add_with_overflow" | "u64_sub_with_overflow" | "u64_mul_with_overflow" =>
(0, ~[ty::mk_u64(), ty::mk_u64()],
ty::mk_tup(tcx, ~[ty::mk_u64(), ty::mk_bool()])),

ref other => {
tcx.sess.span_err(it.span,
fmt!("unrecognized intrinsic function: `%s`",
@@ -1184,13 +1184,35 @@ pub fn ty_of_foreign_item(ccx: &CrateCtxt,
abis: AbiSet) -> ty::ty_param_bounds_and_ty
{
match it.node {
ast::foreign_item_raw_ir(*) => {
let g = &ast::Generics {
lifetimes: opt_vec::Empty,
ty_params: opt_vec::Empty
};

let ty_generics = ty_generics(ccx, None, g, 0);

ty_param_bounds_and_ty { generics: ty_generics, ty: ty::mk_nil() }
}
ast::foreign_item_fn(ref fn_decl, ref generics) => {
ty_of_foreign_fn_decl(ccx,
fn_decl,
local_def(it.id),
generics,
abis)
}
ast::foreign_item_ir_fn(ref fn_decl, _) => {
let generics = &ast::Generics {
lifetimes: opt_vec::Empty,
ty_params: opt_vec::Empty
};

ty_of_foreign_fn_decl(ccx,
fn_decl,
local_def(it.id),
generics,
abis)
}
ast::foreign_item_static(ref t, _) => {
ty::ty_param_bounds_and_ty {
generics: ty::Generics {
@@ -149,6 +149,8 @@ fn nmoddoc_from_mod(
fns.push(fndoc_from_fn(ItemDoc));
}
ast::foreign_item_static(*) => {} // XXX: Not implemented.
ast::foreign_item_raw_ir(*) => {} // XXX: Not implemented.
ast::foreign_item_ir_fn(*) => {} // XXX: Not implemented.
}
}
doc::NmodDoc {
@@ -23,6 +23,7 @@ use to_str;
pub use cmath::c_float_targ_consts::*;

use self::delegated::*;
use self::unsafe_delegated::*;

macro_rules! delegate(
(
@@ -37,16 +38,38 @@ macro_rules! delegate(
// An inner module is required to get the #[inline] attribute on the
// functions.
mod delegated {
use unstable::intrinsics;

$(
#[inline] #[fixed_stack_segment] #[inline(never)]
pub fn $name($( $arg : $arg_ty ),*) -> $rv {
$bound_name($( $arg ),*)
}
)*
}
)
)

macro_rules! delegate_unsafe(
(
$(
fn $name:ident(
$(
$arg:ident : $arg_ty:ty
),*
) -> $rv:ty = $bound_name:path
),*
) => (
// An inner module is required to get the #[inline] attribute on the
// functions.
mod unsafe_delegated {
use cmath::c_float_utils;
use libc::{c_float, c_int};
use unstable::intrinsics;

$(
#[inline] #[fixed_stack_segment] #[inline(never)]
pub fn $name($( $arg : $arg_ty ),*) -> $rv {
unsafe {
$bound_name($( $arg ),*)
}
unsafe { $bound_name($( $arg ),*) }
}
)*
}
@@ -65,20 +88,18 @@ delegate!(
fn log2(n: f32) -> f32 = intrinsics::log2f32,
fn mul_add(a: f32, b: f32, c: f32) -> f32 = intrinsics::fmaf32,
fn pow(n: f32, e: f32) -> f32 = intrinsics::powf32,
fn powi(n: f32, e: c_int) -> f32 = intrinsics::powif32,
fn powi(n: f32, e: i32) -> f32 = intrinsics::powif32,
fn sin(n: f32) -> f32 = intrinsics::sinf32,
fn sqrt(n: f32) -> f32 = intrinsics::sqrtf32,

// LLVM 3.3 required to use intrinsics for these four
fn ceil(n: c_float) -> c_float = c_float_utils::ceil,
fn trunc(n: c_float) -> c_float = c_float_utils::trunc,
/*
fn ceil(n: f32) -> f32 = intrinsics::ceilf32,
fn trunc(n: f32) -> f32 = intrinsics::truncf32,
fn trunc(n: f32) -> f32 = intrinsics::truncf32
)
/*
fn rint(n: f32) -> f32 = intrinsics::rintf32,
fn nearbyint(n: f32) -> f32 = intrinsics::nearbyintf32,
*/

delegate_unsafe!(
// cmath
fn acos(n: c_float) -> c_float = c_float_utils::acos,
fn asin(n: c_float) -> c_float = c_float_utils::asin,
@@ -25,6 +25,7 @@ pub use cmath::c_double_targ_consts::*;
pub use cmp::{min, max};

use self::delegated::*;
use self::unsafe_delegated::*;

macro_rules! delegate(
(
@@ -39,16 +40,38 @@ macro_rules! delegate(
// An inner module is required to get the #[inline] attribute on the
// functions.
mod delegated {
use unstable::intrinsics;

$(
#[inline] #[fixed_stack_segment] #[inline(never)]
pub fn $name($( $arg : $arg_ty ),*) -> $rv {
$bound_name($( $arg ),*)
}
)*
}
)
)

macro_rules! delegate_unsafe(
(
$(
fn $name:ident(
$(
$arg:ident : $arg_ty:ty
),*
) -> $rv:ty = $bound_name:path
),*
) => (
// An inner module is required to get the #[inline] attribute on the
// functions.
mod unsafe_delegated {
use cmath::c_double_utils;
use libc::{c_double, c_int};
use unstable::intrinsics;

$(
#[inline] #[fixed_stack_segment] #[inline(never)]
pub fn $name($( $arg : $arg_ty ),*) -> $rv {
unsafe {
$bound_name($( $arg ),*)
}
unsafe { $bound_name($( $arg ),*) }
}
)*
}
@@ -67,20 +90,18 @@ delegate!(
fn log2(n: f64) -> f64 = intrinsics::log2f64,
fn mul_add(a: f64, b: f64, c: f64) -> f64 = intrinsics::fmaf64,
fn pow(n: f64, e: f64) -> f64 = intrinsics::powf64,
fn powi(n: f64, e: c_int) -> f64 = intrinsics::powif64,
fn powi(n: f64, e: i32) -> f64 = intrinsics::powif64,
fn sin(n: f64) -> f64 = intrinsics::sinf64,
fn sqrt(n: f64) -> f64 = intrinsics::sqrtf64,

// LLVM 3.3 required to use intrinsics for these four
fn ceil(n: c_double) -> c_double = c_double_utils::ceil,
fn trunc(n: c_double) -> c_double = c_double_utils::trunc,
/*
fn ceil(n: f64) -> f64 = intrinsics::ceilf64,
fn trunc(n: f64) -> f64 = intrinsics::truncf64,
fn trunc(n: f64) -> f64 = intrinsics::truncf64
)
/*
fn rint(n: c_double) -> c_double = intrinsics::rintf64,
fn nearbyint(n: c_double) -> c_double = intrinsics::nearbyintf64,
*/

delegate_unsafe!(
// cmath
fn acos(n: c_double) -> c_double = c_double_utils::acos,
fn asin(n: c_double) -> c_double = c_double_utils::asin,
@@ -21,43 +21,37 @@ int_module!(i16, 16)
impl BitCount for i16 {
/// Counts the number of bits set. Wraps LLVM's `ctpop` intrinsic.
#[inline]
fn population_count(&self) -> i16 { unsafe { intrinsics::ctpop16(*self) } }
fn population_count(&self) -> i16 { intrinsics::ctpop16(*self) }

/// Counts the number of leading zeros. Wraps LLVM's `ctlz` intrinsic.
#[inline]
fn leading_zeros(&self) -> i16 { unsafe { intrinsics::ctlz16(*self) } }
fn leading_zeros(&self) -> i16 { intrinsics::ctlz16(*self) }

/// Counts the number of trailing zeros. Wraps LLVM's `cttz` intrinsic.
#[inline]
fn trailing_zeros(&self) -> i16 { unsafe { intrinsics::cttz16(*self) } }
fn trailing_zeros(&self) -> i16 { intrinsics::cttz16(*self) }
}

impl CheckedAdd for i16 {
#[inline]
fn checked_add(&self, v: &i16) -> Option<i16> {
unsafe {
let (x, y) = intrinsics::i16_add_with_overflow(*self, *v);
if y { None } else { Some(x) }
}
let (x, y) = intrinsics::i16_add_with_overflow(*self, *v);
if y { None } else { Some(x) }
}
}

impl CheckedSub for i16 {
#[inline]
fn checked_sub(&self, v: &i16) -> Option<i16> {
unsafe {
let (x, y) = intrinsics::i16_sub_with_overflow(*self, *v);
if y { None } else { Some(x) }
}
let (x, y) = intrinsics::i16_sub_with_overflow(*self, *v);
if y { None } else { Some(x) }
}
}

impl CheckedMul for i16 {
#[inline]
fn checked_mul(&self, v: &i16) -> Option<i16> {
unsafe {
let (x, y) = intrinsics::i16_mul_with_overflow(*self, *v);
if y { None } else { Some(x) }
}
let (x, y) = intrinsics::i16_mul_with_overflow(*self, *v);
if y { None } else { Some(x) }
}
}
@@ -21,43 +21,37 @@ int_module!(i32, 32)
impl BitCount for i32 {
/// Counts the number of bits set. Wraps LLVM's `ctpop` intrinsic.
#[inline]
fn population_count(&self) -> i32 { unsafe { intrinsics::ctpop32(*self) } }
fn population_count(&self) -> i32 { intrinsics::ctpop32(*self) }

/// Counts the number of leading zeros. Wraps LLVM's `ctlz` intrinsic.
#[inline]
fn leading_zeros(&self) -> i32 { unsafe { intrinsics::ctlz32(*self) } }
fn leading_zeros(&self) -> i32 { intrinsics::ctlz32(*self) }

/// Counts the number of trailing zeros. Wraps LLVM's `cttz` intrinsic.
#[inline]
fn trailing_zeros(&self) -> i32 { unsafe { intrinsics::cttz32(*self) } }
fn trailing_zeros(&self) -> i32 { intrinsics::cttz32(*self) }
}

impl CheckedAdd for i32 {
#[inline]
fn checked_add(&self, v: &i32) -> Option<i32> {
unsafe {
let (x, y) = intrinsics::i32_add_with_overflow(*self, *v);
if y { None } else { Some(x) }
}
let (x, y) = intrinsics::i32_add_with_overflow(*self, *v);
if y { None } else { Some(x) }
}
}

impl CheckedSub for i32 {
#[inline]
fn checked_sub(&self, v: &i32) -> Option<i32> {
unsafe {
let (x, y) = intrinsics::i32_sub_with_overflow(*self, *v);
if y { None } else { Some(x) }
}
let (x, y) = intrinsics::i32_sub_with_overflow(*self, *v);
if y { None } else { Some(x) }
}
}

impl CheckedMul for i32 {
#[inline]
fn checked_mul(&self, v: &i32) -> Option<i32> {
unsafe {
let (x, y) = intrinsics::i32_mul_with_overflow(*self, *v);
if y { None } else { Some(x) }
}
let (x, y) = intrinsics::i32_mul_with_overflow(*self, *v);
if y { None } else { Some(x) }
}
}
@@ -23,34 +23,30 @@ int_module!(i64, 64)
impl BitCount for i64 {
/// Counts the number of bits set. Wraps LLVM's `ctpop` intrinsic.
#[inline]
fn population_count(&self) -> i64 { unsafe { intrinsics::ctpop64(*self) } }
fn population_count(&self) -> i64 { intrinsics::ctpop64(*self) }

/// Counts the number of leading zeros. Wraps LLVM's `ctlz` intrinsic.
#[inline]
fn leading_zeros(&self) -> i64 { unsafe { intrinsics::ctlz64(*self) } }
fn leading_zeros(&self) -> i64 { intrinsics::ctlz64(*self) }

/// Counts the number of trailing zeros. Wraps LLVM's `cttz` intrinsic.
#[inline]
fn trailing_zeros(&self) -> i64 { unsafe { intrinsics::cttz64(*self) } }
fn trailing_zeros(&self) -> i64 { intrinsics::cttz64(*self) }
}

impl CheckedAdd for i64 {
#[inline]
fn checked_add(&self, v: &i64) -> Option<i64> {
unsafe {
let (x, y) = intrinsics::i64_add_with_overflow(*self, *v);
if y { None } else { Some(x) }
}
let (x, y) = intrinsics::i64_add_with_overflow(*self, *v);
if y { None } else { Some(x) }
}
}

impl CheckedSub for i64 {
#[inline]
fn checked_sub(&self, v: &i64) -> Option<i64> {
unsafe {
let (x, y) = intrinsics::i64_sub_with_overflow(*self, *v);
if y { None } else { Some(x) }
}
let (x, y) = intrinsics::i64_sub_with_overflow(*self, *v);
if y { None } else { Some(x) }
}
}

@@ -59,9 +55,7 @@ impl CheckedSub for i64 {
impl CheckedMul for i64 {
#[inline]
fn checked_mul(&self, v: &i64) -> Option<i64> {
unsafe {
let (x, y) = intrinsics::i64_mul_with_overflow(*self, *v);
if y { None } else { Some(x) }
}
let (x, y) = intrinsics::i64_mul_with_overflow(*self, *v);
if y { None } else { Some(x) }
}
}
@@ -21,43 +21,37 @@ int_module!(i8, 8)
impl BitCount for i8 {
/// Counts the number of bits set. Wraps LLVM's `ctpop` intrinsic.
#[inline]
fn population_count(&self) -> i8 { unsafe { intrinsics::ctpop8(*self) } }
fn population_count(&self) -> i8 { intrinsics::ctpop8(*self) }

/// Counts the number of leading zeros. Wraps LLVM's `ctlz` intrinsic.
#[inline]
fn leading_zeros(&self) -> i8 { unsafe { intrinsics::ctlz8(*self) } }
fn leading_zeros(&self) -> i8 { intrinsics::ctlz8(*self) }

/// Counts the number of trailing zeros. Wraps LLVM's `cttz` intrinsic.
#[inline]
fn trailing_zeros(&self) -> i8 { unsafe { intrinsics::cttz8(*self) } }
fn trailing_zeros(&self) -> i8 { intrinsics::cttz8(*self) }
}

impl CheckedAdd for i8 {
#[inline]
fn checked_add(&self, v: &i8) -> Option<i8> {
unsafe {
let (x, y) = intrinsics::i8_add_with_overflow(*self, *v);
if y { None } else { Some(x) }
}
let (x, y) = intrinsics::i8_add_with_overflow(*self, *v);
if y { None } else { Some(x) }
}
}

impl CheckedSub for i8 {
#[inline]
fn checked_sub(&self, v: &i8) -> Option<i8> {
unsafe {
let (x, y) = intrinsics::i8_sub_with_overflow(*self, *v);
if y { None } else { Some(x) }
}
let (x, y) = intrinsics::i8_sub_with_overflow(*self, *v);
if y { None } else { Some(x) }
}
}

impl CheckedMul for i8 {
#[inline]
fn checked_mul(&self, v: &i8) -> Option<i8> {
unsafe {
let (x, y) = intrinsics::i8_mul_with_overflow(*self, *v);
if y { None } else { Some(x) }
}
let (x, y) = intrinsics::i8_mul_with_overflow(*self, *v);
if y { None } else { Some(x) }
}
}
@@ -57,65 +57,53 @@ impl BitCount for int {
impl CheckedAdd for int {
#[inline]
fn checked_add(&self, v: &int) -> Option<int> {
unsafe {
let (x, y) = intrinsics::i32_add_with_overflow(*self as i32, *v as i32);
if y { None } else { Some(x as int) }
}
let (x, y) = intrinsics::i32_add_with_overflow(*self as i32, *v as i32);
if y { None } else { Some(x as int) }
}
}

#[cfg(target_word_size = "64")]
impl CheckedAdd for int {
#[inline]
fn checked_add(&self, v: &int) -> Option<int> {
unsafe {
let (x, y) = intrinsics::i64_add_with_overflow(*self as i64, *v as i64);
if y { None } else { Some(x as int) }
}
let (x, y) = intrinsics::i64_add_with_overflow(*self as i64, *v as i64);
if y { None } else { Some(x as int) }
}
}

#[cfg(target_word_size = "32")]
impl CheckedSub for int {
#[inline]
fn checked_sub(&self, v: &int) -> Option<int> {
unsafe {
let (x, y) = intrinsics::i32_sub_with_overflow(*self as i32, *v as i32);
if y { None } else { Some(x as int) }
}
let (x, y) = intrinsics::i32_sub_with_overflow(*self as i32, *v as i32);
if y { None } else { Some(x as int) }
}
}

#[cfg(target_word_size = "64")]
impl CheckedSub for int {
#[inline]
fn checked_sub(&self, v: &int) -> Option<int> {
unsafe {
let (x, y) = intrinsics::i64_sub_with_overflow(*self as i64, *v as i64);
if y { None } else { Some(x as int) }
}
let (x, y) = intrinsics::i64_sub_with_overflow(*self as i64, *v as i64);
if y { None } else { Some(x as int) }
}
}

#[cfg(target_word_size = "32")]
impl CheckedMul for int {
#[inline]
fn checked_mul(&self, v: &int) -> Option<int> {
unsafe {
let (x, y) = intrinsics::i32_mul_with_overflow(*self as i32, *v as i32);
if y { None } else { Some(x as int) }
}
let (x, y) = intrinsics::i32_mul_with_overflow(*self as i32, *v as i32);
if y { None } else { Some(x as int) }
}
}

#[cfg(target_word_size = "64")]
impl CheckedMul for int {
#[inline]
fn checked_mul(&self, v: &int) -> Option<int> {
unsafe {
let (x, y) = intrinsics::i64_mul_with_overflow(*self as i64, *v as i64);
if y { None } else { Some(x as int) }
}
let (x, y) = intrinsics::i64_mul_with_overflow(*self as i64, *v as i64);
if y { None } else { Some(x as int) }
}
}

@@ -21,29 +21,23 @@ uint_module!(u16, i16, 16)
impl CheckedAdd for u16 {
#[inline]
fn checked_add(&self, v: &u16) -> Option<u16> {
unsafe {
let (x, y) = intrinsics::u16_add_with_overflow(*self, *v);
if y { None } else { Some(x) }
}
let (x, y) = intrinsics::u16_add_with_overflow(*self, *v);
if y { None } else { Some(x) }
}
}

impl CheckedSub for u16 {
#[inline]
fn checked_sub(&self, v: &u16) -> Option<u16> {
unsafe {
let (x, y) = intrinsics::u16_sub_with_overflow(*self, *v);
if y { None } else { Some(x) }
}
let (x, y) = intrinsics::u16_sub_with_overflow(*self, *v);
if y { None } else { Some(x) }
}
}

impl CheckedMul for u16 {
#[inline]
fn checked_mul(&self, v: &u16) -> Option<u16> {
unsafe {
let (x, y) = intrinsics::u16_mul_with_overflow(*self, *v);
if y { None } else { Some(x) }
}
let (x, y) = intrinsics::u16_mul_with_overflow(*self, *v);
if y { None } else { Some(x) }
}
}
@@ -21,29 +21,23 @@ uint_module!(u32, i32, 32)
impl CheckedAdd for u32 {
#[inline]
fn checked_add(&self, v: &u32) -> Option<u32> {
unsafe {
let (x, y) = intrinsics::u32_add_with_overflow(*self, *v);
if y { None } else { Some(x) }
}
let (x, y) = intrinsics::u32_add_with_overflow(*self, *v);
if y { None } else { Some(x) }
}
}

impl CheckedSub for u32 {
#[inline]
fn checked_sub(&self, v: &u32) -> Option<u32> {
unsafe {
let (x, y) = intrinsics::u32_sub_with_overflow(*self, *v);
if y { None } else { Some(x) }
}
let (x, y) = intrinsics::u32_sub_with_overflow(*self, *v);
if y { None } else { Some(x) }
}
}

impl CheckedMul for u32 {
#[inline]
fn checked_mul(&self, v: &u32) -> Option<u32> {
unsafe {
let (x, y) = intrinsics::u32_mul_with_overflow(*self, *v);
if y { None } else { Some(x) }
}
let (x, y) = intrinsics::u32_mul_with_overflow(*self, *v);
if y { None } else { Some(x) }
}
}
@@ -23,20 +23,16 @@ uint_module!(u64, i64, 64)
impl CheckedAdd for u64 {
#[inline]
fn checked_add(&self, v: &u64) -> Option<u64> {
unsafe {
let (x, y) = intrinsics::u64_add_with_overflow(*self, *v);
if y { None } else { Some(x) }
}
let (x, y) = intrinsics::u64_add_with_overflow(*self, *v);
if y { None } else { Some(x) }
}
}

impl CheckedSub for u64 {
#[inline]
fn checked_sub(&self, v: &u64) -> Option<u64> {
unsafe {
let (x, y) = intrinsics::u64_sub_with_overflow(*self, *v);
if y { None } else { Some(x) }
}
let (x, y) = intrinsics::u64_sub_with_overflow(*self, *v);
if y { None } else { Some(x) }
}
}

@@ -45,9 +41,7 @@ impl CheckedSub for u64 {
impl CheckedMul for u64 {
#[inline]
fn checked_mul(&self, v: &u64) -> Option<u64> {
unsafe {
let (x, y) = intrinsics::u64_mul_with_overflow(*self, *v);
if y { None } else { Some(x) }
}
let (x, y) = intrinsics::u64_mul_with_overflow(*self, *v);
if y { None } else { Some(x) }
}
}
@@ -21,29 +21,23 @@ uint_module!(u8, i8, 8)
impl CheckedAdd for u8 {
#[inline]
fn checked_add(&self, v: &u8) -> Option<u8> {
unsafe {
let (x, y) = intrinsics::u8_add_with_overflow(*self, *v);
if y { None } else { Some(x) }
}
let (x, y) = intrinsics::u8_add_with_overflow(*self, *v);
if y { None } else { Some(x) }
}
}

impl CheckedSub for u8 {
#[inline]
fn checked_sub(&self, v: &u8) -> Option<u8> {
unsafe {
let (x, y) = intrinsics::u8_sub_with_overflow(*self, *v);
if y { None } else { Some(x) }
}
let (x, y) = intrinsics::u8_sub_with_overflow(*self, *v);
if y { None } else { Some(x) }
}
}

impl CheckedMul for u8 {
#[inline]
fn checked_mul(&self, v: &u8) -> Option<u8> {
unsafe {
let (x, y) = intrinsics::u8_mul_with_overflow(*self, *v);
if y { None } else { Some(x) }
}
let (x, y) = intrinsics::u8_mul_with_overflow(*self, *v);
if y { None } else { Some(x) }
}
}
@@ -118,65 +118,53 @@ pub fn next_power_of_two_opt(n: uint) -> Option<uint> {
impl CheckedAdd for uint {
#[inline]
fn checked_add(&self, v: &uint) -> Option<uint> {
unsafe {
let (x, y) = intrinsics::u32_add_with_overflow(*self as u32, *v as u32);
if y { None } else { Some(x as uint) }
}
let (x, y) = intrinsics::u32_add_with_overflow(*self as u32, *v as u32);
if y { None } else { Some(x as uint) }
}
}

#[cfg(target_word_size = "64")]
impl CheckedAdd for uint {
#[inline]
fn checked_add(&self, v: &uint) -> Option<uint> {
unsafe {
let (x, y) = intrinsics::u64_add_with_overflow(*self as u64, *v as u64);
if y { None } else { Some(x as uint) }
}
let (x, y) = intrinsics::u64_add_with_overflow(*self as u64, *v as u64);
if y { None } else { Some(x as uint) }
}
}

#[cfg(target_word_size = "32")]
impl CheckedSub for uint {
#[inline]
fn checked_sub(&self, v: &uint) -> Option<uint> {
unsafe {
let (x, y) = intrinsics::u32_sub_with_overflow(*self as u32, *v as u32);
if y { None } else { Some(x as uint) }
}
let (x, y) = intrinsics::u32_sub_with_overflow(*self as u32, *v as u32);
if y { None } else { Some(x as uint) }
}
}

#[cfg(target_word_size = "64")]
impl CheckedSub for uint {
#[inline]
fn checked_sub(&self, v: &uint) -> Option<uint> {
unsafe {
let (x, y) = intrinsics::u64_sub_with_overflow(*self as u64, *v as u64);
if y { None } else { Some(x as uint) }
}
let (x, y) = intrinsics::u64_sub_with_overflow(*self as u64, *v as u64);
if y { None } else { Some(x as uint) }
}
}

#[cfg(target_word_size = "32")]
impl CheckedMul for uint {
#[inline]
fn checked_mul(&self, v: &uint) -> Option<uint> {
unsafe {
let (x, y) = intrinsics::u32_mul_with_overflow(*self as u32, *v as u32);
if y { None } else { Some(x as uint) }
}
let (x, y) = intrinsics::u32_mul_with_overflow(*self as u32, *v as u32);
if y { None } else { Some(x as uint) }
}
}

#[cfg(target_word_size = "64")]
impl CheckedMul for uint {
#[inline]
fn checked_mul(&self, v: &uint) -> Option<uint> {
unsafe {
let (x, y) = intrinsics::u64_mul_with_overflow(*self as u64, *v as u64);
if y { None } else { Some(x as uint) }
}
let (x, y) = intrinsics::u64_mul_with_overflow(*self as u64, *v as u64);
if y { None } else { Some(x as uint) }
}
}

Large diffs are not rendered by default.

Oops, something went wrong.
@@ -1151,7 +1151,9 @@ pub struct foreign_item {

#[deriving(Eq, Encodable, Decodable,IterBytes)]
pub enum foreign_item_ {
foreign_item_raw_ir(@str),
foreign_item_fn(fn_decl, Generics),
foreign_item_ir_fn(fn_decl, /* code */ @str),
foreign_item_static(Ty, /* is_mutbl */ bool),
}

@@ -220,6 +220,8 @@ pub fn syntax_expander_table() -> SyntaxEnv {
ext::source_util::expand_mod));
syntax_expanders.insert(intern(&"asm"),
builtin_normal_tt_no_ctxt(ext::asm::expand_asm));
syntax_expanders.insert(intern(&"llvm"),
builtin_normal_tt_no_ctxt(ext::ir_module::expand_ir_module));
syntax_expanders.insert(intern(&"cfg"),
builtin_normal_tt_no_ctxt(ext::cfg::expand_cfg));
syntax_expanders.insert(
@@ -0,0 +1,97 @@
// Copyright 2012-2013 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 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

/*
* Inline IR support.
*/

use abi;
use ast;
use ast::token_tree;
use codemap::Span;
use ext::base::*;
use parse;
use parse::token;
use parse::token::keywords;
use parse::token::special_idents;

pub fn expand_ir_module(cx: @ExtCtxt, sp: Span, tts: &[token_tree]) -> MacResult {
let p = parse::new_parser_from_tts(cx.parse_sess(), cx.cfg(), tts.to_owned());

p.expect_keyword(keywords::Extern);

let abis = p.parse_opt_abis().unwrap_or(abi::AbiSet::C());

p.expect(&token::LBRACE);

let mut items = ~[];

let is_raw_ir = match *p.token {
token::IDENT(sid, false) => { token::intern(&"ir") == sid.name },
_ => false
};

if is_raw_ir {
p.bump();

let ir = p.parse_expr();
let src = expr_to_str(cx, ir, "inline IR must be a string literal.");

items.push(@ast::foreign_item {
ident: special_idents::anon,
attrs: ~[],
node: ast::foreign_item_raw_ir(src),
id: ast::DUMMY_NODE_ID,
span: ir.span,
vis: ast::inherited,
});

p.expect(&token::SEMI);
}

while p.eat_keyword(keywords::Fn) {
let fn_id = p.parse_ident();
let fn_decl = p.parse_fn_decl();

p.expect(&token::LBRACE);

let ir = p.parse_expr();
let src = expr_to_str(cx, ir, "inline IR must be a string literal.");

p.expect(&token::RBRACE);

items.push(@ast::foreign_item {
ident: fn_id,
attrs: ~[],
node: ast::foreign_item_ir_fn(fn_decl, src),
id: ast::DUMMY_NODE_ID,
span: ir.span,
vis: ast::inherited,
});
}

p.expect(&token::RBRACE);

let module = ast::foreign_mod {
sort: ast::anonymous,
abis: abis,
view_items: ~[],
items: items
};

MRItem(@ast::item {
ident: special_idents::clownshoes_foreign_mod,
attrs: ~[],
id: ast::DUMMY_NODE_ID,
node: ast::item_foreign_mod(module),
vis: ast::private,
span: sp
})
}
@@ -298,6 +298,9 @@ fn noop_fold_foreign_item(ni: @foreign_item, fld: @ast_fold)
attrs: fld.fold_attributes(ni.attrs),
node:
match ni.node {
foreign_item_raw_ir(ir) => {
foreign_item_raw_ir(ir)
}
foreign_item_fn(ref fdec, ref generics) => {
foreign_item_fn(
ast::fn_decl {
@@ -307,6 +310,14 @@ fn noop_fold_foreign_item(ni: @foreign_item, fld: @ast_fold)
},
fold_generics(generics, fld))
}
foreign_item_ir_fn(ref fdec, ir) => {
foreign_item_ir_fn(ast::fn_decl {
inputs: fdec.inputs.map(|a| fld.fold_arg(a)),
output: fld.fold_ty(&fdec.output),
cf: fdec.cf
},
ir)
}
foreign_item_static(ref t, m) => {
foreign_item_static(fld.fold_ty(t), m)
}
@@ -4554,7 +4554,7 @@ impl Parser {
}

// parse a string as an ABI spec on an extern type or module
fn parse_opt_abis(&self) -> Option<AbiSet> {
pub fn parse_opt_abis(&self) -> Option<AbiSet> {
match *self.token {
token::LIT_STR(s) => {
self.bump();
@@ -457,13 +457,28 @@ pub fn print_foreign_item(s: @ps, item: &ast::foreign_item) {
maybe_print_comment(s, item.span.lo);
print_outer_attributes(s, item.attrs);
match item.node {
ast::foreign_item_raw_ir(ir) => {
word_space(s, "ir");
print_string(s, ir);
}
ast::foreign_item_fn(ref decl, ref generics) => {
print_fn(s, decl, None, AbiSet::Rust(), item.ident, generics, None,
item.vis);
end(s); // end head-ibox
word(s.s, ";");
end(s); // end the outer fn box
}
ast::foreign_item_ir_fn(ref decl, ir) => {
word_space(s, "fn");
print_ident(s, item.ident);
print_fn_args_and_ret(s, decl, None);

nbsp(s);

bopen(s);
print_string(s, ir);
bclose(s, item.span);
}
ast::foreign_item_static(ref t, m) => {
head(s, visibility_qualified(item.vis, "static"));
if m {
@@ -54,6 +54,8 @@ pub mod print {

pub mod ext {
pub mod asm;
pub mod ir_module;

pub mod base;
pub mod expand;

@@ -386,10 +386,14 @@ pub fn walk_foreign_item<E:Clone, V:Visitor<E>>(visitor: &mut V,
foreign_item: &foreign_item,
env: E) {
match foreign_item.node {
foreign_item_raw_ir(*) => {}
foreign_item_fn(ref function_declaration, ref generics) => {
walk_fn_decl(visitor, function_declaration, env.clone());
visitor.visit_generics(generics, env)
}
foreign_item_ir_fn(ref function_declaration, _) => {
walk_fn_decl(visitor, function_declaration, env.clone());
}
foreign_item_static(ref typ, _) => visitor.visit_ty(typ, env),
}
}
@@ -796,3 +796,51 @@ extern "C" void LLVMDICompositeTypeSetTypeArray(
{
unwrapDI<DICompositeType>(CompositeType).setTypeArray(unwrapDI<DIArray>(TypeArray));
}

static char raw_ir_error[8096];

extern "C" bool LLVMRustAddRawIR(LLVMModuleRef M, const char * code) {
SMDiagnostic err;
ParseAssemblyString(code, unwrap(M), err, unwrap(M)->getContext());

std::string message = err.getMessage().str();

if (message == "") {
return true;
} else {
(message + "\n" + code).copy(raw_ir_error, sizeof(raw_ir_error));

LLVMRustError = raw_ir_error;

return false;
}
}

extern "C" bool LLVMRustCreateIRFunction(LLVMModuleRef M, LLVMTypeRef f, const char * name, const char * code) {
std::string str;
llvm::raw_string_ostream stream(str);

LLVMTypeRef return_type = LLVMGetReturnType(f);

stream << "define ";
unwrap(return_type)->print(stream);
stream << " @" << name << "(";

unsigned n = LLVMCountParamTypes(f);

LLVMTypeRef * arguments = (LLVMTypeRef*)calloc((size_t)n, sizeof(LLVMTypeRef));
LLVMGetParamTypes(f, arguments);
for (unsigned i = 0; i < n; i++) {
if (i != 0) {
stream << ", ";
}

unwrap(arguments[i])->print(stream);
stream << " %arg" << i;
}
free(arguments);

stream << ") alwaysinline {\n" << code << "\n}";

return LLVMRustAddRawIR(M, stream.str().c_str());
}
@@ -628,3 +628,5 @@ LLVMRustSetNormalizedTarget
LLVMRustAddAlwaysInlinePass
LLVMAddReturnAttribute
LLVMRemoveReturnAttribute
LLVMRustAddRawIR
LLVMRustCreateIRFunction
@@ -12,33 +12,9 @@

extern mod extra;

mod rusti {
#[abi = "rust-intrinsic"]
extern "rust-intrinsic" {
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 bswap16(x: i16) -> i16;
fn bswap32(x: i32) -> i32;
fn bswap64(x: i64) -> i64;
}
}

pub fn main() {
unsafe {
use rusti::*;
use std::unstable::intrinsics::*;

assert_eq!(ctpop8(0i8), 0i8);
assert_eq!(ctpop16(0i16), 0i16);
@@ -10,45 +10,9 @@
// option. This file may not be copied, modified, or distributed
// except according to those terms.

mod rusti {
#[abi = "rust-intrinsic"]
extern "rust-intrinsic" {
pub fn sqrtf32(x: f32) -> f32;
pub fn sqrtf64(x: f64) -> f64;
pub fn powif32(a: f32, x: i32) -> f32;
pub fn powif64(a: f64, x: i32) -> f64;
pub fn sinf32(x: f32) -> f32;
pub fn sinf64(x: f64) -> f64;
pub fn cosf32(x: f32) -> f32;
pub fn cosf64(x: f64) -> f64;
pub fn powf32(a: f32, x: f32) -> f32;
pub fn powf64(a: f64, x: f64) -> f64;
pub fn expf32(x: f32) -> f32;
pub fn expf64(x: f64) -> f64;
pub fn exp2f32(x: f32) -> f32;
pub fn exp2f64(x: f64) -> f64;
pub fn logf32(x: f32) -> f32;
pub fn logf64(x: f64) -> f64;
pub fn log10f32(x: f32) -> f32;
pub fn log10f64(x: f64) -> f64;
pub fn log2f32(x: f32) -> f32;
pub fn log2f64(x: f64) -> f64;
pub fn fmaf32(a: f32, b: f32, c: f32) -> f32;
pub fn fmaf64(a: f64, b: f64, c: f64) -> f64;
pub fn fabsf32(x: f32) -> f32;
pub fn fabsf64(x: f64) -> f64;
pub fn floorf32(x: f32) -> f32;
pub fn floorf64(x: f64) -> f64;
pub fn ceilf32(x: f32) -> f32;
pub fn ceilf64(x: f64) -> f64;
pub fn truncf32(x: f32) -> f32;
pub fn truncf64(x: f64) -> f64;
}
}

pub fn main() {
unsafe {
use rusti::*;
use std::unstable::intrinsics::*;

use std::f32;
use std::f64;
@@ -92,15 +56,10 @@ pub fn main() {
assert!((floorf32(3.8f32).approx_eq(&3.0f32)));
assert!((floorf64(-1.1f64).approx_eq(&-2.0f64)));

// Causes linker error
// undefined reference to llvm.ceil.f32/64
//assert!((ceilf32(-2.3f32) == -2.0f32));
//assert!((ceilf64(3.8f64) == 4.0f64));
assert!((ceilf32(-2.3f32) == -2.0f32));
assert!((ceilf64(3.8f64) == 4.0f64));

// Causes linker error
// undefined reference to llvm.trunc.f32/64
//assert!((truncf32(0.1f32) == 0.0f32));
//assert!((truncf64(-0.1f64) == 0.0f64));
assert!((truncf32(0.1f32) == 0.0f32));
assert!((truncf64(-0.1f64) == 0.0f64));
}

}