Skip to content

Add bswap/bswap16 post MVP polyfills #34

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Feb 19, 2018
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions std/assembly.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -175,6 +175,11 @@ declare function free_memory(ptr: usize): void;
/** Emits an unreachable operation that results in a runtime error when executed. Both a statement and an expression of any type. */
declare function unreachable(): any; // sic

/** [Polyfill] Performs the sign-agnostic reverse bytes **/
declare function bswap<T = i8 | u8 | i16 | u16 | i32 | u32 | i64 | u64 | isize | usize>(value: T): T;
/** [Polyfill] Performs the sign-agnostic reverse bytes only for last 16-bit **/
declare function bswap16<T = i8 | u8 | i16 | u16 | i32 | u32>(value: T): T;

/** NaN (not a number) as a 32-bit or 64-bit float depending on context. */
declare const NaN: f32 | f64;
/** Positive infinity as a 32-bit or 64-bit float depending on context. */
Expand Down
4 changes: 4 additions & 0 deletions std/assembly/error.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,3 +12,7 @@ export class Error {
export class RangeError extends Error {
name: string = "RangeError";
}

export class TypeError extends Error {
name: string = "TypeError";
}
31 changes: 31 additions & 0 deletions std/assembly/polyfills.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
export function bswap<T>(value: T): T {
assert(sizeof<T>() == 1 || sizeof<T>() == 2 || sizeof<T>() == 4 || sizeof<T>() == 8);

if (sizeof<T>() == 2) {
return bswap16<T>(value);
} else if (sizeof<T>() == 4) {
return <T>(
rotl<u32>(<u32>value & 0xFF00FF00, 8) |
rotr<u32>(<u32>value & 0x00FF00FF, 8)
);
} else if (sizeof<T>() == 8) {
var a: u64 = (<u64>value >> 8) & 0x00FF00FF00FF00FF;
var b: u64 = (<u64>value & 0x00FF00FF00FF00FF) << 8;
var v: u64 = a | b;

a = (v >> 16) & 0x0000FFFF0000FFFF;
b = (v & 0x0000FFFF0000FFFF) << 16;

return <T>rotr<u64>(a | b, 32);
}
return value;
}

export function bswap16<T>(value: T): T {
assert(sizeof<T>() == 1 || sizeof<T>() == 2 || sizeof<T>() == 4);

if (sizeof<T>() == 2 || sizeof<T>() == 4) {
return <T>(((value << 8) & <T>0xFF00) | ((value >> 8) & <T>0x00FF) | (value & <T>0xFFFF0000));
}
return value;
}
5 changes: 5 additions & 0 deletions std/portable.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -129,6 +129,11 @@ declare function store<T = u8>(ptr: usize, value: T, constantOffset?: usize): vo
/** Emits an unreachable operation that results in a runtime error when executed. */
declare function unreachable(): any; // sic

/** [Polyfill] Performs the sign-agnostic reverse bytes **/
declare function bswap<T = i32 | u32 | isize | usize>(value: T): T;
/** [Polyfill] Performs the sign-agnostic reverse bytes only for last 16-bit **/
declare function bswap16<T = i16 | u16 | i32 | u32>(value: T): T;

/** Changes the type of any value of `usize` kind to another one of `usize` kind. Useful for casting class instances to their pointer values and vice-versa. Beware that this is unsafe.*/
declare function changetype<T>(value: any): T;
/** Traps if the specified value is not true-ish, otherwise returns the value. */
Expand Down
13 changes: 13 additions & 0 deletions std/portable.js
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,19 @@ globalScope["select"] = function select(ifTrue, ifFalse, condition) { return con
globalScope["sqrt"] = Math.sqrt;
globalScope["trunc"] = Math.trunc;

globalScope["bswap"] = function bswap(value) {
var a = value >> 8 & 0x00FF00FF;
var b = (value & 0x00FF00FF) << 8;
value = a | b;
a = value >> 16 & 0x0000FFFF;
b = (value & 0x0000FFFF) << 16;
return a | b;
}

globalScope["bswap16"] = function bswap16(value) {
return ((value << 8) & 0xFF00) | ((value >> 8) & 0x00FF) | (value & 0xFFFF0000);
}

function UnreachableError() {
if (Error.captureStackTrace)
Error.captureStackTrace(this, UnreachableError);
Expand Down
Loading