mirror of
https://github.com/fluencelabs/assemblyscript
synced 2025-04-25 15:12:12 +00:00
Smarter temp locals; Less binaryen boilerplate
This commit is contained in:
parent
7a5f7dba50
commit
f75b962c74
8
assembly.d.ts
vendored
8
assembly.d.ts
vendored
@ -115,4 +115,10 @@ interface IArguments {}
|
||||
interface Number {}
|
||||
interface Object {}
|
||||
interface RegExp {}
|
||||
interface String {}
|
||||
|
||||
declare class String {
|
||||
static fromCharCode(ls: i32, hs?: i32): string;
|
||||
static fromCharCodes(arr: u16[]): string;
|
||||
static fromCodePoint(cp: i32): string;
|
||||
static fromCodePoints(arr: i32[]): string;
|
||||
}
|
||||
|
3
portable.d.ts
vendored
3
portable.d.ts
vendored
@ -83,6 +83,9 @@ declare class Int32Array extends Array<i32> {}
|
||||
|
||||
declare class String {
|
||||
static fromCharCode(ls: i32, hs?: i32): string;
|
||||
static fromCharCodes(arr: u16[]): string;
|
||||
static fromCodePoint(cp: i32): string;
|
||||
static fromCodePoints(arr: i32[]): string;
|
||||
readonly length: i32;
|
||||
indexOf(subject: string): i32;
|
||||
charCodeAt(index: i32): i32;
|
||||
|
@ -28,3 +28,6 @@ AssertionError.prototype.message = "assertion failed";
|
||||
|
||||
globalScope["assert"] = function assert(isTrue) { if (!isTrue) throw new AssertionError(); };
|
||||
globalScope["changetype"] = function changetype(value) { return value; }
|
||||
|
||||
String["fromCharCodes"] = function fromCharCodes(arr) { return String.fromCharCode.apply(String, arr); }
|
||||
String["fromCodePoints"] = function fromCodePoints(arr) { return String.fromCodePoint.apply(String, arr); }
|
||||
|
@ -156,7 +156,7 @@ export function compileCall(compiler: Compiler, prototype: FunctionPrototype, ty
|
||||
: module.createUnary(UnaryOp.AbsF64, arg0);
|
||||
if (typeArguments[0].isAnyInteger) {
|
||||
if (typeArguments[0].isSignedInteger) {
|
||||
tempLocal0 = compiler.currentFunction.addLocal(typeArguments[0]);
|
||||
tempLocal0 = compiler.currentFunction.getAndFreeTempLocal(typeArguments[0]);
|
||||
if (typeArguments[0].isLongInteger)
|
||||
return module.createSelect(
|
||||
module.createBinary(BinaryOp.SubI64,
|
||||
@ -198,8 +198,9 @@ export function compileCall(compiler: Compiler, prototype: FunctionPrototype, ty
|
||||
? module.createBinary(BinaryOp.MaxF32, arg0, arg1)
|
||||
: module.createBinary(BinaryOp.MaxF64, arg0, arg1);
|
||||
if (typeArguments[0].isAnyInteger) {
|
||||
tempLocal0 = compiler.currentFunction.addLocal(typeArguments[0]);
|
||||
tempLocal1 = compiler.currentFunction.addLocal(typeArguments[0]);
|
||||
tempLocal0 = compiler.currentFunction.getTempLocal(typeArguments[0]);
|
||||
tempLocal1 = compiler.currentFunction.getAndFreeTempLocal(typeArguments[0]);
|
||||
compiler.currentFunction.freeTempLocal(tempLocal0);
|
||||
if (typeArguments[0].isLongInteger)
|
||||
return module.createSelect(
|
||||
module.createTeeLocal(tempLocal0.index, arg0),
|
||||
@ -233,8 +234,9 @@ export function compileCall(compiler: Compiler, prototype: FunctionPrototype, ty
|
||||
? module.createBinary(BinaryOp.MinF32, arg0, arg1)
|
||||
: module.createBinary(BinaryOp.MinF64, arg0, arg1);
|
||||
if (typeArguments[0].isAnyInteger) {
|
||||
tempLocal0 = compiler.currentFunction.addLocal(typeArguments[0]);
|
||||
tempLocal1 = compiler.currentFunction.addLocal(typeArguments[0]);
|
||||
tempLocal0 = compiler.currentFunction.getTempLocal(typeArguments[0]);
|
||||
tempLocal1 = compiler.currentFunction.getAndFreeTempLocal(typeArguments[0]);
|
||||
compiler.currentFunction.freeTempLocal(tempLocal0);
|
||||
if (typeArguments[0].isLongInteger)
|
||||
return module.createSelect(
|
||||
module.createTeeLocal(tempLocal0.index, arg0),
|
||||
@ -428,13 +430,13 @@ export function compileCall(compiler: Compiler, prototype: FunctionPrototype, ty
|
||||
arg0 = compiler.compileExpression(operands[0], typeArguments[0]); // reports
|
||||
compiler.currentType = Type.bool;
|
||||
if (typeArguments[0] == Type.f32) {
|
||||
tempLocal0 = compiler.currentFunction.addLocal(Type.f32);
|
||||
tempLocal0 = compiler.currentFunction.getAndFreeTempLocal(Type.f32);
|
||||
return module.createBinary(BinaryOp.NeF32,
|
||||
module.createTeeLocal(tempLocal0.index, arg0),
|
||||
module.createGetLocal(tempLocal0.index, NativeType.F32)
|
||||
);
|
||||
} else {
|
||||
tempLocal0 = compiler.currentFunction.addLocal(Type.f64);
|
||||
tempLocal0 = compiler.currentFunction.getAndFreeTempLocal(Type.f64);
|
||||
return module.createBinary(BinaryOp.NeF64,
|
||||
module.createTeeLocal(tempLocal0.index, arg0),
|
||||
module.createGetLocal(tempLocal0.index, NativeType.F64)
|
||||
@ -453,7 +455,7 @@ export function compileCall(compiler: Compiler, prototype: FunctionPrototype, ty
|
||||
arg0 = compiler.compileExpression(operands[0], typeArguments[0]); // reports
|
||||
compiler.currentType = Type.bool;
|
||||
if (typeArguments[0] == Type.f32) {
|
||||
tempLocal0 = compiler.currentFunction.addLocal(Type.f32);
|
||||
tempLocal0 = compiler.currentFunction.getAndFreeTempLocal(Type.f32);
|
||||
return module.createSelect(
|
||||
module.createBinary(BinaryOp.NeF32,
|
||||
module.createUnary(UnaryOp.AbsF32,
|
||||
@ -468,7 +470,7 @@ export function compileCall(compiler: Compiler, prototype: FunctionPrototype, ty
|
||||
)
|
||||
);
|
||||
} else {
|
||||
tempLocal0 = compiler.currentFunction.addLocal(Type.f64);
|
||||
tempLocal0 = compiler.currentFunction.getAndFreeTempLocal(Type.f64);
|
||||
return module.createSelect(
|
||||
module.createBinary(BinaryOp.NeF64,
|
||||
module.createUnary(UnaryOp.AbsF64,
|
||||
|
@ -11,28 +11,7 @@ import {
|
||||
NativeType,
|
||||
FunctionTypeRef,
|
||||
FunctionRef,
|
||||
ExpressionId,
|
||||
|
||||
getExpressionId,
|
||||
getExpressionType,
|
||||
getFunctionBody,
|
||||
getConstValueI32,
|
||||
getConstValueI64Low,
|
||||
getConstValueI64High,
|
||||
getConstValueF32,
|
||||
getConstValueF64,
|
||||
getGetLocalIndex,
|
||||
getGetGlobalName,
|
||||
isLoadAtomic,
|
||||
isLoadSigned,
|
||||
getLoadBytes,
|
||||
getLoadOffset,
|
||||
getLoadPtr,
|
||||
getUnaryOp,
|
||||
getUnaryValue,
|
||||
getBinaryOp,
|
||||
getBinaryLeft,
|
||||
getBinaryRight
|
||||
ExpressionId
|
||||
|
||||
} from "./module";
|
||||
import {
|
||||
@ -373,10 +352,10 @@ export class Compiler extends DiagnosticEmitter {
|
||||
} else if (declaration) {
|
||||
if (declaration.initializer) {
|
||||
initializer = this.compileExpression(declaration.initializer, type);
|
||||
if (getExpressionId(initializer) != ExpressionId.Const) {
|
||||
if (_BinaryenExpressionGetId(initializer) != ExpressionId.Const) {
|
||||
if (!element.isMutable) {
|
||||
initializer = this.precomputeExpressionRef(initializer);
|
||||
if (getExpressionId(initializer) != ExpressionId.Const) {
|
||||
if (_BinaryenExpressionGetId(initializer) != ExpressionId.Const) {
|
||||
this.warning(DiagnosticCode.Compiling_constant_global_with_non_constant_initializer_as_mutable, declaration.range);
|
||||
initializeInStart = true;
|
||||
}
|
||||
@ -395,19 +374,19 @@ export class Compiler extends DiagnosticEmitter {
|
||||
this.module.addGlobal(internalName, nativeType, element.isMutable, initializer);
|
||||
if (!element.isMutable) {
|
||||
element.hasConstantValue = true;
|
||||
const exprType: NativeType = getExpressionType(initializer);
|
||||
const exprType: NativeType = _BinaryenExpressionGetType(initializer);
|
||||
switch (exprType) {
|
||||
case NativeType.I32:
|
||||
element.constantIntegerValue = new I64(getConstValueI32(initializer), 0);
|
||||
element.constantIntegerValue = new I64(_BinaryenConstGetValueI32(initializer), 0);
|
||||
break;
|
||||
case NativeType.I64:
|
||||
element.constantIntegerValue = new I64(getConstValueI64Low(initializer), getConstValueI64High(initializer));
|
||||
element.constantIntegerValue = new I64(_BinaryenConstGetValueI64Low(initializer), _BinaryenConstGetValueI64High(initializer));
|
||||
break;
|
||||
case NativeType.F32:
|
||||
element.constantFloatValue = getConstValueF32(initializer);
|
||||
element.constantFloatValue = _BinaryenConstGetValueF32(initializer);
|
||||
break;
|
||||
case NativeType.F64:
|
||||
element.constantFloatValue = getConstValueF64(initializer);
|
||||
element.constantFloatValue = _BinaryenConstGetValueF64(initializer);
|
||||
break;
|
||||
default:
|
||||
throw new Error("unexpected initializer type");
|
||||
@ -439,9 +418,9 @@ export class Compiler extends DiagnosticEmitter {
|
||||
let initializeInStart: bool = false;
|
||||
if (declaration.value) {
|
||||
initializer = this.compileExpression(<Expression>declaration.value, Type.i32);
|
||||
if (getExpressionId(initializer) != ExpressionId.Const) {
|
||||
if (_BinaryenExpressionGetId(initializer) != ExpressionId.Const) {
|
||||
initializer = this.precomputeExpressionRef(initializer);
|
||||
if (getExpressionId(initializer) != ExpressionId.Const) {
|
||||
if (_BinaryenExpressionGetId(initializer) != ExpressionId.Const) {
|
||||
if (element.isConstant)
|
||||
this.warning(DiagnosticCode.Compiling_constant_global_with_non_constant_initializer_as_mutable, declaration.range);
|
||||
initializeInStart = true;
|
||||
@ -466,9 +445,9 @@ export class Compiler extends DiagnosticEmitter {
|
||||
this.startFunctionBody.push(this.module.createSetGlobal(val.internalName, initializer));
|
||||
} else {
|
||||
this.module.addGlobal(val.internalName, NativeType.I32, false, initializer);
|
||||
if (getExpressionType(initializer) == NativeType.I32) {
|
||||
if (_BinaryenExpressionGetType(initializer) == NativeType.I32) {
|
||||
val.hasConstantValue = true;
|
||||
val.constantValue = getConstValueI32(initializer);
|
||||
val.constantValue = _BinaryenConstGetValueI32(initializer);
|
||||
} else
|
||||
throw new Error("unexpected initializer type");
|
||||
}
|
||||
@ -1068,7 +1047,7 @@ export class Compiler extends DiagnosticEmitter {
|
||||
typeRef = this.module.addFunctionType(typeToSignatureNamePart(this.currentType), nativeType, []);
|
||||
const funcRef: FunctionRef = this.module.addFunction("__precompute", typeRef, [], expr);
|
||||
this.module.runPasses([ "precompute" ], funcRef);
|
||||
const ret: ExpressionRef = getFunctionBody(funcRef);
|
||||
const ret: ExpressionRef = _BinaryenFunctionGetBody(funcRef);
|
||||
this.module.removeFunction("__precompute");
|
||||
// TODO: also remove the function type somehow if no longer used or make the C-API accept
|
||||
// a `null` typeRef, using an implicit type.
|
||||
@ -1240,41 +1219,6 @@ 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: explodes if it doesn't have a name
|
||||
// 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
|
||||
if (!toType)
|
||||
@ -1537,7 +1481,7 @@ export class Compiler extends DiagnosticEmitter {
|
||||
right = this.compileExpression(expression.right, this.currentType);
|
||||
|
||||
// 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))
|
||||
// if (condition = this.module.cloneExpression(left, true, 2))
|
||||
// return this.module.createIf(
|
||||
// this.currentType.isLongInteger
|
||||
// ? this.module.createBinary(BinaryOp.NeI64, condition, this.module.createI64(0, 0))
|
||||
@ -1570,7 +1514,7 @@ export class Compiler extends DiagnosticEmitter {
|
||||
right = this.compileExpression(expression.right, this.currentType);
|
||||
|
||||
// simplify if left is free of side effects while tolerating two levels of nesting
|
||||
// if (condition = this.cloneExpressionRef(left, true, 2))
|
||||
// if (condition = this.module.cloneExpression(left, true, 2))
|
||||
// return this.module.createIf(
|
||||
// this.currentType.isLongInteger
|
||||
// ? this.module.createBinary(BinaryOp.NeI64, condition, this.module.createI64(0, 0))
|
||||
|
@ -1,4 +1,5 @@
|
||||
import {
|
||||
|
||||
Module,
|
||||
NativeType,
|
||||
ExpressionId,
|
||||
@ -9,7 +10,9 @@ import {
|
||||
FunctionRef,
|
||||
ExpressionRef,
|
||||
Index,
|
||||
|
||||
readString
|
||||
|
||||
} from "./module";
|
||||
import { I64 } from "./util";
|
||||
|
||||
|
183
src/module.ts
183
src/module.ts
@ -751,7 +751,7 @@ export class Module {
|
||||
}
|
||||
|
||||
interpret(): void {
|
||||
return _BinaryenModuleInterpret(this.ref);
|
||||
_BinaryenModuleInterpret(this.ref);
|
||||
}
|
||||
|
||||
write(output: usize, outputSize: usize = 1048576): usize {
|
||||
@ -759,11 +759,11 @@ export class Module {
|
||||
}
|
||||
|
||||
print(): void {
|
||||
return _BinaryenModulePrint(this.ref);
|
||||
_BinaryenModulePrint(this.ref);
|
||||
}
|
||||
|
||||
printAsmjs(): void {
|
||||
return _BinaryenModulePrintAsmjs(this.ref);
|
||||
_BinaryenModulePrintAsmjs(this.ref);
|
||||
}
|
||||
|
||||
toBinary(bufferSize: usize = 1048576): Uint8Array {
|
||||
@ -785,132 +785,48 @@ export class Module {
|
||||
createRelooper(): Relooper {
|
||||
return this.noEmit ? Relooper.createStub(this) : Relooper.create(this);
|
||||
}
|
||||
}
|
||||
|
||||
export function getExpressionId(expr: ExpressionRef): ExpressionId {
|
||||
return _BinaryenExpressionGetId(expr);
|
||||
}
|
||||
// currently supports side effect free expressions only
|
||||
cloneExpression(expr: ExpressionRef, noSideEffects: bool = false, maxDepth: i32 = 0x7fffffff): ExpressionRef {
|
||||
if (this.noEmit || maxDepth < 0) return 0;
|
||||
|
||||
export function getExpressionType(expr: ExpressionRef): NativeType {
|
||||
return _BinaryenExpressionGetType(expr);
|
||||
}
|
||||
let nested1: ExpressionRef,
|
||||
nested2: ExpressionRef;
|
||||
|
||||
export function printExpression(expr: ExpressionRef): void {
|
||||
return _BinaryenExpressionPrint(expr);
|
||||
}
|
||||
switch (_BinaryenExpressionGetId(expr)) {
|
||||
|
||||
export function getConstValueI32(expr: ExpressionRef): i32 {
|
||||
return _BinaryenConstGetValueI32(expr);
|
||||
}
|
||||
case ExpressionId.Const:
|
||||
switch (_BinaryenExpressionGetType(expr)) {
|
||||
case NativeType.I32: return this.createI32(_BinaryenConstGetValueI32(expr));
|
||||
case NativeType.I64: return this.createI64(_BinaryenConstGetValueI64Low(expr), _BinaryenConstGetValueI64High(expr));
|
||||
case NativeType.F32: return this.createF32(_BinaryenConstGetValueF32(expr));
|
||||
case NativeType.F64: return this.createF64(_BinaryenConstGetValueF64(expr));
|
||||
default: throw new Error("unexpected constant type");
|
||||
}
|
||||
|
||||
export function getConstValueI64Low(expr: ExpressionRef): i32 {
|
||||
return _BinaryenConstGetValueI64Low(expr);
|
||||
}
|
||||
case ExpressionId.GetLocal:
|
||||
return _BinaryenGetLocal(this.ref, _BinaryenGetLocalGetIndex(expr), _BinaryenExpressionGetType(expr));
|
||||
|
||||
export function getConstValueI64High(expr: ExpressionRef): i32 {
|
||||
return _BinaryenConstGetValueI64High(expr);
|
||||
}
|
||||
// case ExpressionId.GetGlobal: explodes if it doesn't have a name
|
||||
// return _BinaryenGetGlobal(this.ref, _BinaryenGetGlobalGetName(expr), _BinaryenExpressionGetType(expr));
|
||||
|
||||
export function getConstValueI64(expr: ExpressionRef): I64 {
|
||||
return new I64(
|
||||
_BinaryenConstGetValueI64Low(expr),
|
||||
_BinaryenConstGetValueI64High(expr)
|
||||
);
|
||||
}
|
||||
case ExpressionId.Load:
|
||||
if (!(nested1 = this.cloneExpression(_BinaryenLoadGetPtr(expr), noSideEffects, maxDepth - 1))) break;
|
||||
return _BinaryenLoadIsAtomic(expr)
|
||||
? _BinaryenAtomicLoad(this.ref, _BinaryenLoadGetBytes(expr), _BinaryenLoadGetOffset(expr), _BinaryenExpressionGetType(expr), nested1)
|
||||
: _BinaryenLoad(this.ref, _BinaryenLoadGetBytes(expr), _BinaryenLoadIsSigned(expr) ? 1 : 0, _BinaryenLoadGetOffset(expr), _BinaryenLoadGetAlign(expr), _BinaryenExpressionGetType(expr), nested1);
|
||||
|
||||
export function getConstValueF32(expr: ExpressionRef): f32 {
|
||||
return _BinaryenConstGetValueF32(expr);
|
||||
}
|
||||
case ExpressionId.Unary:
|
||||
if (!(nested1 = this.cloneExpression(_BinaryenUnaryGetValue(expr), noSideEffects, maxDepth - 1))) break;
|
||||
return _BinaryenUnary(this.ref, _BinaryenUnaryGetOp(expr), nested1);
|
||||
|
||||
export function getConstValueF64(expr: ExpressionRef): f64 {
|
||||
return _BinaryenConstGetValueF64(expr);
|
||||
}
|
||||
|
||||
export function getGetLocalIndex(expr: ExpressionRef): Index {
|
||||
return _BinaryenGetLocalGetIndex(expr);
|
||||
}
|
||||
|
||||
export function getGetGlobalName(expr: ExpressionRef): string | null {
|
||||
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 function getSelectIfTrue(expr: ExpressionRef): ExpressionRef {
|
||||
return _BinaryenSelectGetIfTrue(expr);
|
||||
}
|
||||
|
||||
export function getSelectIfFalse(expr: ExpressionRef): ExpressionRef {
|
||||
return _BinaryenSelectGetIfFalse(expr);
|
||||
}
|
||||
|
||||
export function getSelectCondition(expr: ExpressionRef): ExpressionRef {
|
||||
return _BinaryenSelectGetCondition(expr);
|
||||
}
|
||||
|
||||
export function getReturnValue(expr: ExpressionRef): ExpressionRef {
|
||||
return _BinaryenReturnGetValue(expr);
|
||||
}
|
||||
|
||||
export function getDropValue(expr: ExpressionRef): ExpressionRef {
|
||||
return _BinaryenDropGetValue(expr);
|
||||
}
|
||||
|
||||
export function getHostOp(expr: ExpressionRef): HostOp {
|
||||
return _BinaryenHostGetOp(expr);
|
||||
}
|
||||
|
||||
export function getHostNameOperand(expr: ExpressionRef): string | null {
|
||||
return readString(_BinaryenHostGetNameOperand(expr));
|
||||
}
|
||||
|
||||
export function getHostOperands(expr: ExpressionRef): BinaryenExpressionRef[] {
|
||||
const num: Index = _BinaryenHostGetNumOperands(expr);
|
||||
const arr: BinaryenExpressionRef[] = new Array(num);
|
||||
for (let i: Index = 0; i < num; ++i) arr[i] = _BinaryenHostGetOperand(expr, i);
|
||||
return arr;
|
||||
case ExpressionId.Binary:
|
||||
if (!(nested1 = this.cloneExpression(_BinaryenBinaryGetLeft(expr), noSideEffects, maxDepth - 1))) break;
|
||||
if (!(nested2 = this.cloneExpression(_BinaryenBinaryGetRight(expr), noSideEffects, maxDepth - 1))) break;
|
||||
return _BinaryenBinary(this.ref, _BinaryenBinaryGetOp(expr), nested1, nested2);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
export class Relooper {
|
||||
@ -990,6 +906,7 @@ function allocI32Array(i32s: i32[] | null): usize {
|
||||
let idx: usize = ptr;
|
||||
for (let i: i32 = 0, k: i32 = (<i32[]>i32s).length; i < k; ++i) {
|
||||
let val: i32 = (<i32[]>i32s)[i];
|
||||
// store<i32>(idx, val) is not portable
|
||||
store<u8>(idx , ( val & 0xff) as u8);
|
||||
store<u8>(idx + 1, ((val >> 8) & 0xff) as u8);
|
||||
store<u8>(idx + 2, ((val >> 16) & 0xff) as u8);
|
||||
@ -1022,7 +939,7 @@ function stringLengthUTF8(str: string): usize {
|
||||
}
|
||||
|
||||
function allocString(str: string | null): usize {
|
||||
if (!str) return 0;
|
||||
if (str == null) return 0;
|
||||
const ptr: usize = Heap.allocate(stringLengthUTF8((<string>str)) + 1);
|
||||
let idx: usize = ptr;
|
||||
for (let i: i32 = 0, k: i32 = (<string>str).length; i < k; ++i) {
|
||||
@ -1064,18 +981,18 @@ function allocString(str: string | null): usize {
|
||||
|
||||
export function readString(ptr: usize): string | null {
|
||||
if (!ptr) return null;
|
||||
const utf16le: u32[] = [];
|
||||
const arr: i32[] = [];
|
||||
// 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);
|
||||
arr.push(cp);
|
||||
continue;
|
||||
}
|
||||
u1 = load<u8>(ptr++) & 63;
|
||||
if ((cp & 0xE0) == 0xC0) {
|
||||
utf16le.push(((cp & 31) << 6) | u1);
|
||||
arr.push(((cp & 31) << 6) | u1);
|
||||
continue;
|
||||
}
|
||||
u2 = load<u8>(ptr++) & 63;
|
||||
@ -1095,14 +1012,14 @@ export function readString(ptr: usize): string | null {
|
||||
}
|
||||
}
|
||||
}
|
||||
if (cp < 0x10000) {
|
||||
utf16le.push(cp);
|
||||
} else {
|
||||
var ch = cp - 0x10000;
|
||||
utf16le.push(0xD800 | (ch >> 10));
|
||||
utf16le.push(0xDC00 | (ch & 0x3FF));
|
||||
// if (cp < 0x10000) {
|
||||
// arr.push(cp);
|
||||
// } else {
|
||||
// var ch = cp - 0x10000;
|
||||
// arr.push(0xD800 | (ch >> 10));
|
||||
// arr.push(0xDC00 | (ch & 0x3FF));
|
||||
// }
|
||||
}
|
||||
}
|
||||
// FIXME: not portable and prone to stack overflows. Maybe use CString from stdlib?
|
||||
return String.fromCharCode.apply(utf16le);
|
||||
// return String.fromCharCodes(arr);
|
||||
return String.fromCodePoints(arr);
|
||||
}
|
||||
|
@ -1,5 +1,5 @@
|
||||
import { initialize as initializeBuiltins } from "./builtins";
|
||||
import { Target } from "./compiler";
|
||||
import { Target, typeToNativeType } from "./compiler";
|
||||
import { GETTER_PREFIX, SETTER_PREFIX, PATH_DELIMITER } from "./constants";
|
||||
import { DiagnosticCode, DiagnosticMessage, DiagnosticEmitter } from "./diagnostics";
|
||||
import { Type, typesToString } from "./types";
|
||||
@ -45,6 +45,7 @@ import {
|
||||
mangleInternalName
|
||||
|
||||
} from "./ast";
|
||||
import { NativeType } from "./module";
|
||||
|
||||
class QueuedExport {
|
||||
isReExport: bool;
|
||||
@ -973,6 +974,53 @@ export class Function extends Element {
|
||||
return local;
|
||||
}
|
||||
|
||||
private tempI32s: Local[] = [];
|
||||
private tempI64s: Local[] = [];
|
||||
private tempF32s: Local[] = [];
|
||||
private tempF64s: Local[] = [];
|
||||
|
||||
getTempLocal(type: Type): Local {
|
||||
let temps: Local[];
|
||||
switch (typeToNativeType(type)) {
|
||||
case NativeType.I32: temps = this.tempI32s; break;
|
||||
case NativeType.I64: temps = this.tempI64s; break;
|
||||
case NativeType.F32: temps = this.tempF32s; break;
|
||||
case NativeType.F64: temps = this.tempF64s; break;
|
||||
default: throw new Error("unexpected type");
|
||||
}
|
||||
if (temps.length > 0)
|
||||
return temps.pop();
|
||||
return this.addLocal(type);
|
||||
}
|
||||
|
||||
freeTempLocal(local: Local): void {
|
||||
let temps: Local[];
|
||||
switch (typeToNativeType(local.type)) {
|
||||
case NativeType.I32: temps = this.tempI32s; break;
|
||||
case NativeType.I64: temps = this.tempI64s; break;
|
||||
case NativeType.F32: temps = this.tempF32s; break;
|
||||
case NativeType.F64: temps = this.tempF64s; break;
|
||||
default: throw new Error("unexpected type");
|
||||
}
|
||||
temps.push(local);
|
||||
}
|
||||
|
||||
getAndFreeTempLocal(type: Type): Local {
|
||||
let temps: Local[];
|
||||
switch (typeToNativeType(type)) {
|
||||
case NativeType.I32: temps = this.tempI32s; break;
|
||||
case NativeType.I64: temps = this.tempI64s; break;
|
||||
case NativeType.F32: temps = this.tempF32s; break;
|
||||
case NativeType.F64: temps = this.tempF64s; break;
|
||||
default: throw new Error("unexpected type");
|
||||
}
|
||||
if (temps.length > 0)
|
||||
return temps[temps.length - 1];
|
||||
let local: Local = this.addLocal(type);
|
||||
temps.push(local);
|
||||
return local;
|
||||
}
|
||||
|
||||
/** Enters a(nother) break context. */
|
||||
enterBreakContext(): string {
|
||||
const id: i32 = this.nextBreakId++;
|
||||
|
@ -13,36 +13,10 @@
|
||||
(func $start (; 0 ;) (type $v)
|
||||
(local $0 i32)
|
||||
(local $1 i32)
|
||||
(local $2 i32)
|
||||
(local $3 i32)
|
||||
(local $4 i32)
|
||||
(local $5 i32)
|
||||
(local $6 i32)
|
||||
(local $7 i32)
|
||||
(local $8 i32)
|
||||
(local $9 i32)
|
||||
(local $10 i64)
|
||||
(local $11 i64)
|
||||
(local $12 i64)
|
||||
(local $13 i64)
|
||||
(local $14 i64)
|
||||
(local $15 i64)
|
||||
(local $16 f32)
|
||||
(local $17 f32)
|
||||
(local $18 f32)
|
||||
(local $19 f32)
|
||||
(local $20 f64)
|
||||
(local $21 f64)
|
||||
(local $22 f64)
|
||||
(local $23 f64)
|
||||
(local $24 f32)
|
||||
(local $25 f64)
|
||||
(local $26 f32)
|
||||
(local $27 f32)
|
||||
(local $28 f64)
|
||||
(local $29 f64)
|
||||
(local $30 f32)
|
||||
(local $31 f64)
|
||||
(local $2 i64)
|
||||
(local $3 i64)
|
||||
(local $4 f32)
|
||||
(local $5 f64)
|
||||
(drop
|
||||
(i32.clz
|
||||
(i32.const 1)
|
||||
@ -90,29 +64,29 @@
|
||||
)
|
||||
(drop
|
||||
(select
|
||||
(tee_local $1
|
||||
(tee_local $0
|
||||
(i32.const 1)
|
||||
)
|
||||
(tee_local $2
|
||||
(tee_local $1
|
||||
(i32.const 2)
|
||||
)
|
||||
(i32.gt_s
|
||||
(get_local $0)
|
||||
(get_local $1)
|
||||
(get_local $2)
|
||||
)
|
||||
)
|
||||
)
|
||||
(drop
|
||||
(select
|
||||
(tee_local $3
|
||||
(tee_local $0
|
||||
(i32.const 1)
|
||||
)
|
||||
(tee_local $4
|
||||
(tee_local $1
|
||||
(i32.const 2)
|
||||
)
|
||||
(i32.lt_s
|
||||
(get_local $3)
|
||||
(get_local $4)
|
||||
(get_local $0)
|
||||
(get_local $1)
|
||||
)
|
||||
)
|
||||
)
|
||||
@ -147,16 +121,16 @@
|
||||
(select
|
||||
(i32.sub
|
||||
(i32.const 0)
|
||||
(tee_local $5
|
||||
(tee_local $0
|
||||
(i32.sub
|
||||
(i32.const 0)
|
||||
(i32.const 42)
|
||||
)
|
||||
)
|
||||
)
|
||||
(get_local $5)
|
||||
(get_local $0)
|
||||
(i32.lt_s
|
||||
(get_local $5)
|
||||
(get_local $0)
|
||||
(i32.const 0)
|
||||
)
|
||||
)
|
||||
@ -172,15 +146,15 @@
|
||||
)
|
||||
(set_global $builtins/i
|
||||
(select
|
||||
(tee_local $6
|
||||
(tee_local $0
|
||||
(i32.const 1)
|
||||
)
|
||||
(tee_local $7
|
||||
(tee_local $1
|
||||
(i32.const 2)
|
||||
)
|
||||
(i32.gt_s
|
||||
(get_local $6)
|
||||
(get_local $7)
|
||||
(get_local $0)
|
||||
(get_local $1)
|
||||
)
|
||||
)
|
||||
)
|
||||
@ -195,15 +169,15 @@
|
||||
)
|
||||
(set_global $builtins/i
|
||||
(select
|
||||
(tee_local $8
|
||||
(tee_local $0
|
||||
(i32.const 1)
|
||||
)
|
||||
(tee_local $9
|
||||
(tee_local $1
|
||||
(i32.const 2)
|
||||
)
|
||||
(i32.lt_s
|
||||
(get_local $8)
|
||||
(get_local $9)
|
||||
(get_local $0)
|
||||
(get_local $1)
|
||||
)
|
||||
)
|
||||
)
|
||||
@ -247,16 +221,16 @@
|
||||
(select
|
||||
(i64.sub
|
||||
(i64.const 0)
|
||||
(tee_local $10
|
||||
(tee_local $2
|
||||
(i64.sub
|
||||
(i64.const 0)
|
||||
(i64.const 42)
|
||||
)
|
||||
)
|
||||
)
|
||||
(get_local $10)
|
||||
(get_local $2)
|
||||
(i64.lt_s
|
||||
(get_local $10)
|
||||
(get_local $2)
|
||||
(i64.const 0)
|
||||
)
|
||||
)
|
||||
@ -292,16 +266,16 @@
|
||||
(select
|
||||
(i64.sub
|
||||
(i64.const 0)
|
||||
(tee_local $11
|
||||
(tee_local $2
|
||||
(i64.sub
|
||||
(i64.const 0)
|
||||
(i64.const 42)
|
||||
)
|
||||
)
|
||||
)
|
||||
(get_local $11)
|
||||
(get_local $2)
|
||||
(i64.lt_s
|
||||
(get_local $11)
|
||||
(get_local $2)
|
||||
(i64.const 0)
|
||||
)
|
||||
)
|
||||
@ -317,15 +291,15 @@
|
||||
)
|
||||
(set_global $builtins/I
|
||||
(select
|
||||
(tee_local $12
|
||||
(tee_local $2
|
||||
(i64.const 1)
|
||||
)
|
||||
(tee_local $13
|
||||
(tee_local $3
|
||||
(i64.const 2)
|
||||
)
|
||||
(i64.gt_s
|
||||
(get_local $12)
|
||||
(get_local $13)
|
||||
(get_local $2)
|
||||
(get_local $3)
|
||||
)
|
||||
)
|
||||
)
|
||||
@ -340,15 +314,15 @@
|
||||
)
|
||||
(set_global $builtins/I
|
||||
(select
|
||||
(tee_local $14
|
||||
(tee_local $2
|
||||
(i64.const 1)
|
||||
)
|
||||
(tee_local $15
|
||||
(tee_local $3
|
||||
(i64.const 2)
|
||||
)
|
||||
(i64.lt_s
|
||||
(get_local $14)
|
||||
(get_local $15)
|
||||
(get_local $2)
|
||||
(get_local $3)
|
||||
)
|
||||
)
|
||||
)
|
||||
@ -417,17 +391,17 @@
|
||||
)
|
||||
(drop
|
||||
(f32.ne
|
||||
(tee_local $16
|
||||
(tee_local $4
|
||||
(f32.const 1.25)
|
||||
)
|
||||
(get_local $16)
|
||||
(get_local $4)
|
||||
)
|
||||
)
|
||||
(drop
|
||||
(select
|
||||
(f32.ne
|
||||
(f32.abs
|
||||
(tee_local $17
|
||||
(tee_local $4
|
||||
(f32.const 1.25)
|
||||
)
|
||||
)
|
||||
@ -435,8 +409,8 @@
|
||||
)
|
||||
(i32.const 0)
|
||||
(f32.eq
|
||||
(get_local $17)
|
||||
(get_local $17)
|
||||
(get_local $4)
|
||||
(get_local $4)
|
||||
)
|
||||
)
|
||||
)
|
||||
@ -496,17 +470,17 @@
|
||||
)
|
||||
(set_global $builtins/b
|
||||
(f32.ne
|
||||
(tee_local $18
|
||||
(tee_local $4
|
||||
(f32.const 1.25)
|
||||
)
|
||||
(get_local $18)
|
||||
(get_local $4)
|
||||
)
|
||||
)
|
||||
(set_global $builtins/b
|
||||
(select
|
||||
(f32.ne
|
||||
(f32.abs
|
||||
(tee_local $19
|
||||
(tee_local $4
|
||||
(f32.const 1.25)
|
||||
)
|
||||
)
|
||||
@ -514,8 +488,8 @@
|
||||
)
|
||||
(i32.const 0)
|
||||
(f32.eq
|
||||
(get_local $19)
|
||||
(get_local $19)
|
||||
(get_local $4)
|
||||
(get_local $4)
|
||||
)
|
||||
)
|
||||
)
|
||||
@ -581,17 +555,17 @@
|
||||
)
|
||||
(drop
|
||||
(f64.ne
|
||||
(tee_local $20
|
||||
(tee_local $5
|
||||
(f64.const 1.25)
|
||||
)
|
||||
(get_local $20)
|
||||
(get_local $5)
|
||||
)
|
||||
)
|
||||
(drop
|
||||
(select
|
||||
(f64.ne
|
||||
(f64.abs
|
||||
(tee_local $21
|
||||
(tee_local $5
|
||||
(f64.const 1.25)
|
||||
)
|
||||
)
|
||||
@ -599,8 +573,8 @@
|
||||
)
|
||||
(i32.const 0)
|
||||
(f64.eq
|
||||
(get_local $21)
|
||||
(get_local $21)
|
||||
(get_local $5)
|
||||
(get_local $5)
|
||||
)
|
||||
)
|
||||
)
|
||||
@ -660,17 +634,17 @@
|
||||
)
|
||||
(set_global $builtins/b
|
||||
(f64.ne
|
||||
(tee_local $22
|
||||
(tee_local $5
|
||||
(f64.const 1.25)
|
||||
)
|
||||
(get_local $22)
|
||||
(get_local $5)
|
||||
)
|
||||
)
|
||||
(set_global $builtins/b
|
||||
(select
|
||||
(f64.ne
|
||||
(f64.abs
|
||||
(tee_local $23
|
||||
(tee_local $5
|
||||
(f64.const 1.25)
|
||||
)
|
||||
)
|
||||
@ -678,8 +652,8 @@
|
||||
)
|
||||
(i32.const 0)
|
||||
(f64.eq
|
||||
(get_local $23)
|
||||
(get_local $23)
|
||||
(get_local $5)
|
||||
(get_local $5)
|
||||
)
|
||||
)
|
||||
)
|
||||
@ -910,10 +884,10 @@
|
||||
(if
|
||||
(i32.eqz
|
||||
(f32.ne
|
||||
(tee_local $24
|
||||
(tee_local $4
|
||||
(f32.const nan:0x400000)
|
||||
)
|
||||
(get_local $24)
|
||||
(get_local $4)
|
||||
)
|
||||
)
|
||||
(unreachable)
|
||||
@ -921,10 +895,10 @@
|
||||
(if
|
||||
(i32.eqz
|
||||
(f64.ne
|
||||
(tee_local $25
|
||||
(tee_local $5
|
||||
(f64.const nan:0x8000000000000)
|
||||
)
|
||||
(get_local $25)
|
||||
(get_local $5)
|
||||
)
|
||||
)
|
||||
(unreachable)
|
||||
@ -935,7 +909,7 @@
|
||||
(select
|
||||
(f32.ne
|
||||
(f32.abs
|
||||
(tee_local $26
|
||||
(tee_local $4
|
||||
(f32.const nan:0x400000)
|
||||
)
|
||||
)
|
||||
@ -943,8 +917,8 @@
|
||||
)
|
||||
(i32.const 0)
|
||||
(f32.eq
|
||||
(get_local $26)
|
||||
(get_local $26)
|
||||
(get_local $4)
|
||||
(get_local $4)
|
||||
)
|
||||
)
|
||||
)
|
||||
@ -957,7 +931,7 @@
|
||||
(select
|
||||
(f32.ne
|
||||
(f32.abs
|
||||
(tee_local $27
|
||||
(tee_local $4
|
||||
(f32.const inf)
|
||||
)
|
||||
)
|
||||
@ -965,8 +939,8 @@
|
||||
)
|
||||
(i32.const 0)
|
||||
(f32.eq
|
||||
(get_local $27)
|
||||
(get_local $27)
|
||||
(get_local $4)
|
||||
(get_local $4)
|
||||
)
|
||||
)
|
||||
)
|
||||
@ -979,7 +953,7 @@
|
||||
(select
|
||||
(f64.ne
|
||||
(f64.abs
|
||||
(tee_local $28
|
||||
(tee_local $5
|
||||
(f64.const nan:0x8000000000000)
|
||||
)
|
||||
)
|
||||
@ -987,8 +961,8 @@
|
||||
)
|
||||
(i32.const 0)
|
||||
(f64.eq
|
||||
(get_local $28)
|
||||
(get_local $28)
|
||||
(get_local $5)
|
||||
(get_local $5)
|
||||
)
|
||||
)
|
||||
)
|
||||
@ -1001,7 +975,7 @@
|
||||
(select
|
||||
(f64.ne
|
||||
(f64.abs
|
||||
(tee_local $29
|
||||
(tee_local $5
|
||||
(f64.const inf)
|
||||
)
|
||||
)
|
||||
@ -1009,8 +983,8 @@
|
||||
)
|
||||
(i32.const 0)
|
||||
(f64.eq
|
||||
(get_local $29)
|
||||
(get_local $29)
|
||||
(get_local $5)
|
||||
(get_local $5)
|
||||
)
|
||||
)
|
||||
)
|
||||
@ -1022,7 +996,7 @@
|
||||
(select
|
||||
(f32.ne
|
||||
(f32.abs
|
||||
(tee_local $30
|
||||
(tee_local $4
|
||||
(f32.const 0)
|
||||
)
|
||||
)
|
||||
@ -1030,8 +1004,8 @@
|
||||
)
|
||||
(i32.const 0)
|
||||
(f32.eq
|
||||
(get_local $30)
|
||||
(get_local $30)
|
||||
(get_local $4)
|
||||
(get_local $4)
|
||||
)
|
||||
)
|
||||
)
|
||||
@ -1042,7 +1016,7 @@
|
||||
(select
|
||||
(f64.ne
|
||||
(f64.abs
|
||||
(tee_local $31
|
||||
(tee_local $5
|
||||
(f64.const 0)
|
||||
)
|
||||
)
|
||||
@ -1050,8 +1024,8 @@
|
||||
)
|
||||
(i32.const 0)
|
||||
(f64.eq
|
||||
(get_local $31)
|
||||
(get_local $31)
|
||||
(get_local $5)
|
||||
(get_local $5)
|
||||
)
|
||||
)
|
||||
)
|
||||
|
Loading…
x
Reference in New Issue
Block a user