Add support for byteswap intrinsics
Adds support for the llvm.bswap.i{8,16,32} intrinsics, which swaps the byte order from little endian to big endian, or the reverse.
This commit is contained in:
parent
efb8711f90
commit
a51661e8c1
@ -2423,6 +2423,12 @@ fn declare_intrinsics(llmod: ModuleRef) -> HashMap<~str, ValueRef> {
|
||||
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 bswap16 = decl_cdecl_fn(llmod, ~"llvm.bswap.i16",
|
||||
T_fn(~[T_i16()], T_i16()));
|
||||
let bswap32 = decl_cdecl_fn(llmod, ~"llvm.bswap.i32",
|
||||
T_fn(~[T_i32()], T_i32()));
|
||||
let bswap64 = decl_cdecl_fn(llmod, ~"llvm.bswap.i64",
|
||||
T_fn(~[T_i64()], T_i64()));
|
||||
|
||||
let intrinsics = HashMap();
|
||||
intrinsics.insert(~"llvm.gcroot", gcroot);
|
||||
@ -2475,6 +2481,9 @@ fn declare_intrinsics(llmod: ModuleRef) -> HashMap<~str, ValueRef> {
|
||||
intrinsics.insert(~"llvm.cttz.i16", cttz16);
|
||||
intrinsics.insert(~"llvm.cttz.i32", cttz32);
|
||||
intrinsics.insert(~"llvm.cttz.i64", cttz64);
|
||||
intrinsics.insert(~"llvm.bswap.i16", bswap16);
|
||||
intrinsics.insert(~"llvm.bswap.i32", bswap32);
|
||||
intrinsics.insert(~"llvm.bswap.i64", bswap64);
|
||||
|
||||
return intrinsics;
|
||||
}
|
||||
|
@ -1262,6 +1262,21 @@ fn trans_intrinsic(ccx: @crate_ctxt, decl: ValueRef, item: @ast::foreign_item,
|
||||
let cttz = ccx.intrinsics.get(~"llvm.cttz.i64");
|
||||
Store(bcx, Call(bcx, cttz, ~[x, y]), fcx.llretptr)
|
||||
}
|
||||
~"bswap16" => {
|
||||
let x = get_param(decl, first_real_arg);
|
||||
let cttz = ccx.intrinsics.get(~"llvm.bswap.i16");
|
||||
Store(bcx, Call(bcx, cttz, ~[x]), fcx.llretptr)
|
||||
}
|
||||
~"bswap32" => {
|
||||
let x = get_param(decl, first_real_arg);
|
||||
let cttz = ccx.intrinsics.get(~"llvm.bswap.i32");
|
||||
Store(bcx, Call(bcx, cttz, ~[x]), fcx.llretptr)
|
||||
}
|
||||
~"bswap64" => {
|
||||
let x = get_param(decl, first_real_arg);
|
||||
let cttz = ccx.intrinsics.get(~"llvm.bswap.i64");
|
||||
Store(bcx, Call(bcx, cttz, ~[x]), fcx.llretptr)
|
||||
}
|
||||
_ => {
|
||||
// Could we make this an enum rather than a string? does it get
|
||||
// checked earlier?
|
||||
|
@ -135,6 +135,8 @@ fn type_uses_for(ccx: @crate_ctxt, fn_id: def_id, n_tps: uint)
|
||||
~"ctlz8" | ~"ctlz16" | ~"ctlz32" | ~"ctlz64" => 0,
|
||||
~"cttz8" | ~"cttz16" | ~"cttz32" | ~"cttz64" => 0,
|
||||
|
||||
~"bswap16" | ~"bswap32" | ~"bswap64" => 0,
|
||||
|
||||
// would be cool to make these an enum instead of strings!
|
||||
_ => fail ~"unknown intrinsic in type_use"
|
||||
};
|
||||
|
@ -3204,6 +3204,18 @@ fn check_intrinsic_type(ccx: @crate_ctxt, it: @ast::foreign_item) {
|
||||
(0u, ~[arg(ast::by_copy, ty::mk_i64(tcx))],
|
||||
ty::mk_i64(tcx))
|
||||
}
|
||||
~"bswap16" => {
|
||||
(0u, ~[arg(ast::by_copy, ty::mk_i16(tcx))],
|
||||
ty::mk_i16(tcx))
|
||||
}
|
||||
~"bswap32" => {
|
||||
(0u, ~[arg(ast::by_copy, ty::mk_i32(tcx))],
|
||||
ty::mk_i32(tcx))
|
||||
}
|
||||
~"bswap64" => {
|
||||
(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) + ~"`");
|
||||
|
@ -28,6 +28,10 @@ extern mod rusti {
|
||||
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;
|
||||
}
|
||||
|
||||
fn main() {
|
||||
@ -109,4 +113,8 @@ fn main() {
|
||||
assert(cttz32(-1i32) == 0i32);
|
||||
assert(cttz64(-1i64) == 0i64);
|
||||
|
||||
assert(bswap16(0x0A0Bi16) == 0x0B0Ai16);
|
||||
assert(bswap32(0x0ABBCC0Di32) == 0x0DCCBB0Ai32);
|
||||
assert(bswap64(0x0122334455667708i64) == 0x0877665544332201i64);
|
||||
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user