Minor restructure and fixes; README; Proposed binaryen additions

This commit is contained in:
dcodeIO
2017-12-10 21:59:45 +01:00
parent 5ff88e126e
commit 0228ab91d9
13 changed files with 391 additions and 72 deletions

View File

@ -1,8 +1,56 @@
import { compileCall as compileBuiltinCall, initialize } from "./builtins";
import { PATH_DELIMITER } from "./constants";
import { DiagnosticCode, DiagnosticEmitter } from "./diagnostics";
import { Module, MemorySegment, ExpressionRef, UnaryOp, BinaryOp, NativeType, FunctionRef, FunctionTypeRef, getExpressionId, ExpressionId, getExpressionType, getFunctionBody, getConstValueI32, getConstValueI64Low, getConstValueI64High, getConstValueF32, getConstValueF64 } from "./module";
import { Program, ClassPrototype, Class, Element, ElementKind, Enum, FunctionPrototype, Function, Global, Local, Namespace, Parameter, EnumValue } from "./program";
import {
Module,
MemorySegment,
ExpressionRef,
UnaryOp,
BinaryOp,
NativeType,
FunctionTypeRef,
FunctionRef,
ExpressionId,
getExpressionId,
getExpressionType,
getFunctionBody,
getConstValueI32,
getConstValueI64Low,
getConstValueI64High,
getConstValueF32,
getConstValueF64,
getGetLocalIndex,
getGetGlobalName,
isLoadAtomic,
isLoadSigned,
getLoadBytes,
getLoadOffset,
getLoadPtr,
getUnaryOp,
getUnaryValue,
getBinaryOp,
getBinaryLeft,
getBinaryRight
} from "./module";
import {
Program,
ClassPrototype,
Class, Element,
ElementKind,
Enum,
FunctionPrototype,
Function,
Global,
Local,
Namespace,
Parameter,
EnumValue
} from "./program";
import { I64, U64, sb } from "./util";
import { Token } from "./tokenizer";
import {
@ -65,6 +113,7 @@ import {
UnaryPostfixExpression,
UnaryPrefixExpression,
// utility
hasModifier
} from "./ast";
@ -1021,7 +1070,8 @@ export class Compiler extends DiagnosticEmitter {
this.module.runPasses([ "precompute" ], funcRef);
const ret: ExpressionRef = getFunctionBody(funcRef);
this.module.removeFunction("__precompute");
// TODO: also remove the function type somehow if no longer used
// TODO: also remove the function type somehow if no longer used or make the C-API accept
// a `null` typeRef, using an implicit type.
return ret;
}
@ -1190,6 +1240,41 @@ export class Compiler extends DiagnosticEmitter {
return expr;
}
cloneExpressionRef(expr: ExpressionRef, noSideEffects: bool = false, maxDepth: i32 = 0x7fffffff): ExpressionRef {
// currently supports side effect free expressions only
if (maxDepth < 0)
return 0;
let nested1: ExpressionRef,
nested2: ExpressionRef;
switch (getExpressionId(expr)) {
case ExpressionId.Const:
switch (getExpressionType(expr)) {
case NativeType.I32: return this.module.createI32(getConstValueI32(expr));
case NativeType.I64: return this.module.createI64(getConstValueI64Low(expr), getConstValueI64High(expr));
case NativeType.F32: return this.module.createF32(getConstValueF32(expr));
case NativeType.F64: return this.module.createF64(getConstValueF64(expr));
default: throw new Error("unexpected expression type");
}
case ExpressionId.GetLocal:
return this.module.createGetLocal(getGetLocalIndex(expr), getExpressionType(expr));
case ExpressionId.GetGlobal:
return this.module.createGetGlobal(getGetGlobalName(expr), getExpressionType(expr));
case ExpressionId.Load:
if (!(nested1 = this.cloneExpressionRef(getLoadPtr(expr), noSideEffects, maxDepth - 1))) break;
return isLoadAtomic(expr)
? this.module.createAtomicLoad(getLoadBytes(expr), nested1, getExpressionType(expr), getLoadOffset(expr))
: this.module.createLoad(getLoadBytes(expr), isLoadSigned(expr), nested1, getExpressionType(expr), getLoadOffset(expr));
case ExpressionId.Unary:
if (!(nested1 = this.cloneExpressionRef(getUnaryValue(expr), noSideEffects, maxDepth - 1))) break;
return this.module.createUnary(getUnaryOp(expr), nested1);
case ExpressionId.Binary:
if (!(nested1 = this.cloneExpressionRef(getBinaryLeft(expr), noSideEffects, maxDepth - 1))) break;
if (!(nested2 = this.cloneExpressionRef(getBinaryLeft(expr), noSideEffects, maxDepth - 1))) break;
return this.module.createBinary(getBinaryOp(expr), nested1, nested2);
}
return 0;
}
compileAssertionExpression(expression: AssertionExpression, contextualType: Type): ExpressionRef {
const toType: Type | null = this.program.resolveType(expression.toType, this.currentFunction.contextualTypeArguments); // reports
return toType && toType != contextualType
@ -1426,15 +1511,31 @@ export class Compiler extends DiagnosticEmitter {
case Token.AMPERSAND_AMPERSAND: // left && right
left = this.compileExpression(expression.left, contextualType, contextualType == Type.void ? ConversionKind.NONE : ConversionKind.IMPLICIT);
right = this.compileExpression(expression.right, this.currentType);
// TODO: once it's possible to clone 'left', we could check if it is a Const, GetLocal, GetGlobal or Load and avoid the tempLocal
// simplify if left is free of side effects while tolerating two levels of nesting, e.g., i32.load(i32.load(i32.const))
// if (condition = this.cloneExpressionRef(left, true, 2))
// return this.module.createIf(
// this.currentType.isLongInteger
// ? this.module.createBinary(BinaryOp.NeI64, condition, this.module.createI64(0, 0))
// : this.currentType == Type.f64
// ? this.module.createBinary(BinaryOp.NeF64, condition, this.module.createF64(0))
// : this.currentType == Type.f32
// ? this.module.createBinary(BinaryOp.NeF32, condition, this.module.createF32(0))
// : condition, // usual case: saves one EQZ when not using EQZ above
// right,
// left
// );
// otherwise use a temporary local for the intermediate value
tempLocal = this.currentFunction.addLocal(this.currentType);
condition = this.module.createTeeLocal(tempLocal.index, left);
return this.module.createIf(
this.currentType.isLongInteger
? this.module.createBinary(BinaryOp.NeI64, this.module.createTeeLocal(tempLocal.index, left), this.module.createI64(0, 0))
? this.module.createBinary(BinaryOp.NeI64, condition, this.module.createI64(0, 0))
: this.currentType == Type.f64
? this.module.createBinary(BinaryOp.NeF64, this.module.createTeeLocal(tempLocal.index, left), this.module.createF64(0))
? this.module.createBinary(BinaryOp.NeF64, condition, this.module.createF64(0))
: this.currentType == Type.f32
? this.module.createBinary(BinaryOp.NeF32, this.module.createTeeLocal(tempLocal.index, left), this.module.createF32(0))
? this.module.createBinary(BinaryOp.NeF32, condition, this.module.createF32(0))
: this.module.createTeeLocal(tempLocal.index, left),
right,
this.module.createGetLocal(tempLocal.index, typeToNativeType(tempLocal.type))
@ -1443,15 +1544,31 @@ export class Compiler extends DiagnosticEmitter {
case Token.BAR_BAR: // left || right
left = this.compileExpression(expression.left, contextualType, contextualType == Type.void ? ConversionKind.NONE : ConversionKind.IMPLICIT);
right = this.compileExpression(expression.right, this.currentType);
// TODO: same as above
// simplify if left is free of side effects while tolerating two levels of nesting
// if (condition = this.cloneExpressionRef(left, true, 2))
// return this.module.createIf(
// this.currentType.isLongInteger
// ? this.module.createBinary(BinaryOp.NeI64, condition, this.module.createI64(0, 0))
// : this.currentType == Type.f64
// ? this.module.createBinary(BinaryOp.NeF64, condition, this.module.createF64(0))
// : this.currentType == Type.f32
// ? this.module.createBinary(BinaryOp.NeF32, condition, this.module.createF32(0))
// : condition, // usual case: saves one EQZ when not using EQZ above
// left,
// right
// );
// otherwise use a temporary local for the intermediate value
tempLocal = this.currentFunction.addLocal(this.currentType);
condition = this.module.createTeeLocal(tempLocal.index, left);
return this.module.createIf(
this.currentType.isLongInteger
? this.module.createBinary(BinaryOp.NeI64, this.module.createTeeLocal(tempLocal.index, left), this.module.createI64(0, 0))
? this.module.createBinary(BinaryOp.NeI64, condition, this.module.createI64(0, 0))
: this.currentType == Type.f64
? this.module.createBinary(BinaryOp.NeF64, this.module.createTeeLocal(tempLocal.index, left), this.module.createF64(0))
? this.module.createBinary(BinaryOp.NeF64, condition, this.module.createF64(0))
: this.currentType == Type.f32
? this.module.createBinary(BinaryOp.NeF32, this.module.createTeeLocal(tempLocal.index, left), this.module.createF32(0))
? this.module.createBinary(BinaryOp.NeF32, condition, this.module.createF32(0))
: this.module.createTeeLocal(tempLocal.index, left),
this.module.createGetLocal(tempLocal.index, typeToNativeType(tempLocal.type)),
right

View File

@ -60,13 +60,9 @@ declare type BinaryenModuleRef = usize;
declare function _BinaryenModuleCreate(): BinaryenModuleRef;
declare function _BinaryenModuleDispose(module: BinaryenModuleRef): void;
declare type BinaryenFunctionTypeRef = usize;
declare type CString = usize;
declare type CArray<T> = usize;
declare function _BinaryenAddFunctionType(module: BinaryenModuleRef, name: CString, result: BinaryenType, paramTypes: CArray<BinaryenType>, numParams: BinaryenIndex): BinaryenFunctionTypeRef;
declare function _BinaryenGetFunctionTypeBySignature(module: BinaryenModuleRef, result: BinaryenType, paramTypes: CArray<BinaryenType>, numParams: BinaryenIndex): BinaryenFunctionTypeRef;
declare type BinaryenLiteral = CArray<u8>;
// LLVM C ABI with `out` being a buffer of 16 bytes receiving the BinaryenLiteral struct.
@ -256,18 +252,134 @@ declare function _BinaryenAtomicWake(module: BinaryenModuleRef, ptr: BinaryenExp
declare function _BinaryenExpressionGetId(expr: BinaryenExpressionRef): BinaryenExpressionId;
declare function _BinaryenExpressionGetType(expr: BinaryenExpressionRef): BinaryenType;
declare function _BinaryenExpressionPrint(expr: BinaryenExpressionRef): void;
declare function _BinaryenBlockGetName(expr: BinaryenExpressionRef): CString;
declare function _BinaryenBlockGetNumChildren(expr: BinaryenExpressionRef): BinaryenIndex;
declare function _BinaryenBlockGetChild(expr: BinaryenExpressionRef, index: BinaryenIndex): BinaryenExpressionRef;
declare function _BinaryenIfGetCondition(expr: BinaryenExpressionRef): BinaryenExpressionRef;
declare function _BinaryenIfGetIfTrue(expr: BinaryenExpressionRef): BinaryenExpressionRef;
declare function _BinaryenIfGetIfFalse(expr: BinaryenExpressionRef): BinaryenExpressionRef;
declare function _BinaryenLoopGetName(expr: BinaryenExpressionRef): CString;
declare function _BinaryenLoopGetBody(expr: BinaryenExpressionRef): BinaryenExpressionRef;
declare function _BinaryenBreakGetName(expr: BinaryenExpressionRef): CString;
declare function _BinaryenBreakGetCondition(expr: BinaryenExpressionRef): BinaryenExpressionRef;
declare function _BinaryenBreakGetValue(expr: BinaryenExpressionRef): BinaryenExpressionRef;
declare function _BinaryenSwitchGetNumNames(expr: BinaryenExpressionRef): BinaryenIndex;
declare function _BinaryenSwitchGetName(expr: BinaryenExpressionRef, index: BinaryenIndex): CString;
declare function _BinaryenSwitchGetDefaultName(expr: BinaryenExpressionRef): CString;
declare function _BinaryenSwitchGetCondition(expr: BinaryenExpressionRef): BinaryenExpressionRef;
declare function _BinaryenSwitchGetValue(expr: BinaryenExpressionRef): BinaryenExpressionRef;
declare function _BinaryenCallGetTarget(expr: BinaryenExpressionRef): CString;
declare function _BinaryenCallGetNumOperands(expr: BinaryenExpressionRef): BinaryenIndex;
declare function _BinaryenCallGetOperand(expr: BinaryenExpressionRef, index: BinaryenIndex): BinaryenExpressionRef;
declare function _BinaryenCallImportGetTarget(expr: BinaryenExpressionRef): CString;
declare function _BinaryenCallImportGetNumOperands(expr: BinaryenExpressionRef): BinaryenIndex;
declare function _BinaryenCallImportGetOperand(expr: BinaryenExpressionRef, index: BinaryenIndex): BinaryenExpressionRef;
declare function _BinaryenCallIndirectGetTarget(expr: BinaryenExpressionRef): BinaryenExpressionRef;
declare function _BinaryenCallIndirectGetNumOperands(expr: BinaryenExpressionRef): BinaryenIndex;
declare function _BinaryenCallIndirectGetOperand(expr: BinaryenExpressionRef, index: BinaryenIndex): BinaryenExpressionRef;
declare function _BinaryenGetLocalGetIndex(expr: BinaryenExpressionRef): BinaryenIndex;
declare function _BinaryenSetLocalIsTee(expr: BinaryenExpressionRef): bool;
declare function _BinaryenSetLocalGetIndex(expr: BinaryenExpressionRef): BinaryenIndex;
declare function _BinaryenSetLocalGetValue(expr: BinaryenExpressionRef): BinaryenExpressionRef;
declare function _BinaryenGetGlobalGetName(expr: BinaryenExpressionRef): CString;
declare function _BinaryenSetGlobalGetName(expr: BinaryenExpressionRef): CString;
declare function _BinaryenSetGlobalGetValue(expr: BinaryenExpressionRef): BinaryenExpressionRef;
declare function _BinaryenHostGetOp(expr: BinaryenExpressionRef): BinaryenOp;
declare function _BinaryenHostGetNameOperand(expr: BinaryenExpressionRef): CString;
declare function _BinaryenHostGetNumOperands(expr: BinaryenExpressionRef): BinaryenIndex;
declare function _BinaryenHostGetOperand(expr: BinaryenExpressionRef, index: BinaryenIndex): BinaryenExpressionRef;
declare function _BinaryenLoadIsAtomic(expr: BinaryenExpressionRef): bool;
declare function _BinaryenLoadIsSigned(expr: BinaryenExpressionRef): bool;
declare function _BinaryenLoadGetBytes(expr: BinaryenExpressionRef): u32;
declare function _BinaryenLoadGetOffset(expr: BinaryenExpressionRef): u32;
declare function _BinaryenLoadGetAlign(expr: BinaryenExpressionRef): u32;
declare function _BinaryenLoadGetPtr(expr: BinaryenExpressionRef): BinaryenExpressionRef;
declare function _BinaryenStoreIsAtomic(expr: BinaryenExpressionRef): bool;
declare function _BinaryenStoreGetBytes(expr: BinaryenExpressionRef): u32;
declare function _BinaryenStoreGetOffset(expr: BinaryenExpressionRef): u32;
declare function _BinaryenStoreGetAlign(expr: BinaryenExpressionRef): u32;
declare function _BinaryenStoreGetPtr(expr: BinaryenExpressionRef): BinaryenExpressionRef;
declare function _BinaryenStoreGetValue(expr: BinaryenExpressionRef): BinaryenExpressionRef;
declare function _BinaryenConstGetValueI32(expr: BinaryenExpressionRef): i32;
declare function _BinaryenConstGetValueI64Low(expr: BinaryenExpressionRef): i32;
declare function _BinaryenConstGetValueI64High(expr: BinaryenExpressionRef): i32;
declare function _BinaryenConstGetValueF32(expr: BinaryenExpressionRef): f32;
declare function _BinaryenConstGetValueF64(expr: BinaryenExpressionRef): f64;
declare function _BinaryenUnaryGetOp(expr: BinaryenExpressionRef): BinaryenOp;
declare function _BinaryenUnaryGetValue(expr: BinaryenExpressionRef): BinaryenExpressionRef;
declare function _BinaryenBinaryGetOp(expr: BinaryenExpressionRef): BinaryenOp;
declare function _BinaryenBinaryGetLeft(expr: BinaryenExpressionRef): BinaryenExpressionRef;
declare function _BinaryenBinaryGetRight(expr: BinaryenExpressionRef): BinaryenExpressionRef;
declare function _BinaryenSelectGetIfTrue(expr: BinaryenExpressionRef): BinaryenExpressionRef;
declare function _BinaryenSelectGetIfFalse(expr: BinaryenExpressionRef): BinaryenExpressionRef;
declare function _BinaryenSelectGetCondition(expr: BinaryenExpressionRef): BinaryenExpressionRef;
declare function _BinaryenDropGetValue(expr: BinaryenExpressionRef): BinaryenExpressionRef;
declare function _BinaryenReturnGetValue(expr: BinaryenExpressionRef): BinaryenExpressionRef;
declare function _BinaryenAtomicRMWGetOp(expr: BinaryenExpressionRef): BinaryenOp;
declare function _BinaryenAtomicRMWGetBytes(expr: BinaryenExpressionRef): u32;
declare function _BinaryenAtomicRMWGetOffset(expr: BinaryenExpressionRef): u32;
declare function _BinaryenAtomicRMWGetPtr(expr: BinaryenExpressionRef): BinaryenExpressionRef;
declare function _BinaryenAtomicRMWGetValue(expr: BinaryenExpressionRef): BinaryenExpressionRef;
declare function _BinaryenAtomicCmpxchgGetBytes(expr: BinaryenExpressionRef): u32;
declare function _BinaryenAtomicCmpxchgGetOffset(expr: BinaryenExpressionRef): u32;
declare function _BinaryenAtomicCmpxchgGetPtr(expr: BinaryenExpressionRef): BinaryenExpressionRef;
declare function _BinaryenAtomicCmpxchgGetExpected(expr: BinaryenExpressionRef): BinaryenExpressionRef;
declare function _BinaryenAtomicCmpxchgGetReplacement(expr: BinaryenExpressionRef): BinaryenExpressionRef;
declare function _BinaryenAtomicWaitGetPtr(expr: BinaryenExpressionRef): BinaryenExpressionRef;
declare function _BinaryenAtomicWaitGetExpected(expr: BinaryenExpressionRef): BinaryenExpressionRef;
declare function _BinaryenAtomicWaitGetTimeout(expr: BinaryenExpressionRef): BinaryenExpressionRef;
declare function _BinaryenAtomicWaitGetExpectedType(expr: BinaryenExpressionRef): BinaryenType;
declare function _BinaryenAtomicWakeGetPtr(expr: BinaryenExpressionRef): BinaryenExpressionRef;
declare function _BinaryenAtomicWakeGetWakeCount(expr: BinaryenExpressionRef): BinaryenExpressionRef;
declare type BinaryenFunctionTypeRef = usize;
declare function _BinaryenAddFunctionType(module: BinaryenModuleRef, name: CString, result: BinaryenType, paramTypes: CArray<BinaryenType>, numParams: BinaryenIndex): BinaryenFunctionTypeRef;
declare function _BinaryenGetFunctionTypeBySignature(module: BinaryenModuleRef, result: BinaryenType, paramTypes: CArray<BinaryenType>, numParams: BinaryenIndex): BinaryenFunctionTypeRef;
declare function _BinaryenFunctionTypeGetName(ftype: BinaryenFunctionTypeRef): CString;
declare function _BinaryenFunctionTypeGetNumParams(ftype: BinaryenFunctionTypeRef): BinaryenIndex;
declare function _BinaryenFunctionTypeGetParam(ftype: BinaryenFunctionTypeRef, index: BinaryenIndex): BinaryenType;
declare function _BinaryenFunctionTypeGetResult(ftype: BinaryenFunctionTypeRef): BinaryenType;
declare type BinaryenFunctionRef = usize;
declare function _BinaryenAddFunction(module: BinaryenModuleRef, name: CString, type: BinaryenFunctionTypeRef, varTypes: CArray<BinaryenType>, numVarTypes: BinaryenIndex, body: BinaryenExpressionRef): BinaryenFunctionRef;
declare function _BinaryenGetFunction(module: BinaryenModuleRef, name: CString): BinaryenFunctionRef;
declare function _BinaryenRemoveFunction(module: BinaryenModuleRef, name: CString): void;
declare function _BinaryenFunctionGetName(func: BinaryenFunctionRef): CString;
declare function _BinaryenFunctionGetType(func: BinaryenFunctionRef): BinaryenFunctionTypeRef;
declare function _BinaryenFunctionGetNumParams(func: BinaryenFunctionRef): BinaryenIndex;
declare function _BinaryenFunctionGetParam(func: BinaryenFunctionRef, index: BinaryenIndex): BinaryenType;
declare function _BinaryenFunctionGetResult(func: BinaryenFunctionRef): BinaryenType;
declare function _BinaryenFunctionGetNumVars(func: BinaryenFunctionRef): BinaryenIndex;
declare function _BinaryenFunctionGetVar(func: BinaryenFunctionRef, index: BinaryenIndex): BinaryenType;
declare function _BinaryenFunctionGetBody(func: BinaryenFunctionRef): BinaryenExpressionRef;
declare function _BinaryenFunctionOptimize(func: BinaryenFunctionRef, module: BinaryenModuleRef): void;
declare function _BinaryenFunctionRunPasses(func: BinaryenFunctionRef, module: BinaryenModuleRef, passes: CArray<CString>, numPasses: BinaryenIndex): void;

View File

@ -807,10 +807,58 @@ export function getConstValueF64(expr: ExpressionRef): f64 {
return _BinaryenConstGetValueF64(expr);
}
export function getGetLocalIndex(expr: ExpressionRef): Index {
return _BinaryenGetLocalGetIndex(expr);
}
export function getGetGlobalName(expr: ExpressionRef): string {
return readString(_BinaryenGetGlobalGetName(expr));
}
export function isLoadAtomic(expr: ExpressionRef): bool {
return _BinaryenLoadIsAtomic(expr);
}
export function isLoadSigned(expr: ExpressionRef): bool {
return _BinaryenLoadIsSigned(expr);
}
export function getLoadBytes(expr: ExpressionRef): u32 {
return _BinaryenLoadGetBytes(expr);
}
export function getLoadOffset(expr: ExpressionRef): u32 {
return _BinaryenLoadGetOffset(expr);
}
export function getLoadPtr(expr: ExpressionRef): ExpressionRef {
return _BinaryenLoadGetPtr(expr);
}
export function getFunctionBody(func: FunctionRef): ExpressionRef {
return _BinaryenFunctionGetBody(func);
}
export function getUnaryOp(expr: ExpressionRef): UnaryOp {
return _BinaryenUnaryGetOp(expr);
}
export function getUnaryValue(expr: ExpressionRef): ExpressionRef {
return _BinaryenUnaryGetValue(expr);
}
export function getBinaryOp(expr: ExpressionRef): BinaryOp {
return _BinaryenBinaryGetOp(expr);
}
export function getBinaryLeft(expr: ExpressionRef): ExpressionRef {
return _BinaryenBinaryGetLeft(expr);
}
export function getBinaryRight(expr: ExpressionRef): ExpressionRef {
return _BinaryenBinaryGetRight(expr);
}
export class Relooper {
module: Module;
@ -866,9 +914,9 @@ export class Relooper {
}
}
// export function setAPITracing(on: bool): void {
// _BinaryenSetAPITracing(on ? 1 : 0);
// }
export function setAPITracing(on: bool): void {
_BinaryenSetAPITracing(on ? 1 : 0);
}
// helpers
// can't do stack allocation here: STACKTOP is a global in WASM but a hidden variable in asm.js
@ -959,3 +1007,47 @@ function allocString(str: string | null): CString {
store<u8>(idx, 0);
return ptr;
}
function readString(ptr: usize): string {
const utf16le: u32[] = [];
// the following is based on Emscripten's UTF8ArrayToString
let cp: u32;
let u1: u32, u2: u32, u3: u32, u4: u32, u5: u32;
while (cp = load<u8>(ptr++)) {
if (!(cp & 0x80)) {
utf16le.push(cp);
continue;
}
u1 = load<u8>(ptr++) & 63;
if ((cp & 0xE0) == 0xC0) {
utf16le.push(((cp & 31) << 6) | u1);
continue;
}
u2 = load<u8>(ptr++) & 63;
if ((cp & 0xF0) == 0xE0) {
cp = ((cp & 15) << 12) | (u1 << 6) | u2;
} else {
u3 = load<u8>(ptr++) & 63;
if ((cp & 0xF8) == 0xF0) {
cp = ((cp & 7) << 18) | (u1 << 12) | (u2 << 6) | u3;
} else {
u4 = load<u8>(ptr++) & 63;
if ((cp & 0xFC) == 0xF8) {
cp = ((cp & 3) << 24) | (u1 << 18) | (u2 << 12) | (u3 << 6) | u4;
} else {
u5 = load<u8>(ptr++) & 63;
cp = ((cp & 1) << 30) | (u1 << 24) | (u2 << 18) | (u3 << 12) | (u4 << 6) | u5;
}
}
}
if (cp < 0x10000) {
utf16le.push(cp);
} else {
var ch = cp - 0x10000;
utf16le.push(0xD800 | (ch >> 10));
utf16le.push(0xDC00 | (ch & 0x3FF));
}
}
// FIXME: not portable and prone to stack overflows. Maybe use CString from stdlib?
return String.fromCharCode.apply(utf16le);
}

View File

@ -37,7 +37,7 @@ export class Type {
constructor(kind: TypeKind, size: i32) {
this.kind = kind;
this.size = size;
this.byteSize = ceil<f64>(<f64>size / 8);
this.byteSize = <i32>ceil<f64>(<f64>size / 8);
this.classType = null;
}