This commit is contained in:
dcode
2019-03-27 14:43:35 +01:00
parent 3146f8f9e0
commit bb1609c9ea
91 changed files with 6426 additions and 11009 deletions

View File

@ -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)

View File

@ -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);
// }
// }

View File

@ -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);
}

View File

@ -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";
}

File diff suppressed because it is too large Load Diff

View File

@ -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. */