mirror of
https://github.com/fluencelabs/assemblyscript
synced 2025-06-19 18:01:31 +00:00
baseline
This commit is contained in:
@ -48,10 +48,7 @@ import {
|
||||
getConstValueI64Low,
|
||||
getConstValueI32,
|
||||
getConstValueF32,
|
||||
getConstValueF64,
|
||||
getBinaryOp,
|
||||
getBinaryLeft,
|
||||
getBinaryRight
|
||||
getConstValueF64
|
||||
} from "./module";
|
||||
|
||||
import {
|
||||
@ -60,14 +57,11 @@ import {
|
||||
Class,
|
||||
Field,
|
||||
Global,
|
||||
DecoratorFlags,
|
||||
Local,
|
||||
Program
|
||||
DecoratorFlags
|
||||
} from "./program";
|
||||
|
||||
import {
|
||||
FlowFlags,
|
||||
Flow
|
||||
FlowFlags
|
||||
} from "./flow";
|
||||
|
||||
import {
|
||||
@ -478,10 +472,18 @@ export namespace BuiltinSymbols {
|
||||
export const memory_grow = "~lib/memory/memory.grow";
|
||||
export const memory_copy = "~lib/memory/memory.copy";
|
||||
export const memory_fill = "~lib/memory/memory.fill";
|
||||
export const memory_allocate = "~lib/memory/memory.allocate";
|
||||
export const memory_free = "~lib/memory/memory.free";
|
||||
export const memory_reset = "~lib/memory/memory.reset";
|
||||
|
||||
// std/runtime.ts
|
||||
export const CLASSID = "~lib/runtime/CLASSID";
|
||||
export const ITERATEROOTS = "~lib/runtime/ITERATEROOTS";
|
||||
export const classId = "~lib/runtime/classId";
|
||||
export const iterateRoots = "~lib/runtime/iterateRoots";
|
||||
export const allocate = "~lib/runtime/allocate";
|
||||
export const reallocate = "~lib/runtime/reallocate";
|
||||
export const register = "~lib/runtime/register";
|
||||
export const discard = "~lib/runtime/discard";
|
||||
export const makeArray = "~lib/runtime/makeArray";
|
||||
|
||||
// std/typedarray.ts
|
||||
export const Int8Array = "~lib/typedarray/Int8Array";
|
||||
@ -495,6 +497,12 @@ export namespace BuiltinSymbols {
|
||||
export const Uint8ClampedArray = "~lib/typedarray/Uint8ClampedArray";
|
||||
export const Float32Array = "~lib/typedarray/Float32Array";
|
||||
export const Float64Array = "~lib/typedarray/Float64Array";
|
||||
|
||||
// compiler generated
|
||||
export const started = "~lib/started";
|
||||
export const argc = "~lib/argc";
|
||||
export const setargc = "~lib/setargc";
|
||||
export const capabilities = "~lib/capabilities";
|
||||
}
|
||||
|
||||
/** Compiles a call to a built-in function. */
|
||||
@ -3607,7 +3615,7 @@ export function compileCall(
|
||||
|
||||
// === Internal runtime =======================================================================
|
||||
|
||||
case BuiltinSymbols.CLASSID: {
|
||||
case BuiltinSymbols.classId: {
|
||||
let type = evaluateConstantType(compiler, typeArguments, operands, reportNode);
|
||||
compiler.currentType = Type.u32;
|
||||
if (!type) return module.createUnreachable();
|
||||
@ -3615,7 +3623,7 @@ export function compileCall(
|
||||
if (!classReference) return module.createUnreachable();
|
||||
return module.createI32(classReference.id);
|
||||
}
|
||||
case BuiltinSymbols.ITERATEROOTS: {
|
||||
case BuiltinSymbols.iterateRoots: {
|
||||
if (
|
||||
checkTypeAbsent(typeArguments, reportNode, prototype) |
|
||||
checkArgsRequired(operands, 1, reportNode, compiler)
|
||||
|
@ -1,281 +0,0 @@
|
||||
// TBD: managed reference handling makes this cumbersome, and there is a binaryen pass that can
|
||||
// help propagating constant offsets. ideally, using operator overloads would be enough because
|
||||
// it's the most flexible way to do this.
|
||||
|
||||
// import { Compiler, ConversionKind, WrapMode } from "../compiler";
|
||||
// import { Class, ElementKind, Field, Local } from "../program";
|
||||
// import { Expression } from "../ast";
|
||||
// import { Type, TypeFlags } from "../types";
|
||||
// import { ExpressionRef, getExpressionId, getBinaryOp, getBinaryLeft, getBinaryRight, getConstValueI32, ExpressionId, BinaryOp, NativeType, UnaryOp } from "../module";
|
||||
// import { BuiltinSymbols } from "../builtins";
|
||||
|
||||
// export function makeArrayGet(
|
||||
// compiler: Compiler,
|
||||
// target: Class,
|
||||
// thisExpression: Expression,
|
||||
// elementExpression: Expression,
|
||||
// contextualType: Type
|
||||
// ): ExpressionRef {
|
||||
// var type = assert(compiler.program.determineBuiltinArrayType(target));
|
||||
// var module = compiler.module;
|
||||
// var outType = (
|
||||
// type.is(TypeFlags.INTEGER) &&
|
||||
// contextualType.is(TypeFlags.INTEGER) &&
|
||||
// contextualType.size > type.size
|
||||
// ) ? contextualType : type;
|
||||
|
||||
// var dataStart = assert(target.lookupInSelf("dataStart"));
|
||||
// assert(dataStart.kind == ElementKind.FIELD);
|
||||
// var dataLength = assert(target.lookupInSelf("dataLength"));
|
||||
// assert(dataLength.kind == ElementKind.FIELD);
|
||||
|
||||
// // compile the index expression and shift it to become the actual byteOffset
|
||||
// var dynamicOffset = compiler.compileExpression(
|
||||
// elementExpression,
|
||||
// Type.i32,
|
||||
// ConversionKind.IMPLICIT,
|
||||
// WrapMode.NONE
|
||||
// );
|
||||
// var alignLog2 = type.alignLog2;
|
||||
// if (alignLog2) {
|
||||
// dynamicOffset = module.createBinary(BinaryOp.ShlI32,
|
||||
// dynamicOffset,
|
||||
// module.createI32(alignLog2)
|
||||
// );
|
||||
// }
|
||||
|
||||
// var usizeType = compiler.options.usizeType;
|
||||
// var nativeSizeType = compiler.options.nativeSizeType;
|
||||
// var ptrExpr: ExpressionRef;
|
||||
// var constantOffset: i32 = 0;
|
||||
|
||||
// // precompute byteOffset into a constant and a dynamic part
|
||||
// dynamicOffset = module.precomputeExpression(dynamicOffset);
|
||||
// if (getExpressionId(dynamicOffset) == ExpressionId.Const) {
|
||||
// constantOffset = getConstValueI32(dynamicOffset);
|
||||
// dynamicOffset = 0;
|
||||
// } else if (getExpressionId(dynamicOffset) == ExpressionId.Binary) {
|
||||
// if (getBinaryOp(dynamicOffset) == BinaryOp.AddI32) {
|
||||
// let left = getBinaryLeft(dynamicOffset);
|
||||
// let right = getBinaryRight(dynamicOffset);
|
||||
// if (getExpressionId(left) == ExpressionId.Const) {
|
||||
// constantOffset = getConstValueI32(left);
|
||||
// dynamicOffset = right;
|
||||
// } else if (getExpressionId(right) == ExpressionId.Const) {
|
||||
// constantOffset = getConstValueI32(right);
|
||||
// dynamicOffset = left;
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// // ptr = this.dataStart
|
||||
// ptrExpr = module.createLoad(usizeType.byteSize, true,
|
||||
// compiler.compileExpression(
|
||||
// thisExpression,
|
||||
// target.type,
|
||||
// ConversionKind.IMPLICIT,
|
||||
// WrapMode.NONE
|
||||
// ),
|
||||
// nativeSizeType, (<Field>dataStart).memoryOffset
|
||||
// );
|
||||
// // ptr = ptr + <usize>dynamicOffset
|
||||
// if (dynamicOffset) {
|
||||
// if (nativeSizeType == NativeType.I64) {
|
||||
// ptrExpr = module.createBinary(BinaryOp.AddI64,
|
||||
// ptrExpr,
|
||||
// module.createUnary(UnaryOp.ExtendU32, dynamicOffset)
|
||||
// );
|
||||
// } else {
|
||||
// ptrExpr = module.createBinary(BinaryOp.AddI32,
|
||||
// ptrExpr,
|
||||
// dynamicOffset
|
||||
// );
|
||||
// }
|
||||
// }
|
||||
|
||||
// compiler.currentType = outType;
|
||||
// return module.createLoad(
|
||||
// type.byteSize,
|
||||
// type.is(TypeFlags.SIGNED),
|
||||
// ptrExpr,
|
||||
// outType.toNativeType(),
|
||||
// constantOffset
|
||||
// );
|
||||
// }
|
||||
|
||||
// export function makeArraySet(
|
||||
// compiler: Compiler,
|
||||
// target: Class,
|
||||
// thisExpression: Expression,
|
||||
// elementExpression: Expression,
|
||||
// valueExpression: Expression,
|
||||
// contextualType: Type
|
||||
// ): ExpressionRef {
|
||||
// var type = assert(compiler.program.determineBuiltinArrayType(target));
|
||||
// return makeArraySetWithValue(
|
||||
// compiler,
|
||||
// target,
|
||||
// thisExpression,
|
||||
// elementExpression,
|
||||
// compiler.compileExpression(
|
||||
// valueExpression,
|
||||
// type.is(TypeFlags.INTEGER | TypeFlags.VALUE)
|
||||
// ? type.is(TypeFlags.LONG)
|
||||
// ? type.is(TypeFlags.SIGNED)
|
||||
// ? Type.i64
|
||||
// : Type.u64
|
||||
// : type.is(TypeFlags.SIGNED)
|
||||
// ? Type.i32
|
||||
// : Type.u32
|
||||
// : type,
|
||||
// ConversionKind.IMPLICIT,
|
||||
// WrapMode.NONE
|
||||
// ),
|
||||
// contextualType != Type.void
|
||||
// );
|
||||
// }
|
||||
|
||||
// export function makeArraySetWithValue(
|
||||
// compiler: Compiler,
|
||||
// target: Class,
|
||||
// thisExpression: Expression,
|
||||
// elementExpression: Expression,
|
||||
// valueExpr: ExpressionRef,
|
||||
// tee: bool
|
||||
// ): ExpressionRef {
|
||||
// var type = assert(compiler.program.determineBuiltinArrayType(target));
|
||||
// var module = compiler.module;
|
||||
|
||||
// var dataStart = assert(target.lookupInSelf("dataStart"));
|
||||
// assert(dataStart.kind == ElementKind.FIELD);
|
||||
// var dataLength = assert(target.lookupInSelf("dataLength"));
|
||||
// assert(dataLength.kind == ElementKind.FIELD);
|
||||
|
||||
// var constantOffset: i32 = 0;
|
||||
// var dynamicOffset = module.precomputeExpression(
|
||||
// compiler.compileExpression(
|
||||
// elementExpression,
|
||||
// Type.i32,
|
||||
// ConversionKind.IMPLICIT,
|
||||
// WrapMode.NONE
|
||||
// )
|
||||
// );
|
||||
// if (getExpressionId(dynamicOffset) == ExpressionId.Const) {
|
||||
// constantOffset = getConstValueI32(dynamicOffset);
|
||||
// dynamicOffset = 0;
|
||||
// } else if (getExpressionId(dynamicOffset) == ExpressionId.Binary) {
|
||||
// if (getBinaryOp(dynamicOffset) == BinaryOp.AddI32) {
|
||||
// let left = getBinaryLeft(dynamicOffset);
|
||||
// let right = getBinaryRight(dynamicOffset);
|
||||
// if (getExpressionId(left) == ExpressionId.Const) {
|
||||
// constantOffset = getConstValueI32(left);
|
||||
// dynamicOffset = right;
|
||||
// } else if (getExpressionId(right) == ExpressionId.Const) {
|
||||
// constantOffset = getConstValueI32(right);
|
||||
// dynamicOffset = left;
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
|
||||
// var program = compiler.program;
|
||||
// var isManaged = type.isManaged(program) && target.type.isManaged(program);
|
||||
// var usizeType = compiler.options.usizeType;
|
||||
// var nativeSizeType = compiler.options.nativeSizeType;
|
||||
// var thisExpr = compiler.compileExpression(
|
||||
// thisExpression,
|
||||
// target.type,
|
||||
// ConversionKind.IMPLICIT,
|
||||
// WrapMode.NONE
|
||||
// );
|
||||
// var tempThis: Local | null = null;
|
||||
// if (isManaged) {
|
||||
// tempThis = compiler.currentFlow.getTempLocal(target.type, false);
|
||||
// thisExpr = module.createTeeLocal(tempThis.index, thisExpr);
|
||||
// }
|
||||
// var dataStartExpr = module.createLoad(usizeType.byteSize, true,
|
||||
// thisExpr, nativeSizeType, (<Field>dataStart).memoryOffset
|
||||
// );
|
||||
|
||||
// var typeAlignLog2 = type.alignLog2;
|
||||
// constantOffset <<= typeAlignLog2;
|
||||
// if (dynamicOffset) {
|
||||
// if (typeAlignLog2) {
|
||||
// dynamicOffset = module.createBinary(BinaryOp.ShlI32,
|
||||
// dynamicOffset,
|
||||
// module.createI32(typeAlignLog2)
|
||||
// );
|
||||
// }
|
||||
// if (nativeSizeType == NativeType.I64) {
|
||||
// dataStartExpr = module.createBinary(BinaryOp.AddI64,
|
||||
// dataStartExpr,
|
||||
// module.createUnary(UnaryOp.ExtendU32, dynamicOffset)
|
||||
// );
|
||||
// } else {
|
||||
// dataStartExpr = module.createBinary(BinaryOp.AddI32,
|
||||
// dataStartExpr,
|
||||
// dynamicOffset
|
||||
// );
|
||||
// }
|
||||
// }
|
||||
|
||||
// // handle Array<Ref>: value = RETAIN<T, TArray>(value, this)
|
||||
// if (isManaged) {
|
||||
// let program = compiler.program;
|
||||
// let retainInstance = compiler.resolver.resolveFunction(assert(program.retainPrototype), [ type, target.type ]);
|
||||
// if (!retainInstance) return module.createUnreachable();
|
||||
// valueExpr = compiler.makeCallInlinePrechecked(retainInstance, [
|
||||
// valueExpr,
|
||||
// module.createGetLocal(assert(tempThis).index, nativeSizeType)
|
||||
// ], 0, true);
|
||||
|
||||
// // handle Uint8ClampedArray: value = ~(value >> 31) & (((255 - value) >> 31) | value)
|
||||
// } else if (target.internalName == BuiltinSymbols.Uint8ClampedArray) {
|
||||
// let tempLocal = compiler.currentFlow.getAndFreeTempLocal(Type.i32, true);
|
||||
// valueExpr = module.createBinary(BinaryOp.AndI32,
|
||||
// module.createBinary(BinaryOp.XorI32,
|
||||
// module.createBinary(BinaryOp.ShrI32,
|
||||
// module.createTeeLocal(tempLocal.index, valueExpr),
|
||||
// module.createI32(31)
|
||||
// ),
|
||||
// module.createI32(-1)
|
||||
// ),
|
||||
// module.createBinary(BinaryOp.OrI32,
|
||||
// module.createBinary(BinaryOp.ShrI32,
|
||||
// module.createBinary(BinaryOp.SubI32,
|
||||
// module.createI32(255),
|
||||
// module.createGetLocal(tempLocal.index, NativeType.I32)
|
||||
// ),
|
||||
// module.createI32(31)
|
||||
// ),
|
||||
// module.createGetLocal(tempLocal.index, NativeType.I32)
|
||||
// )
|
||||
// );
|
||||
// }
|
||||
// assert(!tempThis);
|
||||
|
||||
// var nativeType = type.toNativeType();
|
||||
|
||||
// if (!tee) {
|
||||
// compiler.currentType = Type.void;
|
||||
// return module.createStore(
|
||||
// type.byteSize,
|
||||
// dataStartExpr,
|
||||
// valueExpr,
|
||||
// nativeType,
|
||||
// constantOffset
|
||||
// );
|
||||
// } else {
|
||||
// let flow = compiler.currentFlow;
|
||||
// let tempLocal = flow.getAndFreeTempLocal(type, false);
|
||||
// compiler.currentType = type;
|
||||
// return module.createBlock(null, [
|
||||
// module.createStore(
|
||||
// type.byteSize,
|
||||
// dataStartExpr,
|
||||
// module.createTeeLocal(tempLocal.index, valueExpr),
|
||||
// nativeType,
|
||||
// constantOffset
|
||||
// ),
|
||||
// module.createGetLocal(tempLocal.index, nativeType)
|
||||
// ], nativeType);
|
||||
// }
|
||||
// }
|
@ -1,156 +0,0 @@
|
||||
import { Compiler } from "../compiler";
|
||||
import { ExpressionRef, NativeType, BinaryOp } from "../module";
|
||||
import { Local, Function, Class } from "../program";
|
||||
import { Type } from "../types";
|
||||
|
||||
/** Prepares the insertion of a reference into an _uninitialized_ parent using the GC interface. */
|
||||
export function makeInsertRef(
|
||||
compiler: Compiler,
|
||||
valueExpr: ExpressionRef,
|
||||
tempParent: Local,
|
||||
nullable: bool
|
||||
): ExpressionRef {
|
||||
var module = compiler.module;
|
||||
var program = compiler.program;
|
||||
var usizeType = compiler.options.usizeType;
|
||||
var nativeSizeType = compiler.options.nativeSizeType;
|
||||
var flow = compiler.currentFlow;
|
||||
var tempValue = flow.getTempLocal(usizeType, false);
|
||||
var handle: ExpressionRef;
|
||||
var fn: Function | null;
|
||||
if (fn = program.linkRef) { // tracing
|
||||
handle = module.createCall(fn.internalName, [
|
||||
module.createGetLocal(tempValue.index, nativeSizeType),
|
||||
module.createGetLocal(tempParent.index, nativeSizeType)
|
||||
], NativeType.None);
|
||||
} else if (fn = program.retainRef) { // arc
|
||||
handle = module.createCall(fn.internalName, [
|
||||
module.createGetLocal(tempValue.index, nativeSizeType)
|
||||
], NativeType.None);
|
||||
} else {
|
||||
assert(false);
|
||||
return module.createUnreachable();
|
||||
}
|
||||
flow.freeTempLocal(tempValue);
|
||||
if (!compiler.compileFunction(fn)) return module.createUnreachable();
|
||||
// {
|
||||
// [if (value !== null)] link/retain(value[, parent])
|
||||
// } -> value
|
||||
return module.createBlock(null, [
|
||||
module.createSetLocal(tempValue.index, valueExpr),
|
||||
nullable
|
||||
? module.createIf(
|
||||
module.createGetLocal(tempValue.index, nativeSizeType),
|
||||
handle
|
||||
)
|
||||
: handle,
|
||||
module.createGetLocal(tempValue.index, nativeSizeType)
|
||||
], nativeSizeType);
|
||||
}
|
||||
|
||||
/** Prepares the replaces a reference hold by an _initialized_ parent using the GC interface. */
|
||||
export function makeReplaceRef(
|
||||
compiler: Compiler,
|
||||
valueExpr: ExpressionRef,
|
||||
oldValueExpr: ExpressionRef,
|
||||
tempParent: Local,
|
||||
nullable: bool
|
||||
): ExpressionRef {
|
||||
var module = compiler.module;
|
||||
var program = compiler.program;
|
||||
var usizeType = compiler.options.usizeType;
|
||||
var nativeSizeType = compiler.options.nativeSizeType;
|
||||
var flow = compiler.currentFlow;
|
||||
var tempValue = flow.getTempLocal(usizeType, false);
|
||||
var tempOldValue = flow.getTempLocal(usizeType, false);
|
||||
var handleOld: ExpressionRef;
|
||||
var handleNew: ExpressionRef;
|
||||
var fn1: Function | null, fn2: Function | null;
|
||||
if (fn1 = program.linkRef) { // tracing
|
||||
fn2 = assert(program.unlinkRef);
|
||||
handleOld = module.createCall(fn2.internalName, [
|
||||
module.createGetLocal(tempOldValue.index, nativeSizeType),
|
||||
module.createGetLocal(tempParent.index, nativeSizeType)
|
||||
], NativeType.None);
|
||||
handleNew = module.createCall(fn1.internalName, [
|
||||
module.createGetLocal(tempValue.index, nativeSizeType),
|
||||
module.createGetLocal(tempParent.index, nativeSizeType)
|
||||
], NativeType.None);
|
||||
} else if (fn1 = program.retainRef) { // arc
|
||||
fn2 = assert(program.releaseRef);
|
||||
handleOld = module.createCall(fn2.internalName, [
|
||||
module.createGetLocal(tempOldValue.index, nativeSizeType)
|
||||
], NativeType.None);
|
||||
handleNew = module.createCall(fn1.internalName, [
|
||||
module.createGetLocal(tempValue.index, nativeSizeType)
|
||||
], NativeType.None);
|
||||
} else {
|
||||
assert(false);
|
||||
return module.createUnreachable();
|
||||
}
|
||||
flow.freeTempLocal(tempValue);
|
||||
flow.freeTempLocal(tempOldValue);
|
||||
if (!compiler.compileFunction(fn1) || !compiler.compileFunction(fn2)) return module.createUnreachable();
|
||||
// if (value != oldValue) {
|
||||
// if (oldValue !== null) unlink/release(oldValue[, parent])
|
||||
// [if (value !== null)] link/retain(value[, parent])
|
||||
// } -> value
|
||||
return module.createIf(
|
||||
module.createBinary(nativeSizeType == NativeType.I32 ? BinaryOp.NeI32 : BinaryOp.NeI64,
|
||||
module.createTeeLocal(tempValue.index, valueExpr),
|
||||
module.createTeeLocal(tempOldValue.index, oldValueExpr)
|
||||
),
|
||||
module.createBlock(null, [
|
||||
module.createIf(
|
||||
module.createGetLocal(tempOldValue.index, nativeSizeType),
|
||||
handleOld
|
||||
),
|
||||
nullable
|
||||
? module.createIf(
|
||||
module.createGetLocal(tempValue.index, nativeSizeType),
|
||||
handleNew
|
||||
)
|
||||
: handleNew,
|
||||
module.createGetLocal(tempValue.index, nativeSizeType)
|
||||
], nativeSizeType),
|
||||
module.createGetLocal(tempValue.index, nativeSizeType)
|
||||
);
|
||||
}
|
||||
|
||||
export function makeInstanceOfClass(
|
||||
compiler: Compiler,
|
||||
expr: ExpressionRef,
|
||||
classInstance: Class
|
||||
): ExpressionRef {
|
||||
var module = compiler.module;
|
||||
var flow = compiler.currentFlow;
|
||||
var idTemp = flow.getTempLocal(Type.i32, false);
|
||||
var idExpr = module.createLoad(4, false,
|
||||
module.createBinary(BinaryOp.SubI32,
|
||||
expr,
|
||||
module.createI32(compiler.program.runtimeHeaderSize)
|
||||
),
|
||||
NativeType.I32
|
||||
);
|
||||
var label = "instanceof_" + classInstance.name + "|" + flow.pushBreakLabel();
|
||||
var conditions: ExpressionRef[] = [];
|
||||
conditions.push(
|
||||
module.createDrop( // br_if returns the value too
|
||||
module.createBreak(label,
|
||||
module.createBinary(BinaryOp.EqI32, // classId == class.id
|
||||
module.createTeeLocal(idTemp.index, idExpr),
|
||||
module.createI32(classInstance.id)
|
||||
),
|
||||
module.createI32(1) // ? true
|
||||
)
|
||||
)
|
||||
);
|
||||
// TODO: insert conditions for all possible subclasses (i.e. cat is also animal)
|
||||
// TODO: simplify if there are none
|
||||
conditions.push(
|
||||
module.createI32(0) // : false
|
||||
);
|
||||
flow.freeTempLocal(idTemp);
|
||||
flow.popBreakLabel();
|
||||
return module.createBlock(label, conditions, NativeType.I32);
|
||||
}
|
@ -142,10 +142,6 @@ export namespace CommonSymbols {
|
||||
export const this_ = "this";
|
||||
export const super_ = "super";
|
||||
export const constructor = "constructor";
|
||||
}
|
||||
|
||||
/** Common standard library symbols. */
|
||||
export namespace LibrarySymbols {
|
||||
// constants
|
||||
export const ASC_TARGET = "ASC_TARGET";
|
||||
export const ASC_NO_TREESHAKING = "ASC_NO_TREESHAKING";
|
||||
@ -182,19 +178,11 @@ export namespace LibrarySymbols {
|
||||
export const Mathf = "Mathf";
|
||||
// runtime
|
||||
export const abort = "abort";
|
||||
export const ALLOCATE = "ALLOCATE";
|
||||
export const ALLOCATE_UNMANAGED = "ALLOCATE_UNMANAGED";
|
||||
export const REALLOCATE = "REALLOCATE";
|
||||
export const DISCARD = "DISCARD";
|
||||
export const REGISTER = "REGISTER";
|
||||
export const RETAIN = "RETAIN";
|
||||
export const RELEASE = "RELEASE";
|
||||
export const MOVE = "MOVE";
|
||||
export const REPLACE = "REPLACE";
|
||||
export const MAKEARRAY = "MAKEARRAY";
|
||||
// other
|
||||
export const length = "length";
|
||||
export const byteLength = "byteLength";
|
||||
export const pow = "pow";
|
||||
export const mod = "mod";
|
||||
export const allocate = "allocate";
|
||||
export const reallocate = "reallocate";
|
||||
export const register = "register";
|
||||
export const discard = "discard";
|
||||
export const makeArray = "makeArray";
|
||||
}
|
||||
|
684
src/compiler.ts
684
src/compiler.ts
File diff suppressed because it is too large
Load Diff
108
src/program.ts
108
src/program.ts
@ -13,8 +13,7 @@ import {
|
||||
INNER_DELIMITER,
|
||||
LIBRARY_SUBST,
|
||||
INDEX_SUFFIX,
|
||||
CommonSymbols,
|
||||
LibrarySymbols
|
||||
CommonSymbols
|
||||
} from "./common";
|
||||
|
||||
import {
|
||||
@ -355,18 +354,18 @@ export class Program extends DiagnosticEmitter {
|
||||
/** Abort function reference, if present. */
|
||||
abortInstance: Function | null = null;
|
||||
|
||||
/** Runtime allocation macro. `ALLOCATE(payloadSize: usize): usize` */
|
||||
/** Runtime allocation function. `allocate(payloadSize: usize): usize` */
|
||||
allocateInstance: Function | null = null;
|
||||
/** Unmanaged allocation macro. `ALLOCATE_UNMANAGED(size: usize): usize` */
|
||||
allocateUnmanagedInstance: Function | null = null;
|
||||
/** Runtime reallocation macro. `REALLOCATE(ref: usize, newPayloadSize: usize): usize` */
|
||||
/** Memory allocation function. `memory.allocate(size)` */
|
||||
memoryAllocateInstance: Function | null = null;
|
||||
/** Runtime reallocation function. `reallocate(ref: usize, newPayloadSize: usize): usize` */
|
||||
reallocateInstance: Function | null = null;
|
||||
/** Runtime discard macro. `DISCARD(ref: usize): void` */
|
||||
/** Runtime discard function. `discard(ref: usize): void` */
|
||||
discardInstance: Function | null = null;
|
||||
/** Runtime register macro. `REGISTER<T>(ref: usize): T` */
|
||||
registerPrototype: FunctionPrototype | null = null;
|
||||
/** Runtime make array macro. `MAKEARRAY<V>(capacity: i32, source: usize = 0): Array<V>` */
|
||||
makeArrayPrototype: FunctionPrototype | null = null;
|
||||
/** Runtime register function. `register(ref: usize, cid: u32): usize` */
|
||||
registerInstance: Function | null = null;
|
||||
/** Runtime make array function. `makeArray(capacity: i32, source: usize = 0, cid: u32): usize` */
|
||||
makeArrayInstance: Function | null = null;
|
||||
|
||||
linkRef: Function | null = null;
|
||||
unlinkRef: Function | null = null;
|
||||
@ -542,25 +541,25 @@ export class Program extends DiagnosticEmitter {
|
||||
if (options.hasFeature(Feature.SIMD)) this.registerNativeType(CommonSymbols.v128, Type.v128);
|
||||
|
||||
// register compiler hints
|
||||
this.registerConstantInteger(LibrarySymbols.ASC_TARGET, Type.i32,
|
||||
this.registerConstantInteger(CommonSymbols.ASC_TARGET, Type.i32,
|
||||
i64_new(options.isWasm64 ? 2 : 1));
|
||||
this.registerConstantInteger(LibrarySymbols.ASC_NO_ASSERT, Type.bool,
|
||||
this.registerConstantInteger(CommonSymbols.ASC_NO_ASSERT, Type.bool,
|
||||
i64_new(options.noAssert ? 1 : 0, 0));
|
||||
this.registerConstantInteger(LibrarySymbols.ASC_MEMORY_BASE, Type.i32,
|
||||
this.registerConstantInteger(CommonSymbols.ASC_MEMORY_BASE, Type.i32,
|
||||
i64_new(options.memoryBase, 0));
|
||||
this.registerConstantInteger(LibrarySymbols.ASC_OPTIMIZE_LEVEL, Type.i32,
|
||||
this.registerConstantInteger(CommonSymbols.ASC_OPTIMIZE_LEVEL, Type.i32,
|
||||
i64_new(options.optimizeLevelHint, 0));
|
||||
this.registerConstantInteger(LibrarySymbols.ASC_SHRINK_LEVEL, Type.i32,
|
||||
this.registerConstantInteger(CommonSymbols.ASC_SHRINK_LEVEL, Type.i32,
|
||||
i64_new(options.shrinkLevelHint, 0));
|
||||
this.registerConstantInteger(LibrarySymbols.ASC_FEATURE_MUTABLE_GLOBAL, Type.bool,
|
||||
this.registerConstantInteger(CommonSymbols.ASC_FEATURE_MUTABLE_GLOBAL, Type.bool,
|
||||
i64_new(options.hasFeature(Feature.MUTABLE_GLOBAL) ? 1 : 0, 0));
|
||||
this.registerConstantInteger(LibrarySymbols.ASC_FEATURE_SIGN_EXTENSION, Type.bool,
|
||||
this.registerConstantInteger(CommonSymbols.ASC_FEATURE_SIGN_EXTENSION, Type.bool,
|
||||
i64_new(options.hasFeature(Feature.SIGN_EXTENSION) ? 1 : 0, 0));
|
||||
this.registerConstantInteger(LibrarySymbols.ASC_FEATURE_BULK_MEMORY, Type.bool,
|
||||
this.registerConstantInteger(CommonSymbols.ASC_FEATURE_BULK_MEMORY, Type.bool,
|
||||
i64_new(options.hasFeature(Feature.BULK_MEMORY) ? 1 : 0, 0));
|
||||
this.registerConstantInteger(LibrarySymbols.ASC_FEATURE_SIMD, Type.bool,
|
||||
this.registerConstantInteger(CommonSymbols.ASC_FEATURE_SIMD, Type.bool,
|
||||
i64_new(options.hasFeature(Feature.SIMD) ? 1 : 0, 0));
|
||||
this.registerConstantInteger(LibrarySymbols.ASC_FEATURE_THREADS, Type.bool,
|
||||
this.registerConstantInteger(CommonSymbols.ASC_FEATURE_THREADS, Type.bool,
|
||||
i64_new(options.hasFeature(Feature.THREADS) ? 1 : 0, 0));
|
||||
|
||||
// remember deferred elements
|
||||
@ -720,20 +719,20 @@ export class Program extends DiagnosticEmitter {
|
||||
}
|
||||
|
||||
// register classes backing basic types
|
||||
this.registerNativeTypeClass(TypeKind.I8, LibrarySymbols.I8);
|
||||
this.registerNativeTypeClass(TypeKind.I16, LibrarySymbols.I16);
|
||||
this.registerNativeTypeClass(TypeKind.I32, LibrarySymbols.I32);
|
||||
this.registerNativeTypeClass(TypeKind.I64, LibrarySymbols.I64);
|
||||
this.registerNativeTypeClass(TypeKind.ISIZE, LibrarySymbols.Isize);
|
||||
this.registerNativeTypeClass(TypeKind.U8, LibrarySymbols.U8);
|
||||
this.registerNativeTypeClass(TypeKind.U16, LibrarySymbols.U16);
|
||||
this.registerNativeTypeClass(TypeKind.U32, LibrarySymbols.U32);
|
||||
this.registerNativeTypeClass(TypeKind.U64, LibrarySymbols.U64);
|
||||
this.registerNativeTypeClass(TypeKind.USIZE, LibrarySymbols.Usize);
|
||||
this.registerNativeTypeClass(TypeKind.BOOL, LibrarySymbols.Bool);
|
||||
this.registerNativeTypeClass(TypeKind.F32, LibrarySymbols.F32);
|
||||
this.registerNativeTypeClass(TypeKind.F64, LibrarySymbols.F64);
|
||||
if (options.hasFeature(Feature.SIMD)) this.registerNativeTypeClass(TypeKind.V128, LibrarySymbols.V128);
|
||||
this.registerNativeTypeClass(TypeKind.I8, CommonSymbols.I8);
|
||||
this.registerNativeTypeClass(TypeKind.I16, CommonSymbols.I16);
|
||||
this.registerNativeTypeClass(TypeKind.I32, CommonSymbols.I32);
|
||||
this.registerNativeTypeClass(TypeKind.I64, CommonSymbols.I64);
|
||||
this.registerNativeTypeClass(TypeKind.ISIZE, CommonSymbols.Isize);
|
||||
this.registerNativeTypeClass(TypeKind.U8, CommonSymbols.U8);
|
||||
this.registerNativeTypeClass(TypeKind.U16, CommonSymbols.U16);
|
||||
this.registerNativeTypeClass(TypeKind.U32, CommonSymbols.U32);
|
||||
this.registerNativeTypeClass(TypeKind.U64, CommonSymbols.U64);
|
||||
this.registerNativeTypeClass(TypeKind.USIZE, CommonSymbols.Usize);
|
||||
this.registerNativeTypeClass(TypeKind.BOOL, CommonSymbols.Bool);
|
||||
this.registerNativeTypeClass(TypeKind.F32, CommonSymbols.F32);
|
||||
this.registerNativeTypeClass(TypeKind.F64, CommonSymbols.F64);
|
||||
if (options.hasFeature(Feature.SIMD)) this.registerNativeTypeClass(TypeKind.V128, CommonSymbols.V128);
|
||||
|
||||
// resolve base prototypes of derived classes
|
||||
var resolver = this.resolver;
|
||||
@ -785,56 +784,56 @@ export class Program extends DiagnosticEmitter {
|
||||
}
|
||||
}
|
||||
|
||||
// register global library elements
|
||||
// register library elements
|
||||
{
|
||||
let element: Element | null;
|
||||
if (element = this.lookupGlobal(LibrarySymbols.ArrayBufferView)) {
|
||||
if (element = this.lookupGlobal(CommonSymbols.ArrayBufferView)) {
|
||||
assert(element.kind == ElementKind.CLASS_PROTOTYPE);
|
||||
this.arrayBufferViewInstance = resolver.resolveClass(<ClassPrototype>element, null);
|
||||
}
|
||||
if (element = this.lookupGlobal(LibrarySymbols.ArrayBuffer)) {
|
||||
if (element = this.lookupGlobal(CommonSymbols.ArrayBuffer)) {
|
||||
assert(element.kind == ElementKind.CLASS_PROTOTYPE);
|
||||
this.arrayBufferInstance = resolver.resolveClass(<ClassPrototype>element, null);
|
||||
}
|
||||
if (element = this.lookupGlobal(LibrarySymbols.String)) {
|
||||
if (element = this.lookupGlobal(CommonSymbols.String)) {
|
||||
assert(element.kind == ElementKind.CLASS_PROTOTYPE);
|
||||
this.stringInstance = resolver.resolveClass(<ClassPrototype>element, null);
|
||||
}
|
||||
if (element = this.lookupGlobal(LibrarySymbols.Array)) {
|
||||
if (element = this.lookupGlobal(CommonSymbols.Array)) {
|
||||
assert(element.kind == ElementKind.CLASS_PROTOTYPE);
|
||||
this.arrayPrototype = <ClassPrototype>element;
|
||||
}
|
||||
if (element = this.lookupGlobal(LibrarySymbols.FixedArray)) {
|
||||
if (element = this.lookupGlobal(CommonSymbols.FixedArray)) {
|
||||
assert(element.kind == ElementKind.CLASS_PROTOTYPE);
|
||||
this.fixedArrayPrototype = <ClassPrototype>element;
|
||||
}
|
||||
if (element = this.lookupGlobal(LibrarySymbols.abort)) {
|
||||
if (element = this.lookupGlobal(CommonSymbols.abort)) {
|
||||
assert(element.kind == ElementKind.FUNCTION_PROTOTYPE);
|
||||
this.abortInstance = this.resolver.resolveFunction(<FunctionPrototype>element, null);
|
||||
}
|
||||
if (element = this.lookupGlobal(LibrarySymbols.ALLOCATE)) {
|
||||
if (element = this.lookupGlobal(BuiltinSymbols.allocate)) {
|
||||
assert(element.kind == ElementKind.FUNCTION_PROTOTYPE);
|
||||
this.allocateInstance = this.resolver.resolveFunction(<FunctionPrototype>element, null);
|
||||
}
|
||||
if (element = this.lookupGlobal(LibrarySymbols.ALLOCATE_UNMANAGED)) {
|
||||
if (element = this.lookupGlobal(BuiltinSymbols.memory_allocate)) {
|
||||
assert(element.kind == ElementKind.FUNCTION_PROTOTYPE);
|
||||
this.allocateUnmanagedInstance = this.resolver.resolveFunction(<FunctionPrototype>element, null);
|
||||
this.memoryAllocateInstance = this.resolver.resolveFunction(<FunctionPrototype>element, null);
|
||||
}
|
||||
if (element = this.lookupGlobal(LibrarySymbols.REALLOCATE)) {
|
||||
if (element = this.lookupGlobal(BuiltinSymbols.reallocate)) {
|
||||
assert(element.kind == ElementKind.FUNCTION_PROTOTYPE);
|
||||
this.reallocateInstance = this.resolver.resolveFunction(<FunctionPrototype>element, null);
|
||||
}
|
||||
if (element = this.lookupGlobal(LibrarySymbols.DISCARD)) {
|
||||
if (element = this.lookupGlobal(BuiltinSymbols.discard)) {
|
||||
assert(element.kind == ElementKind.FUNCTION_PROTOTYPE);
|
||||
this.discardInstance = this.resolver.resolveFunction(<FunctionPrototype>element, null);
|
||||
}
|
||||
if (element = this.lookupGlobal(LibrarySymbols.REGISTER)) {
|
||||
if (element = this.lookupGlobal(BuiltinSymbols.register)) {
|
||||
assert(element.kind == ElementKind.FUNCTION_PROTOTYPE);
|
||||
this.registerPrototype = <FunctionPrototype>element;
|
||||
this.registerInstance = this.resolver.resolveFunction(<FunctionPrototype>element, null);
|
||||
}
|
||||
if (element = this.lookupGlobal(LibrarySymbols.MAKEARRAY)) {
|
||||
if (element = this.lookupGlobal(BuiltinSymbols.makeArray)) {
|
||||
assert(element.kind == ElementKind.FUNCTION_PROTOTYPE);
|
||||
this.makeArrayPrototype = <FunctionPrototype>element;
|
||||
this.makeArrayInstance = this.resolver.resolveFunction(<FunctionPrototype>element, null);
|
||||
}
|
||||
if (this.lookupGlobal("__ref_collect")) {
|
||||
if (element = this.lookupGlobal("__ref_link")) {
|
||||
@ -970,6 +969,13 @@ export class Program extends DiagnosticEmitter {
|
||||
return null;
|
||||
}
|
||||
|
||||
/** Looks up the element of the specified name in the global scope. Errors if not present. */
|
||||
requireGlobal(name: string): Element {
|
||||
var elements = this.elementsByName;
|
||||
if (elements.has(name)) return elements.get(name)!;
|
||||
throw new Error("missing global");
|
||||
}
|
||||
|
||||
/** Tries to locate a foreign file given its normalized path. */
|
||||
private lookupForeignFile(
|
||||
/** Normalized path to the other file. */
|
||||
|
Reference in New Issue
Block a user