Use long.js in JS and native i64 in WASM; Compile literals more thoroughly

This commit is contained in:
dcodeIO
2018-02-14 09:18:43 +01:00
parent 874f87f478
commit b1c6ccab2a
82 changed files with 1753 additions and 2199 deletions

View File

@ -1,54 +0,0 @@
require("../../std/portable");
// Copy Binaryen exports to global scope
var globalScope = typeof window !== "undefined" && window || typeof global !== "undefined" && global || self;
var binaryen = globalScope["Binaryen"]; // allow overriding for testing purposes
if (!binaryen) {
try {
binaryen = require("binaryen");
} catch (e) {
binaryen = globalScope["Binaryen"];
}
}
for (var key in binaryen)
if (/^_(?:Binaryen|Relooper)/.test(key))
globalScope[key] = binaryen[key];
// Use Binaryen's heap instead of std heap
globalScope["allocate_memory"] = function allocate_memory(size) {
if (!size) return 0; // should be safe in our case
return binaryen._malloc(size);
};
globalScope["free_memory"] = function free_memory(ptr) {
if (ptr) binaryen._free(ptr);
};
globalScope["move_memory"] = function move_memory(dest, src, n) {
return binaryen._memmove(dest, src, n);
};
globalScope["store"] = function store(ptr, val) {
binaryen.HEAPU8[ptr] = val;
};
globalScope["load"] = function load(ptr) {
return binaryen.HEAPU8[ptr];
};
// Implement module stubs
var Module = require("../module").Module;
Module.prototype.toText = function toText() {
var previousPrint = binaryen.print;
var ret = "";
binaryen.print = function print(x) { ret += x + "\n" };
this.print();
binaryen.print = previousPrint;
return ret;
};
Module.prototype.toAsmjs = function toAsmjs() {
var previousPrint = binaryen.print;
var ret = "";
binaryen.print = function print(x) { ret += x + "\n" };
this.printAsmjs();
binaryen.print = previousPrint;
return ret;
};

36
src/glue/js/i64.d.ts vendored Normal file
View File

@ -0,0 +1,36 @@
declare type I64 = Long;
declare function i64_new(lo: i32, hi?: i32): I64;
declare function i64_low(value: I64): i32;
declare function i64_high(value: I64): i32;
declare function i64_add(left: I64, right: I64): I64;
declare function i64_sub(left: I64, right: I64): I64;
declare function i64_mul(left: I64, right: I64): I64;
declare function i64_div(left: I64, right: I64): I64;
declare function i64_div_u(left: I64, right: I64): I64;
declare function i64_rem(left: I64, right: I64): I64;
declare function i64_rem_u(left: I64, right: I64): I64;
declare function i64_and(left: I64, right: I64): I64;
declare function i64_or(left: I64, right: I64): I64;
declare function i64_xor(left: I64, right: I64): I64;
declare function i64_shl(left: I64, right: I64): I64;
declare function i64_shr(left: I64, right: I64): I64;
declare function i64_shr_u(left: I64, right: I64): I64;
declare function i64_not(value: I64): I64;
declare function i64_align(value: I64, alignment: i32): I64;
declare function i64_is_i8(value: I64): bool;
declare function i64_is_i16(value: I64): bool;
declare function i64_is_i32(value: I64): bool;
declare function i64_is_u8(value: I64): bool;
declare function i64_is_u16(value: I64): bool;
declare function i64_is_u32(value: I64): bool;
declare function i64_is_bool(value: I64): bool;
declare function i64_is_f32(value: I64): bool;
declare function i64_is_f64(value: I64): bool;
declare function i64_to_f32(value: I64): f64;
declare function i64_to_f64(value: I64): f64;
declare function i64_to_string(value: I64, unsigned?: bool): string;

193
src/glue/js/index.ts Normal file
View File

@ -0,0 +1,193 @@
import "../../../std/portable";
// Copy Binaryen exports to global scope
declare const global: any;
declare function require(name: string): any;
const binaryen: any = global.Binaryen || require("binaryen");
for (let key in binaryen)
if (key.startsWith("_Binaryen") || key.startsWith("_Relooper"))
global[key] = (<any>binaryen)[key];
// Use Binaryen's heap instead of std heap
global.allocate_memory = function(size: number): number {
if (!size) return 0; // should be safe in our case
return (<any>binaryen)._malloc(size);
};
global.free_memory = function(ptr: number): void {
if (ptr) (<any>binaryen)._free(ptr);
};
global.move_memory = function(dest: number, src: number, n: number): number {
return (<any>binaryen)._memmove(dest, src, n);
};
global.store = function(ptr: number, val: number): void {
(<any>binaryen).HEAPU8[ptr] = val;
};
global.load = function(ptr: number): number {
return (<any>binaryen).HEAPU8[ptr];
};
// Implement module stubs
import { Module } from "../../module";
Module.prototype.toText = function toText() {
var previousPrint = binaryen.print;
var ret = "";
binaryen.print = (x: string) => { ret += x + "\n" };
this.print();
binaryen.print = previousPrint;
return ret;
};
Module.prototype.toAsmjs = function toAsmjs() {
var previousPrint = binaryen.print;
var ret = "";
binaryen.print = (x: string) => { ret += x + "\n" };
this.printAsmjs();
binaryen.print = previousPrint;
return ret;
};
// Implement I64 using long.js
import * as Long from "long";
/// <reference path="./i64.d.ts" />
global.i64_new = function(lo: number, hi: number = 0): I64 {
return Long.fromBits(lo, hi);
};
global.i64_low = function(value: I64): i32 {
return value.low;
};
global.i64_high = function(value: I64): i32 {
return value.high;
};
global.i64_add = function(left: I64, right: I64): I64 {
return left.add(right);
};
global.i64_sub = function(left: I64, right: I64): I64 {
return left.sub(right);
};
global.i64_mul = function(left: I64, right: I64): I64 {
return left.mul(right);
};
global.i64_div = function(left: I64, right: I64): I64 {
return left.div(right);
};
global.i64_div_u = function(left: I64, right: I64): I64 {
return left.toUnsigned().div(right.toUnsigned()).toSigned();
};
global.i64_rem = function(left: I64, right: I64): I64 {
return left.mod(right);
};
global.i64_rem_u = function(left: I64, right: I64): I64 {
return left.toUnsigned().mod(right.toUnsigned()).toSigned();
};
global.i64_and = function(left: I64, right: I64): I64 {
return left.and(right);
};
global.i64_or = function(left: I64, right: I64): I64 {
return left.or(right);
};
global.i64_xor = function(left: I64, right: I64): I64 {
return left.xor(right);
};
global.i64_shl = function(left: I64, right: I64): I64 {
return left.shl(right);
};
global.i64_shr = function(left: I64, right: I64): I64 {
return left.shr(right);
};
global.i64_shr_u = function(left: I64, right: I64): I64 {
return left.shru(right);
};
global.i64_not = function(value: I64): I64 {
return value.not();
};
global.i64_align = function(value: I64, alignment: i32): I64 {
assert(alignment && (alignment & (alignment - 1)) == 0);
var mask = Long.fromInt(alignment - 1);
return value.add(mask).and(mask.not());
};
global.i64_is_i8 = function(value: I64): bool {
return value.high === 0 && (value.low >= 0 && value.low <= i8.MAX_VALUE)
|| value.high === -1 && (value.low >= i8.MIN_VALUE && value.low < 0);
};
global.i64_is_i16 = function(value: I64): bool {
return value.high === 0 && (value.low >= 0 && value.low <= i16.MAX_VALUE)
|| value.high === -1 && (value.low >= i16.MIN_VALUE && value.low < 0);
};
global.i64_is_i32 = function(value: I64): bool {
return (value.high === 0 && value.low >= 0) || (value.high === -1 && value.low < 0);
};
global.i64_is_u8 = function(value: I64): bool {
return value.high === 0 && value.low >= 0 && value.low <= u8.MAX_VALUE;
};
global.i64_is_u16 = function(value: I64): bool {
return value.high === 0 && value.low >= 0 && value.low <= u16.MAX_VALUE;
};
global.i64_is_u32 = function(value: I64): bool {
return value.high === 0;
};
global.i64_is_bool = function(value: I64): bool {
return value.high === 0 && (value.low === 0 || value.low === 1);
};
const minSafeF32 = Long.fromNumber(f32.MIN_SAFE_INTEGER);
const maxSafeF32 = Long.fromNumber(f32.MAX_SAFE_INTEGER);
global.i64_is_f32 = function(value: I64): bool {
return value.gte(minSafeF32) && value.lte(maxSafeF32);
};
const minSafeF64 = Long.fromNumber(f64.MIN_SAFE_INTEGER);
const maxSafeF64 = Long.fromNumber(f64.MAX_SAFE_INTEGER);
global.i64_is_f64 = function(value: I64): bool {
return value.gte(minSafeF64) && value.lte(maxSafeF64);
};
global.i64_to_f32 = function(value: I64): f64 {
return global.Math.fround(value.toNumber());
};
global.i64_to_f64 = function(value: I64): f64 {
return value.toNumber();
};
global.i64_to_string = function(value: I64, unsigned: bool = false): string {
return (unsigned ? value.toUnsigned() : value).toString(10);
};

164
src/glue/wasm/index.ts Normal file
View File

@ -0,0 +1,164 @@
type I64 = i64;
@global
function i64_new(lo: i32, hi: i32 = 0): I64 {
return lo | (hi << 32);
}
@global
function i64_low(value: I64): i32 {
return <i32>value;
}
@global
function i64_high(value: I64): i32 {
return <i32>(value >>> 32);
}
@global
function i64_add(left: I64, right: I64): I64 {
return left + right;
}
@global
function i64_sub(left: I64, right: I64): I64 {
return left - right;
}
@global
function i64_mul(left: I64, right: I64): I64 {
return left * right;
}
@global
function i64_div(left: I64, right: I64): I64 {
return left / right;
}
@global
function i64_div_u(left: I64, right: I64): I64 {
return <u64>left / <u64>right;
}
@global
function i64_rem(left: I64, right: I64): I64 {
return left % right;
}
@global
function i64_rem_u(left: I64, right: I64): I64 {
return <u64>left % <u64>right;
}
@global
function i64_and(left: I64, right: I64): I64 {
return left & right;
}
@global
function i64_or(left: I64, right: I64): I64 {
return left | right;
}
@global
function i64_xor(left: I64, right: I64): I64 {
return left ^ right;
}
@global
function i64_shl(left: I64, right: I64): I64 {
return left << right;
}
@global
function i64_shr(left: I64, right: I64): I64 {
return left >> right;
}
@global
function i64_shr_u(left: I64, right: I64): I64 {
return left >>> right;
}
@global
function i64_not(value: I64): I64 {
return ~value;
}
@global
function i64_align(value: I64, alignment: i64): I64 {
var mask: i64 = alignment - 1;
assert(alignment && (alignment & mask) == 0);
return (value + mask) & ~mask;
}
@global
function i64_is_i8(value: I64): bool {
return value >= i8.MIN_VALUE && value <= i8.MAX_VALUE;
}
@global
function i64_is_i16(value: I64): bool {
return value >= i16.MIN_VALUE && value <= i16.MAX_VALUE;
}
@global
function i64_is_i32(value: I64): bool {
return value >= i32.MIN_VALUE && value <= i32.MAX_VALUE;
}
@global
function i64_is_u8(value: I64): bool {
return value >= 0 && value <= u8.MAX_VALUE;
}
@global
function i64_is_u16(value: I64): bool {
return value >= 0 && value <= u16.MAX_VALUE;
}
@global
function i64_is_u32(value: I64): bool {
return value >= 0 && value <= u32.MAX_VALUE;
}
@global
function i64_is_bool(value: I64): bool {
return value === 0 || value === 1;
}
@global
function i64_is_f32(value: I64): bool {
return value >= f32.MIN_SAFE_INTEGER && value <= f32.MAX_SAFE_INTEGER;
}
@global
function i64_is_f64(value: I64): bool {
return value >= f64.MIN_SAFE_INTEGER && value <= f64.MAX_SAFE_INTEGER;
}
@global
function i64_to_f32(value: I64): f32 {
return <f32>value;
}
@global
function i64_to_f64(value: I64): f64 {
return <f64>value;
}
import { CharCode } from "../../util/charcode";
@global
function i64_to_string(value: I64): string {
var chars = new Array<u16>();
if (value < 0) {
chars.push(CharCode.MINUS);
value = -value;
}
do {
chars.push(CharCode._0 + (value % 10));
value /= 10;
} while (value);
return String.fromCharCodes(chars);
}

View File

@ -0,0 +1,6 @@
{
"extends": "../../../std/assembly.json",
"include": [
"./**/*.ts"
]
}