This commit is contained in:
dcode
2019-03-16 11:24:13 +01:00
parent b8a08da7a5
commit 05a35f42f6
18 changed files with 15370 additions and 16933 deletions

View File

@ -585,11 +585,7 @@ export function compileCall(
let classReference = type.classReference;
if (!classReference) return module.createI32(0);
let classPrototype = classReference.prototype;
return module.createI32(
(<ClassPrototype>classPrototype).extends(compiler.program.arrayPrototype)
? 1
: 0
);
return module.createI32(classPrototype.extends(compiler.program.arrayPrototype) ? 1 : 0);
}
case BuiltinSymbols.isArrayLike: { // isArrayLike<T!>() / isArrayLike<T?>(value: T) -> bool
let type = evaluateConstantType(compiler, typeArguments, operands, reportNode);
@ -597,12 +593,7 @@ export function compileCall(
if (!type) return module.createUnreachable();
let classReference = type.classReference;
if (!classReference) return module.createI32(0);
return module.createI32(
classReference.lookupInSelf("length") && (
classReference.lookupOverload(OperatorKind.INDEXED_GET) ||
classReference.lookupOverload(OperatorKind.UNCHECKED_INDEXED_GET)
) ? 1 : 0
);
return module.createI32(classReference.isArrayLike ? 1 : 0);
}
case BuiltinSymbols.isFunction: { // isFunction<T!> / isFunction<T?>(value: T) -> bool
let type = evaluateConstantType(compiler, typeArguments, operands, reportNode);
@ -4153,17 +4144,17 @@ function compileTypedArrayGet(
WrapMode.NONE
));
if (getExpressionId(dynamicOffset) == ExpressionId.Const) {
constantOffset = getConstValueI32(dynamicOffset) * type.byteSize;
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) * type.byteSize;
constantOffset = getConstValueI32(left);
dynamicOffset = right;
} else if (getExpressionId(right) == ExpressionId.Const) {
constantOffset = getConstValueI32(right) * type.byteSize;
constantOffset = getConstValueI32(right);
dynamicOffset = left;
}
}
@ -4180,7 +4171,16 @@ function compileTypedArrayGet(
),
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,
@ -4242,12 +4242,14 @@ function compileTypedArraySet(
assert(dataEnd.kind == ElementKind.FIELD);
var constantOffset: i32 = 0;
var dynamicOffset = module.precomputeExpression(compiler.compileExpression(
elementExpression,
Type.i32,
ConversionKind.IMPLICIT,
WrapMode.NONE
));
var dynamicOffset = module.precomputeExpression(
compiler.compileExpression(
elementExpression,
Type.i32,
ConversionKind.IMPLICIT,
WrapMode.NONE
)
);
if (getExpressionId(dynamicOffset) == ExpressionId.Const) {
constantOffset = getConstValueI32(dynamicOffset);
dynamicOffset = 0;
@ -4276,7 +4278,16 @@ function compileTypedArraySet(
),
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,
@ -4292,13 +4303,47 @@ function compileTypedArraySet(
var valueExpr = compiler.compileExpression(
valueExpression,
type.is(TypeFlags.SIGNED) ? Type.i32 : Type.u32,
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
);
// clamp
if (target.internalName == BuiltinSymbols.Uint8ClampedArray) {
let tempLocal = compiler.currentFlow.getAndFreeTempLocal(Type.i32, true);
// ~(value >> 31) & (((255 - value) >> 31) | value)
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)
)
);
}
var nativeType = type.toNativeType();
// TODO: check offset, clamp
// TODO: check offset
if (contextualType == Type.void) {
compiler.currentType = Type.void;

View File

@ -2837,6 +2837,13 @@ export class ClassPrototype extends DeclaredElement {
return (<ClassDeclaration>this.declaration).implementsTypes;
}
/** Tests if this prototype is of a builtin array type (Array/TypedArray). */
get isBuiltinArray(): bool {
var arrayBufferViewInstance = this.program.arrayBufferViewInstance;
return arrayBufferViewInstance !== null
&& this.extends(arrayBufferViewInstance.prototype);
}
/** Tests if this prototype extends the specified. */
extends(basePtototype: ClassPrototype | null): bool {
var current: ClassPrototype | null = this;
@ -2919,6 +2926,27 @@ export class Class extends TypedElement {
return id;
}
/** Tests if this class is of a builtin array type (Array/TypedArray). */
get isBuiltinArray(): bool {
return this.prototype.isBuiltinArray;
}
/** Tests if this class is array-like. */
get isArrayLike(): bool {
if (this.isBuiltinArray) return true;
var lengthField = this.lookupInSelf("length");
return lengthField !== null && (
lengthField.kind == ElementKind.FIELD ||
(
lengthField.kind == ElementKind.PROPERTY &&
(<Property>lengthField).getterInstance !== null // TODO: resolve & check type?
)
) && (
this.lookupOverload(OperatorKind.INDEXED_GET) !== null ||
this.lookupOverload(OperatorKind.UNCHECKED_INDEXED_GET) !== null
);
}
/** Constructs a new class. */
constructor(
/** Name incl. type parameters, i.e. `Foo<i32>`. */

View File

@ -145,6 +145,11 @@ export class Type {
}
}
/** Gets this type's logarithmic alignment in memory. */
get alignLog2(): i32 {
return 31 - clz<i32>(this.byteSize);
}
/** Tests if this is a managed type that needs GC hooks. */
isManaged(program: Program): bool {
if (program.gcImplemented) {