2017-12-24 03:19:47 +01:00
|
|
|
import {
|
|
|
|
Compiler,
|
2018-01-10 23:19:14 +01:00
|
|
|
ConversionKind,
|
|
|
|
|
|
|
|
makeSmallIntegerWrap
|
2017-12-24 03:19:47 +01:00
|
|
|
} from "./compiler";
|
|
|
|
|
|
|
|
import {
|
|
|
|
DiagnosticCode
|
|
|
|
} from "./diagnostics";
|
|
|
|
|
|
|
|
import {
|
|
|
|
Node,
|
2018-02-14 19:21:31 +01:00
|
|
|
Expression
|
2017-12-24 03:19:47 +01:00
|
|
|
} from "./ast";
|
|
|
|
|
|
|
|
import {
|
2018-01-10 23:19:14 +01:00
|
|
|
Type,
|
|
|
|
TypeKind,
|
|
|
|
TypeFlags
|
2017-12-24 03:19:47 +01:00
|
|
|
} from "./types";
|
|
|
|
|
|
|
|
import {
|
|
|
|
UnaryOp,
|
|
|
|
BinaryOp,
|
|
|
|
HostOp,
|
|
|
|
NativeType,
|
|
|
|
ExpressionRef,
|
2018-01-21 16:34:50 +01:00
|
|
|
ExpressionId
|
2017-12-24 03:19:47 +01:00
|
|
|
} from "./module";
|
|
|
|
|
|
|
|
import {
|
|
|
|
Global,
|
|
|
|
FunctionPrototype,
|
2018-01-18 23:34:12 +01:00
|
|
|
Local,
|
2018-01-20 05:27:54 +01:00
|
|
|
Class,
|
|
|
|
ElementKind
|
2017-12-24 03:19:47 +01:00
|
|
|
} from "./program";
|
2017-12-05 01:45:15 +01:00
|
|
|
|
2017-12-16 17:54:53 +01:00
|
|
|
/** Compiles a get of a built-in global. */
|
2018-02-16 18:57:51 +01:00
|
|
|
export function compileGetConstant(
|
|
|
|
compiler: Compiler,
|
|
|
|
global: Global,
|
|
|
|
reportNode: Node
|
|
|
|
): ExpressionRef {
|
2018-02-14 19:21:31 +01:00
|
|
|
switch (global.internalName) {
|
2018-03-12 14:06:39 +01:00
|
|
|
case "NaN": { // context-sensitive
|
2018-02-25 00:13:39 +01:00
|
|
|
if (compiler.currentType == Type.f32) {
|
2017-12-16 02:27:39 +01:00
|
|
|
return compiler.module.createF32(NaN);
|
2018-02-25 00:13:39 +01:00
|
|
|
} else {
|
|
|
|
compiler.currentType = Type.f64;
|
|
|
|
return compiler.module.createF64(NaN);
|
|
|
|
}
|
2018-03-12 14:06:39 +01:00
|
|
|
}
|
|
|
|
case "Infinity": { // context-sensitive
|
2018-02-25 00:13:39 +01:00
|
|
|
if (compiler.currentType == Type.f32) {
|
2017-12-16 02:27:39 +01:00
|
|
|
return compiler.module.createF32(Infinity);
|
2018-02-25 00:13:39 +01:00
|
|
|
} else {
|
|
|
|
compiler.currentType = Type.f64;
|
|
|
|
return compiler.module.createF64(Infinity);
|
|
|
|
}
|
2018-03-12 14:06:39 +01:00
|
|
|
}
|
|
|
|
case "HEAP_BASE": { // never inlined for linking purposes
|
2018-02-09 02:31:48 +01:00
|
|
|
compiler.currentType = compiler.options.usizeType;
|
2018-02-25 00:13:39 +01:00
|
|
|
return compiler.module.createGetGlobal("HEAP_BASE", compiler.currentType.toNativeType());
|
2018-03-12 14:06:39 +01:00
|
|
|
}
|
2017-12-16 02:27:39 +01:00
|
|
|
}
|
2018-02-25 00:13:39 +01:00
|
|
|
compiler.error(
|
|
|
|
DiagnosticCode.Operation_not_supported,
|
|
|
|
reportNode.range
|
|
|
|
);
|
2018-01-05 01:55:59 +01:00
|
|
|
return compiler.module.createUnreachable();
|
2017-12-16 02:27:39 +01:00
|
|
|
}
|
|
|
|
|
2017-12-05 13:35:14 +01:00
|
|
|
/** Compiles a call to a built-in function. */
|
2018-02-16 18:57:51 +01:00
|
|
|
export function compileCall(
|
|
|
|
compiler: Compiler,
|
|
|
|
prototype: FunctionPrototype,
|
|
|
|
typeArguments: Type[] | null,
|
|
|
|
operands: Expression[],
|
|
|
|
contextualType: Type,
|
|
|
|
reportNode: Node
|
|
|
|
): ExpressionRef {
|
2017-12-28 04:09:40 +01:00
|
|
|
var module = compiler.module;
|
2017-12-05 01:45:15 +01:00
|
|
|
|
2017-12-28 04:09:40 +01:00
|
|
|
var arg0: ExpressionRef,
|
2017-12-05 01:45:15 +01:00
|
|
|
arg1: ExpressionRef,
|
2018-01-10 13:09:05 +01:00
|
|
|
arg2: ExpressionRef,
|
|
|
|
ret: ExpressionRef;
|
2017-12-05 01:45:15 +01:00
|
|
|
|
2017-12-28 04:09:40 +01:00
|
|
|
var tempLocal0: Local,
|
|
|
|
tempLocal1: Local;
|
2017-12-08 04:03:44 +01:00
|
|
|
|
2018-01-10 13:09:05 +01:00
|
|
|
var type: Type,
|
2018-02-14 19:21:31 +01:00
|
|
|
offset: i32;
|
2018-01-21 16:34:50 +01:00
|
|
|
|
2018-01-10 13:09:05 +01:00
|
|
|
// NOTE that some implementations below make use of the select expression where straight-forward.
|
2018-02-25 00:13:39 +01:00
|
|
|
// whether worth or not should probably be tested once/ it's known if/how embedders handle it.
|
2018-01-10 13:09:05 +01:00
|
|
|
// search: createSelect
|
2017-12-05 01:45:15 +01:00
|
|
|
|
2017-12-12 01:35:48 +01:00
|
|
|
switch (prototype.internalName) {
|
2017-12-05 01:45:15 +01:00
|
|
|
|
2017-12-15 17:23:04 +01:00
|
|
|
// math
|
|
|
|
|
2018-03-12 14:06:39 +01:00
|
|
|
case "isNaN": { // isNaN<T?>(value: T) -> bool
|
2017-12-15 17:23:04 +01:00
|
|
|
compiler.currentType = Type.bool;
|
2018-01-10 13:09:05 +01:00
|
|
|
if (operands.length != 1) {
|
2018-02-25 00:13:39 +01:00
|
|
|
if (typeArguments && typeArguments.length != 1) {
|
|
|
|
compiler.error(
|
|
|
|
DiagnosticCode.Expected_0_type_arguments_but_got_1,
|
|
|
|
reportNode.range, "1", typeArguments.length.toString(10)
|
|
|
|
);
|
|
|
|
}
|
|
|
|
compiler.error(
|
|
|
|
DiagnosticCode.Expected_0_arguments_but_got_1,
|
|
|
|
reportNode.range, "1", operands.length.toString(10)
|
|
|
|
);
|
2018-01-10 13:09:05 +01:00
|
|
|
return module.createUnreachable();
|
|
|
|
}
|
|
|
|
if (typeArguments) {
|
|
|
|
if (typeArguments.length != 1) {
|
2018-02-25 00:13:39 +01:00
|
|
|
compiler.error(
|
|
|
|
DiagnosticCode.Expected_0_type_arguments_but_got_1,
|
|
|
|
reportNode.range, "1", typeArguments.length.toString(10)
|
|
|
|
);
|
2018-01-10 13:09:05 +01:00
|
|
|
return module.createUnreachable();
|
|
|
|
}
|
|
|
|
arg0 = compiler.compileExpression(operands[0], typeArguments[0]);
|
2018-02-25 00:13:39 +01:00
|
|
|
} else {
|
2018-01-10 13:09:05 +01:00
|
|
|
arg0 = compiler.compileExpression(operands[0], Type.f64, ConversionKind.NONE);
|
2018-02-25 00:13:39 +01:00
|
|
|
}
|
2018-01-10 13:09:05 +01:00
|
|
|
|
|
|
|
switch (compiler.currentType.kind) {
|
2018-03-12 14:06:39 +01:00
|
|
|
case TypeKind.F32: {
|
2017-12-15 17:23:04 +01:00
|
|
|
tempLocal0 = compiler.currentFunction.getAndFreeTempLocal(Type.f32);
|
2018-01-10 13:09:05 +01:00
|
|
|
ret = module.createBinary(BinaryOp.NeF32,
|
2017-12-15 17:23:04 +01:00
|
|
|
module.createTeeLocal(tempLocal0.index, arg0),
|
|
|
|
module.createGetLocal(tempLocal0.index, NativeType.F32)
|
|
|
|
);
|
2018-01-10 13:09:05 +01:00
|
|
|
break;
|
2018-03-12 14:06:39 +01:00
|
|
|
}
|
|
|
|
case TypeKind.F64: {
|
2017-12-15 17:23:04 +01:00
|
|
|
tempLocal0 = compiler.currentFunction.getAndFreeTempLocal(Type.f64);
|
2018-01-10 13:09:05 +01:00
|
|
|
ret = module.createBinary(BinaryOp.NeF64,
|
2017-12-15 17:23:04 +01:00
|
|
|
module.createTeeLocal(tempLocal0.index, arg0),
|
|
|
|
module.createGetLocal(tempLocal0.index, NativeType.F64)
|
|
|
|
);
|
2018-01-10 13:09:05 +01:00
|
|
|
break;
|
2018-03-12 14:06:39 +01:00
|
|
|
}
|
|
|
|
case TypeKind.VOID: {
|
2018-02-25 00:13:39 +01:00
|
|
|
compiler.error(
|
|
|
|
DiagnosticCode.Operation_not_supported,
|
|
|
|
reportNode.range
|
|
|
|
);
|
2018-01-10 13:09:05 +01:00
|
|
|
ret = module.createUnreachable();
|
|
|
|
break;
|
2018-03-12 14:06:39 +01:00
|
|
|
}
|
|
|
|
default: { // every other type is never NaN
|
2018-01-10 13:09:05 +01:00
|
|
|
ret = module.createI32(0);
|
|
|
|
break;
|
2018-03-12 14:06:39 +01:00
|
|
|
}
|
2017-12-15 17:23:04 +01:00
|
|
|
}
|
2018-01-10 13:09:05 +01:00
|
|
|
compiler.currentType = Type.bool;
|
|
|
|
return ret;
|
2018-03-12 14:06:39 +01:00
|
|
|
}
|
|
|
|
case "isFinite": { // isFinite<T?>(value: T) -> bool
|
2017-12-15 17:23:04 +01:00
|
|
|
compiler.currentType = Type.bool;
|
2018-01-10 13:09:05 +01:00
|
|
|
if (operands.length != 1) {
|
2018-02-25 00:13:39 +01:00
|
|
|
if (typeArguments && typeArguments.length != 1) {
|
|
|
|
compiler.error(
|
|
|
|
DiagnosticCode.Expected_0_type_arguments_but_got_1,
|
|
|
|
reportNode.range, "1", typeArguments.length.toString(10)
|
|
|
|
);
|
|
|
|
}
|
|
|
|
compiler.error(
|
|
|
|
DiagnosticCode.Expected_0_arguments_but_got_1,
|
|
|
|
reportNode.range, "1", operands.length.toString(10)
|
|
|
|
);
|
2017-12-15 17:23:04 +01:00
|
|
|
return module.createUnreachable();
|
2018-01-10 13:09:05 +01:00
|
|
|
}
|
|
|
|
if (typeArguments) {
|
|
|
|
if (typeArguments.length != 1) {
|
2018-02-25 00:13:39 +01:00
|
|
|
compiler.error(
|
|
|
|
DiagnosticCode.Expected_0_type_arguments_but_got_1,
|
|
|
|
reportNode.range, "1", typeArguments.length.toString(10)
|
|
|
|
);
|
2018-01-10 13:09:05 +01:00
|
|
|
return module.createUnreachable();
|
|
|
|
}
|
|
|
|
arg0 = compiler.compileExpression(operands[0], typeArguments[0]);
|
2018-02-25 00:13:39 +01:00
|
|
|
} else {
|
2018-01-10 13:09:05 +01:00
|
|
|
arg0 = compiler.compileExpression(operands[0], Type.f64, ConversionKind.NONE);
|
2018-02-25 00:13:39 +01:00
|
|
|
}
|
2018-01-10 13:09:05 +01:00
|
|
|
switch (compiler.currentType.kind) {
|
2018-03-12 14:06:39 +01:00
|
|
|
case TypeKind.F32: {
|
2017-12-15 17:23:04 +01:00
|
|
|
tempLocal0 = compiler.currentFunction.getAndFreeTempLocal(Type.f32);
|
2018-01-10 13:09:05 +01:00
|
|
|
ret = module.createSelect(
|
2017-12-15 17:23:04 +01:00
|
|
|
module.createBinary(BinaryOp.NeF32,
|
|
|
|
module.createUnary(UnaryOp.AbsF32,
|
|
|
|
module.createTeeLocal(tempLocal0.index, arg0)
|
|
|
|
),
|
|
|
|
module.createF32(Infinity)
|
|
|
|
),
|
|
|
|
module.createI32(0),
|
|
|
|
module.createBinary(BinaryOp.EqF32,
|
|
|
|
module.createGetLocal(tempLocal0.index, NativeType.F32),
|
|
|
|
module.createGetLocal(tempLocal0.index, NativeType.F32)
|
|
|
|
)
|
|
|
|
);
|
2018-01-10 13:09:05 +01:00
|
|
|
break;
|
2018-03-12 14:06:39 +01:00
|
|
|
}
|
|
|
|
case TypeKind.F64: {
|
2017-12-15 17:23:04 +01:00
|
|
|
tempLocal0 = compiler.currentFunction.getAndFreeTempLocal(Type.f64);
|
2018-01-10 13:09:05 +01:00
|
|
|
ret = module.createSelect(
|
2017-12-15 17:23:04 +01:00
|
|
|
module.createBinary(BinaryOp.NeF64,
|
|
|
|
module.createUnary(UnaryOp.AbsF64,
|
|
|
|
module.createTeeLocal(tempLocal0.index, arg0)
|
|
|
|
),
|
|
|
|
module.createF64(Infinity)
|
|
|
|
),
|
|
|
|
module.createI32(0),
|
|
|
|
module.createBinary(BinaryOp.EqF64,
|
|
|
|
module.createGetLocal(tempLocal0.index, NativeType.F64),
|
|
|
|
module.createGetLocal(tempLocal0.index, NativeType.F64)
|
|
|
|
)
|
|
|
|
);
|
2018-01-10 13:09:05 +01:00
|
|
|
break;
|
2018-03-12 14:06:39 +01:00
|
|
|
}
|
|
|
|
case TypeKind.VOID: {
|
2018-02-25 00:13:39 +01:00
|
|
|
compiler.error(
|
|
|
|
DiagnosticCode.Operation_not_supported,
|
|
|
|
reportNode.range
|
|
|
|
);
|
2018-01-10 13:09:05 +01:00
|
|
|
ret = module.createUnreachable();
|
|
|
|
break;
|
2018-03-12 14:06:39 +01:00
|
|
|
}
|
|
|
|
default: { // every other type is always finite
|
2018-01-10 13:09:05 +01:00
|
|
|
ret = module.createI32(1);
|
|
|
|
break;
|
2018-03-12 14:06:39 +01:00
|
|
|
}
|
2018-01-10 13:09:05 +01:00
|
|
|
}
|
|
|
|
compiler.currentType = Type.bool;
|
|
|
|
return ret;
|
2018-03-12 14:06:39 +01:00
|
|
|
}
|
|
|
|
case "clz": { // clz<T?>(value: T) -> T
|
2018-01-10 13:09:05 +01:00
|
|
|
if (operands.length != 1) {
|
|
|
|
if (typeArguments) {
|
2018-02-25 00:13:39 +01:00
|
|
|
if (typeArguments.length) compiler.currentType = typeArguments[0];
|
|
|
|
if (typeArguments.length != 1) {
|
|
|
|
compiler.error(
|
|
|
|
DiagnosticCode.Expected_0_type_arguments_but_got_1,
|
|
|
|
reportNode.range, "1", typeArguments.length.toString(10)
|
|
|
|
);
|
|
|
|
}
|
2017-12-15 17:23:04 +01:00
|
|
|
}
|
2018-02-25 00:13:39 +01:00
|
|
|
compiler.error(
|
|
|
|
DiagnosticCode.Expected_0_arguments_but_got_1,
|
|
|
|
reportNode.range, "1", operands.length.toString(10)
|
|
|
|
);
|
2018-01-10 13:09:05 +01:00
|
|
|
return module.createUnreachable();
|
2017-12-15 17:23:04 +01:00
|
|
|
}
|
2018-01-10 13:09:05 +01:00
|
|
|
if (typeArguments) {
|
|
|
|
if (typeArguments.length != 1) {
|
2018-02-25 00:13:39 +01:00
|
|
|
if (typeArguments.length) compiler.currentType = typeArguments[0];
|
|
|
|
compiler.error(
|
|
|
|
DiagnosticCode.Expected_0_type_arguments_but_got_1,
|
|
|
|
reportNode.range, "1", typeArguments.length.toString(10)
|
|
|
|
);
|
2018-01-10 13:09:05 +01:00
|
|
|
return module.createUnreachable();
|
|
|
|
}
|
|
|
|
arg0 = compiler.compileExpression(operands[0], typeArguments[0]);
|
2018-02-25 00:13:39 +01:00
|
|
|
} else {
|
2018-01-10 13:09:05 +01:00
|
|
|
arg0 = compiler.compileExpression(operands[0], Type.i32, ConversionKind.NONE);
|
2018-02-25 00:13:39 +01:00
|
|
|
}
|
2018-01-10 13:09:05 +01:00
|
|
|
switch (compiler.currentType.kind) {
|
2018-03-12 14:06:39 +01:00
|
|
|
default: { // any integer up to 32-bits incl. bool
|
2018-01-10 13:09:05 +01:00
|
|
|
ret = module.createUnary(UnaryOp.ClzI32, arg0);
|
|
|
|
break;
|
2018-03-12 14:06:39 +01:00
|
|
|
}
|
|
|
|
case TypeKind.USIZE: {
|
2018-01-10 13:09:05 +01:00
|
|
|
if (compiler.currentType.isReference) {
|
2018-02-25 00:13:39 +01:00
|
|
|
compiler.error(
|
|
|
|
DiagnosticCode.Operation_not_supported,
|
|
|
|
reportNode.range
|
|
|
|
);
|
2018-01-10 13:09:05 +01:00
|
|
|
ret = module.createUnreachable();
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
// fall-through
|
2018-03-12 14:06:39 +01:00
|
|
|
}
|
|
|
|
case TypeKind.ISIZE: {
|
2018-02-25 00:13:39 +01:00
|
|
|
ret = module.createUnary(
|
|
|
|
compiler.options.isWasm64
|
|
|
|
? UnaryOp.ClzI64
|
|
|
|
: UnaryOp.ClzI32,
|
|
|
|
arg0
|
|
|
|
);
|
2018-01-10 13:09:05 +01:00
|
|
|
break;
|
2018-03-12 14:06:39 +01:00
|
|
|
}
|
2018-01-10 13:09:05 +01:00
|
|
|
case TypeKind.I64:
|
2018-03-12 14:06:39 +01:00
|
|
|
case TypeKind.U64: {
|
2018-01-10 13:09:05 +01:00
|
|
|
ret = module.createUnary(UnaryOp.ClzI64, arg0);
|
|
|
|
break;
|
2018-03-12 14:06:39 +01:00
|
|
|
}
|
2018-01-10 13:09:05 +01:00
|
|
|
case TypeKind.F32:
|
|
|
|
case TypeKind.F64:
|
2018-03-12 14:06:39 +01:00
|
|
|
case TypeKind.VOID: {
|
2018-02-25 00:13:39 +01:00
|
|
|
compiler.error(
|
|
|
|
DiagnosticCode.Operation_not_supported,
|
|
|
|
reportNode.range
|
|
|
|
);
|
2018-01-10 13:09:05 +01:00
|
|
|
ret = module.createUnreachable();
|
|
|
|
break;
|
2018-03-12 14:06:39 +01:00
|
|
|
}
|
2018-01-10 13:09:05 +01:00
|
|
|
}
|
|
|
|
return ret;
|
2018-03-12 14:06:39 +01:00
|
|
|
}
|
|
|
|
case "ctz": { // ctz<T?>(value: T) -> T
|
2018-01-10 13:09:05 +01:00
|
|
|
if (operands.length != 1) {
|
|
|
|
if (typeArguments) {
|
2018-02-25 00:13:39 +01:00
|
|
|
if (typeArguments.length) compiler.currentType = typeArguments[0];
|
|
|
|
if (typeArguments.length != 1) {
|
|
|
|
compiler.error(
|
|
|
|
DiagnosticCode.Expected_0_type_arguments_but_got_1,
|
|
|
|
reportNode.range, "1", typeArguments.length.toString(10)
|
|
|
|
);
|
|
|
|
}
|
2018-01-10 13:09:05 +01:00
|
|
|
}
|
2018-02-25 00:13:39 +01:00
|
|
|
compiler.error(
|
|
|
|
DiagnosticCode.Expected_0_arguments_but_got_1,
|
|
|
|
reportNode.range, "1", operands.length.toString(10)
|
|
|
|
);
|
2017-12-08 04:03:44 +01:00
|
|
|
return module.createUnreachable();
|
2017-12-05 01:45:15 +01:00
|
|
|
}
|
2018-01-10 13:09:05 +01:00
|
|
|
if (typeArguments) {
|
|
|
|
if (typeArguments.length != 1) {
|
2018-02-25 00:13:39 +01:00
|
|
|
if (typeArguments.length) compiler.currentType = typeArguments[0];
|
|
|
|
compiler.error(
|
|
|
|
DiagnosticCode.Expected_0_type_arguments_but_got_1,
|
|
|
|
reportNode.range, "1", typeArguments.length.toString(10)
|
|
|
|
);
|
2018-01-10 13:09:05 +01:00
|
|
|
return module.createUnreachable();
|
|
|
|
}
|
|
|
|
arg0 = compiler.compileExpression(operands[0], typeArguments[0]);
|
2018-02-25 00:13:39 +01:00
|
|
|
} else {
|
2018-01-10 13:09:05 +01:00
|
|
|
arg0 = compiler.compileExpression(operands[0], Type.i32, ConversionKind.NONE);
|
2018-02-25 00:13:39 +01:00
|
|
|
}
|
2018-01-10 13:09:05 +01:00
|
|
|
switch (compiler.currentType.kind) {
|
2018-03-12 14:06:39 +01:00
|
|
|
default: { // any integer up to 32-bits incl. bool
|
2018-01-10 13:09:05 +01:00
|
|
|
ret = module.createUnary(UnaryOp.CtzI32, arg0);
|
|
|
|
break;
|
2018-03-12 14:06:39 +01:00
|
|
|
}
|
|
|
|
case TypeKind.USIZE: {
|
2018-01-10 13:09:05 +01:00
|
|
|
if (compiler.currentType.isReference) {
|
2018-02-25 00:13:39 +01:00
|
|
|
compiler.error(
|
|
|
|
DiagnosticCode.Operation_not_supported,
|
|
|
|
reportNode.range
|
|
|
|
);
|
2018-01-10 13:09:05 +01:00
|
|
|
ret = module.createUnreachable();
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
// fall-through
|
2018-03-12 14:06:39 +01:00
|
|
|
}
|
|
|
|
case TypeKind.ISIZE: {
|
2018-02-25 00:13:39 +01:00
|
|
|
ret = module.createUnary(
|
|
|
|
compiler.options.isWasm64
|
|
|
|
? UnaryOp.CtzI64
|
|
|
|
: UnaryOp.CtzI32,
|
|
|
|
arg0
|
|
|
|
);
|
2018-01-10 13:09:05 +01:00
|
|
|
break;
|
2018-03-12 14:06:39 +01:00
|
|
|
}
|
2018-01-10 13:09:05 +01:00
|
|
|
case TypeKind.I64:
|
2018-03-12 14:06:39 +01:00
|
|
|
case TypeKind.U64: {
|
2018-01-10 13:09:05 +01:00
|
|
|
ret = module.createUnary(UnaryOp.CtzI64, arg0);
|
|
|
|
break;
|
2018-03-12 14:06:39 +01:00
|
|
|
}
|
2018-01-10 13:09:05 +01:00
|
|
|
case TypeKind.F32:
|
|
|
|
case TypeKind.F64:
|
2018-03-12 14:06:39 +01:00
|
|
|
case TypeKind.VOID: {
|
2018-02-25 00:13:39 +01:00
|
|
|
compiler.error(
|
|
|
|
DiagnosticCode.Operation_not_supported,
|
|
|
|
reportNode.range
|
|
|
|
);
|
2018-01-10 13:09:05 +01:00
|
|
|
ret = module.createUnreachable();
|
|
|
|
break;
|
2018-03-12 14:06:39 +01:00
|
|
|
}
|
2018-01-10 13:09:05 +01:00
|
|
|
}
|
|
|
|
return ret;
|
2018-03-12 14:06:39 +01:00
|
|
|
}
|
|
|
|
case "popcnt": { // popcnt<T?>(value: T) -> T
|
2018-01-10 13:09:05 +01:00
|
|
|
if (operands.length != 1) {
|
|
|
|
if (typeArguments) {
|
2018-02-25 00:13:39 +01:00
|
|
|
if (typeArguments.length) compiler.currentType = typeArguments[0];
|
|
|
|
if (typeArguments.length != 1) {
|
|
|
|
compiler.error(
|
|
|
|
DiagnosticCode.Expected_0_type_arguments_but_got_1,
|
|
|
|
reportNode.range, "1", typeArguments.length.toString(10)
|
|
|
|
);
|
|
|
|
}
|
2018-01-10 13:09:05 +01:00
|
|
|
}
|
2018-02-25 00:13:39 +01:00
|
|
|
compiler.error(
|
|
|
|
DiagnosticCode.Expected_0_arguments_but_got_1,
|
|
|
|
reportNode.range, "1", operands.length.toString(10)
|
|
|
|
);
|
2017-12-08 04:03:44 +01:00
|
|
|
return module.createUnreachable();
|
2017-12-05 01:45:15 +01:00
|
|
|
}
|
2018-01-10 13:09:05 +01:00
|
|
|
if (typeArguments) {
|
|
|
|
if (typeArguments.length != 1) {
|
2018-02-25 00:13:39 +01:00
|
|
|
if (typeArguments.length) compiler.currentType = typeArguments[0];
|
|
|
|
compiler.error(
|
|
|
|
DiagnosticCode.Expected_0_type_arguments_but_got_1,
|
|
|
|
reportNode.range, "1", typeArguments.length.toString(10)
|
|
|
|
);
|
2018-01-10 13:09:05 +01:00
|
|
|
return module.createUnreachable();
|
|
|
|
}
|
|
|
|
arg0 = compiler.compileExpression(operands[0], typeArguments[0]);
|
2018-02-25 00:13:39 +01:00
|
|
|
} else {
|
2018-01-10 13:09:05 +01:00
|
|
|
arg0 = compiler.compileExpression(operands[0], Type.i32, ConversionKind.NONE);
|
2018-02-25 00:13:39 +01:00
|
|
|
}
|
2018-01-10 13:09:05 +01:00
|
|
|
switch (compiler.currentType.kind) {
|
2018-03-12 14:06:39 +01:00
|
|
|
default: { // any integer up to 32-bits incl. bool
|
2018-01-10 13:09:05 +01:00
|
|
|
ret = module.createUnary(UnaryOp.PopcntI32, arg0);
|
|
|
|
break;
|
2018-03-12 14:06:39 +01:00
|
|
|
}
|
|
|
|
case TypeKind.USIZE: {
|
2018-01-10 13:09:05 +01:00
|
|
|
if (compiler.currentType.isReference) {
|
2018-02-25 00:13:39 +01:00
|
|
|
compiler.error(
|
|
|
|
DiagnosticCode.Operation_not_supported,
|
|
|
|
reportNode.range
|
|
|
|
);
|
2018-01-10 13:09:05 +01:00
|
|
|
ret = module.createUnreachable();
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
// fall-through
|
2018-03-12 14:06:39 +01:00
|
|
|
}
|
|
|
|
case TypeKind.ISIZE: {
|
2018-02-25 00:13:39 +01:00
|
|
|
ret = module.createUnary(
|
|
|
|
compiler.options.isWasm64
|
|
|
|
? UnaryOp.PopcntI64
|
|
|
|
: UnaryOp.PopcntI32,
|
|
|
|
arg0
|
|
|
|
);
|
2018-01-10 13:09:05 +01:00
|
|
|
break;
|
2018-03-12 14:06:39 +01:00
|
|
|
}
|
2018-01-10 13:09:05 +01:00
|
|
|
case TypeKind.I64:
|
2018-03-12 14:06:39 +01:00
|
|
|
case TypeKind.U64: {
|
2018-01-10 13:09:05 +01:00
|
|
|
ret = module.createUnary(UnaryOp.PopcntI64, arg0);
|
|
|
|
break;
|
2018-03-12 14:06:39 +01:00
|
|
|
}
|
2018-01-10 13:09:05 +01:00
|
|
|
case TypeKind.F32:
|
|
|
|
case TypeKind.F64:
|
2018-03-12 14:06:39 +01:00
|
|
|
case TypeKind.VOID: {
|
2018-02-25 00:13:39 +01:00
|
|
|
compiler.error(
|
|
|
|
DiagnosticCode.Operation_not_supported,
|
|
|
|
reportNode.range
|
|
|
|
);
|
2018-01-10 13:09:05 +01:00
|
|
|
ret = module.createUnreachable();
|
|
|
|
break;
|
2018-03-12 14:06:39 +01:00
|
|
|
}
|
2018-01-10 13:09:05 +01:00
|
|
|
}
|
|
|
|
return ret;
|
2018-03-12 14:06:39 +01:00
|
|
|
}
|
|
|
|
case "rotl": { // rotl<T?>(value: T, shift: T) -> T
|
2018-01-10 13:09:05 +01:00
|
|
|
if (operands.length != 2) {
|
|
|
|
if (typeArguments) {
|
2018-02-25 00:13:39 +01:00
|
|
|
if (typeArguments.length) compiler.currentType = typeArguments[0];
|
|
|
|
if (typeArguments.length != 1) {
|
|
|
|
compiler.error(
|
|
|
|
DiagnosticCode.Expected_0_type_arguments_but_got_1,
|
|
|
|
reportNode.range, "1", typeArguments.length.toString(10)
|
|
|
|
);
|
|
|
|
}
|
2018-01-10 13:09:05 +01:00
|
|
|
}
|
2018-02-25 00:13:39 +01:00
|
|
|
compiler.error(
|
|
|
|
DiagnosticCode.Expected_0_arguments_but_got_1,
|
|
|
|
reportNode.range, "2", operands.length.toString(10)
|
|
|
|
);
|
2017-12-08 04:03:44 +01:00
|
|
|
return module.createUnreachable();
|
2017-12-05 01:45:15 +01:00
|
|
|
}
|
2018-01-10 13:09:05 +01:00
|
|
|
if (typeArguments) {
|
|
|
|
if (typeArguments.length != 1) {
|
2018-02-25 00:13:39 +01:00
|
|
|
if (typeArguments.length) compiler.currentType = typeArguments[0];
|
|
|
|
compiler.error(
|
|
|
|
DiagnosticCode.Expected_0_type_arguments_but_got_1,
|
|
|
|
reportNode.range, "1", typeArguments.length.toString(10)
|
|
|
|
);
|
2018-01-10 13:09:05 +01:00
|
|
|
return module.createUnreachable();
|
|
|
|
}
|
|
|
|
arg0 = compiler.compileExpression(operands[0], typeArguments[0]);
|
2018-02-25 00:13:39 +01:00
|
|
|
} else {
|
2018-01-10 13:09:05 +01:00
|
|
|
arg0 = compiler.compileExpression(operands[0], Type.i32, ConversionKind.NONE);
|
2018-02-25 00:13:39 +01:00
|
|
|
}
|
2018-01-10 13:09:05 +01:00
|
|
|
arg1 = compiler.compileExpression(operands[1], compiler.currentType);
|
|
|
|
switch (compiler.currentType.kind) {
|
|
|
|
case TypeKind.I8:
|
|
|
|
case TypeKind.I16:
|
|
|
|
case TypeKind.U8:
|
|
|
|
case TypeKind.U16:
|
2018-03-12 14:06:39 +01:00
|
|
|
case TypeKind.BOOL: {
|
2018-02-25 00:13:39 +01:00
|
|
|
ret = makeSmallIntegerWrap(
|
|
|
|
module.createBinary(BinaryOp.RotlI32, arg0, arg1),
|
|
|
|
compiler.currentType,
|
|
|
|
module
|
|
|
|
);
|
|
|
|
// fall-through
|
2018-03-12 14:06:39 +01:00
|
|
|
}
|
2018-01-10 13:09:05 +01:00
|
|
|
case TypeKind.I32:
|
2018-03-12 14:06:39 +01:00
|
|
|
case TypeKind.U32: {
|
2018-01-10 13:09:05 +01:00
|
|
|
ret = module.createBinary(BinaryOp.RotlI32, arg0, arg1);
|
|
|
|
break;
|
2018-03-12 14:06:39 +01:00
|
|
|
}
|
|
|
|
case TypeKind.USIZE: {
|
2018-01-10 13:09:05 +01:00
|
|
|
if (compiler.currentType.isReference) {
|
2018-02-25 00:13:39 +01:00
|
|
|
compiler.error(
|
|
|
|
DiagnosticCode.Operation_not_supported,
|
|
|
|
reportNode.range
|
|
|
|
);
|
2018-01-10 13:09:05 +01:00
|
|
|
ret = module.createUnreachable();
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
// fall-through
|
2018-03-12 14:06:39 +01:00
|
|
|
}
|
|
|
|
case TypeKind.ISIZE: {
|
2018-02-25 00:13:39 +01:00
|
|
|
ret = module.createBinary(
|
|
|
|
compiler.options.isWasm64
|
|
|
|
? BinaryOp.RotlI64
|
|
|
|
: BinaryOp.RotlI32,
|
|
|
|
arg0,
|
|
|
|
arg1
|
|
|
|
);
|
2018-01-10 13:09:05 +01:00
|
|
|
break;
|
2018-03-12 14:06:39 +01:00
|
|
|
}
|
2018-01-10 13:09:05 +01:00
|
|
|
case TypeKind.I64:
|
2018-03-12 14:06:39 +01:00
|
|
|
case TypeKind.U64: {
|
2018-01-10 13:09:05 +01:00
|
|
|
ret = module.createBinary(BinaryOp.RotlI64, arg0, arg1);
|
|
|
|
break;
|
2018-03-12 14:06:39 +01:00
|
|
|
}
|
|
|
|
default: {
|
2018-02-25 00:13:39 +01:00
|
|
|
compiler.error(
|
|
|
|
DiagnosticCode.Operation_not_supported,
|
|
|
|
reportNode.range
|
|
|
|
);
|
2018-01-10 13:09:05 +01:00
|
|
|
ret = module.createUnreachable();
|
|
|
|
break;
|
2018-03-12 14:06:39 +01:00
|
|
|
}
|
2017-12-05 01:45:15 +01:00
|
|
|
}
|
2018-01-10 13:09:05 +01:00
|
|
|
return ret;
|
2018-03-12 14:06:39 +01:00
|
|
|
}
|
|
|
|
case "rotr": { // rotr<T?>(value: T, shift: T) -> T
|
2018-01-10 13:09:05 +01:00
|
|
|
if (operands.length != 2) {
|
|
|
|
if (typeArguments) {
|
2018-02-25 00:13:39 +01:00
|
|
|
if (typeArguments.length) compiler.currentType = typeArguments[0];
|
|
|
|
if (typeArguments.length != 1) {
|
|
|
|
compiler.error(
|
|
|
|
DiagnosticCode.Expected_0_type_arguments_but_got_1,
|
|
|
|
reportNode.range, "1", typeArguments.length.toString(10)
|
|
|
|
);
|
|
|
|
}
|
2018-01-10 13:09:05 +01:00
|
|
|
}
|
2018-02-25 00:13:39 +01:00
|
|
|
compiler.error(
|
|
|
|
DiagnosticCode.Expected_0_arguments_but_got_1,
|
|
|
|
reportNode.range, "2", operands.length.toString(10)
|
|
|
|
);
|
2017-12-08 04:03:44 +01:00
|
|
|
return module.createUnreachable();
|
2018-01-10 13:09:05 +01:00
|
|
|
}
|
|
|
|
if (typeArguments) {
|
|
|
|
if (typeArguments.length != 1) {
|
2018-02-25 00:13:39 +01:00
|
|
|
if (typeArguments.length) compiler.currentType = typeArguments[0];
|
|
|
|
compiler.error(
|
|
|
|
DiagnosticCode.Expected_0_type_arguments_but_got_1,
|
|
|
|
reportNode.range, "1", typeArguments.length.toString(10)
|
|
|
|
);
|
2018-01-10 13:09:05 +01:00
|
|
|
return module.createUnreachable();
|
|
|
|
}
|
|
|
|
arg0 = compiler.compileExpression(operands[0], typeArguments[0]);
|
2018-02-25 00:13:39 +01:00
|
|
|
} else {
|
2018-01-10 13:09:05 +01:00
|
|
|
arg0 = compiler.compileExpression(operands[0], Type.i32, ConversionKind.NONE);
|
2018-02-25 00:13:39 +01:00
|
|
|
}
|
2018-01-10 13:09:05 +01:00
|
|
|
arg1 = compiler.compileExpression(operands[1], compiler.currentType);
|
|
|
|
switch (compiler.currentType.kind) {
|
|
|
|
case TypeKind.I8:
|
|
|
|
case TypeKind.I16:
|
|
|
|
case TypeKind.U8:
|
|
|
|
case TypeKind.U16:
|
2018-03-12 14:06:39 +01:00
|
|
|
case TypeKind.BOOL: {
|
2018-02-25 00:13:39 +01:00
|
|
|
ret = makeSmallIntegerWrap(
|
|
|
|
module.createBinary(BinaryOp.RotrI32, arg0, arg1),
|
|
|
|
compiler.currentType,
|
|
|
|
module
|
|
|
|
);
|
2018-01-10 13:09:05 +01:00
|
|
|
break;
|
2018-03-12 14:06:39 +01:00
|
|
|
}
|
2018-01-10 13:09:05 +01:00
|
|
|
case TypeKind.I32:
|
2018-03-12 14:06:39 +01:00
|
|
|
case TypeKind.U32: {
|
2018-01-10 13:09:05 +01:00
|
|
|
ret = module.createBinary(BinaryOp.RotrI32, arg0, arg1);
|
|
|
|
break;
|
2018-03-12 14:06:39 +01:00
|
|
|
}
|
|
|
|
case TypeKind.USIZE: {
|
2018-01-10 13:09:05 +01:00
|
|
|
if (compiler.currentType.isReference) {
|
2018-02-25 00:13:39 +01:00
|
|
|
compiler.error(
|
|
|
|
DiagnosticCode.Operation_not_supported,
|
|
|
|
reportNode.range
|
|
|
|
);
|
2018-01-10 13:09:05 +01:00
|
|
|
ret = module.createUnreachable();
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
// fall-through
|
2018-03-12 14:06:39 +01:00
|
|
|
}
|
|
|
|
case TypeKind.ISIZE: {
|
2018-02-25 00:13:39 +01:00
|
|
|
ret = module.createBinary(
|
|
|
|
compiler.options.isWasm64
|
|
|
|
? BinaryOp.RotrI64
|
|
|
|
: BinaryOp.RotrI32,
|
|
|
|
arg0,
|
|
|
|
arg1
|
|
|
|
);
|
2018-01-10 13:09:05 +01:00
|
|
|
break;
|
2018-03-12 14:06:39 +01:00
|
|
|
}
|
2018-01-10 13:09:05 +01:00
|
|
|
case TypeKind.I64:
|
2018-03-12 14:06:39 +01:00
|
|
|
case TypeKind.U64: {
|
2018-01-10 13:09:05 +01:00
|
|
|
ret = module.createBinary(BinaryOp.RotrI64, arg0, arg1);
|
|
|
|
break;
|
2018-03-12 14:06:39 +01:00
|
|
|
}
|
|
|
|
default: {
|
2018-02-25 00:13:39 +01:00
|
|
|
compiler.error(
|
|
|
|
DiagnosticCode.Operation_not_supported,
|
|
|
|
reportNode.range
|
|
|
|
);
|
2018-01-10 13:09:05 +01:00
|
|
|
ret = module.createUnreachable();
|
|
|
|
break;
|
2018-03-12 14:06:39 +01:00
|
|
|
}
|
2018-01-10 13:09:05 +01:00
|
|
|
}
|
|
|
|
return ret;
|
2018-03-12 14:06:39 +01:00
|
|
|
}
|
|
|
|
case "abs": { // abs<T?>(value: T) -> T
|
2018-01-10 13:09:05 +01:00
|
|
|
if (operands.length != 1) {
|
|
|
|
if (typeArguments) {
|
2018-02-25 00:13:39 +01:00
|
|
|
if (typeArguments.length) compiler.currentType = typeArguments[0];
|
|
|
|
if (typeArguments.length != 1) {
|
|
|
|
compiler.error(
|
|
|
|
DiagnosticCode.Expected_0_type_arguments_but_got_1,
|
|
|
|
reportNode.range, "1", typeArguments.length.toString(10)
|
|
|
|
);
|
|
|
|
}
|
2017-12-05 01:45:15 +01:00
|
|
|
}
|
2018-02-25 00:13:39 +01:00
|
|
|
compiler.error(
|
|
|
|
DiagnosticCode.Expected_0_arguments_but_got_1,
|
|
|
|
reportNode.range, "1", operands.length.toString(10)
|
|
|
|
);
|
2018-01-10 13:09:05 +01:00
|
|
|
return module.createUnreachable();
|
2017-12-05 01:45:15 +01:00
|
|
|
}
|
2018-01-10 13:09:05 +01:00
|
|
|
if (typeArguments) {
|
|
|
|
if (typeArguments.length != 1) {
|
2018-02-25 00:13:39 +01:00
|
|
|
if (typeArguments.length) compiler.currentType = typeArguments[0];
|
|
|
|
compiler.error(
|
|
|
|
DiagnosticCode.Expected_0_type_arguments_but_got_1,
|
|
|
|
reportNode.range, "1", typeArguments.length.toString(10)
|
|
|
|
);
|
2018-01-10 13:09:05 +01:00
|
|
|
return module.createUnreachable();
|
|
|
|
}
|
|
|
|
arg0 = compiler.compileExpression(operands[0], typeArguments[0]);
|
2018-02-25 00:13:39 +01:00
|
|
|
} else {
|
2018-01-10 13:09:05 +01:00
|
|
|
arg0 = compiler.compileExpression(operands[0], Type.f64, ConversionKind.NONE);
|
2018-02-25 00:13:39 +01:00
|
|
|
}
|
2018-01-10 13:09:05 +01:00
|
|
|
switch (compiler.currentType.kind) {
|
|
|
|
case TypeKind.I8:
|
|
|
|
case TypeKind.I16:
|
|
|
|
// doesn't need sign-extension here because ifFalse below is either positive
|
|
|
|
// or MIN_VALUE (-MIN_VALUE == MIN_VALUE) if selected
|
2018-03-12 14:06:39 +01:00
|
|
|
case TypeKind.I32: {
|
2018-01-10 13:09:05 +01:00
|
|
|
tempLocal0 = compiler.currentFunction.getAndFreeTempLocal(Type.i32);
|
|
|
|
ret = module.createSelect(
|
|
|
|
module.createTeeLocal(tempLocal0.index, arg0),
|
|
|
|
module.createBinary(BinaryOp.SubI32, // ifFalse
|
|
|
|
module.createI32(0),
|
|
|
|
module.createGetLocal(tempLocal0.index, NativeType.I32)
|
|
|
|
),
|
|
|
|
module.createBinary(BinaryOp.GtI32,
|
|
|
|
module.createGetLocal(tempLocal0.index, NativeType.I32),
|
|
|
|
module.createI32(0)
|
|
|
|
)
|
|
|
|
);
|
|
|
|
break;
|
2018-03-12 14:06:39 +01:00
|
|
|
}
|
|
|
|
case TypeKind.ISIZE: {
|
2018-01-21 17:52:44 +01:00
|
|
|
tempLocal0 = compiler.currentFunction.getAndFreeTempLocal(compiler.options.usizeType);
|
2018-01-10 13:09:05 +01:00
|
|
|
ret = module.createSelect(
|
|
|
|
module.createTeeLocal(tempLocal0.index, arg0),
|
2018-02-25 00:13:39 +01:00
|
|
|
module.createBinary(
|
|
|
|
compiler.options.isWasm64
|
|
|
|
? BinaryOp.SubI64
|
|
|
|
: BinaryOp.SubI32,
|
2018-01-21 17:52:44 +01:00
|
|
|
compiler.options.usizeType.toNativeZero(module),
|
|
|
|
module.createGetLocal(tempLocal0.index, compiler.options.nativeSizeType)
|
2018-01-10 13:09:05 +01:00
|
|
|
),
|
2018-02-25 00:13:39 +01:00
|
|
|
module.createBinary(
|
|
|
|
compiler.options.isWasm64
|
|
|
|
? BinaryOp.GtI64
|
|
|
|
: BinaryOp.GtI32,
|
2018-01-21 17:52:44 +01:00
|
|
|
module.createGetLocal(tempLocal0.index, compiler.options.nativeSizeType),
|
|
|
|
compiler.options.usizeType.toNativeZero(module)
|
2018-01-10 13:09:05 +01:00
|
|
|
)
|
|
|
|
);
|
|
|
|
break;
|
2018-03-12 14:06:39 +01:00
|
|
|
}
|
|
|
|
case TypeKind.I64: {
|
2018-01-10 13:09:05 +01:00
|
|
|
tempLocal0 = compiler.currentFunction.getAndFreeTempLocal(Type.i64);
|
|
|
|
ret = module.createSelect(
|
|
|
|
module.createTeeLocal(tempLocal0.index, arg0),
|
|
|
|
module.createBinary(BinaryOp.SubI64,
|
|
|
|
module.createI64(0, 0),
|
|
|
|
module.createGetLocal(tempLocal0.index, NativeType.I64),
|
|
|
|
),
|
|
|
|
module.createBinary(BinaryOp.GtI64,
|
|
|
|
module.createGetLocal(tempLocal0.index, NativeType.I64),
|
|
|
|
module.createI64(0, 0)
|
|
|
|
)
|
|
|
|
);
|
|
|
|
break;
|
2018-03-12 14:06:39 +01:00
|
|
|
}
|
|
|
|
case TypeKind.USIZE: {
|
2018-01-10 13:09:05 +01:00
|
|
|
if (compiler.currentType.isReference) {
|
2018-02-25 00:13:39 +01:00
|
|
|
compiler.error(
|
|
|
|
DiagnosticCode.Operation_not_supported,
|
|
|
|
reportNode.range
|
|
|
|
);
|
2018-01-10 13:09:05 +01:00
|
|
|
ret = module.createUnreachable();
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
// fall-through
|
2018-03-12 14:06:39 +01:00
|
|
|
}
|
2018-01-10 13:09:05 +01:00
|
|
|
case TypeKind.U8:
|
|
|
|
case TypeKind.U16:
|
|
|
|
case TypeKind.U32:
|
|
|
|
case TypeKind.U64:
|
2018-03-12 14:06:39 +01:00
|
|
|
case TypeKind.BOOL: {
|
2018-01-10 13:09:05 +01:00
|
|
|
ret = arg0;
|
|
|
|
break;
|
2018-03-12 14:06:39 +01:00
|
|
|
}
|
|
|
|
case TypeKind.F32: {
|
2018-01-10 13:09:05 +01:00
|
|
|
ret = module.createUnary(UnaryOp.AbsF32, arg0);
|
|
|
|
break;
|
2018-03-12 14:06:39 +01:00
|
|
|
}
|
|
|
|
case TypeKind.F64: {
|
2018-01-10 13:09:05 +01:00
|
|
|
ret = module.createUnary(UnaryOp.AbsF64, arg0);
|
|
|
|
break;
|
2018-03-12 14:06:39 +01:00
|
|
|
}
|
|
|
|
case TypeKind.VOID: {
|
2018-01-10 13:09:05 +01:00
|
|
|
ret = module.createUnreachable();
|
|
|
|
break;
|
2018-03-12 14:06:39 +01:00
|
|
|
}
|
|
|
|
default: { // void
|
2018-02-25 00:13:39 +01:00
|
|
|
compiler.error(
|
|
|
|
DiagnosticCode.Operation_not_supported,
|
|
|
|
reportNode.range
|
|
|
|
);
|
2018-01-10 13:09:05 +01:00
|
|
|
ret = module.createUnreachable();
|
|
|
|
break;
|
2018-03-12 14:06:39 +01:00
|
|
|
}
|
2018-01-10 13:09:05 +01:00
|
|
|
}
|
|
|
|
return ret;
|
2018-03-12 14:06:39 +01:00
|
|
|
}
|
|
|
|
case "max": { // max<T?>(left: T, right: T) -> T
|
2018-01-10 13:09:05 +01:00
|
|
|
if (operands.length != 2) {
|
|
|
|
if (typeArguments) {
|
2018-02-25 00:13:39 +01:00
|
|
|
if (typeArguments.length) compiler.currentType = typeArguments[0];
|
|
|
|
if (typeArguments.length != 1) {
|
|
|
|
compiler.error(
|
|
|
|
DiagnosticCode.Expected_0_type_arguments_but_got_1,
|
|
|
|
reportNode.range, "1", typeArguments.length.toString(10)
|
|
|
|
);
|
|
|
|
}
|
2017-12-05 01:45:15 +01:00
|
|
|
}
|
2018-02-25 00:13:39 +01:00
|
|
|
compiler.error(
|
|
|
|
DiagnosticCode.Expected_0_arguments_but_got_1,
|
|
|
|
reportNode.range, "2", operands.length.toString(10)
|
|
|
|
);
|
2018-01-10 13:09:05 +01:00
|
|
|
return module.createUnreachable();
|
2017-12-05 01:45:15 +01:00
|
|
|
}
|
2018-01-10 13:09:05 +01:00
|
|
|
if (typeArguments) {
|
|
|
|
if (typeArguments.length != 1) {
|
2018-02-25 00:13:39 +01:00
|
|
|
if (typeArguments.length) compiler.currentType = typeArguments[0];
|
|
|
|
compiler.error(
|
|
|
|
DiagnosticCode.Expected_0_type_arguments_but_got_1,
|
|
|
|
reportNode.range, "1", typeArguments.length.toString(10)
|
|
|
|
);
|
2018-01-10 13:09:05 +01:00
|
|
|
return module.createUnreachable();
|
|
|
|
}
|
|
|
|
arg0 = compiler.compileExpression(operands[0], typeArguments[0]);
|
2018-02-25 00:13:39 +01:00
|
|
|
} else {
|
2018-01-10 13:09:05 +01:00
|
|
|
arg0 = compiler.compileExpression(operands[0], Type.f64, ConversionKind.NONE);
|
2018-02-25 00:13:39 +01:00
|
|
|
}
|
2018-01-10 13:09:05 +01:00
|
|
|
arg1 = compiler.compileExpression(operands[1], compiler.currentType);
|
|
|
|
switch (compiler.currentType.kind) {
|
|
|
|
case TypeKind.I8:
|
|
|
|
case TypeKind.I16:
|
2018-03-12 14:06:39 +01:00
|
|
|
case TypeKind.I32: {
|
2018-01-10 13:09:05 +01:00
|
|
|
tempLocal0 = compiler.currentFunction.getTempLocal(Type.i32);
|
|
|
|
tempLocal1 = compiler.currentFunction.getAndFreeTempLocal(Type.i32);
|
|
|
|
compiler.currentFunction.freeTempLocal(tempLocal0);
|
|
|
|
ret = module.createSelect(
|
|
|
|
module.createTeeLocal(tempLocal0.index, arg0),
|
|
|
|
module.createTeeLocal(tempLocal1.index, arg1),
|
|
|
|
module.createBinary(BinaryOp.GtI32,
|
|
|
|
module.createGetLocal(tempLocal0.index, NativeType.I32),
|
|
|
|
module.createGetLocal(tempLocal1.index, NativeType.I32)
|
|
|
|
)
|
|
|
|
);
|
|
|
|
break;
|
2018-03-12 14:06:39 +01:00
|
|
|
}
|
2018-01-10 13:09:05 +01:00
|
|
|
case TypeKind.U8:
|
|
|
|
case TypeKind.U16:
|
|
|
|
case TypeKind.U32:
|
2018-03-12 14:06:39 +01:00
|
|
|
case TypeKind.BOOL: {
|
2018-01-10 13:09:05 +01:00
|
|
|
tempLocal0 = compiler.currentFunction.getTempLocal(Type.i32);
|
|
|
|
tempLocal1 = compiler.currentFunction.getAndFreeTempLocal(Type.i32);
|
|
|
|
compiler.currentFunction.freeTempLocal(tempLocal0);
|
|
|
|
ret = module.createSelect(
|
|
|
|
module.createTeeLocal(tempLocal0.index, arg0),
|
|
|
|
module.createTeeLocal(tempLocal1.index, arg1),
|
|
|
|
module.createBinary(BinaryOp.GtU32,
|
|
|
|
module.createGetLocal(tempLocal0.index, NativeType.I32),
|
|
|
|
module.createGetLocal(tempLocal1.index, NativeType.I32)
|
|
|
|
)
|
|
|
|
);
|
|
|
|
break;
|
2018-03-12 14:06:39 +01:00
|
|
|
}
|
|
|
|
case TypeKind.I64: {
|
2018-01-10 13:09:05 +01:00
|
|
|
tempLocal0 = compiler.currentFunction.getTempLocal(Type.i64);
|
|
|
|
tempLocal1 = compiler.currentFunction.getAndFreeTempLocal(Type.i64);
|
2017-12-12 09:32:03 +01:00
|
|
|
compiler.currentFunction.freeTempLocal(tempLocal0);
|
2018-01-10 13:09:05 +01:00
|
|
|
ret = module.createSelect(
|
|
|
|
module.createTeeLocal(tempLocal0.index, arg0),
|
|
|
|
module.createTeeLocal(tempLocal1.index, arg1),
|
|
|
|
module.createBinary(BinaryOp.GtI64,
|
|
|
|
module.createGetLocal(tempLocal0.index, NativeType.I64),
|
|
|
|
module.createGetLocal(tempLocal1.index, NativeType.I64)
|
|
|
|
)
|
|
|
|
);
|
|
|
|
break;
|
2018-03-12 14:06:39 +01:00
|
|
|
}
|
|
|
|
case TypeKind.U64: {
|
2018-01-10 13:09:05 +01:00
|
|
|
tempLocal0 = compiler.currentFunction.getTempLocal(Type.i64);
|
|
|
|
tempLocal1 = compiler.currentFunction.getAndFreeTempLocal(Type.i64);
|
|
|
|
compiler.currentFunction.freeTempLocal(tempLocal0);
|
|
|
|
ret = module.createSelect(
|
|
|
|
module.createTeeLocal(tempLocal0.index, arg0),
|
|
|
|
module.createTeeLocal(tempLocal1.index, arg1),
|
|
|
|
module.createBinary(BinaryOp.GtU64,
|
|
|
|
module.createGetLocal(tempLocal0.index, NativeType.I64),
|
|
|
|
module.createGetLocal(tempLocal1.index, NativeType.I64)
|
|
|
|
)
|
|
|
|
);
|
|
|
|
break;
|
2018-03-12 14:06:39 +01:00
|
|
|
}
|
|
|
|
case TypeKind.ISIZE: {
|
2018-01-21 17:52:44 +01:00
|
|
|
tempLocal0 = compiler.currentFunction.getTempLocal(compiler.options.usizeType);
|
|
|
|
tempLocal1 = compiler.currentFunction.getAndFreeTempLocal(compiler.options.usizeType);
|
2018-01-10 13:09:05 +01:00
|
|
|
compiler.currentFunction.freeTempLocal(tempLocal0);
|
|
|
|
ret = module.createSelect(
|
|
|
|
module.createTeeLocal(tempLocal0.index, arg0),
|
|
|
|
module.createTeeLocal(tempLocal1.index, arg1),
|
2018-02-25 00:13:39 +01:00
|
|
|
module.createBinary(
|
|
|
|
compiler.options.isWasm64
|
|
|
|
? BinaryOp.GtI64
|
|
|
|
: BinaryOp.GtI32,
|
2018-01-21 17:52:44 +01:00
|
|
|
module.createGetLocal(tempLocal0.index, compiler.options.nativeSizeType),
|
|
|
|
module.createGetLocal(tempLocal1.index, compiler.options.nativeSizeType)
|
2018-01-10 13:09:05 +01:00
|
|
|
)
|
|
|
|
);
|
|
|
|
break;
|
2018-03-12 14:06:39 +01:00
|
|
|
}
|
|
|
|
case TypeKind.USIZE: {
|
2018-01-10 13:09:05 +01:00
|
|
|
if (compiler.currentType.isReference) {
|
2018-02-25 00:13:39 +01:00
|
|
|
compiler.error(
|
|
|
|
DiagnosticCode.Operation_not_supported,
|
|
|
|
reportNode.range
|
|
|
|
);
|
2018-01-10 13:09:05 +01:00
|
|
|
ret = module.createUnreachable();
|
|
|
|
break;
|
|
|
|
}
|
2018-01-21 17:52:44 +01:00
|
|
|
tempLocal0 = compiler.currentFunction.getTempLocal(compiler.options.usizeType);
|
|
|
|
tempLocal1 = compiler.currentFunction.getAndFreeTempLocal(compiler.options.usizeType);
|
2018-01-10 13:09:05 +01:00
|
|
|
compiler.currentFunction.freeTempLocal(tempLocal0);
|
|
|
|
ret = module.createSelect(
|
|
|
|
module.createTeeLocal(tempLocal0.index, arg0),
|
|
|
|
module.createTeeLocal(tempLocal1.index, arg1),
|
2018-02-25 00:13:39 +01:00
|
|
|
module.createBinary(
|
|
|
|
compiler.options.isWasm64
|
|
|
|
? BinaryOp.GtU64
|
|
|
|
: BinaryOp.GtU32,
|
2018-01-21 17:52:44 +01:00
|
|
|
module.createGetLocal(tempLocal0.index, compiler.options.nativeSizeType),
|
|
|
|
module.createGetLocal(tempLocal1.index, compiler.options.nativeSizeType)
|
2018-01-10 13:09:05 +01:00
|
|
|
)
|
|
|
|
);
|
|
|
|
break;
|
2018-03-12 14:06:39 +01:00
|
|
|
}
|
|
|
|
case TypeKind.F32: {
|
2018-01-10 13:09:05 +01:00
|
|
|
ret = module.createBinary(BinaryOp.MaxF32, arg0, arg1);
|
|
|
|
break;
|
2018-03-12 14:06:39 +01:00
|
|
|
}
|
|
|
|
case TypeKind.F64: {
|
2018-01-10 13:09:05 +01:00
|
|
|
ret = module.createBinary(BinaryOp.MaxF64, arg0, arg1);
|
|
|
|
break;
|
2018-03-12 14:06:39 +01:00
|
|
|
}
|
|
|
|
default: { // void
|
2018-02-25 00:13:39 +01:00
|
|
|
compiler.error(
|
|
|
|
DiagnosticCode.Operation_not_supported,
|
|
|
|
reportNode.range
|
|
|
|
);
|
2018-01-10 13:09:05 +01:00
|
|
|
ret = module.createUnreachable();
|
|
|
|
break;
|
2018-03-12 14:06:39 +01:00
|
|
|
}
|
2018-01-10 13:09:05 +01:00
|
|
|
}
|
|
|
|
return ret;
|
2018-03-12 14:06:39 +01:00
|
|
|
}
|
|
|
|
case "min": { // min<T?>(left: T, right: T) -> T
|
2018-01-10 13:09:05 +01:00
|
|
|
if (operands.length != 2) {
|
|
|
|
if (typeArguments) {
|
2018-02-25 00:13:39 +01:00
|
|
|
if (typeArguments.length) compiler.currentType = typeArguments[0];
|
|
|
|
if (typeArguments.length != 1) {
|
|
|
|
compiler.error(
|
|
|
|
DiagnosticCode.Expected_0_type_arguments_but_got_1,
|
|
|
|
reportNode.range, "1", typeArguments.length.toString(10)
|
|
|
|
);
|
|
|
|
}
|
2018-01-10 13:09:05 +01:00
|
|
|
}
|
2018-02-25 00:13:39 +01:00
|
|
|
compiler.error(
|
|
|
|
DiagnosticCode.Expected_0_arguments_but_got_1,
|
|
|
|
reportNode.range, "2", operands.length.toString(10)
|
|
|
|
);
|
2017-12-08 04:03:44 +01:00
|
|
|
return module.createUnreachable();
|
2017-12-05 01:45:15 +01:00
|
|
|
}
|
2018-01-10 13:09:05 +01:00
|
|
|
if (typeArguments) {
|
|
|
|
if (typeArguments.length != 1) {
|
2018-02-25 00:13:39 +01:00
|
|
|
if (typeArguments.length) compiler.currentType = typeArguments[0];
|
|
|
|
compiler.error(
|
|
|
|
DiagnosticCode.Expected_0_type_arguments_but_got_1,
|
|
|
|
reportNode.range, "1", typeArguments.length.toString(10)
|
|
|
|
);
|
2018-01-10 13:09:05 +01:00
|
|
|
return module.createUnreachable();
|
|
|
|
}
|
|
|
|
arg0 = compiler.compileExpression(operands[0], typeArguments[0]);
|
2018-02-25 00:13:39 +01:00
|
|
|
} else {
|
2018-01-10 13:09:05 +01:00
|
|
|
arg0 = compiler.compileExpression(operands[0], Type.f64, ConversionKind.NONE);
|
2018-02-25 00:13:39 +01:00
|
|
|
}
|
2018-01-10 13:09:05 +01:00
|
|
|
arg1 = compiler.compileExpression(operands[1], compiler.currentType);
|
|
|
|
switch (compiler.currentType.kind) {
|
|
|
|
case TypeKind.I8:
|
|
|
|
case TypeKind.I16:
|
2018-03-12 14:06:39 +01:00
|
|
|
case TypeKind.I32: {
|
2018-01-10 13:09:05 +01:00
|
|
|
tempLocal0 = compiler.currentFunction.getTempLocal(Type.i32);
|
|
|
|
tempLocal1 = compiler.currentFunction.getAndFreeTempLocal(Type.i32);
|
|
|
|
compiler.currentFunction.freeTempLocal(tempLocal0);
|
|
|
|
ret = module.createSelect(
|
|
|
|
module.createTeeLocal(tempLocal0.index, arg0),
|
|
|
|
module.createTeeLocal(tempLocal1.index, arg1),
|
|
|
|
module.createBinary(BinaryOp.LtI32,
|
|
|
|
module.createGetLocal(tempLocal0.index, NativeType.I32),
|
|
|
|
module.createGetLocal(tempLocal1.index, NativeType.I32)
|
|
|
|
)
|
|
|
|
);
|
|
|
|
break;
|
2018-03-12 14:06:39 +01:00
|
|
|
}
|
2018-01-10 13:09:05 +01:00
|
|
|
case TypeKind.U8:
|
|
|
|
case TypeKind.U16:
|
|
|
|
case TypeKind.U32:
|
2018-03-12 14:06:39 +01:00
|
|
|
case TypeKind.BOOL: {
|
2018-01-10 13:09:05 +01:00
|
|
|
tempLocal0 = compiler.currentFunction.getTempLocal(Type.i32);
|
|
|
|
tempLocal1 = compiler.currentFunction.getAndFreeTempLocal(Type.i32);
|
|
|
|
compiler.currentFunction.freeTempLocal(tempLocal0);
|
|
|
|
ret = module.createSelect(
|
|
|
|
module.createTeeLocal(tempLocal0.index, arg0),
|
|
|
|
module.createTeeLocal(tempLocal1.index, arg1),
|
|
|
|
module.createBinary(BinaryOp.LtU32,
|
|
|
|
module.createGetLocal(tempLocal0.index, NativeType.I32),
|
|
|
|
module.createGetLocal(tempLocal1.index, NativeType.I32)
|
|
|
|
)
|
|
|
|
);
|
|
|
|
break;
|
2018-03-12 14:06:39 +01:00
|
|
|
}
|
|
|
|
case TypeKind.I64: {
|
2018-01-10 13:09:05 +01:00
|
|
|
tempLocal0 = compiler.currentFunction.getTempLocal(Type.i64);
|
|
|
|
tempLocal1 = compiler.currentFunction.getAndFreeTempLocal(Type.i64);
|
|
|
|
compiler.currentFunction.freeTempLocal(tempLocal0);
|
|
|
|
ret = module.createSelect(
|
|
|
|
module.createTeeLocal(tempLocal0.index, arg0),
|
|
|
|
module.createTeeLocal(tempLocal1.index, arg1),
|
|
|
|
module.createBinary(BinaryOp.LtI64,
|
|
|
|
module.createGetLocal(tempLocal0.index, NativeType.I64),
|
|
|
|
module.createGetLocal(tempLocal1.index, NativeType.I64)
|
|
|
|
)
|
|
|
|
);
|
|
|
|
break;
|
2018-03-12 14:06:39 +01:00
|
|
|
}
|
|
|
|
case TypeKind.U64: {
|
2018-01-10 13:09:05 +01:00
|
|
|
tempLocal0 = compiler.currentFunction.getTempLocal(Type.i64);
|
|
|
|
tempLocal1 = compiler.currentFunction.getAndFreeTempLocal(Type.i64);
|
|
|
|
compiler.currentFunction.freeTempLocal(tempLocal0);
|
|
|
|
ret = module.createSelect(
|
|
|
|
module.createTeeLocal(tempLocal0.index, arg0),
|
|
|
|
module.createTeeLocal(tempLocal1.index, arg1),
|
|
|
|
module.createBinary(BinaryOp.LtU64,
|
|
|
|
module.createGetLocal(tempLocal0.index, NativeType.I64),
|
|
|
|
module.createGetLocal(tempLocal1.index, NativeType.I64)
|
|
|
|
)
|
|
|
|
);
|
|
|
|
break;
|
2018-03-12 14:06:39 +01:00
|
|
|
}
|
|
|
|
case TypeKind.ISIZE: {
|
2018-01-21 17:52:44 +01:00
|
|
|
tempLocal0 = compiler.currentFunction.getTempLocal(compiler.options.usizeType);
|
|
|
|
tempLocal1 = compiler.currentFunction.getAndFreeTempLocal(compiler.options.usizeType);
|
2018-01-10 13:09:05 +01:00
|
|
|
compiler.currentFunction.freeTempLocal(tempLocal0);
|
|
|
|
ret = module.createSelect(
|
|
|
|
module.createTeeLocal(tempLocal0.index, arg0),
|
|
|
|
module.createTeeLocal(tempLocal1.index, arg1),
|
2018-02-25 00:13:39 +01:00
|
|
|
module.createBinary(
|
|
|
|
compiler.options.isWasm64
|
|
|
|
? BinaryOp.LtI64
|
|
|
|
: BinaryOp.LtI32,
|
2018-01-21 17:52:44 +01:00
|
|
|
module.createGetLocal(tempLocal0.index, compiler.options.nativeSizeType),
|
|
|
|
module.createGetLocal(tempLocal1.index, compiler.options.nativeSizeType)
|
2018-01-10 13:09:05 +01:00
|
|
|
)
|
|
|
|
);
|
|
|
|
break;
|
2018-03-12 14:06:39 +01:00
|
|
|
}
|
|
|
|
case TypeKind.USIZE: {
|
2018-01-10 13:09:05 +01:00
|
|
|
if (compiler.currentType.isReference) {
|
2018-02-25 00:13:39 +01:00
|
|
|
compiler.error(
|
|
|
|
DiagnosticCode.Operation_not_supported,
|
|
|
|
reportNode.range
|
|
|
|
);
|
2018-01-10 13:09:05 +01:00
|
|
|
ret = module.createUnreachable();
|
|
|
|
break;
|
|
|
|
}
|
2018-01-21 17:52:44 +01:00
|
|
|
tempLocal0 = compiler.currentFunction.getTempLocal(compiler.options.usizeType);
|
|
|
|
tempLocal1 = compiler.currentFunction.getAndFreeTempLocal(compiler.options.usizeType);
|
2018-01-10 13:09:05 +01:00
|
|
|
compiler.currentFunction.freeTempLocal(tempLocal0);
|
|
|
|
ret = module.createSelect(
|
|
|
|
module.createTeeLocal(tempLocal0.index, arg0),
|
|
|
|
module.createTeeLocal(tempLocal1.index, arg1),
|
2018-02-25 00:13:39 +01:00
|
|
|
module.createBinary(
|
|
|
|
compiler.options.isWasm64
|
|
|
|
? BinaryOp.LtU64
|
|
|
|
: BinaryOp.LtU32,
|
2018-01-21 17:52:44 +01:00
|
|
|
module.createGetLocal(tempLocal0.index, compiler.options.nativeSizeType),
|
|
|
|
module.createGetLocal(tempLocal1.index, compiler.options.nativeSizeType)
|
2018-01-10 13:09:05 +01:00
|
|
|
)
|
|
|
|
);
|
|
|
|
break;
|
2018-03-12 14:06:39 +01:00
|
|
|
}
|
|
|
|
case TypeKind.F32: {
|
2018-01-10 13:09:05 +01:00
|
|
|
ret = module.createBinary(BinaryOp.MinF32, arg0, arg1);
|
|
|
|
break;
|
2018-03-12 14:06:39 +01:00
|
|
|
}
|
|
|
|
case TypeKind.F64: {
|
2018-01-10 13:09:05 +01:00
|
|
|
ret = module.createBinary(BinaryOp.MinF64, arg0, arg1);
|
|
|
|
break;
|
2018-03-12 14:06:39 +01:00
|
|
|
}
|
|
|
|
default: { // void
|
2018-02-25 00:13:39 +01:00
|
|
|
compiler.error(
|
|
|
|
DiagnosticCode.Operation_not_supported,
|
|
|
|
reportNode.range
|
|
|
|
);
|
2018-01-10 13:09:05 +01:00
|
|
|
ret = module.createUnreachable();
|
|
|
|
break;
|
2018-03-12 14:06:39 +01:00
|
|
|
}
|
2018-01-10 13:09:05 +01:00
|
|
|
}
|
|
|
|
return ret;
|
2018-03-12 14:06:39 +01:00
|
|
|
}
|
|
|
|
case "ceil": { // ceil<T?>(value: T) -> T
|
2018-01-10 13:09:05 +01:00
|
|
|
if (operands.length != 1) {
|
|
|
|
if (typeArguments) {
|
2018-02-25 00:13:39 +01:00
|
|
|
if (typeArguments.length) compiler.currentType = typeArguments[0];
|
|
|
|
if (typeArguments.length != 1) {
|
|
|
|
compiler.error(
|
|
|
|
DiagnosticCode.Expected_0_type_arguments_but_got_1,
|
|
|
|
reportNode.range, "1", typeArguments.length.toString(10)
|
|
|
|
);
|
|
|
|
}
|
2018-01-10 13:09:05 +01:00
|
|
|
}
|
2018-02-25 00:13:39 +01:00
|
|
|
compiler.error(
|
|
|
|
DiagnosticCode.Expected_0_arguments_but_got_1,
|
|
|
|
reportNode.range, "1", operands.length.toString(10)
|
|
|
|
);
|
2017-12-08 04:03:44 +01:00
|
|
|
return module.createUnreachable();
|
2017-12-05 01:45:15 +01:00
|
|
|
}
|
2018-01-10 13:09:05 +01:00
|
|
|
if (typeArguments) {
|
|
|
|
if (typeArguments.length != 1) {
|
2018-02-25 00:13:39 +01:00
|
|
|
if (typeArguments.length) compiler.currentType = typeArguments[0];
|
|
|
|
compiler.error(
|
|
|
|
DiagnosticCode.Expected_0_type_arguments_but_got_1,
|
|
|
|
reportNode.range, "1", typeArguments.length.toString(10)
|
|
|
|
);
|
2018-01-10 13:09:05 +01:00
|
|
|
return module.createUnreachable();
|
|
|
|
}
|
|
|
|
arg0 = compiler.compileExpression(operands[0], typeArguments[0]);
|
2018-02-25 00:13:39 +01:00
|
|
|
} else {
|
2018-01-10 13:09:05 +01:00
|
|
|
arg0 = compiler.compileExpression(operands[0], Type.f64, ConversionKind.NONE);
|
2018-02-25 00:13:39 +01:00
|
|
|
}
|
2018-01-10 13:09:05 +01:00
|
|
|
switch (compiler.currentType.kind) {
|
2018-03-12 14:06:39 +01:00
|
|
|
case TypeKind.USIZE: {
|
2018-01-10 13:09:05 +01:00
|
|
|
if (compiler.currentType.isReference) {
|
2018-02-25 00:13:39 +01:00
|
|
|
compiler.error(
|
|
|
|
DiagnosticCode.Operation_not_supported,
|
|
|
|
reportNode.range
|
|
|
|
);
|
2018-01-10 13:09:05 +01:00
|
|
|
ret = module.createUnreachable();
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
// fall-through
|
2018-03-12 14:06:39 +01:00
|
|
|
}
|
|
|
|
default: { // any integer
|
2018-01-10 13:09:05 +01:00
|
|
|
ret = arg0;
|
|
|
|
break;
|
2018-03-12 14:06:39 +01:00
|
|
|
}
|
|
|
|
case TypeKind.F32: {
|
2018-01-10 13:09:05 +01:00
|
|
|
ret = module.createUnary(UnaryOp.CeilF32, arg0);
|
|
|
|
break;
|
2018-03-12 14:06:39 +01:00
|
|
|
}
|
|
|
|
case TypeKind.F64: {
|
2018-01-10 13:09:05 +01:00
|
|
|
ret = module.createUnary(UnaryOp.CeilF64, arg0);
|
|
|
|
break;
|
2018-03-12 14:06:39 +01:00
|
|
|
}
|
|
|
|
case TypeKind.VOID: {
|
2018-02-25 00:13:39 +01:00
|
|
|
compiler.error(
|
|
|
|
DiagnosticCode.Operation_not_supported,
|
|
|
|
reportNode.range
|
|
|
|
);
|
2018-01-10 13:09:05 +01:00
|
|
|
ret = module.createUnreachable();
|
|
|
|
break;
|
2018-03-12 14:06:39 +01:00
|
|
|
}
|
2018-01-10 13:09:05 +01:00
|
|
|
}
|
|
|
|
return ret;
|
2018-03-12 14:06:39 +01:00
|
|
|
}
|
|
|
|
case "floor": { // floor<T?>(value: T) -> T
|
2018-01-10 13:09:05 +01:00
|
|
|
if (operands.length != 1) {
|
|
|
|
if (typeArguments) {
|
2018-02-25 00:13:39 +01:00
|
|
|
if (typeArguments.length) compiler.currentType = typeArguments[0];
|
|
|
|
if (typeArguments.length != 1) {
|
|
|
|
compiler.error(
|
|
|
|
DiagnosticCode.Expected_0_type_arguments_but_got_1,
|
|
|
|
reportNode.range, "1", typeArguments.length.toString(10)
|
|
|
|
);
|
|
|
|
}
|
2018-01-10 13:09:05 +01:00
|
|
|
}
|
2018-02-25 00:13:39 +01:00
|
|
|
compiler.error(
|
|
|
|
DiagnosticCode.Expected_0_arguments_but_got_1,
|
|
|
|
reportNode.range, "1", operands.length.toString(10)
|
|
|
|
);
|
2017-12-08 04:03:44 +01:00
|
|
|
return module.createUnreachable();
|
2017-12-05 01:45:15 +01:00
|
|
|
}
|
2018-01-10 13:09:05 +01:00
|
|
|
if (typeArguments) {
|
|
|
|
if (typeArguments.length != 1) {
|
2018-02-25 00:13:39 +01:00
|
|
|
if (typeArguments.length) compiler.currentType = typeArguments[0];
|
|
|
|
compiler.error(
|
|
|
|
DiagnosticCode.Expected_0_type_arguments_but_got_1,
|
|
|
|
reportNode.range, "1", typeArguments.length.toString(10)
|
|
|
|
);
|
2018-01-10 13:09:05 +01:00
|
|
|
return module.createUnreachable();
|
|
|
|
}
|
|
|
|
arg0 = compiler.compileExpression(operands[0], typeArguments[0]);
|
2018-02-25 00:13:39 +01:00
|
|
|
} else {
|
2018-01-10 13:09:05 +01:00
|
|
|
arg0 = compiler.compileExpression(operands[0], Type.f64, ConversionKind.NONE);
|
2018-02-25 00:13:39 +01:00
|
|
|
}
|
2018-01-10 13:09:05 +01:00
|
|
|
switch (compiler.currentType.kind) {
|
2018-03-12 14:06:39 +01:00
|
|
|
case TypeKind.USIZE: {
|
2018-01-10 13:09:05 +01:00
|
|
|
if (compiler.currentType.isReference) {
|
2018-02-25 00:13:39 +01:00
|
|
|
compiler.error(
|
|
|
|
DiagnosticCode.Operation_not_supported,
|
|
|
|
reportNode.range
|
|
|
|
);
|
2018-01-10 13:09:05 +01:00
|
|
|
ret = module.createUnreachable();
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
// fall-through
|
2018-03-12 14:06:39 +01:00
|
|
|
}
|
|
|
|
default: { // any integer
|
2018-01-10 13:09:05 +01:00
|
|
|
ret = arg0;
|
|
|
|
break;
|
2018-03-12 14:06:39 +01:00
|
|
|
}
|
|
|
|
case TypeKind.F32: {
|
2018-01-10 13:09:05 +01:00
|
|
|
ret = module.createUnary(UnaryOp.FloorF32, arg0);
|
|
|
|
break;
|
2018-03-12 14:06:39 +01:00
|
|
|
}
|
|
|
|
case TypeKind.F64: {
|
2018-01-10 13:09:05 +01:00
|
|
|
ret = module.createUnary(UnaryOp.FloorF64, arg0);
|
|
|
|
break;
|
2018-03-12 14:06:39 +01:00
|
|
|
}
|
|
|
|
case TypeKind.VOID: {
|
2018-02-25 00:13:39 +01:00
|
|
|
compiler.error(
|
|
|
|
DiagnosticCode.Operation_not_supported,
|
|
|
|
reportNode.range
|
|
|
|
);
|
2018-01-10 13:09:05 +01:00
|
|
|
ret = module.createUnreachable();
|
|
|
|
break;
|
2018-03-12 14:06:39 +01:00
|
|
|
}
|
2018-01-10 13:09:05 +01:00
|
|
|
}
|
|
|
|
return ret;
|
2018-03-12 14:06:39 +01:00
|
|
|
}
|
|
|
|
case "copysign": { // copysign<T?>(left: T, right: T) -> T
|
2018-01-10 13:09:05 +01:00
|
|
|
if (operands.length != 2) {
|
|
|
|
if (typeArguments) {
|
2018-02-25 00:13:39 +01:00
|
|
|
if (typeArguments.length) compiler.currentType = typeArguments[0];
|
|
|
|
if (typeArguments.length != 1) {
|
|
|
|
compiler.error(
|
|
|
|
DiagnosticCode.Expected_0_type_arguments_but_got_1,
|
|
|
|
reportNode.range, "1", typeArguments.length.toString(10)
|
|
|
|
);
|
|
|
|
}
|
2018-01-10 13:09:05 +01:00
|
|
|
}
|
2018-02-25 00:13:39 +01:00
|
|
|
compiler.error(
|
|
|
|
DiagnosticCode.Expected_0_arguments_but_got_1,
|
|
|
|
reportNode.range, "2", operands.length.toString(10)
|
|
|
|
);
|
2017-12-08 04:03:44 +01:00
|
|
|
return module.createUnreachable();
|
2017-12-05 01:45:15 +01:00
|
|
|
}
|
2018-01-10 13:09:05 +01:00
|
|
|
if (typeArguments) {
|
|
|
|
if (typeArguments.length != 1) {
|
2018-02-25 00:13:39 +01:00
|
|
|
if (typeArguments.length) compiler.currentType = typeArguments[0];
|
|
|
|
compiler.error(
|
|
|
|
DiagnosticCode.Expected_0_type_arguments_but_got_1,
|
|
|
|
reportNode.range, "1", typeArguments.length.toString(10)
|
|
|
|
);
|
2018-01-10 13:09:05 +01:00
|
|
|
return module.createUnreachable();
|
|
|
|
}
|
|
|
|
arg0 = compiler.compileExpression(operands[0], typeArguments[0]);
|
2018-02-25 00:13:39 +01:00
|
|
|
} else {
|
2018-01-10 13:09:05 +01:00
|
|
|
arg0 = compiler.compileExpression(operands[0], Type.f64, ConversionKind.NONE);
|
2018-02-25 00:13:39 +01:00
|
|
|
}
|
2018-01-10 13:09:05 +01:00
|
|
|
arg1 = compiler.compileExpression(operands[1], compiler.currentType);
|
2018-03-12 14:06:39 +01:00
|
|
|
switch (compiler.currentType.kind) { // TODO: does an integer version make sense?
|
|
|
|
case TypeKind.F32: {
|
2018-01-10 13:09:05 +01:00
|
|
|
ret = module.createBinary(BinaryOp.CopysignF32, arg0, arg1);
|
|
|
|
break;
|
2018-03-12 14:06:39 +01:00
|
|
|
}
|
|
|
|
case TypeKind.F64: {
|
2018-01-10 13:09:05 +01:00
|
|
|
ret = module.createBinary(BinaryOp.CopysignF64, arg0, arg1);
|
|
|
|
break;
|
2018-03-12 14:06:39 +01:00
|
|
|
}
|
|
|
|
default: {
|
2018-02-25 00:13:39 +01:00
|
|
|
compiler.error(
|
|
|
|
DiagnosticCode.Operation_not_supported,
|
|
|
|
reportNode.range
|
|
|
|
);
|
2018-01-10 13:09:05 +01:00
|
|
|
ret = module.createUnreachable();
|
|
|
|
break;
|
2018-03-12 14:06:39 +01:00
|
|
|
}
|
2018-01-10 13:09:05 +01:00
|
|
|
}
|
|
|
|
return ret;
|
2018-03-12 14:06:39 +01:00
|
|
|
}
|
|
|
|
case "nearest": { // nearest<T?>(value: T) -> T
|
2018-01-10 13:09:05 +01:00
|
|
|
if (operands.length != 1) {
|
|
|
|
if (typeArguments) {
|
2018-02-25 00:13:39 +01:00
|
|
|
if (typeArguments.length) compiler.currentType = typeArguments[0];
|
|
|
|
if (typeArguments.length != 1) {
|
|
|
|
compiler.error(
|
|
|
|
DiagnosticCode.Expected_0_type_arguments_but_got_1,
|
|
|
|
reportNode.range, "1", typeArguments.length.toString(10)
|
|
|
|
);
|
|
|
|
}
|
2018-01-10 13:09:05 +01:00
|
|
|
}
|
2018-02-25 00:13:39 +01:00
|
|
|
compiler.error(
|
|
|
|
DiagnosticCode.Expected_0_arguments_but_got_1,
|
|
|
|
reportNode.range, "1", operands.length.toString(10)
|
|
|
|
);
|
2017-12-15 17:23:04 +01:00
|
|
|
return module.createUnreachable();
|
|
|
|
}
|
2018-01-10 13:09:05 +01:00
|
|
|
if (typeArguments) {
|
|
|
|
if (typeArguments.length != 1) {
|
2018-02-25 00:13:39 +01:00
|
|
|
if (typeArguments.length) compiler.currentType = typeArguments[0];
|
|
|
|
compiler.error(
|
|
|
|
DiagnosticCode.Expected_0_type_arguments_but_got_1,
|
|
|
|
reportNode.range, "1", typeArguments.length.toString(10)
|
|
|
|
);
|
2018-01-10 13:09:05 +01:00
|
|
|
return module.createUnreachable();
|
|
|
|
}
|
|
|
|
arg0 = compiler.compileExpression(operands[0], typeArguments[0]);
|
2018-02-25 00:13:39 +01:00
|
|
|
} else {
|
2018-01-10 13:09:05 +01:00
|
|
|
arg0 = compiler.compileExpression(operands[0], Type.f64, ConversionKind.NONE);
|
2018-02-25 00:13:39 +01:00
|
|
|
}
|
2018-01-10 13:09:05 +01:00
|
|
|
switch (compiler.currentType.kind) {
|
2018-03-12 14:06:39 +01:00
|
|
|
case TypeKind.USIZE: {
|
2018-01-10 13:09:05 +01:00
|
|
|
if (compiler.currentType.isReference) {
|
2018-02-25 00:13:39 +01:00
|
|
|
compiler.error(
|
|
|
|
DiagnosticCode.Operation_not_supported,
|
|
|
|
reportNode.range
|
|
|
|
);
|
2018-01-10 13:09:05 +01:00
|
|
|
ret = module.createUnreachable();
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
// fall-through
|
2018-03-12 14:06:39 +01:00
|
|
|
}
|
|
|
|
default: { // any integer
|
2018-01-10 13:09:05 +01:00
|
|
|
ret = arg0;
|
|
|
|
break;
|
2018-03-12 14:06:39 +01:00
|
|
|
}
|
|
|
|
case TypeKind.F32: {
|
2018-01-10 13:09:05 +01:00
|
|
|
ret = module.createUnary(UnaryOp.NearestF32, arg0);
|
|
|
|
break;
|
2018-03-12 14:06:39 +01:00
|
|
|
}
|
|
|
|
case TypeKind.F64: {
|
2018-01-10 13:09:05 +01:00
|
|
|
ret = module.createUnary(UnaryOp.NearestF64, arg0);
|
|
|
|
break;
|
2018-03-12 14:06:39 +01:00
|
|
|
}
|
|
|
|
case TypeKind.VOID: {
|
2018-02-25 00:13:39 +01:00
|
|
|
compiler.error(
|
|
|
|
DiagnosticCode.Operation_not_supported,
|
|
|
|
reportNode.range
|
|
|
|
);
|
2018-01-10 13:09:05 +01:00
|
|
|
ret = module.createUnreachable();
|
|
|
|
break;
|
2018-03-12 14:06:39 +01:00
|
|
|
}
|
2017-12-15 17:23:04 +01:00
|
|
|
}
|
2018-01-10 13:09:05 +01:00
|
|
|
return ret;
|
2018-03-12 14:06:39 +01:00
|
|
|
}
|
|
|
|
case "reinterpret": { // reinterpret<T!>(value: *) -> T
|
2018-01-10 13:09:05 +01:00
|
|
|
if (operands.length != 1) {
|
2018-01-13 01:15:09 +01:00
|
|
|
if (!(typeArguments && typeArguments.length == 1)) {
|
2018-02-25 00:13:39 +01:00
|
|
|
if (typeArguments && typeArguments.length) compiler.currentType = typeArguments[0];
|
|
|
|
compiler.error(
|
|
|
|
DiagnosticCode.Expected_0_type_arguments_but_got_1,
|
|
|
|
reportNode.range, "1", typeArguments ? typeArguments.length.toString(10) : "0"
|
|
|
|
);
|
2018-01-10 13:09:05 +01:00
|
|
|
}
|
2018-02-25 00:13:39 +01:00
|
|
|
compiler.error(
|
|
|
|
DiagnosticCode.Expected_0_arguments_but_got_1,
|
|
|
|
reportNode.range, "1", operands.length.toString(10)
|
|
|
|
);
|
2018-01-10 13:09:05 +01:00
|
|
|
return module.createUnreachable();
|
2017-12-15 17:23:04 +01:00
|
|
|
}
|
2018-01-13 01:15:09 +01:00
|
|
|
if (!(typeArguments && typeArguments.length == 1)) {
|
2018-02-25 00:13:39 +01:00
|
|
|
if (typeArguments && typeArguments.length) compiler.currentType = typeArguments[0];
|
|
|
|
compiler.error(
|
|
|
|
DiagnosticCode.Expected_0_type_arguments_but_got_1,
|
|
|
|
reportNode.range, "1", typeArguments ? typeArguments.length.toString(10) : "0"
|
|
|
|
);
|
2018-01-13 01:15:09 +01:00
|
|
|
return module.createUnreachable();
|
|
|
|
}
|
|
|
|
switch (typeArguments[0].kind) {
|
2018-01-10 13:09:05 +01:00
|
|
|
case TypeKind.I32:
|
2018-03-12 14:06:39 +01:00
|
|
|
case TypeKind.U32: {
|
2018-01-13 01:15:09 +01:00
|
|
|
arg0 = compiler.compileExpression(operands[0], Type.f32);
|
|
|
|
ret = module.createUnary(UnaryOp.ReinterpretF32, arg0);
|
2018-01-10 13:09:05 +01:00
|
|
|
break;
|
2018-03-12 14:06:39 +01:00
|
|
|
}
|
2018-01-10 13:09:05 +01:00
|
|
|
case TypeKind.I64:
|
2018-03-12 14:06:39 +01:00
|
|
|
case TypeKind.U64: {
|
2018-01-13 01:15:09 +01:00
|
|
|
arg0 = compiler.compileExpression(operands[0], Type.f64);
|
|
|
|
ret = module.createUnary(UnaryOp.ReinterpretF64, arg0);
|
|
|
|
break;
|
2018-03-12 14:06:39 +01:00
|
|
|
}
|
|
|
|
case TypeKind.USIZE: {
|
2018-01-13 01:15:09 +01:00
|
|
|
if (typeArguments[0].isReference) {
|
2018-02-25 00:13:39 +01:00
|
|
|
compiler.error(
|
|
|
|
DiagnosticCode.Operation_not_supported,
|
|
|
|
reportNode.range
|
|
|
|
);
|
2018-01-13 01:15:09 +01:00
|
|
|
compiler.currentType = typeArguments[0];
|
|
|
|
return module.createUnreachable();
|
|
|
|
}
|
|
|
|
// fall-through
|
2018-03-12 14:06:39 +01:00
|
|
|
}
|
|
|
|
case TypeKind.ISIZE: {
|
2018-02-25 00:13:39 +01:00
|
|
|
arg0 = compiler.compileExpression(
|
|
|
|
operands[0],
|
|
|
|
compiler.options.isWasm64
|
|
|
|
? Type.f64
|
|
|
|
: Type.f32
|
|
|
|
);
|
|
|
|
ret = module.createUnary(
|
|
|
|
compiler.options.isWasm64
|
|
|
|
? UnaryOp.ReinterpretF64
|
|
|
|
: UnaryOp.ReinterpretF32,
|
|
|
|
arg0
|
|
|
|
);
|
2018-01-10 13:09:05 +01:00
|
|
|
break;
|
2018-03-12 14:06:39 +01:00
|
|
|
}
|
|
|
|
case TypeKind.F32: {
|
2018-01-13 01:15:09 +01:00
|
|
|
arg0 = compiler.compileExpression(operands[0], Type.u32);
|
|
|
|
ret = module.createUnary(UnaryOp.ReinterpretI32, arg0);
|
2018-01-10 13:09:05 +01:00
|
|
|
break;
|
2018-03-12 14:06:39 +01:00
|
|
|
}
|
|
|
|
case TypeKind.F64: {
|
2018-01-13 01:15:09 +01:00
|
|
|
arg0 = compiler.compileExpression(operands[0], Type.u64);
|
|
|
|
ret = module.createUnary(UnaryOp.ReinterpretI64, arg0);
|
2018-01-10 13:09:05 +01:00
|
|
|
break;
|
2018-03-12 14:06:39 +01:00
|
|
|
}
|
|
|
|
default: { // small integers and void
|
2018-02-25 00:13:39 +01:00
|
|
|
compiler.error(
|
|
|
|
DiagnosticCode.Operation_not_supported,
|
|
|
|
reportNode.range
|
|
|
|
);
|
2018-01-10 13:09:05 +01:00
|
|
|
ret = module.createUnreachable();
|
|
|
|
break;
|
2018-03-12 14:06:39 +01:00
|
|
|
}
|
2017-12-15 17:23:04 +01:00
|
|
|
}
|
2018-01-13 01:15:09 +01:00
|
|
|
compiler.currentType = typeArguments[0];
|
2018-01-10 13:09:05 +01:00
|
|
|
return ret;
|
2018-03-12 14:06:39 +01:00
|
|
|
}
|
|
|
|
case "sqrt": { // sqrt<T?>(value: T) -> T
|
2018-01-10 13:09:05 +01:00
|
|
|
if (operands.length != 1) {
|
|
|
|
if (typeArguments) {
|
2018-02-25 00:13:39 +01:00
|
|
|
if (typeArguments.length) compiler.currentType = typeArguments[0];
|
|
|
|
if (typeArguments.length != 1) {
|
|
|
|
compiler.error(
|
|
|
|
DiagnosticCode.Expected_0_type_arguments_but_got_1,
|
|
|
|
reportNode.range, "1", typeArguments.length.toString(10)
|
|
|
|
);
|
|
|
|
}
|
2018-01-10 13:09:05 +01:00
|
|
|
}
|
2018-02-25 00:13:39 +01:00
|
|
|
compiler.error(
|
|
|
|
DiagnosticCode.Expected_0_arguments_but_got_1,
|
|
|
|
reportNode.range, "1", operands.length.toString(10)
|
|
|
|
);
|
2017-12-08 04:03:44 +01:00
|
|
|
return module.createUnreachable();
|
2017-12-05 01:45:15 +01:00
|
|
|
}
|
2018-01-10 13:09:05 +01:00
|
|
|
if (typeArguments) {
|
|
|
|
if (typeArguments.length != 1) {
|
2018-02-25 00:13:39 +01:00
|
|
|
if (typeArguments.length) compiler.currentType = typeArguments[0];
|
|
|
|
compiler.error(
|
|
|
|
DiagnosticCode.Expected_0_type_arguments_but_got_1,
|
|
|
|
reportNode.range, "1", typeArguments.length.toString(10)
|
|
|
|
);
|
2018-01-10 13:09:05 +01:00
|
|
|
return module.createUnreachable();
|
|
|
|
}
|
|
|
|
arg0 = compiler.compileExpression(operands[0], typeArguments[0]);
|
2018-02-25 00:13:39 +01:00
|
|
|
} else {
|
2018-01-10 13:09:05 +01:00
|
|
|
arg0 = compiler.compileExpression(operands[0], Type.f64, ConversionKind.NONE);
|
2018-02-25 00:13:39 +01:00
|
|
|
}
|
2018-03-12 14:06:39 +01:00
|
|
|
switch (compiler.currentType.kind) { // TODO: integer versions (that return f64 or convert)?
|
|
|
|
case TypeKind.F32: {
|
2018-01-10 13:09:05 +01:00
|
|
|
ret = module.createUnary(UnaryOp.SqrtF32, arg0);
|
|
|
|
break;
|
2018-03-12 14:06:39 +01:00
|
|
|
}
|
|
|
|
case TypeKind.F64: {
|
2018-01-10 13:09:05 +01:00
|
|
|
ret = module.createUnary(UnaryOp.SqrtF64, arg0);
|
|
|
|
break;
|
2018-03-12 14:06:39 +01:00
|
|
|
}
|
2018-01-10 13:09:05 +01:00
|
|
|
// case TypeKind.VOID:
|
2018-03-12 14:06:39 +01:00
|
|
|
default: {
|
2018-02-25 00:13:39 +01:00
|
|
|
compiler.error(
|
|
|
|
DiagnosticCode.Operation_not_supported,
|
|
|
|
reportNode.range
|
|
|
|
);
|
2018-01-10 13:09:05 +01:00
|
|
|
ret = module.createUnreachable();
|
|
|
|
break;
|
2018-03-12 14:06:39 +01:00
|
|
|
}
|
2018-01-10 13:09:05 +01:00
|
|
|
}
|
|
|
|
return ret;
|
2018-03-12 14:06:39 +01:00
|
|
|
}
|
|
|
|
case "trunc": { // trunc<T?>(value: T) -> T
|
2018-01-10 13:09:05 +01:00
|
|
|
if (operands.length != 1) {
|
|
|
|
if (typeArguments) {
|
2018-02-25 00:13:39 +01:00
|
|
|
if (typeArguments.length) compiler.currentType = typeArguments[0];
|
|
|
|
if (typeArguments.length != 1) {
|
|
|
|
compiler.error(
|
|
|
|
DiagnosticCode.Expected_0_type_arguments_but_got_1,
|
|
|
|
reportNode.range, "1", typeArguments.length.toString(10)
|
|
|
|
);
|
|
|
|
}
|
2018-01-10 13:09:05 +01:00
|
|
|
}
|
2018-02-25 00:13:39 +01:00
|
|
|
compiler.error(
|
|
|
|
DiagnosticCode.Expected_0_arguments_but_got_1,
|
|
|
|
reportNode.range, "1", operands.length.toString(10)
|
|
|
|
);
|
2017-12-08 04:03:44 +01:00
|
|
|
return module.createUnreachable();
|
2017-12-05 01:45:15 +01:00
|
|
|
}
|
2018-01-10 13:09:05 +01:00
|
|
|
if (typeArguments && typeArguments.length) {
|
|
|
|
compiler.currentType = typeArguments[0];
|
|
|
|
if (typeArguments.length != 1) {
|
2018-02-25 00:13:39 +01:00
|
|
|
if (typeArguments.length) compiler.currentType = typeArguments[0];
|
|
|
|
compiler.error(
|
|
|
|
DiagnosticCode.Expected_0_type_arguments_but_got_1,
|
|
|
|
reportNode.range, "1", typeArguments.length.toString(10)
|
|
|
|
);
|
2018-01-10 13:09:05 +01:00
|
|
|
return module.createUnreachable();
|
|
|
|
}
|
|
|
|
arg0 = compiler.compileExpression(operands[0], typeArguments[0]);
|
2018-02-25 00:13:39 +01:00
|
|
|
} else {
|
2018-01-10 13:09:05 +01:00
|
|
|
arg0 = compiler.compileExpression(operands[0], Type.f64, ConversionKind.NONE);
|
2018-02-25 00:13:39 +01:00
|
|
|
}
|
2018-01-10 13:09:05 +01:00
|
|
|
switch (compiler.currentType.kind) {
|
2018-03-12 14:06:39 +01:00
|
|
|
case TypeKind.USIZE: {
|
2018-01-10 13:09:05 +01:00
|
|
|
if (compiler.currentType.isReference) {
|
2018-02-25 00:13:39 +01:00
|
|
|
compiler.error(
|
|
|
|
DiagnosticCode.Operation_not_supported,
|
|
|
|
reportNode.range
|
|
|
|
);
|
2018-01-10 13:09:05 +01:00
|
|
|
ret = module.createUnreachable();
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
// fall-through
|
2018-03-12 14:06:39 +01:00
|
|
|
}
|
|
|
|
default: { // any integer
|
2018-01-10 13:09:05 +01:00
|
|
|
ret = arg0;
|
|
|
|
break;
|
2018-03-12 14:06:39 +01:00
|
|
|
}
|
2018-01-10 13:09:05 +01:00
|
|
|
// TODO: truncate to contextual type directly (if not void etc.)?
|
2018-03-12 14:06:39 +01:00
|
|
|
case TypeKind.F32: {
|
2018-01-10 13:09:05 +01:00
|
|
|
ret = module.createUnary(UnaryOp.TruncF32, arg0);
|
|
|
|
break;
|
2018-03-12 14:06:39 +01:00
|
|
|
}
|
|
|
|
case TypeKind.F64: {
|
2018-01-10 13:09:05 +01:00
|
|
|
ret = module.createUnary(UnaryOp.TruncF64, arg0);
|
|
|
|
break;
|
2018-03-12 14:06:39 +01:00
|
|
|
}
|
|
|
|
case TypeKind.VOID: {
|
2018-02-25 00:13:39 +01:00
|
|
|
compiler.error(
|
|
|
|
DiagnosticCode.Operation_not_supported,
|
|
|
|
reportNode.range
|
|
|
|
);
|
2018-01-10 13:09:05 +01:00
|
|
|
ret = module.createUnreachable();
|
|
|
|
break;
|
2018-03-12 14:06:39 +01:00
|
|
|
}
|
2018-01-10 13:09:05 +01:00
|
|
|
}
|
|
|
|
return ret;
|
2018-03-12 14:06:39 +01:00
|
|
|
}
|
2017-12-05 01:45:15 +01:00
|
|
|
|
2017-12-15 17:23:04 +01:00
|
|
|
// memory access
|
|
|
|
|
2018-03-12 14:06:39 +01:00
|
|
|
case "load": { // load<T!>(offset: usize, constantOffset?: usize) -> *
|
2018-01-21 16:34:50 +01:00
|
|
|
if (operands.length < 1 || operands.length > 2) {
|
2018-02-25 00:13:39 +01:00
|
|
|
if (!(typeArguments && typeArguments.length == 1)) {
|
|
|
|
compiler.error(
|
|
|
|
DiagnosticCode.Expected_0_type_arguments_but_got_1,
|
|
|
|
reportNode.range, "1", typeArguments ? typeArguments.length.toString(10) : "0"
|
|
|
|
);
|
|
|
|
}
|
|
|
|
if (operands.length < 1) {
|
|
|
|
compiler.error(
|
|
|
|
DiagnosticCode.Expected_at_least_0_arguments_but_got_1,
|
|
|
|
reportNode.range, "1", operands.length.toString(10)
|
|
|
|
);
|
|
|
|
} else {
|
|
|
|
compiler.error(
|
|
|
|
DiagnosticCode.Expected_0_arguments_but_got_1,
|
|
|
|
reportNode.range, "2", operands.length.toString(10)
|
|
|
|
);
|
|
|
|
}
|
2017-12-08 04:03:44 +01:00
|
|
|
return module.createUnreachable();
|
2018-01-10 13:09:05 +01:00
|
|
|
}
|
|
|
|
if (!(typeArguments && typeArguments.length == 1)) {
|
2018-02-25 00:13:39 +01:00
|
|
|
if (typeArguments && typeArguments.length) compiler.currentType = typeArguments[0];
|
|
|
|
compiler.error(
|
|
|
|
DiagnosticCode.Expected_0_type_arguments_but_got_1,
|
|
|
|
reportNode.range, "1", typeArguments ? typeArguments.length.toString(10) : "0"
|
|
|
|
);
|
2018-01-10 13:09:05 +01:00
|
|
|
return module.createUnreachable();
|
|
|
|
}
|
2018-01-21 17:52:44 +01:00
|
|
|
arg0 = compiler.compileExpression(operands[0], compiler.options.usizeType);
|
2018-01-21 16:34:50 +01:00
|
|
|
offset = operands.length == 2 ? evaluateConstantOffset(compiler, operands[1]) : 0; // reports
|
2018-02-25 00:13:39 +01:00
|
|
|
if (offset < 0) { // reported in evaluateConstantOffset
|
2018-01-21 16:34:50 +01:00
|
|
|
return module.createUnreachable();
|
2018-02-25 00:13:39 +01:00
|
|
|
}
|
2018-03-01 19:42:07 +01:00
|
|
|
compiler.currentType = typeArguments[0];
|
2018-02-25 00:13:39 +01:00
|
|
|
return module.createLoad(
|
|
|
|
typeArguments[0].byteSize,
|
|
|
|
typeArguments[0].is(TypeFlags.SIGNED | TypeFlags.INTEGER),
|
|
|
|
arg0,
|
|
|
|
typeArguments[0].is(TypeFlags.INTEGER) &&
|
|
|
|
contextualType.is(TypeFlags.INTEGER) &&
|
2018-03-01 19:42:07 +01:00
|
|
|
contextualType.size > typeArguments[0].size
|
2018-01-23 15:44:25 +01:00
|
|
|
? (compiler.currentType = contextualType).toNativeType()
|
2018-02-25 00:13:39 +01:00
|
|
|
: (compiler.currentType = typeArguments[0]).toNativeType(),
|
|
|
|
offset
|
|
|
|
);
|
2018-03-12 14:06:39 +01:00
|
|
|
}
|
|
|
|
case "store": { // store<T!>(offset: usize, value: *, constantOffset?: usize) -> void
|
2017-12-05 01:45:15 +01:00
|
|
|
compiler.currentType = Type.void;
|
2018-01-21 16:34:50 +01:00
|
|
|
if (operands.length < 2 || operands.length > 3) {
|
2018-02-25 00:13:39 +01:00
|
|
|
if (!(typeArguments && typeArguments.length == 1)) {
|
|
|
|
compiler.error(
|
|
|
|
DiagnosticCode.Expected_0_type_arguments_but_got_1,
|
|
|
|
reportNode.range, "1", typeArguments ? typeArguments.length.toString(10) : "0"
|
|
|
|
);
|
|
|
|
}
|
|
|
|
if (operands.length < 2) {
|
|
|
|
compiler.error(
|
|
|
|
DiagnosticCode.Expected_at_least_0_arguments_but_got_1,
|
|
|
|
reportNode.range, "2", operands.length.toString(10)
|
|
|
|
);
|
|
|
|
} else {
|
|
|
|
compiler.error(
|
|
|
|
DiagnosticCode.Expected_0_arguments_but_got_1,
|
|
|
|
reportNode.range, "3", operands.length.toString(10)
|
|
|
|
);
|
|
|
|
}
|
2017-12-08 04:03:44 +01:00
|
|
|
return module.createUnreachable();
|
2018-01-10 13:09:05 +01:00
|
|
|
}
|
2018-01-23 15:44:25 +01:00
|
|
|
if (!(typeArguments && typeArguments.length == 1)) {
|
2018-02-25 00:13:39 +01:00
|
|
|
compiler.error(
|
|
|
|
DiagnosticCode.Expected_0_type_arguments_but_got_1,
|
|
|
|
reportNode.range, "1", typeArguments ? typeArguments.length.toString(10) : "0"
|
|
|
|
);
|
2018-01-23 15:44:25 +01:00
|
|
|
return module.createUnreachable();
|
2018-01-10 13:09:05 +01:00
|
|
|
}
|
2018-01-23 15:44:25 +01:00
|
|
|
arg0 = compiler.compileExpression(operands[0], compiler.options.usizeType);
|
2018-02-25 00:13:39 +01:00
|
|
|
arg1 = compiler.compileExpression(
|
|
|
|
operands[1],
|
|
|
|
typeArguments[0],
|
2018-01-23 15:44:25 +01:00
|
|
|
typeArguments[0].is(TypeFlags.INTEGER)
|
|
|
|
? ConversionKind.NONE // wraps a larger integer type to a smaller one, i.e. i32.store8
|
|
|
|
: ConversionKind.IMPLICIT
|
|
|
|
);
|
2018-02-25 00:13:39 +01:00
|
|
|
if (
|
|
|
|
compiler.currentType.is(TypeFlags.INTEGER) &&
|
|
|
|
typeArguments[0].is(TypeFlags.INTEGER) &&
|
|
|
|
typeArguments[0].size > compiler.currentType.size
|
|
|
|
) {
|
|
|
|
arg1 = compiler.convertExpression(
|
|
|
|
arg1,
|
|
|
|
compiler.currentType, typeArguments[0],
|
|
|
|
ConversionKind.IMPLICIT,
|
|
|
|
operands[1]
|
|
|
|
);
|
2018-01-23 15:44:25 +01:00
|
|
|
type = typeArguments[0];
|
2018-02-25 00:13:39 +01:00
|
|
|
} else {
|
2018-01-23 15:44:25 +01:00
|
|
|
type = compiler.currentType;
|
2018-02-25 00:13:39 +01:00
|
|
|
}
|
2018-01-21 16:34:50 +01:00
|
|
|
offset = operands.length == 3 ? evaluateConstantOffset(compiler, operands[2]) : 0; // reports
|
2018-02-25 00:13:39 +01:00
|
|
|
if (offset < 0) { // reported in evaluateConstantOffset
|
2018-01-21 16:34:50 +01:00
|
|
|
return module.createUnreachable();
|
2018-02-25 00:13:39 +01:00
|
|
|
}
|
2017-12-05 01:45:15 +01:00
|
|
|
compiler.currentType = Type.void;
|
2018-01-23 15:44:25 +01:00
|
|
|
return module.createStore(typeArguments[0].byteSize, arg0, arg1, type.toNativeType(), offset);
|
2018-03-12 14:06:39 +01:00
|
|
|
}
|
|
|
|
case "sizeof": { // sizeof<T!>() -> usize
|
2018-01-21 17:52:44 +01:00
|
|
|
compiler.currentType = compiler.options.usizeType;
|
2018-01-10 13:09:05 +01:00
|
|
|
if (operands.length != 0) {
|
2018-02-25 00:13:39 +01:00
|
|
|
if (!(typeArguments && typeArguments.length == 1)) {
|
|
|
|
compiler.error(
|
|
|
|
DiagnosticCode.Expected_0_type_arguments_but_got_1,
|
|
|
|
reportNode.range, "1", typeArguments ? typeArguments.length.toString(10) : "0"
|
|
|
|
);
|
|
|
|
}
|
|
|
|
compiler.error(
|
|
|
|
DiagnosticCode.Expected_0_arguments_but_got_1,
|
|
|
|
reportNode.range, "0", operands.length.toString(10)
|
|
|
|
);
|
2017-12-08 04:03:44 +01:00
|
|
|
return module.createUnreachable();
|
2018-01-10 13:09:05 +01:00
|
|
|
}
|
|
|
|
if (typeArguments) {
|
|
|
|
if (typeArguments.length != 1) {
|
2018-02-25 00:13:39 +01:00
|
|
|
compiler.error(
|
|
|
|
DiagnosticCode.Expected_0_type_arguments_but_got_1,
|
|
|
|
reportNode.range, "1", typeArguments.length.toString(10)
|
|
|
|
);
|
2018-01-10 13:09:05 +01:00
|
|
|
return module.createUnreachable();
|
|
|
|
}
|
2018-02-25 00:13:39 +01:00
|
|
|
ret = compiler.options.isWasm64
|
|
|
|
? module.createI64(typeArguments[0].byteSize, 0)
|
|
|
|
: module.createI32(typeArguments[0].byteSize);
|
2018-01-10 13:09:05 +01:00
|
|
|
} else {
|
2018-02-25 00:13:39 +01:00
|
|
|
compiler.error(
|
|
|
|
DiagnosticCode.Expected_0_type_arguments_but_got_1,
|
|
|
|
reportNode.range, "1", "0"
|
|
|
|
);
|
2018-01-10 13:09:05 +01:00
|
|
|
return module.createUnreachable();
|
|
|
|
}
|
|
|
|
return ret;
|
2018-03-12 14:06:39 +01:00
|
|
|
}
|
2017-12-15 17:23:04 +01:00
|
|
|
|
|
|
|
// control flow
|
2017-12-05 01:45:15 +01:00
|
|
|
|
2018-03-12 14:06:39 +01:00
|
|
|
case "select": { // select<T?>(ifTrue: T, ifFalse: T, condition: bool) -> T
|
2018-01-10 13:09:05 +01:00
|
|
|
if (operands.length != 3) {
|
|
|
|
if (typeArguments) {
|
2018-02-25 00:13:39 +01:00
|
|
|
if (typeArguments.length) compiler.currentType = typeArguments[0];
|
|
|
|
if (typeArguments.length != 1) {
|
|
|
|
compiler.error(
|
|
|
|
DiagnosticCode.Expected_0_type_arguments_but_got_1,
|
|
|
|
reportNode.range, "1", typeArguments.length.toString(10)
|
|
|
|
);
|
|
|
|
}
|
2018-01-10 13:09:05 +01:00
|
|
|
}
|
2018-02-25 00:13:39 +01:00
|
|
|
compiler.error(
|
|
|
|
DiagnosticCode.Expected_0_arguments_but_got_1,
|
|
|
|
reportNode.range, "3", operands.length.toString(10)
|
|
|
|
);
|
2017-12-08 04:03:44 +01:00
|
|
|
return module.createUnreachable();
|
2017-12-05 01:45:15 +01:00
|
|
|
}
|
2018-01-10 13:09:05 +01:00
|
|
|
if (typeArguments) {
|
|
|
|
if (typeArguments.length != 1) {
|
2018-02-25 00:13:39 +01:00
|
|
|
if (typeArguments.length) compiler.currentType = typeArguments[0];
|
|
|
|
compiler.error(
|
|
|
|
DiagnosticCode.Expected_0_type_arguments_but_got_1,
|
|
|
|
reportNode.range, "1", typeArguments.length.toString(10)
|
|
|
|
);
|
2018-01-10 13:09:05 +01:00
|
|
|
return module.createUnreachable();
|
|
|
|
}
|
|
|
|
arg0 = compiler.compileExpression(operands[0], typeArguments[0]);
|
2018-02-25 00:13:39 +01:00
|
|
|
} else {
|
2018-01-10 13:09:05 +01:00
|
|
|
arg0 = compiler.compileExpression(operands[0], Type.i32, ConversionKind.NONE);
|
2018-02-25 00:13:39 +01:00
|
|
|
}
|
2018-01-10 13:09:05 +01:00
|
|
|
arg1 = compiler.compileExpression(operands[1], type = compiler.currentType);
|
|
|
|
arg2 = compiler.compileExpression(operands[2], Type.bool);
|
|
|
|
compiler.currentType = type;
|
|
|
|
switch (compiler.currentType.kind) {
|
2018-03-12 14:06:39 +01:00
|
|
|
default: { // any value type
|
2018-01-10 13:09:05 +01:00
|
|
|
ret = module.createSelect(arg0, arg1, arg2);
|
|
|
|
break;
|
2018-03-12 14:06:39 +01:00
|
|
|
}
|
|
|
|
case TypeKind.VOID: {
|
2018-02-25 00:13:39 +01:00
|
|
|
compiler.error(
|
|
|
|
DiagnosticCode.Operation_not_supported,
|
|
|
|
reportNode.range
|
|
|
|
);
|
2018-01-10 13:09:05 +01:00
|
|
|
ret = module.createUnreachable();
|
|
|
|
break;
|
2018-03-12 14:06:39 +01:00
|
|
|
}
|
2018-01-10 13:09:05 +01:00
|
|
|
}
|
|
|
|
return ret;
|
2018-03-12 14:06:39 +01:00
|
|
|
}
|
|
|
|
case "unreachable": { // unreachable() -> *
|
2018-02-25 00:13:39 +01:00
|
|
|
if (operands.length != 0) {
|
|
|
|
compiler.error(
|
|
|
|
DiagnosticCode.Expected_0_arguments_but_got_1,
|
|
|
|
reportNode.range, "0", operands.length.toString(10)
|
|
|
|
);
|
|
|
|
}
|
|
|
|
if (typeArguments) {
|
|
|
|
compiler.error(
|
|
|
|
DiagnosticCode.Type_0_is_not_generic,
|
|
|
|
reportNode.range, prototype.internalName
|
|
|
|
);
|
|
|
|
}
|
2017-12-15 17:23:04 +01:00
|
|
|
return module.createUnreachable();
|
2018-03-12 14:06:39 +01:00
|
|
|
}
|
2017-12-15 17:23:04 +01:00
|
|
|
|
|
|
|
// host operations
|
|
|
|
|
2018-03-12 14:06:39 +01:00
|
|
|
case "current_memory": { // current_memory() -> i32
|
2017-12-05 01:45:15 +01:00
|
|
|
compiler.currentType = Type.i32;
|
2018-02-25 00:13:39 +01:00
|
|
|
if (operands.length != 0) {
|
|
|
|
compiler.error(
|
|
|
|
DiagnosticCode.Expected_0_arguments_but_got_1,
|
|
|
|
reportNode.range, "0", operands.length.toString(10)
|
|
|
|
);
|
|
|
|
}
|
|
|
|
if (typeArguments) {
|
|
|
|
compiler.error(
|
|
|
|
DiagnosticCode.Type_0_is_not_generic,
|
|
|
|
reportNode.range, prototype.internalName
|
|
|
|
);
|
|
|
|
}
|
2017-12-08 04:03:44 +01:00
|
|
|
return module.createHost(HostOp.CurrentMemory);
|
2018-03-12 14:06:39 +01:00
|
|
|
}
|
|
|
|
case "grow_memory": { // grow_memory(pages: i32) -> i32
|
2017-12-05 01:45:15 +01:00
|
|
|
compiler.currentType = Type.i32;
|
2018-01-10 13:09:05 +01:00
|
|
|
if (operands.length != 1) {
|
2018-02-25 00:13:39 +01:00
|
|
|
compiler.error(
|
|
|
|
DiagnosticCode.Expected_0_arguments_but_got_1,
|
|
|
|
reportNode.range, "0", operands.length.toString(10)
|
|
|
|
);
|
2018-01-10 13:09:05 +01:00
|
|
|
arg0 = module.createUnreachable();
|
2018-02-25 00:13:39 +01:00
|
|
|
} else {
|
2018-01-10 13:09:05 +01:00
|
|
|
arg0 = compiler.compileExpression(operands[0], Type.i32);
|
2018-02-25 00:13:39 +01:00
|
|
|
}
|
|
|
|
if (typeArguments) {
|
|
|
|
compiler.error(
|
|
|
|
DiagnosticCode.Type_0_is_not_generic,
|
|
|
|
reportNode.range, prototype.internalName
|
|
|
|
);
|
|
|
|
}
|
2017-12-08 04:03:44 +01:00
|
|
|
return module.createHost(HostOp.GrowMemory, null, [ arg0 ]);
|
2018-03-12 14:06:39 +01:00
|
|
|
}
|
2018-02-25 00:13:39 +01:00
|
|
|
// see: https://github.com/WebAssembly/bulk-memory-operations
|
2018-03-12 14:06:39 +01:00
|
|
|
case "move_memory": { // move_memory(dest: usize, src: usize: n: usize) -> void
|
2018-02-25 00:13:39 +01:00
|
|
|
if (typeArguments) {
|
|
|
|
compiler.error(
|
|
|
|
DiagnosticCode.Type_0_is_not_generic,
|
|
|
|
reportNode.range, prototype.internalName
|
|
|
|
);
|
|
|
|
}
|
2018-01-10 13:09:05 +01:00
|
|
|
if (operands.length != 3) {
|
2018-02-25 00:13:39 +01:00
|
|
|
compiler.error(
|
|
|
|
DiagnosticCode.Expected_0_arguments_but_got_1,
|
|
|
|
reportNode.range, "3", operands.length.toString(10)
|
|
|
|
);
|
2018-01-10 13:09:05 +01:00
|
|
|
compiler.currentType = Type.void;
|
2017-12-19 17:49:15 +01:00
|
|
|
return module.createUnreachable();
|
2018-01-10 13:09:05 +01:00
|
|
|
}
|
2018-01-21 17:52:44 +01:00
|
|
|
arg0 = compiler.compileExpression(operands[0], compiler.options.usizeType);
|
|
|
|
arg1 = compiler.compileExpression(operands[1], compiler.options.usizeType);
|
|
|
|
arg2 = compiler.compileExpression(operands[2], compiler.options.usizeType);
|
2017-12-19 17:49:15 +01:00
|
|
|
compiler.currentType = Type.void;
|
2018-01-10 13:09:05 +01:00
|
|
|
throw new Error("not implemented");
|
|
|
|
// return module.createHost(HostOp.MoveMemory, null, [ arg0, arg1, arg2 ]);
|
2018-03-12 14:06:39 +01:00
|
|
|
}
|
|
|
|
case "set_memory": { // set_memory(dest: usize, value: u32, n: usize) -> void
|
2018-02-25 00:13:39 +01:00
|
|
|
if (typeArguments) {
|
|
|
|
compiler.error(
|
|
|
|
DiagnosticCode.Type_0_is_not_generic,
|
|
|
|
reportNode.range, prototype.internalName
|
|
|
|
);
|
|
|
|
}
|
2018-01-10 13:09:05 +01:00
|
|
|
if (operands.length != 3) {
|
2018-02-25 00:13:39 +01:00
|
|
|
compiler.error(
|
|
|
|
DiagnosticCode.Expected_0_arguments_but_got_1,
|
|
|
|
reportNode.range, "3", operands.length.toString(10)
|
|
|
|
);
|
2018-01-10 13:09:05 +01:00
|
|
|
compiler.currentType = Type.void;
|
2017-12-19 17:49:15 +01:00
|
|
|
return module.createUnreachable();
|
2018-01-10 13:09:05 +01:00
|
|
|
}
|
2018-01-21 17:52:44 +01:00
|
|
|
arg0 = compiler.compileExpression(operands[0], compiler.options.usizeType);
|
2017-12-19 17:49:15 +01:00
|
|
|
arg1 = compiler.compileExpression(operands[1], Type.u32);
|
2018-01-21 17:52:44 +01:00
|
|
|
arg2 = compiler.compileExpression(operands[2], compiler.options.usizeType);
|
2017-12-19 17:49:15 +01:00
|
|
|
compiler.currentType = Type.void;
|
2018-01-10 13:09:05 +01:00
|
|
|
throw new Error("not implemented");
|
|
|
|
// return module.createHost(HostOp.SetMemory, null, [ arg0, arg1, arg2 ]);
|
2018-03-12 14:06:39 +01:00
|
|
|
}
|
2017-12-19 17:49:15 +01:00
|
|
|
|
2018-01-10 13:09:05 +01:00
|
|
|
// other
|
2017-12-08 04:03:44 +01:00
|
|
|
|
2018-03-12 14:06:39 +01:00
|
|
|
case "changetype": { // changetype<T!>(value: *) -> T
|
2018-01-10 13:09:05 +01:00
|
|
|
if (!(typeArguments && typeArguments.length == 1)) {
|
2018-02-25 00:13:39 +01:00
|
|
|
if (typeArguments && typeArguments.length) compiler.currentType = typeArguments[0];
|
|
|
|
compiler.error(
|
|
|
|
DiagnosticCode.Expected_0_type_arguments_but_got_1,
|
|
|
|
reportNode.range, "1", typeArguments ? typeArguments.length.toString(10) : "0"
|
|
|
|
);
|
2017-12-08 04:03:44 +01:00
|
|
|
return module.createUnreachable();
|
2018-01-10 13:09:05 +01:00
|
|
|
} else if (typeArguments[0].kind != TypeKind.USIZE) { // any usize
|
2018-02-25 00:13:39 +01:00
|
|
|
compiler.error(
|
|
|
|
DiagnosticCode.Operation_not_supported,
|
|
|
|
reportNode.range
|
|
|
|
);
|
2018-01-10 13:09:05 +01:00
|
|
|
compiler.currentType = typeArguments[0];
|
2017-12-15 17:23:04 +01:00
|
|
|
return module.createUnreachable();
|
|
|
|
}
|
2018-01-10 13:09:05 +01:00
|
|
|
if (operands.length != 1) {
|
2018-02-25 00:13:39 +01:00
|
|
|
compiler.error(
|
|
|
|
DiagnosticCode.Expected_0_arguments_but_got_1,
|
|
|
|
reportNode.range, "1", operands.length.toString(10)
|
|
|
|
);
|
2018-01-10 13:09:05 +01:00
|
|
|
compiler.currentType = typeArguments[0];
|
2017-12-15 17:23:04 +01:00
|
|
|
return module.createUnreachable();
|
|
|
|
}
|
2018-02-25 00:13:39 +01:00
|
|
|
arg0 = compiler.compileExpression(
|
|
|
|
operands[0],
|
|
|
|
compiler.options.usizeType,
|
|
|
|
ConversionKind.NONE
|
|
|
|
);
|
2018-01-10 13:09:05 +01:00
|
|
|
compiler.currentType = typeArguments[0];
|
|
|
|
if (compiler.currentType.kind != TypeKind.USIZE) {
|
2018-02-25 00:13:39 +01:00
|
|
|
compiler.error(
|
|
|
|
DiagnosticCode.Operation_not_supported,
|
|
|
|
reportNode.range
|
|
|
|
);
|
2017-12-15 17:23:04 +01:00
|
|
|
return module.createUnreachable();
|
|
|
|
}
|
2018-02-02 03:07:54 +01:00
|
|
|
// if (reportNode.range.source.sourceKind != SourceKind.STDLIB)
|
|
|
|
// compiler.warning(DiagnosticCode.Operation_is_unsafe, reportNode.range);
|
2018-01-10 13:09:05 +01:00
|
|
|
return arg0; // any usize to any usize
|
2018-03-12 14:06:39 +01:00
|
|
|
}
|
|
|
|
case "assert": { // assert<T?>(isTrueish: T, message?: string) -> T with T != null
|
2018-01-10 13:09:05 +01:00
|
|
|
if (operands.length < 1 || operands.length > 2) {
|
|
|
|
if (typeArguments) {
|
2018-02-25 00:13:39 +01:00
|
|
|
if (typeArguments.length) compiler.currentType = typeArguments[0].nonNullableType;
|
|
|
|
if (typeArguments.length != 1) {
|
|
|
|
compiler.error(
|
|
|
|
DiagnosticCode.Expected_0_type_arguments_but_got_1,
|
|
|
|
reportNode.range, "1", typeArguments.length.toString(10)
|
|
|
|
);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (operands.length < 1) {
|
|
|
|
compiler.error(
|
|
|
|
DiagnosticCode.Expected_at_least_0_arguments_but_got_1,
|
|
|
|
reportNode.range, "1", operands.length.toString(10)
|
|
|
|
);
|
|
|
|
} else if (operands.length > 2) {
|
|
|
|
compiler.error(
|
|
|
|
DiagnosticCode.Expected_0_arguments_but_got_1,
|
|
|
|
reportNode.range, "2", operands.length.toString(10)
|
|
|
|
);
|
2018-01-10 13:09:05 +01:00
|
|
|
}
|
2017-12-08 04:03:44 +01:00
|
|
|
return module.createUnreachable();
|
2018-01-10 13:09:05 +01:00
|
|
|
}
|
|
|
|
if (typeArguments) {
|
2018-02-25 00:13:39 +01:00
|
|
|
if (typeArguments.length) compiler.currentType = typeArguments[0].nonNullableType;
|
2018-01-10 13:09:05 +01:00
|
|
|
if (typeArguments.length != 1) {
|
2018-02-25 00:13:39 +01:00
|
|
|
compiler.error(
|
|
|
|
DiagnosticCode.Expected_0_type_arguments_but_got_1,
|
|
|
|
reportNode.range, "1", typeArguments.length.toString(10)
|
|
|
|
);
|
2018-01-10 13:09:05 +01:00
|
|
|
return module.createUnreachable();
|
|
|
|
}
|
|
|
|
arg0 = compiler.compileExpression(operands[0], typeArguments[0]);
|
2018-02-25 00:13:39 +01:00
|
|
|
} else {
|
2018-03-01 19:42:07 +01:00
|
|
|
arg0 = compiler.compileExpressionRetainType(operands[0], Type.i32);
|
2018-02-25 00:13:39 +01:00
|
|
|
}
|
2018-01-10 13:09:05 +01:00
|
|
|
|
|
|
|
type = compiler.currentType;
|
|
|
|
compiler.currentType = type.nonNullableType;
|
|
|
|
|
|
|
|
// just return ifTrueish if assertions are disabled, or simplify if dropped anyway
|
|
|
|
if (compiler.options.noAssert) {
|
|
|
|
if (contextualType == Type.void) {
|
|
|
|
compiler.currentType = Type.void;
|
|
|
|
return module.createNop();
|
|
|
|
}
|
2017-12-08 04:03:44 +01:00
|
|
|
return arg0;
|
|
|
|
}
|
2017-12-05 01:45:15 +01:00
|
|
|
|
2018-03-13 02:32:10 +01:00
|
|
|
let abort = compileAbort(compiler, operands.length == 2 ? operands[1] : null, reportNode);
|
2018-01-27 17:02:52 +01:00
|
|
|
|
2018-01-27 16:23:00 +01:00
|
|
|
compiler.currentType = type.nonNullableType;
|
|
|
|
|
2018-01-10 13:09:05 +01:00
|
|
|
if (contextualType == Type.void) { // simplify if dropped anyway
|
|
|
|
switch (compiler.currentType.kind) {
|
2018-03-12 14:06:39 +01:00
|
|
|
default: { // any integer up to 32-bits incl. bool
|
2018-01-10 13:09:05 +01:00
|
|
|
ret = module.createIf(
|
|
|
|
module.createUnary(UnaryOp.EqzI32,
|
|
|
|
arg0
|
|
|
|
),
|
2018-01-27 16:23:00 +01:00
|
|
|
abort
|
2018-01-10 13:09:05 +01:00
|
|
|
);
|
|
|
|
break;
|
2018-03-12 14:06:39 +01:00
|
|
|
}
|
2018-01-10 13:09:05 +01:00
|
|
|
case TypeKind.I64:
|
2018-03-12 14:06:39 +01:00
|
|
|
case TypeKind.U64: {
|
2018-01-10 13:09:05 +01:00
|
|
|
ret = module.createIf(
|
|
|
|
module.createUnary(UnaryOp.EqzI64,
|
|
|
|
arg0
|
|
|
|
),
|
2018-01-27 16:23:00 +01:00
|
|
|
abort
|
2018-01-10 13:09:05 +01:00
|
|
|
);
|
|
|
|
break;
|
2018-03-12 14:06:39 +01:00
|
|
|
}
|
2018-01-10 13:09:05 +01:00
|
|
|
case TypeKind.ISIZE:
|
2018-03-12 14:06:39 +01:00
|
|
|
case TypeKind.USIZE: {
|
2018-01-10 13:09:05 +01:00
|
|
|
ret = module.createIf(
|
2018-02-25 00:13:39 +01:00
|
|
|
module.createUnary(
|
|
|
|
compiler.options.isWasm64
|
|
|
|
? UnaryOp.EqzI64
|
|
|
|
: UnaryOp.EqzI32,
|
2018-01-10 13:09:05 +01:00
|
|
|
arg0
|
|
|
|
),
|
2018-01-27 16:23:00 +01:00
|
|
|
abort
|
2018-01-10 13:09:05 +01:00
|
|
|
);
|
|
|
|
break;
|
2018-03-12 14:06:39 +01:00
|
|
|
}
|
2018-01-10 13:09:05 +01:00
|
|
|
// TODO: also check for NaN in float assertions, as in `Boolean(NaN) -> false`?
|
2018-03-12 14:06:39 +01:00
|
|
|
case TypeKind.F32: {
|
2018-01-10 13:09:05 +01:00
|
|
|
ret = module.createIf(
|
|
|
|
module.createBinary(BinaryOp.EqF32,
|
|
|
|
arg0,
|
|
|
|
module.createF32(0)
|
|
|
|
),
|
2018-01-27 16:23:00 +01:00
|
|
|
abort
|
2018-01-10 13:09:05 +01:00
|
|
|
);
|
|
|
|
break;
|
2018-03-12 14:06:39 +01:00
|
|
|
}
|
|
|
|
case TypeKind.F64: {
|
2018-01-10 13:09:05 +01:00
|
|
|
ret = module.createIf(
|
|
|
|
module.createBinary(BinaryOp.EqF64,
|
|
|
|
arg0,
|
|
|
|
module.createF64(0)
|
|
|
|
),
|
2018-01-27 16:23:00 +01:00
|
|
|
abort
|
2018-01-10 13:09:05 +01:00
|
|
|
);
|
|
|
|
break;
|
2018-03-12 14:06:39 +01:00
|
|
|
}
|
|
|
|
case TypeKind.VOID: {
|
2018-02-25 00:13:39 +01:00
|
|
|
compiler.error(
|
|
|
|
DiagnosticCode.Operation_not_supported,
|
|
|
|
reportNode.range
|
|
|
|
);
|
2018-01-27 16:23:00 +01:00
|
|
|
ret = abort;
|
2018-01-10 13:09:05 +01:00
|
|
|
break;
|
2018-03-12 14:06:39 +01:00
|
|
|
}
|
2018-01-10 13:09:05 +01:00
|
|
|
}
|
|
|
|
compiler.currentType = Type.void;
|
|
|
|
} else {
|
|
|
|
switch (compiler.currentType.kind) {
|
2018-03-12 14:06:39 +01:00
|
|
|
default: { // any integer up to 32-bits incl. bool
|
2018-01-10 13:09:05 +01:00
|
|
|
tempLocal0 = compiler.currentFunction.getAndFreeTempLocal(Type.i32);
|
|
|
|
ret = module.createIf(
|
|
|
|
module.createUnary(UnaryOp.EqzI32,
|
|
|
|
module.createTeeLocal(tempLocal0.index, arg0)
|
|
|
|
),
|
2018-01-27 16:23:00 +01:00
|
|
|
abort,
|
2018-01-10 13:09:05 +01:00
|
|
|
module.createGetLocal(tempLocal0.index, NativeType.I32)
|
|
|
|
);
|
|
|
|
break;
|
2018-03-12 14:06:39 +01:00
|
|
|
}
|
2018-01-10 13:09:05 +01:00
|
|
|
case TypeKind.I64:
|
2018-03-12 14:06:39 +01:00
|
|
|
case TypeKind.U64: {
|
2018-01-10 13:09:05 +01:00
|
|
|
tempLocal0 = compiler.currentFunction.getAndFreeTempLocal(Type.i64);
|
|
|
|
ret = module.createIf(
|
|
|
|
module.createUnary(UnaryOp.EqzI64,
|
|
|
|
module.createTeeLocal(tempLocal0.index, arg0)
|
|
|
|
),
|
2018-01-27 16:23:00 +01:00
|
|
|
abort,
|
2018-01-10 13:09:05 +01:00
|
|
|
module.createGetLocal(tempLocal0.index, NativeType.I64)
|
|
|
|
);
|
|
|
|
break;
|
2018-03-12 14:06:39 +01:00
|
|
|
}
|
2018-01-10 13:09:05 +01:00
|
|
|
case TypeKind.ISIZE:
|
2018-03-12 14:06:39 +01:00
|
|
|
case TypeKind.USIZE: {
|
2018-01-21 17:52:44 +01:00
|
|
|
tempLocal0 = compiler.currentFunction.getAndFreeTempLocal(compiler.options.usizeType);
|
2018-01-10 13:09:05 +01:00
|
|
|
ret = module.createIf(
|
2018-02-25 00:13:39 +01:00
|
|
|
module.createUnary(
|
|
|
|
compiler.options.isWasm64
|
|
|
|
? UnaryOp.EqzI64
|
|
|
|
: UnaryOp.EqzI32,
|
2018-01-10 13:09:05 +01:00
|
|
|
module.createTeeLocal(tempLocal0.index, arg0)
|
|
|
|
),
|
2018-01-27 16:23:00 +01:00
|
|
|
abort,
|
2018-01-21 17:52:44 +01:00
|
|
|
module.createGetLocal(tempLocal0.index, compiler.options.nativeSizeType)
|
2018-01-10 13:09:05 +01:00
|
|
|
);
|
|
|
|
break;
|
2018-03-12 14:06:39 +01:00
|
|
|
}
|
|
|
|
case TypeKind.F32: {
|
2018-01-10 13:09:05 +01:00
|
|
|
tempLocal0 = compiler.currentFunction.getAndFreeTempLocal(Type.f32);
|
|
|
|
ret = module.createIf(
|
|
|
|
module.createBinary(BinaryOp.EqF32,
|
|
|
|
module.createTeeLocal(tempLocal0.index, arg0),
|
|
|
|
module.createF32(0)
|
|
|
|
),
|
2018-01-27 16:23:00 +01:00
|
|
|
abort,
|
2018-01-10 13:09:05 +01:00
|
|
|
module.createGetLocal(tempLocal0.index, NativeType.F32)
|
|
|
|
);
|
|
|
|
break;
|
2018-03-12 14:06:39 +01:00
|
|
|
}
|
|
|
|
case TypeKind.F64: {
|
2018-01-10 13:09:05 +01:00
|
|
|
tempLocal0 = compiler.currentFunction.getAndFreeTempLocal(Type.f64);
|
|
|
|
ret = module.createIf(
|
|
|
|
module.createBinary(BinaryOp.EqF64,
|
|
|
|
module.createTeeLocal(tempLocal0.index, arg0),
|
|
|
|
module.createF64(0)
|
|
|
|
),
|
2018-01-27 16:23:00 +01:00
|
|
|
abort,
|
2018-01-10 13:09:05 +01:00
|
|
|
module.createGetLocal(tempLocal0.index, NativeType.F64)
|
|
|
|
);
|
|
|
|
break;
|
2018-03-12 14:06:39 +01:00
|
|
|
}
|
|
|
|
case TypeKind.VOID: {
|
2018-02-25 00:13:39 +01:00
|
|
|
compiler.error(
|
|
|
|
DiagnosticCode.Operation_not_supported,
|
|
|
|
reportNode.range
|
|
|
|
);
|
2018-01-27 16:23:00 +01:00
|
|
|
ret = abort;
|
2018-01-10 13:09:05 +01:00
|
|
|
break;
|
2018-03-12 14:06:39 +01:00
|
|
|
}
|
2018-01-10 13:09:05 +01:00
|
|
|
}
|
2017-12-14 11:55:35 +01:00
|
|
|
}
|
2018-01-10 13:09:05 +01:00
|
|
|
return ret;
|
2018-03-12 14:06:39 +01:00
|
|
|
}
|
2017-12-05 15:06:44 +01:00
|
|
|
|
2017-12-15 17:23:04 +01:00
|
|
|
// conversions
|
|
|
|
|
2018-03-12 14:06:39 +01:00
|
|
|
case "i8": {
|
2018-02-25 00:13:39 +01:00
|
|
|
if (typeArguments) {
|
|
|
|
compiler.error(
|
|
|
|
DiagnosticCode.Type_0_is_not_generic,
|
|
|
|
reportNode.range, prototype.internalName
|
|
|
|
);
|
|
|
|
}
|
2018-01-10 13:09:05 +01:00
|
|
|
if (operands.length != 1) {
|
2018-02-25 00:13:39 +01:00
|
|
|
compiler.error(
|
|
|
|
DiagnosticCode.Expected_0_arguments_but_got_1,
|
|
|
|
reportNode.range, "1", operands.length.toString(10)
|
|
|
|
);
|
2018-01-10 13:09:05 +01:00
|
|
|
compiler.currentType = Type.i8;
|
2017-12-12 01:35:48 +01:00
|
|
|
return module.createUnreachable();
|
2018-01-10 13:09:05 +01:00
|
|
|
}
|
2017-12-15 17:23:04 +01:00
|
|
|
return compiler.compileExpression(operands[0], Type.i8, ConversionKind.EXPLICIT);
|
2018-03-12 14:06:39 +01:00
|
|
|
}
|
|
|
|
case "i16": {
|
2018-02-25 00:13:39 +01:00
|
|
|
if (typeArguments) {
|
|
|
|
compiler.error(
|
|
|
|
DiagnosticCode.Type_0_is_not_generic,
|
|
|
|
reportNode.range, prototype.internalName
|
|
|
|
);
|
|
|
|
}
|
2018-01-10 13:09:05 +01:00
|
|
|
if (operands.length != 1) {
|
2018-02-25 00:13:39 +01:00
|
|
|
compiler.error(
|
|
|
|
DiagnosticCode.Expected_0_arguments_but_got_1,
|
|
|
|
reportNode.range, "1", operands.length.toString(10)
|
|
|
|
);
|
2018-01-10 13:09:05 +01:00
|
|
|
compiler.currentType = Type.i16;
|
2017-12-12 01:35:48 +01:00
|
|
|
return module.createUnreachable();
|
2018-01-10 13:09:05 +01:00
|
|
|
}
|
2017-12-15 17:23:04 +01:00
|
|
|
return compiler.compileExpression(operands[0], Type.i16, ConversionKind.EXPLICIT);
|
2018-03-12 14:06:39 +01:00
|
|
|
}
|
|
|
|
case "i32": {
|
2018-02-25 00:13:39 +01:00
|
|
|
if (typeArguments) {
|
|
|
|
compiler.error(
|
|
|
|
DiagnosticCode.Type_0_is_not_generic,
|
|
|
|
reportNode.range, prototype.internalName
|
|
|
|
);
|
|
|
|
}
|
2018-01-10 13:09:05 +01:00
|
|
|
if (operands.length != 1) {
|
2018-02-25 00:13:39 +01:00
|
|
|
compiler.error(
|
|
|
|
DiagnosticCode.Expected_0_arguments_but_got_1,
|
|
|
|
reportNode.range, "1", operands.length.toString(10)
|
|
|
|
);
|
2018-01-10 13:09:05 +01:00
|
|
|
compiler.currentType = Type.i32;
|
2017-12-12 01:35:48 +01:00
|
|
|
return module.createUnreachable();
|
2018-01-10 13:09:05 +01:00
|
|
|
}
|
2017-12-15 17:23:04 +01:00
|
|
|
return compiler.compileExpression(operands[0], Type.i32, ConversionKind.EXPLICIT);
|
2018-03-12 14:06:39 +01:00
|
|
|
}
|
|
|
|
case "i64": {
|
2018-02-25 00:13:39 +01:00
|
|
|
if (typeArguments) {
|
|
|
|
compiler.error(
|
|
|
|
DiagnosticCode.Type_0_is_not_generic,
|
|
|
|
reportNode.range, prototype.internalName
|
|
|
|
);
|
|
|
|
}
|
2018-01-10 13:09:05 +01:00
|
|
|
if (operands.length != 1) {
|
2018-02-25 00:13:39 +01:00
|
|
|
compiler.error(
|
|
|
|
DiagnosticCode.Expected_0_arguments_but_got_1,
|
|
|
|
reportNode.range, "1", operands.length.toString(10)
|
|
|
|
);
|
2018-01-10 13:09:05 +01:00
|
|
|
compiler.currentType = Type.i64;
|
2017-12-12 01:35:48 +01:00
|
|
|
return module.createUnreachable();
|
2018-01-10 13:09:05 +01:00
|
|
|
}
|
2017-12-15 17:23:04 +01:00
|
|
|
return compiler.compileExpression(operands[0], Type.i64, ConversionKind.EXPLICIT);
|
2018-03-12 14:06:39 +01:00
|
|
|
}
|
|
|
|
case "isize": {
|
2018-02-25 00:13:39 +01:00
|
|
|
if (typeArguments) {
|
|
|
|
compiler.error(
|
|
|
|
DiagnosticCode.Type_0_is_not_generic,
|
|
|
|
reportNode.range, prototype.internalName
|
|
|
|
);
|
|
|
|
}
|
2018-01-10 13:09:05 +01:00
|
|
|
if (operands.length != 1) {
|
2018-02-25 00:13:39 +01:00
|
|
|
compiler.error(
|
|
|
|
DiagnosticCode.Expected_0_arguments_but_got_1,
|
|
|
|
reportNode.range, "1", operands.length.toString(10)
|
|
|
|
);
|
|
|
|
compiler.currentType = compiler.options.isWasm64
|
|
|
|
? Type.isize64
|
|
|
|
: Type.isize32;
|
2017-12-15 17:23:04 +01:00
|
|
|
return module.createUnreachable();
|
2018-01-10 13:09:05 +01:00
|
|
|
}
|
2018-02-25 00:13:39 +01:00
|
|
|
return compiler.compileExpression(
|
|
|
|
operands[0],
|
|
|
|
compiler.options.isWasm64
|
|
|
|
? Type.isize64
|
|
|
|
: Type.isize32,
|
|
|
|
ConversionKind.EXPLICIT
|
|
|
|
);
|
2018-03-12 14:06:39 +01:00
|
|
|
}
|
|
|
|
case "u8": {
|
2018-02-25 00:13:39 +01:00
|
|
|
if (typeArguments) {
|
|
|
|
compiler.error(
|
|
|
|
DiagnosticCode.Type_0_is_not_generic,
|
|
|
|
reportNode.range, prototype.internalName
|
|
|
|
);
|
|
|
|
}
|
2018-01-10 13:09:05 +01:00
|
|
|
if (operands.length != 1) {
|
2018-02-25 00:13:39 +01:00
|
|
|
compiler.error(
|
|
|
|
DiagnosticCode.Expected_0_arguments_but_got_1,
|
|
|
|
reportNode.range, "1", operands.length.toString(10)
|
|
|
|
);
|
2018-01-10 13:09:05 +01:00
|
|
|
compiler.currentType = Type.u8;
|
2017-12-15 17:23:04 +01:00
|
|
|
return module.createUnreachable();
|
2018-01-10 13:09:05 +01:00
|
|
|
}
|
2017-12-15 17:23:04 +01:00
|
|
|
return compiler.compileExpression(operands[0], Type.u8, ConversionKind.EXPLICIT);
|
2018-03-12 14:06:39 +01:00
|
|
|
}
|
|
|
|
case "u16": {
|
2018-02-25 00:13:39 +01:00
|
|
|
if (typeArguments) {
|
|
|
|
compiler.error(
|
|
|
|
DiagnosticCode.Type_0_is_not_generic,
|
|
|
|
reportNode.range, prototype.internalName
|
|
|
|
);
|
|
|
|
}
|
2018-01-10 13:09:05 +01:00
|
|
|
if (operands.length != 1) {
|
2018-02-25 00:13:39 +01:00
|
|
|
compiler.error(
|
|
|
|
DiagnosticCode.Expected_0_arguments_but_got_1,
|
|
|
|
reportNode.range, "1", operands.length.toString(10)
|
|
|
|
);
|
2018-01-10 13:09:05 +01:00
|
|
|
compiler.currentType = Type.u16;
|
2017-12-15 17:23:04 +01:00
|
|
|
return module.createUnreachable();
|
2018-01-10 13:09:05 +01:00
|
|
|
}
|
2017-12-15 17:23:04 +01:00
|
|
|
return compiler.compileExpression(operands[0], Type.u16, ConversionKind.EXPLICIT);
|
2018-03-12 14:06:39 +01:00
|
|
|
}
|
|
|
|
case "u32": {
|
2018-02-25 00:13:39 +01:00
|
|
|
if (typeArguments) {
|
|
|
|
compiler.error(
|
|
|
|
DiagnosticCode.Type_0_is_not_generic,
|
|
|
|
reportNode.range, prototype.internalName
|
|
|
|
);
|
|
|
|
}
|
2018-01-10 13:09:05 +01:00
|
|
|
if (operands.length != 1) {
|
2018-02-25 00:13:39 +01:00
|
|
|
compiler.error(
|
|
|
|
DiagnosticCode.Expected_0_arguments_but_got_1,
|
|
|
|
reportNode.range, "1", operands.length.toString(10)
|
|
|
|
);
|
2018-01-10 13:09:05 +01:00
|
|
|
compiler.currentType = Type.u32;
|
2017-12-15 17:23:04 +01:00
|
|
|
return module.createUnreachable();
|
2018-01-10 13:09:05 +01:00
|
|
|
}
|
2017-12-15 17:23:04 +01:00
|
|
|
return compiler.compileExpression(operands[0], Type.u32, ConversionKind.EXPLICIT);
|
2018-03-12 14:06:39 +01:00
|
|
|
}
|
|
|
|
case "u64": {
|
2018-02-25 00:13:39 +01:00
|
|
|
if (typeArguments) {
|
|
|
|
compiler.error(
|
|
|
|
DiagnosticCode.Type_0_is_not_generic,
|
|
|
|
reportNode.range, prototype.internalName
|
|
|
|
);
|
|
|
|
}
|
2018-01-10 13:09:05 +01:00
|
|
|
if (operands.length != 1) {
|
2018-02-25 00:13:39 +01:00
|
|
|
compiler.error(
|
|
|
|
DiagnosticCode.Expected_0_arguments_but_got_1,
|
|
|
|
reportNode.range, "1", operands.length.toString(10)
|
|
|
|
);
|
2018-01-10 13:09:05 +01:00
|
|
|
compiler.currentType = Type.u64;
|
2017-12-15 17:23:04 +01:00
|
|
|
return module.createUnreachable();
|
2018-01-10 13:09:05 +01:00
|
|
|
}
|
2017-12-15 17:23:04 +01:00
|
|
|
return compiler.compileExpression(operands[0], Type.u64, ConversionKind.EXPLICIT);
|
2018-03-12 14:06:39 +01:00
|
|
|
}
|
|
|
|
case "usize": {
|
2018-02-25 00:13:39 +01:00
|
|
|
if (typeArguments) {
|
|
|
|
compiler.error(
|
|
|
|
DiagnosticCode.Type_0_is_not_generic,
|
|
|
|
reportNode.range, prototype.internalName
|
|
|
|
);
|
|
|
|
}
|
2018-01-10 13:09:05 +01:00
|
|
|
if (operands.length != 1) {
|
2018-02-25 00:13:39 +01:00
|
|
|
compiler.error(
|
|
|
|
DiagnosticCode.Expected_0_arguments_but_got_1,
|
|
|
|
reportNode.range, "1", operands.length.toString(10)
|
|
|
|
);
|
2018-01-21 17:52:44 +01:00
|
|
|
compiler.currentType = compiler.options.usizeType;
|
2017-12-15 17:23:04 +01:00
|
|
|
return module.createUnreachable();
|
2018-01-10 13:09:05 +01:00
|
|
|
}
|
2018-02-25 00:13:39 +01:00
|
|
|
return compiler.compileExpression(
|
|
|
|
operands[0],
|
|
|
|
compiler.options.usizeType,
|
|
|
|
ConversionKind.EXPLICIT
|
|
|
|
);
|
2018-03-12 14:06:39 +01:00
|
|
|
}
|
|
|
|
case "bool": {
|
2018-02-25 00:13:39 +01:00
|
|
|
if (typeArguments) {
|
|
|
|
compiler.error(
|
|
|
|
DiagnosticCode.Type_0_is_not_generic,
|
|
|
|
reportNode.range, prototype.internalName
|
|
|
|
);
|
|
|
|
}
|
2018-01-10 13:09:05 +01:00
|
|
|
if (operands.length != 1) {
|
2018-02-25 00:13:39 +01:00
|
|
|
compiler.error(
|
|
|
|
DiagnosticCode.Expected_0_arguments_but_got_1,
|
|
|
|
reportNode.range, "1", operands.length.toString(10)
|
|
|
|
);
|
2018-01-10 13:09:05 +01:00
|
|
|
compiler.currentType = Type.bool;
|
2017-12-15 17:23:04 +01:00
|
|
|
return module.createUnreachable();
|
2018-01-10 13:09:05 +01:00
|
|
|
}
|
2017-12-15 17:23:04 +01:00
|
|
|
return compiler.compileExpression(operands[0], Type.bool, ConversionKind.EXPLICIT);
|
2018-03-12 14:06:39 +01:00
|
|
|
}
|
|
|
|
case "f32": {
|
2018-02-25 00:13:39 +01:00
|
|
|
if (typeArguments) {
|
|
|
|
compiler.error(
|
|
|
|
DiagnosticCode.Type_0_is_not_generic,
|
|
|
|
reportNode.range, prototype.internalName
|
|
|
|
);
|
|
|
|
}
|
2018-01-10 13:09:05 +01:00
|
|
|
if (operands.length != 1) {
|
2018-02-25 00:13:39 +01:00
|
|
|
compiler.error(
|
|
|
|
DiagnosticCode.Expected_0_arguments_but_got_1,
|
|
|
|
reportNode.range, "1", operands.length.toString(10)
|
|
|
|
);
|
2018-01-10 13:09:05 +01:00
|
|
|
compiler.currentType = Type.f32;
|
2017-12-15 17:23:04 +01:00
|
|
|
return module.createUnreachable();
|
2018-01-10 13:09:05 +01:00
|
|
|
}
|
2017-12-15 17:23:04 +01:00
|
|
|
return compiler.compileExpression(operands[0], Type.f32, ConversionKind.EXPLICIT);
|
2018-03-12 14:06:39 +01:00
|
|
|
}
|
|
|
|
case "f64": {
|
2018-02-25 00:13:39 +01:00
|
|
|
if (typeArguments) {
|
|
|
|
compiler.error(
|
|
|
|
DiagnosticCode.Type_0_is_not_generic,
|
|
|
|
reportNode.range, prototype.internalName
|
|
|
|
);
|
|
|
|
}
|
2018-01-10 13:09:05 +01:00
|
|
|
if (operands.length != 1) {
|
2018-02-25 00:13:39 +01:00
|
|
|
compiler.error(
|
|
|
|
DiagnosticCode.Expected_0_arguments_but_got_1,
|
|
|
|
reportNode.range, "1", operands.length.toString(10)
|
|
|
|
);
|
2018-01-10 13:09:05 +01:00
|
|
|
compiler.currentType = Type.f64;
|
2017-12-15 17:23:04 +01:00
|
|
|
return module.createUnreachable();
|
2018-01-10 13:09:05 +01:00
|
|
|
}
|
2017-12-15 17:23:04 +01:00
|
|
|
return compiler.compileExpression(operands[0], Type.f64, ConversionKind.EXPLICIT);
|
2018-03-12 14:06:39 +01:00
|
|
|
}
|
2017-12-05 01:45:15 +01:00
|
|
|
}
|
2018-02-25 00:13:39 +01:00
|
|
|
compiler.error(
|
|
|
|
DiagnosticCode.Operation_not_supported,
|
|
|
|
reportNode.range
|
|
|
|
);
|
2018-01-05 01:55:59 +01:00
|
|
|
return module.createUnreachable();
|
2017-12-05 01:45:15 +01:00
|
|
|
}
|
2018-01-19 16:13:14 +01:00
|
|
|
|
2018-01-21 16:34:50 +01:00
|
|
|
function evaluateConstantOffset(compiler: Compiler, expression: Expression): i32 {
|
|
|
|
var expr: ExpressionRef;
|
|
|
|
var value: i32;
|
2018-02-25 00:13:39 +01:00
|
|
|
if (compiler.options.isWasm64) {
|
2018-02-28 01:48:01 +01:00
|
|
|
expr = compiler.precomputeExpression(expression, Type.usize64);
|
2018-01-21 16:34:50 +01:00
|
|
|
if (
|
|
|
|
_BinaryenExpressionGetId(expr) != ExpressionId.Const ||
|
|
|
|
_BinaryenExpressionGetType(expr) != NativeType.I64 ||
|
|
|
|
_BinaryenConstGetValueI64High(expr) != 0 ||
|
|
|
|
(value = _BinaryenConstGetValueI64Low(expr)) < 0
|
|
|
|
) {
|
2018-02-25 00:13:39 +01:00
|
|
|
compiler.error(
|
|
|
|
DiagnosticCode.Operation_not_supported,
|
|
|
|
expression.range
|
|
|
|
);
|
2018-01-21 16:34:50 +01:00
|
|
|
value = -1;
|
|
|
|
}
|
|
|
|
} else {
|
2018-02-28 01:48:01 +01:00
|
|
|
expr = compiler.precomputeExpression(expression, Type.usize32);
|
2018-01-21 16:34:50 +01:00
|
|
|
if (
|
|
|
|
_BinaryenExpressionGetId(expr) != ExpressionId.Const ||
|
|
|
|
_BinaryenExpressionGetType(expr) != NativeType.I32 ||
|
|
|
|
(value = _BinaryenConstGetValueI32(expr)) < 0
|
|
|
|
) {
|
2018-02-25 00:13:39 +01:00
|
|
|
compiler.error(
|
|
|
|
DiagnosticCode.Operation_not_supported,
|
|
|
|
expression.range
|
|
|
|
);
|
2018-01-21 16:34:50 +01:00
|
|
|
value = -1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return value;
|
|
|
|
}
|
|
|
|
|
2018-01-20 05:27:54 +01:00
|
|
|
/** Compiles a memory allocation for an instance of the specified class. */
|
2018-02-25 00:13:39 +01:00
|
|
|
export function compileAllocate(
|
|
|
|
compiler: Compiler,
|
|
|
|
cls: Class,
|
|
|
|
reportNode: Node
|
|
|
|
): ExpressionRef {
|
2018-03-12 14:06:39 +01:00
|
|
|
var program = compiler.program;
|
|
|
|
assert(cls.program == program);
|
|
|
|
var module = compiler.module;
|
|
|
|
var options = compiler.options;
|
|
|
|
|
2018-03-17 01:37:05 +01:00
|
|
|
var prototype = program.elementsLookup.get(options.allocateImpl);
|
2018-03-12 14:06:39 +01:00
|
|
|
if (!prototype) {
|
2018-02-25 00:13:39 +01:00
|
|
|
program.error(
|
|
|
|
DiagnosticCode.Cannot_find_name_0,
|
2018-03-12 14:06:39 +01:00
|
|
|
reportNode.range, options.allocateImpl
|
2018-02-25 00:13:39 +01:00
|
|
|
);
|
2018-03-12 14:06:39 +01:00
|
|
|
return module.createUnreachable();
|
2018-02-25 00:13:39 +01:00
|
|
|
}
|
2018-03-12 14:06:39 +01:00
|
|
|
if (prototype.kind != ElementKind.FUNCTION_PROTOTYPE) {
|
|
|
|
program.error(
|
|
|
|
DiagnosticCode.Cannot_invoke_an_expression_whose_type_lacks_a_call_signature_Type_0_has_no_compatible_call_signatures,
|
|
|
|
reportNode.range, prototype.internalName
|
|
|
|
);
|
|
|
|
return module.createUnreachable();
|
|
|
|
}
|
|
|
|
|
|
|
|
var instance = (<FunctionPrototype>prototype).resolve(); // reports
|
|
|
|
if (!(instance && compiler.compileFunction(instance))) return module.createUnreachable();
|
|
|
|
|
|
|
|
compiler.currentType = cls.type;
|
|
|
|
return module.createCall(
|
|
|
|
instance.internalName, [
|
|
|
|
options.isWasm64
|
|
|
|
? module.createI64(cls.currentMemoryOffset)
|
|
|
|
: module.createI32(cls.currentMemoryOffset)
|
|
|
|
],
|
|
|
|
options.nativeSizeType
|
|
|
|
);
|
2018-01-19 16:13:14 +01:00
|
|
|
}
|
2018-01-27 17:02:52 +01:00
|
|
|
|
2018-02-02 03:07:54 +01:00
|
|
|
/** Compiles an abort wired to the conditionally imported 'abort' function. */
|
2018-02-25 00:13:39 +01:00
|
|
|
export function compileAbort(
|
|
|
|
compiler: Compiler,
|
|
|
|
message: Expression | null,
|
|
|
|
reportNode: Node
|
|
|
|
): ExpressionRef {
|
2018-03-12 14:06:39 +01:00
|
|
|
var program = compiler.program;
|
2018-01-27 17:02:52 +01:00
|
|
|
var module = compiler.module;
|
2018-03-12 14:06:39 +01:00
|
|
|
|
2018-03-17 01:37:05 +01:00
|
|
|
var stringType = program.typesLookup.get("string"); // might be intended
|
2018-03-12 14:06:39 +01:00
|
|
|
if (!stringType) return module.createUnreachable();
|
|
|
|
|
2018-03-17 01:37:05 +01:00
|
|
|
var abortPrototype = program.elementsLookup.get("abort"); // might be intended
|
2018-03-12 14:06:39 +01:00
|
|
|
if (!abortPrototype || abortPrototype.kind != ElementKind.FUNCTION_PROTOTYPE) return module.createUnreachable();
|
|
|
|
|
|
|
|
var abortInstance = (<FunctionPrototype>abortPrototype).resolve(); // reports
|
|
|
|
if (!(abortInstance && compiler.compileFunction(abortInstance))) return module.createUnreachable();
|
|
|
|
|
|
|
|
var messageArg = message != null
|
|
|
|
? compiler.compileExpression(message, stringType)
|
|
|
|
: stringType.toNativeZero(module);
|
|
|
|
|
|
|
|
var filenameArg = compiler.compileStaticString(reportNode.range.source.normalizedPath);
|
|
|
|
|
|
|
|
compiler.currentType = Type.void;
|
|
|
|
return module.createBlock(null, [
|
|
|
|
module.createCallImport(
|
|
|
|
abortInstance.internalName, [
|
|
|
|
messageArg,
|
|
|
|
filenameArg,
|
|
|
|
module.createI32(reportNode.range.line),
|
|
|
|
module.createI32(reportNode.range.column)
|
|
|
|
],
|
|
|
|
NativeType.None
|
|
|
|
),
|
|
|
|
module.createUnreachable()
|
|
|
|
]);
|
2018-01-27 17:02:52 +01:00
|
|
|
}
|