Use a special 'auto' type in type inference (#658)

This commit is contained in:
Daniel Wirtz 2019-06-12 13:54:07 +02:00 committed by GitHub
parent 334d944f67
commit d4313f1ed8
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
10 changed files with 483 additions and 460 deletions

View File

@ -5,7 +5,7 @@
import { import {
Compiler, Compiler,
ContextualFlags, Constraints,
RuntimeFeatures, RuntimeFeatures,
flatten flatten
} from "./compiler"; } from "./compiler";
@ -648,7 +648,7 @@ export function compileCall(
checkTypeAbsent(typeArguments, reportNode, prototype) | checkTypeAbsent(typeArguments, reportNode, prototype) |
checkArgsRequired(operands, 1, reportNode, compiler) checkArgsRequired(operands, 1, reportNode, compiler)
) return module.unreachable(); ) return module.unreachable();
let expr = compiler.compileExpressionRetainType(operands[0], Type.i32); let expr = compiler.compileExpression(operands[0], Type.auto);
compiler.currentType = Type.bool; compiler.currentType = Type.bool;
return module.i32(getExpressionId(expr) == ExpressionId.Const ? 1 : 0); return module.i32(getExpressionId(expr) == ExpressionId.Const ? 1 : 0);
} }
@ -782,8 +782,8 @@ export function compileCall(
checkArgsRequired(operands, 1, reportNode, compiler) checkArgsRequired(operands, 1, reportNode, compiler)
) return module.unreachable(); ) return module.unreachable();
let arg0 = typeArguments let arg0 = typeArguments
? compiler.compileExpression(operands[0], typeArguments[0], ContextualFlags.IMPLICIT | ContextualFlags.WRAP) ? compiler.compileExpression(operands[0], typeArguments[0], Constraints.CONV_IMPLICIT | Constraints.MUST_WRAP)
: compiler.compileExpression(operands[0], Type.i32, ContextualFlags.WRAP); : compiler.compileExpression(operands[0], Type.i32, Constraints.MUST_WRAP);
let type = compiler.currentType; let type = compiler.currentType;
if (type.is(TypeFlags.REFERENCE)) { if (type.is(TypeFlags.REFERENCE)) {
compiler.error( compiler.error(
@ -873,8 +873,8 @@ export function compileCall(
checkArgsRequired(operands, 2, reportNode, compiler) checkArgsRequired(operands, 2, reportNode, compiler)
) return module.unreachable(); ) return module.unreachable();
let arg0 = typeArguments let arg0 = typeArguments
? compiler.compileExpression(operands[0], typeArguments[0], ContextualFlags.IMPLICIT | ContextualFlags.WRAP) ? compiler.compileExpression(operands[0], typeArguments[0], Constraints.CONV_IMPLICIT | Constraints.MUST_WRAP)
: compiler.compileExpression(operands[0], Type.i32, ContextualFlags.WRAP); : compiler.compileExpression(operands[0], Type.i32, Constraints.MUST_WRAP);
let type = compiler.currentType; let type = compiler.currentType;
if (type.is(TypeFlags.REFERENCE)) { if (type.is(TypeFlags.REFERENCE)) {
compiler.error( compiler.error(
@ -883,7 +883,7 @@ export function compileCall(
); );
return module.unreachable(); return module.unreachable();
} }
let arg1 = compiler.compileExpression(operands[1], type, ContextualFlags.IMPLICIT); let arg1 = compiler.compileExpression(operands[1], type, Constraints.CONV_IMPLICIT);
let expr: ExpressionRef; let expr: ExpressionRef;
switch (type.kind) { switch (type.kind) {
case TypeKind.I8: case TypeKind.I8:
@ -934,8 +934,8 @@ export function compileCall(
checkArgsRequired(operands, 2, reportNode, compiler) checkArgsRequired(operands, 2, reportNode, compiler)
) return module.unreachable(); ) return module.unreachable();
let arg0 = typeArguments let arg0 = typeArguments
? compiler.compileExpression(operands[0], typeArguments[0], ContextualFlags.IMPLICIT | ContextualFlags.WRAP) ? compiler.compileExpression(operands[0], typeArguments[0], Constraints.CONV_IMPLICIT | Constraints.MUST_WRAP)
: compiler.compileExpression(operands[0], Type.i32, ContextualFlags.WRAP); : compiler.compileExpression(operands[0], Type.i32, Constraints.MUST_WRAP);
let type = compiler.currentType; let type = compiler.currentType;
if (type.is(TypeFlags.REFERENCE)) { if (type.is(TypeFlags.REFERENCE)) {
compiler.error( compiler.error(
@ -944,7 +944,7 @@ export function compileCall(
); );
return module.unreachable(); return module.unreachable();
} }
let arg1 = compiler.compileExpression(operands[1], type, ContextualFlags.IMPLICIT); let arg1 = compiler.compileExpression(operands[1], type, Constraints.CONV_IMPLICIT);
let expr: ExpressionRef; let expr: ExpressionRef;
switch (type.kind) { switch (type.kind) {
case TypeKind.I8: case TypeKind.I8:
@ -995,8 +995,8 @@ export function compileCall(
checkArgsRequired(operands, 1, reportNode, compiler) checkArgsRequired(operands, 1, reportNode, compiler)
) return module.unreachable(); ) return module.unreachable();
let arg0 = typeArguments let arg0 = typeArguments
? compiler.compileExpression(operands[0], typeArguments[0], ContextualFlags.IMPLICIT | ContextualFlags.WRAP) ? compiler.compileExpression(operands[0], typeArguments[0], Constraints.CONV_IMPLICIT | Constraints.MUST_WRAP)
: compiler.compileExpression(operands[0], Type.f64, ContextualFlags.WRAP); : compiler.compileExpression(operands[0], Type.f64, Constraints.MUST_WRAP);
let type = compiler.currentType; let type = compiler.currentType;
if (type.is(TypeFlags.REFERENCE)) { if (type.is(TypeFlags.REFERENCE)) {
compiler.error( compiler.error(
@ -1120,8 +1120,8 @@ export function compileCall(
checkArgsRequired(operands, 2, reportNode, compiler) checkArgsRequired(operands, 2, reportNode, compiler)
) return module.unreachable(); ) return module.unreachable();
let arg0 = typeArguments let arg0 = typeArguments
? compiler.compileExpression(operands[0], typeArguments[0], ContextualFlags.IMPLICIT | ContextualFlags.WRAP) ? compiler.compileExpression(operands[0], typeArguments[0], Constraints.CONV_IMPLICIT | Constraints.MUST_WRAP)
: compiler.compileExpression(operands[0], Type.f64, ContextualFlags.WRAP); : compiler.compileExpression(operands[0], Type.f64, Constraints.MUST_WRAP);
let type = compiler.currentType; let type = compiler.currentType;
if (type.is(TypeFlags.REFERENCE)) { if (type.is(TypeFlags.REFERENCE)) {
compiler.error( compiler.error(
@ -1130,7 +1130,7 @@ export function compileCall(
); );
return module.unreachable(); return module.unreachable();
} }
let arg1 = compiler.compileExpression(operands[1], type, ContextualFlags.IMPLICIT | ContextualFlags.WRAP); let arg1 = compiler.compileExpression(operands[1], type, Constraints.CONV_IMPLICIT | Constraints.MUST_WRAP);
let op: BinaryOp; let op: BinaryOp;
switch (type.kind) { switch (type.kind) {
case TypeKind.I8: case TypeKind.I8:
@ -1190,8 +1190,8 @@ export function compileCall(
checkArgsRequired(operands, 2, reportNode, compiler) checkArgsRequired(operands, 2, reportNode, compiler)
) return module.unreachable(); ) return module.unreachable();
let arg0 = typeArguments let arg0 = typeArguments
? compiler.compileExpression(operands[0], typeArguments[0], ContextualFlags.IMPLICIT | ContextualFlags.WRAP) ? compiler.compileExpression(operands[0], typeArguments[0], Constraints.CONV_IMPLICIT | Constraints.MUST_WRAP)
: compiler.compileExpression(operands[0], Type.f64, ContextualFlags.WRAP); : compiler.compileExpression(operands[0], Type.f64, Constraints.MUST_WRAP);
let type = compiler.currentType; let type = compiler.currentType;
if (type.is(TypeFlags.REFERENCE)) { if (type.is(TypeFlags.REFERENCE)) {
compiler.error( compiler.error(
@ -1200,7 +1200,7 @@ export function compileCall(
); );
return module.unreachable(); return module.unreachable();
} }
let arg1 = compiler.compileExpression(operands[1], type, ContextualFlags.IMPLICIT | ContextualFlags.WRAP); let arg1 = compiler.compileExpression(operands[1], type, Constraints.CONV_IMPLICIT | Constraints.MUST_WRAP);
let op: BinaryOp; let op: BinaryOp;
switch (type.kind) { switch (type.kind) {
case TypeKind.I8: case TypeKind.I8:
@ -1261,8 +1261,8 @@ export function compileCall(
checkArgsRequired(operands, 1, reportNode, compiler) checkArgsRequired(operands, 1, reportNode, compiler)
) return module.unreachable(); ) return module.unreachable();
let arg0 = typeArguments let arg0 = typeArguments
? compiler.compileExpression(operands[0], typeArguments[0], ContextualFlags.IMPLICIT) ? compiler.compileExpression(operands[0], typeArguments[0], Constraints.CONV_IMPLICIT)
: compiler.compileExpression(operands[0], Type.f64, ContextualFlags.NONE); : compiler.compileExpression(operands[0], Type.f64, Constraints.NONE);
let type = compiler.currentType; let type = compiler.currentType;
if (type.is(TypeFlags.REFERENCE)) { if (type.is(TypeFlags.REFERENCE)) {
compiler.error( compiler.error(
@ -1312,8 +1312,8 @@ export function compileCall(
checkArgsRequired(operands, 2, reportNode, compiler) checkArgsRequired(operands, 2, reportNode, compiler)
) return module.unreachable(); ) return module.unreachable();
let arg0 = typeArguments let arg0 = typeArguments
? compiler.compileExpression(operands[0], typeArguments[0], ContextualFlags.IMPLICIT) ? compiler.compileExpression(operands[0], typeArguments[0], Constraints.CONV_IMPLICIT)
: compiler.compileExpression(operands[0], Type.f64, ContextualFlags.NONE); : compiler.compileExpression(operands[0], Type.f64, Constraints.NONE);
let type = compiler.currentType; let type = compiler.currentType;
if (type.is(TypeFlags.REFERENCE)) { if (type.is(TypeFlags.REFERENCE)) {
compiler.error( compiler.error(
@ -1322,7 +1322,7 @@ export function compileCall(
); );
return module.unreachable(); return module.unreachable();
} }
let arg1 = compiler.compileExpression(operands[1], type, ContextualFlags.IMPLICIT); let arg1 = compiler.compileExpression(operands[1], type, Constraints.CONV_IMPLICIT);
let op: BinaryOp; let op: BinaryOp;
switch (type.kind) { switch (type.kind) {
// TODO: does an integer version make sense? // TODO: does an integer version make sense?
@ -1344,8 +1344,8 @@ export function compileCall(
checkArgsRequired(operands, 1, reportNode, compiler) checkArgsRequired(operands, 1, reportNode, compiler)
) return module.unreachable(); ) return module.unreachable();
let arg0 = typeArguments let arg0 = typeArguments
? compiler.compileExpression(operands[0], typeArguments[0], ContextualFlags.IMPLICIT) ? compiler.compileExpression(operands[0], typeArguments[0], Constraints.CONV_IMPLICIT)
: compiler.compileExpression(operands[0], Type.f64, ContextualFlags.NONE); : compiler.compileExpression(operands[0], Type.f64, Constraints.NONE);
let type = compiler.currentType; let type = compiler.currentType;
if (type.is(TypeFlags.REFERENCE)) { if (type.is(TypeFlags.REFERENCE)) {
compiler.error( compiler.error(
@ -1407,13 +1407,13 @@ export function compileCall(
switch (type.kind) { switch (type.kind) {
case TypeKind.I32: case TypeKind.I32:
case TypeKind.U32: { case TypeKind.U32: {
let arg0 = compiler.compileExpression(operands[0], Type.f32, ContextualFlags.IMPLICIT); let arg0 = compiler.compileExpression(operands[0], Type.f32, Constraints.CONV_IMPLICIT);
expr = module.unary(UnaryOp.ReinterpretF32, arg0); expr = module.unary(UnaryOp.ReinterpretF32, arg0);
break; break;
} }
case TypeKind.I64: case TypeKind.I64:
case TypeKind.U64: { case TypeKind.U64: {
let arg0 = compiler.compileExpression(operands[0], Type.f64, ContextualFlags.IMPLICIT); let arg0 = compiler.compileExpression(operands[0], Type.f64, Constraints.CONV_IMPLICIT);
expr = module.unary(UnaryOp.ReinterpretF64, arg0); expr = module.unary(UnaryOp.ReinterpretF64, arg0);
break; break;
} }
@ -1423,7 +1423,7 @@ export function compileCall(
compiler.options.isWasm64 compiler.options.isWasm64
? Type.f64 ? Type.f64
: Type.f32, : Type.f32,
ContextualFlags.IMPLICIT Constraints.CONV_IMPLICIT
); );
expr = module.unary( expr = module.unary(
compiler.options.isWasm64 compiler.options.isWasm64
@ -1434,12 +1434,12 @@ export function compileCall(
break; break;
} }
case TypeKind.F32: { case TypeKind.F32: {
let arg0 = compiler.compileExpression(operands[0], Type.i32, ContextualFlags.IMPLICIT); let arg0 = compiler.compileExpression(operands[0], Type.i32, Constraints.CONV_IMPLICIT);
expr = module.unary(UnaryOp.ReinterpretI32, arg0); expr = module.unary(UnaryOp.ReinterpretI32, arg0);
break; break;
} }
case TypeKind.F64: { case TypeKind.F64: {
let arg0 = compiler.compileExpression(operands[0], Type.i64, ContextualFlags.IMPLICIT); let arg0 = compiler.compileExpression(operands[0], Type.i64, Constraints.CONV_IMPLICIT);
expr = module.unary(UnaryOp.ReinterpretI64, arg0); expr = module.unary(UnaryOp.ReinterpretI64, arg0);
break; break;
} }
@ -1461,8 +1461,8 @@ export function compileCall(
checkArgsRequired(operands, 1, reportNode, compiler) checkArgsRequired(operands, 1, reportNode, compiler)
) return module.unreachable(); ) return module.unreachable();
let arg0 = typeArguments let arg0 = typeArguments
? compiler.compileExpression(operands[0], typeArguments[0], ContextualFlags.IMPLICIT) ? compiler.compileExpression(operands[0], typeArguments[0], Constraints.CONV_IMPLICIT)
: compiler.compileExpression(operands[0], Type.f64, ContextualFlags.NONE); : compiler.compileExpression(operands[0], Type.f64, Constraints.NONE);
let type = compiler.currentType; let type = compiler.currentType;
if (type.is(TypeFlags.REFERENCE)) { if (type.is(TypeFlags.REFERENCE)) {
compiler.currentType = type; compiler.currentType = type;
@ -1499,8 +1499,8 @@ export function compileCall(
checkArgsRequired(operands, 1, reportNode, compiler) checkArgsRequired(operands, 1, reportNode, compiler)
) return module.unreachable(); ) return module.unreachable();
let arg0 = typeArguments let arg0 = typeArguments
? compiler.compileExpression(operands[0], typeArguments[0], ContextualFlags.IMPLICIT) ? compiler.compileExpression(operands[0], typeArguments[0], Constraints.CONV_IMPLICIT)
: compiler.compileExpression(operands[0], Type.f64, ContextualFlags.NONE); : compiler.compileExpression(operands[0], Type.f64, Constraints.NONE);
let type = compiler.currentType; let type = compiler.currentType;
if (type.is(TypeFlags.REFERENCE)) { if (type.is(TypeFlags.REFERENCE)) {
compiler.error( compiler.error(
@ -1555,13 +1555,14 @@ export function compileCall(
) return module.unreachable(); ) return module.unreachable();
let type = typeArguments![0]; let type = typeArguments![0];
let outType = ( let outType = (
contextualType != Type.auto &&
type.is(TypeFlags.INTEGER) && type.is(TypeFlags.INTEGER) &&
contextualType.is(TypeFlags.INTEGER) && contextualType.is(TypeFlags.INTEGER) &&
contextualType.size > type.size contextualType.size > type.size
) ? contextualType : type; ) ? contextualType : type;
let arg0 = compiler.compileExpression(operands[0], let arg0 = compiler.compileExpression(operands[0],
compiler.options.usizeType, compiler.options.usizeType,
ContextualFlags.IMPLICIT Constraints.CONV_IMPLICIT
); );
let numOperands = operands.length; let numOperands = operands.length;
let immOffset = numOperands >= 2 ? evaluateImmediateOffset(operands[1], compiler) : 0; // reports let immOffset = numOperands >= 2 ? evaluateImmediateOffset(operands[1], compiler) : 0; // reports
@ -1615,19 +1616,19 @@ export function compileCall(
let type = typeArguments![0]; let type = typeArguments![0];
let arg0 = compiler.compileExpression(operands[0], let arg0 = compiler.compileExpression(operands[0],
compiler.options.usizeType, compiler.options.usizeType,
ContextualFlags.IMPLICIT Constraints.CONV_IMPLICIT
); );
let arg1 = isAsm let arg1 = isAsm
? compiler.compileExpression(operands[1], ? compiler.compileExpression(operands[1],
contextualType, contextualType,
ContextualFlags.IMPLICIT Constraints.CONV_IMPLICIT
) )
: compiler.compileExpression( : compiler.compileExpression(
operands[1], operands[1],
type, type,
type.is(TypeFlags.INTEGER) type.is(TypeFlags.INTEGER)
? ContextualFlags.NONE // no need to convert to small int (but now might result in a float) ? Constraints.NONE // no need to convert to small int (but now might result in a float)
: ContextualFlags.IMPLICIT : Constraints.CONV_IMPLICIT
); );
let inType = compiler.currentType; let inType = compiler.currentType;
if ( if (
@ -1704,7 +1705,7 @@ export function compileCall(
} }
let arg0 = compiler.compileExpression(operands[0], let arg0 = compiler.compileExpression(operands[0],
compiler.options.usizeType, compiler.options.usizeType,
ContextualFlags.IMPLICIT Constraints.CONV_IMPLICIT
); );
let immOffset = operands.length == 2 ? evaluateImmediateOffset(operands[1], compiler) : 0; // reports let immOffset = operands.length == 2 ? evaluateImmediateOffset(operands[1], compiler) : 0; // reports
if (immOffset < 0) { if (immOffset < 0) {
@ -1736,20 +1737,20 @@ export function compileCall(
} }
let arg0 = compiler.compileExpression(operands[0], let arg0 = compiler.compileExpression(operands[0],
compiler.options.usizeType, compiler.options.usizeType,
ContextualFlags.IMPLICIT Constraints.CONV_IMPLICIT
); );
let arg1 = isAsm let arg1 = isAsm
? compiler.compileExpression( ? compiler.compileExpression(
operands[1], operands[1],
contextualType, contextualType,
ContextualFlags.IMPLICIT Constraints.CONV_IMPLICIT
) )
: compiler.compileExpression( : compiler.compileExpression(
operands[1], operands[1],
type, type,
type.is(TypeFlags.INTEGER) type.is(TypeFlags.INTEGER)
? ContextualFlags.NONE // no need to convert to small int (but now might result in a float) ? Constraints.NONE // no need to convert to small int (but now might result in a float)
: ContextualFlags.IMPLICIT : Constraints.CONV_IMPLICIT
); );
let inType = compiler.currentType; let inType = compiler.currentType;
if ( if (
@ -1795,19 +1796,19 @@ export function compileCall(
} }
let arg0 = compiler.compileExpression(operands[0], let arg0 = compiler.compileExpression(operands[0],
compiler.options.usizeType, compiler.options.usizeType,
ContextualFlags.IMPLICIT Constraints.CONV_IMPLICIT
); );
let arg1 = isAsm let arg1 = isAsm
? compiler.compileExpression(operands[1], ? compiler.compileExpression(operands[1],
contextualType, contextualType,
ContextualFlags.IMPLICIT Constraints.CONV_IMPLICIT
) )
: compiler.compileExpression( : compiler.compileExpression(
operands[1], operands[1],
type, type,
type.is(TypeFlags.INTEGER) type.is(TypeFlags.INTEGER)
? ContextualFlags.NONE // no need to convert to small int (but now might result in a float) ? Constraints.NONE // no need to convert to small int (but now might result in a float)
: ContextualFlags.IMPLICIT : Constraints.CONV_IMPLICIT
); );
let inType = compiler.currentType; let inType = compiler.currentType;
if ( if (
@ -1860,24 +1861,24 @@ export function compileCall(
} }
let arg0 = compiler.compileExpression(operands[0], let arg0 = compiler.compileExpression(operands[0],
compiler.options.usizeType, compiler.options.usizeType,
ContextualFlags.IMPLICIT Constraints.CONV_IMPLICIT
); );
let arg1 = isAsm let arg1 = isAsm
? compiler.compileExpression(operands[1], ? compiler.compileExpression(operands[1],
contextualType, contextualType,
ContextualFlags.IMPLICIT Constraints.CONV_IMPLICIT
) )
: compiler.compileExpression( : compiler.compileExpression(
operands[1], operands[1],
type, type,
type.is(TypeFlags.INTEGER) type.is(TypeFlags.INTEGER)
? ContextualFlags.NONE // no need to convert to small int (but now might result in a float) ? Constraints.NONE // no need to convert to small int (but now might result in a float)
: ContextualFlags.IMPLICIT : Constraints.CONV_IMPLICIT
); );
let inType = compiler.currentType; let inType = compiler.currentType;
let arg2 = compiler.compileExpression(operands[2], let arg2 = compiler.compileExpression(operands[2],
inType, inType,
ContextualFlags.IMPLICIT Constraints.CONV_IMPLICIT
); );
if ( if (
type.is(TypeFlags.INTEGER) && type.is(TypeFlags.INTEGER) &&
@ -1925,14 +1926,14 @@ export function compileCall(
} }
let arg0 = compiler.compileExpression(operands[0], let arg0 = compiler.compileExpression(operands[0],
compiler.options.usizeType, compiler.options.usizeType,
ContextualFlags.IMPLICIT Constraints.CONV_IMPLICIT
); );
let arg1 = compiler.compileExpression(operands[1], type, let arg1 = compiler.compileExpression(operands[1], type,
ContextualFlags.IMPLICIT Constraints.CONV_IMPLICIT
); );
let arg2 = compiler.compileExpression(operands[2], let arg2 = compiler.compileExpression(operands[2],
Type.i64, Type.i64,
ContextualFlags.IMPLICIT Constraints.CONV_IMPLICIT
); );
compiler.currentType = Type.i32; compiler.currentType = Type.i32;
return module.atomic_wait(arg0, arg1, arg2, type.toNativeType()); return module.atomic_wait(arg0, arg1, arg2, type.toNativeType());
@ -1946,11 +1947,11 @@ export function compileCall(
) return module.unreachable(); ) return module.unreachable();
let arg0 = compiler.compileExpression(operands[0], let arg0 = compiler.compileExpression(operands[0],
compiler.options.usizeType, compiler.options.usizeType,
ContextualFlags.IMPLICIT Constraints.CONV_IMPLICIT
); );
let arg1 = compiler.compileExpression(operands[1], let arg1 = compiler.compileExpression(operands[1],
Type.i32, Type.i32,
ContextualFlags.IMPLICIT Constraints.CONV_IMPLICIT
); );
compiler.currentType = Type.i32; compiler.currentType = Type.i32;
return module.atomic_notify(arg0, arg1); return module.atomic_notify(arg0, arg1);
@ -1964,8 +1965,8 @@ export function compileCall(
checkArgsRequired(operands, 3, reportNode, compiler) checkArgsRequired(operands, 3, reportNode, compiler)
) return module.unreachable(); ) return module.unreachable();
let arg0 = typeArguments let arg0 = typeArguments
? compiler.compileExpression(operands[0], typeArguments[0], ContextualFlags.IMPLICIT) ? compiler.compileExpression(operands[0], typeArguments[0], Constraints.CONV_IMPLICIT)
: compiler.compileExpressionRetainType(operands[0], Type.i32); : compiler.compileExpression(operands[0], Type.auto);
let type = compiler.currentType; let type = compiler.currentType;
if (!type.isAny(TypeFlags.VALUE | TypeFlags.REFERENCE)) { if (!type.isAny(TypeFlags.VALUE | TypeFlags.REFERENCE)) {
compiler.error( compiler.error(
@ -1974,9 +1975,9 @@ export function compileCall(
); );
return module.unreachable(); return module.unreachable();
} }
let arg1 = compiler.compileExpression(operands[1], type, ContextualFlags.IMPLICIT); let arg1 = compiler.compileExpression(operands[1], type, Constraints.CONV_IMPLICIT);
let arg2 = compiler.makeIsTrueish( let arg2 = compiler.makeIsTrueish(
compiler.compileExpressionRetainType(operands[2], Type.bool), compiler.compileExpression(operands[2], Type.bool),
compiler.currentType // ^ compiler.currentType // ^
); );
compiler.currentType = type; compiler.currentType = type;
@ -2010,7 +2011,7 @@ export function compileCall(
checkArgsRequired(operands, 1, reportNode, compiler) checkArgsRequired(operands, 1, reportNode, compiler)
) return module.unreachable(); ) return module.unreachable();
return module.host(HostOp.MemoryGrow, null, [ return module.host(HostOp.MemoryGrow, null, [
compiler.compileExpression(operands[0], Type.i32, ContextualFlags.IMPLICIT) compiler.compileExpression(operands[0], Type.i32, Constraints.CONV_IMPLICIT)
]); ]);
} }
case BuiltinSymbols.memory_copy: { // memory.copy(dest: usize, src: usize: n: usize) -> void case BuiltinSymbols.memory_copy: { // memory.copy(dest: usize, src: usize: n: usize) -> void
@ -2026,9 +2027,9 @@ export function compileCall(
return compiler.compileCallDirect(instance, operands, reportNode); return compiler.compileCallDirect(instance, operands, reportNode);
} }
let usizeType = compiler.options.usizeType; let usizeType = compiler.options.usizeType;
let arg0 = compiler.compileExpression(operands[0], usizeType, ContextualFlags.IMPLICIT); let arg0 = compiler.compileExpression(operands[0], usizeType, Constraints.CONV_IMPLICIT);
let arg1 = compiler.compileExpression(operands[1], usizeType, ContextualFlags.IMPLICIT); let arg1 = compiler.compileExpression(operands[1], usizeType, Constraints.CONV_IMPLICIT);
let arg2 = compiler.compileExpression(operands[2], usizeType, ContextualFlags.IMPLICIT); let arg2 = compiler.compileExpression(operands[2], usizeType, Constraints.CONV_IMPLICIT);
compiler.currentType = Type.void; compiler.currentType = Type.void;
return module.memory_copy(arg0, arg1, arg2); return module.memory_copy(arg0, arg1, arg2);
} }
@ -2045,9 +2046,9 @@ export function compileCall(
return compiler.compileCallDirect(instance, operands, reportNode); return compiler.compileCallDirect(instance, operands, reportNode);
} }
let usizeType = compiler.options.usizeType; let usizeType = compiler.options.usizeType;
let arg0 = compiler.compileExpression(operands[0], usizeType, ContextualFlags.IMPLICIT); let arg0 = compiler.compileExpression(operands[0], usizeType, Constraints.CONV_IMPLICIT);
let arg1 = compiler.compileExpression(operands[1], Type.u8, ContextualFlags.IMPLICIT); let arg1 = compiler.compileExpression(operands[1], Type.u8, Constraints.CONV_IMPLICIT);
let arg2 = compiler.compileExpression(operands[2], usizeType, ContextualFlags.IMPLICIT); let arg2 = compiler.compileExpression(operands[2], usizeType, Constraints.CONV_IMPLICIT);
compiler.currentType = Type.void; compiler.currentType = Type.void;
return module.memory_fill(arg0, arg1, arg2); return module.memory_fill(arg0, arg1, arg2);
} }
@ -2060,7 +2061,7 @@ export function compileCall(
checkArgsRequired(operands, 1, reportNode, compiler) checkArgsRequired(operands, 1, reportNode, compiler)
) return module.unreachable(); ) return module.unreachable();
let toType = typeArguments![0]; let toType = typeArguments![0];
let arg0 = compiler.compileExpressionRetainType(operands[0], toType); let arg0 = compiler.compileExpression(operands[0], toType);
let fromType = compiler.currentType; let fromType = compiler.currentType;
compiler.currentType = toType; compiler.currentType = toType;
if (fromType.size != toType.size) { if (fromType.size != toType.size) {
@ -2084,8 +2085,8 @@ export function compileCall(
return module.unreachable(); return module.unreachable();
} }
let arg0 = typeArguments let arg0 = typeArguments
? compiler.compileExpression(operands[0], typeArguments[0], ContextualFlags.IMPLICIT | ContextualFlags.WRAP) ? compiler.compileExpression(operands[0], typeArguments[0], Constraints.CONV_IMPLICIT | Constraints.MUST_WRAP)
: compiler.compileExpressionRetainType(operands[0], Type.bool, ContextualFlags.WRAP); : compiler.compileExpression(operands[0], Type.bool, Constraints.MUST_WRAP);
let type = compiler.currentType; let type = compiler.currentType;
compiler.currentType = type.nonNullableType; compiler.currentType = type.nonNullableType;
@ -2272,7 +2273,7 @@ export function compileCall(
checkArgsOptional(operands, 1, i32.MAX_VALUE, reportNode, compiler) checkArgsOptional(operands, 1, i32.MAX_VALUE, reportNode, compiler)
) return module.unreachable(); ) return module.unreachable();
let returnType = typeArguments ? typeArguments[0] : contextualType; let returnType = typeArguments ? typeArguments[0] : contextualType;
let arg0 = compiler.compileExpressionRetainType(operands[0], Type.u32); let arg0 = compiler.compileExpression(operands[0], Type.u32);
let arg0Type = compiler.currentType; let arg0Type = compiler.currentType;
if (!( if (!(
arg0Type == Type.u32 || // either plain index arg0Type == Type.u32 || // either plain index
@ -2290,7 +2291,7 @@ export function compileCall(
let parameterTypes = new Array<Type>(numOperands); let parameterTypes = new Array<Type>(numOperands);
let nativeParamTypes = new Array<NativeType>(numOperands); let nativeParamTypes = new Array<NativeType>(numOperands);
for (let i = 0; i < numOperands; ++i) { for (let i = 0; i < numOperands; ++i) {
operandExprs[i] = compiler.compileExpressionRetainType(operands[1 + i], Type.i32); operandExprs[i] = compiler.compileExpression(operands[1 + i], Type.i32);
let operandType = compiler.currentType; let operandType = compiler.currentType;
parameterTypes[i] = operandType; parameterTypes[i] = operandType;
nativeParamTypes[i] = operandType.toNativeType(); nativeParamTypes[i] = operandType.toNativeType();
@ -2332,7 +2333,7 @@ export function compileCall(
return module.unreachable(); return module.unreachable();
} }
compiler.currentType = classInstance.type; compiler.currentType = classInstance.type;
return compiler.compileInstantiate(classInstance, operands, ContextualFlags.NONE, reportNode); return compiler.compileInstantiate(classInstance, operands, Constraints.NONE, reportNode);
} }
// === User-defined diagnostics =============================================================== // === User-defined diagnostics ===============================================================
@ -2372,7 +2373,7 @@ export function compileCall(
compiler.currentType = Type.i8; compiler.currentType = Type.i8;
return module.unreachable(); return module.unreachable();
} }
return compiler.compileExpression(operands[0], Type.i8, ContextualFlags.EXPLICIT); return compiler.compileExpression(operands[0], Type.i8, Constraints.CONV_EXPLICIT);
} }
case BuiltinSymbols.i16: { case BuiltinSymbols.i16: {
if ( if (
@ -2382,7 +2383,7 @@ export function compileCall(
compiler.currentType = Type.i16; compiler.currentType = Type.i16;
return module.unreachable(); return module.unreachable();
} }
return compiler.compileExpression(operands[0], Type.i16, ContextualFlags.EXPLICIT); return compiler.compileExpression(operands[0], Type.i16, Constraints.CONV_EXPLICIT);
} }
case BuiltinSymbols.i32: { case BuiltinSymbols.i32: {
if ( if (
@ -2392,7 +2393,7 @@ export function compileCall(
compiler.currentType = Type.i32; compiler.currentType = Type.i32;
return module.unreachable(); return module.unreachable();
} }
return compiler.compileExpression(operands[0], Type.i32, ContextualFlags.EXPLICIT); return compiler.compileExpression(operands[0], Type.i32, Constraints.CONV_EXPLICIT);
} }
case BuiltinSymbols.i64: { case BuiltinSymbols.i64: {
if ( if (
@ -2402,7 +2403,7 @@ export function compileCall(
compiler.currentType = Type.i64; compiler.currentType = Type.i64;
return module.unreachable(); return module.unreachable();
} }
return compiler.compileExpression(operands[0], Type.i64, ContextualFlags.EXPLICIT); return compiler.compileExpression(operands[0], Type.i64, Constraints.CONV_EXPLICIT);
} }
case BuiltinSymbols.isize: { case BuiltinSymbols.isize: {
let isizeType = compiler.options.isizeType; let isizeType = compiler.options.isizeType;
@ -2413,7 +2414,7 @@ export function compileCall(
compiler.currentType = isizeType; compiler.currentType = isizeType;
return module.unreachable(); return module.unreachable();
} }
return compiler.compileExpression(operands[0], isizeType, ContextualFlags.EXPLICIT); return compiler.compileExpression(operands[0], isizeType, Constraints.CONV_EXPLICIT);
} }
case BuiltinSymbols.u8: { case BuiltinSymbols.u8: {
if ( if (
@ -2423,7 +2424,7 @@ export function compileCall(
compiler.currentType = Type.u8; compiler.currentType = Type.u8;
return module.unreachable(); return module.unreachable();
} }
return compiler.compileExpression(operands[0], Type.u8, ContextualFlags.EXPLICIT); return compiler.compileExpression(operands[0], Type.u8, Constraints.CONV_EXPLICIT);
} }
case BuiltinSymbols.u16: { case BuiltinSymbols.u16: {
if ( if (
@ -2433,7 +2434,7 @@ export function compileCall(
compiler.currentType = Type.u16; compiler.currentType = Type.u16;
return module.unreachable(); return module.unreachable();
} }
return compiler.compileExpression(operands[0], Type.u16, ContextualFlags.EXPLICIT); return compiler.compileExpression(operands[0], Type.u16, Constraints.CONV_EXPLICIT);
} }
case BuiltinSymbols.u32: { case BuiltinSymbols.u32: {
if ( if (
@ -2443,7 +2444,7 @@ export function compileCall(
compiler.currentType = Type.u32; compiler.currentType = Type.u32;
return module.unreachable(); return module.unreachable();
} }
return compiler.compileExpression(operands[0], Type.u32, ContextualFlags.EXPLICIT); return compiler.compileExpression(operands[0], Type.u32, Constraints.CONV_EXPLICIT);
} }
case BuiltinSymbols.u64: { case BuiltinSymbols.u64: {
if ( if (
@ -2453,7 +2454,7 @@ export function compileCall(
compiler.currentType = Type.u64; compiler.currentType = Type.u64;
return module.unreachable(); return module.unreachable();
} }
return compiler.compileExpression(operands[0], Type.u64, ContextualFlags.EXPLICIT); return compiler.compileExpression(operands[0], Type.u64, Constraints.CONV_EXPLICIT);
} }
case BuiltinSymbols.usize: { case BuiltinSymbols.usize: {
let usizeType = compiler.options.usizeType; let usizeType = compiler.options.usizeType;
@ -2464,7 +2465,7 @@ export function compileCall(
compiler.currentType = usizeType; compiler.currentType = usizeType;
return module.unreachable(); return module.unreachable();
} }
return compiler.compileExpression(operands[0], usizeType, ContextualFlags.EXPLICIT); return compiler.compileExpression(operands[0], usizeType, Constraints.CONV_EXPLICIT);
} }
case BuiltinSymbols.bool: { case BuiltinSymbols.bool: {
if ( if (
@ -2474,7 +2475,7 @@ export function compileCall(
compiler.currentType = Type.bool; compiler.currentType = Type.bool;
return module.unreachable(); return module.unreachable();
} }
return compiler.compileExpression(operands[0], Type.bool, ContextualFlags.EXPLICIT); return compiler.compileExpression(operands[0], Type.bool, Constraints.CONV_EXPLICIT);
} }
case BuiltinSymbols.f32: { case BuiltinSymbols.f32: {
if ( if (
@ -2484,7 +2485,7 @@ export function compileCall(
compiler.currentType = Type.f32; compiler.currentType = Type.f32;
return module.unreachable(); return module.unreachable();
} }
return compiler.compileExpression(operands[0], Type.f32, ContextualFlags.EXPLICIT); return compiler.compileExpression(operands[0], Type.f32, Constraints.CONV_EXPLICIT);
} }
case BuiltinSymbols.f64: { case BuiltinSymbols.f64: {
if ( if (
@ -2494,7 +2495,7 @@ export function compileCall(
compiler.currentType = Type.f64; compiler.currentType = Type.f64;
return module.unreachable(); return module.unreachable();
} }
return compiler.compileExpression(operands[0], Type.f64, ContextualFlags.EXPLICIT); return compiler.compileExpression(operands[0], Type.f64, Constraints.CONV_EXPLICIT);
} }
// === SIMD =================================================================================== // === SIMD ===================================================================================
@ -2513,7 +2514,7 @@ export function compileCall(
for (let i = 0; i < 16; ++i) { for (let i = 0; i < 16; ++i) {
let value = operands[i]; let value = operands[i];
if (value) { if (value) {
let expr = compiler.precomputeExpression(value, Type.i8, ContextualFlags.IMPLICIT); let expr = compiler.precomputeExpression(value, Type.i8, Constraints.CONV_IMPLICIT);
if (getExpressionId(expr) != ExpressionId.Const) { if (getExpressionId(expr) != ExpressionId.Const) {
compiler.error( compiler.error(
DiagnosticCode.Expression_must_be_a_compile_time_constant, DiagnosticCode.Expression_must_be_a_compile_time_constant,
@ -2542,7 +2543,7 @@ export function compileCall(
for (let i = 0; i < 8; ++i) { for (let i = 0; i < 8; ++i) {
let value = operands[i]; let value = operands[i];
if (value) { if (value) {
let expr = compiler.precomputeExpression(value, Type.i16, ContextualFlags.IMPLICIT); let expr = compiler.precomputeExpression(value, Type.i16, Constraints.CONV_IMPLICIT);
if (getExpressionId(expr) != ExpressionId.Const) { if (getExpressionId(expr) != ExpressionId.Const) {
compiler.error( compiler.error(
DiagnosticCode.Expression_must_be_a_compile_time_constant, DiagnosticCode.Expression_must_be_a_compile_time_constant,
@ -2571,7 +2572,7 @@ export function compileCall(
for (let i = 0; i < 4; ++i) { for (let i = 0; i < 4; ++i) {
let value = operands[i]; let value = operands[i];
if (value) { if (value) {
let expr = compiler.precomputeExpression(value, Type.i32, ContextualFlags.IMPLICIT); let expr = compiler.precomputeExpression(value, Type.i32, Constraints.CONV_IMPLICIT);
if (getExpressionId(expr) != ExpressionId.Const) { if (getExpressionId(expr) != ExpressionId.Const) {
compiler.error( compiler.error(
DiagnosticCode.Expression_must_be_a_compile_time_constant, DiagnosticCode.Expression_must_be_a_compile_time_constant,
@ -2600,7 +2601,7 @@ export function compileCall(
for (let i = 0; i < 2; ++i) { for (let i = 0; i < 2; ++i) {
let value = operands[i]; let value = operands[i];
if (value) { if (value) {
let expr = compiler.precomputeExpression(value, Type.i64, ContextualFlags.IMPLICIT); let expr = compiler.precomputeExpression(value, Type.i64, Constraints.CONV_IMPLICIT);
if (getExpressionId(expr) != ExpressionId.Const) { if (getExpressionId(expr) != ExpressionId.Const) {
compiler.error( compiler.error(
DiagnosticCode.Expression_must_be_a_compile_time_constant, DiagnosticCode.Expression_must_be_a_compile_time_constant,
@ -2631,7 +2632,7 @@ export function compileCall(
for (let i = 0; i < 4; ++i) { for (let i = 0; i < 4; ++i) {
let value = operands[i]; let value = operands[i];
if (value) { if (value) {
let expr = compiler.precomputeExpression(value, Type.f32, ContextualFlags.IMPLICIT); let expr = compiler.precomputeExpression(value, Type.f32, Constraints.CONV_IMPLICIT);
if (getExpressionId(expr) != ExpressionId.Const) { if (getExpressionId(expr) != ExpressionId.Const) {
compiler.error( compiler.error(
DiagnosticCode.Expression_must_be_a_compile_time_constant, DiagnosticCode.Expression_must_be_a_compile_time_constant,
@ -2660,7 +2661,7 @@ export function compileCall(
for (let i = 0; i < 2; ++i) { for (let i = 0; i < 2; ++i) {
let value = operands[i]; let value = operands[i];
if (value) { if (value) {
let expr = compiler.precomputeExpression(value, Type.f64, ContextualFlags.IMPLICIT); let expr = compiler.precomputeExpression(value, Type.f64, Constraints.CONV_IMPLICIT);
if (getExpressionId(expr) != ExpressionId.Const) { if (getExpressionId(expr) != ExpressionId.Const) {
compiler.error( compiler.error(
DiagnosticCode.Expression_must_be_a_compile_time_constant, DiagnosticCode.Expression_must_be_a_compile_time_constant,
@ -2722,7 +2723,7 @@ export function compileCall(
return module.unreachable(); return module.unreachable();
} }
} }
let arg0 = compiler.compileExpression(operands[0], type, ContextualFlags.IMPLICIT); let arg0 = compiler.compileExpression(operands[0], type, Constraints.CONV_IMPLICIT);
compiler.currentType = Type.v128; compiler.currentType = Type.v128;
return module.unary(op, arg0); return module.unary(op, arg0);
} }
@ -2769,8 +2770,8 @@ export function compileCall(
return module.unreachable(); return module.unreachable();
} }
} }
let arg0 = compiler.compileExpression(operands[0], Type.v128, ContextualFlags.IMPLICIT); let arg0 = compiler.compileExpression(operands[0], Type.v128, Constraints.CONV_IMPLICIT);
let arg1 = compiler.precomputeExpression(operands[1], Type.u8, ContextualFlags.IMPLICIT); let arg1 = compiler.precomputeExpression(operands[1], Type.u8, Constraints.CONV_IMPLICIT);
compiler.currentType = type; compiler.currentType = type;
if (getExpressionId(arg1) != ExpressionId.Const) { if (getExpressionId(arg1) != ExpressionId.Const) {
compiler.error( compiler.error(
@ -2837,8 +2838,8 @@ export function compileCall(
return module.unreachable(); return module.unreachable();
} }
} }
let arg0 = compiler.compileExpression(operands[0], Type.v128, ContextualFlags.IMPLICIT); let arg0 = compiler.compileExpression(operands[0], Type.v128, Constraints.CONV_IMPLICIT);
let arg1 = compiler.precomputeExpression(operands[1], Type.u8, ContextualFlags.IMPLICIT); let arg1 = compiler.precomputeExpression(operands[1], Type.u8, Constraints.CONV_IMPLICIT);
if (getExpressionId(arg1) != ExpressionId.Const) { if (getExpressionId(arg1) != ExpressionId.Const) {
compiler.error( compiler.error(
DiagnosticCode.Expression_must_be_a_compile_time_constant, DiagnosticCode.Expression_must_be_a_compile_time_constant,
@ -2857,7 +2858,7 @@ export function compileCall(
); );
return module.unreachable(); return module.unreachable();
} }
let arg2 = compiler.compileExpression(operands[2], type, ContextualFlags.IMPLICIT); let arg2 = compiler.compileExpression(operands[2], type, Constraints.CONV_IMPLICIT);
compiler.currentType = Type.v128; compiler.currentType = Type.v128;
return module.simd_replace(op, arg0, idx, arg2); return module.simd_replace(op, arg0, idx, arg2);
} }
@ -2909,13 +2910,13 @@ export function compileCall(
return module.unreachable(); return module.unreachable();
} }
} }
let arg0 = compiler.compileExpression(operands[0], Type.v128, ContextualFlags.IMPLICIT); let arg0 = compiler.compileExpression(operands[0], Type.v128, Constraints.CONV_IMPLICIT);
let arg1 = compiler.compileExpression(operands[1], Type.v128, ContextualFlags.IMPLICIT); let arg1 = compiler.compileExpression(operands[1], Type.v128, Constraints.CONV_IMPLICIT);
let mask = new Uint8Array(16); let mask = new Uint8Array(16);
let maxIdx = (laneCount << 1) - 1; let maxIdx = (laneCount << 1) - 1;
for (let i = 0; i < laneCount; ++i) { for (let i = 0; i < laneCount; ++i) {
let operand = operands[2 + i]; let operand = operands[2 + i];
let argN = compiler.precomputeExpression(operand, Type.u8, ContextualFlags.IMPLICIT); let argN = compiler.precomputeExpression(operand, Type.u8, Constraints.CONV_IMPLICIT);
if (getExpressionId(argN) != ExpressionId.Const) { if (getExpressionId(argN) != ExpressionId.Const) {
compiler.error( compiler.error(
DiagnosticCode.Expression_must_be_a_compile_time_constant, DiagnosticCode.Expression_must_be_a_compile_time_constant,
@ -3241,8 +3242,8 @@ export function compileCall(
compiler.currentType = Type.v128; compiler.currentType = Type.v128;
return module.unreachable(); return module.unreachable();
} }
let arg0 = compiler.compileExpression(operands[0], Type.v128, ContextualFlags.IMPLICIT); let arg0 = compiler.compileExpression(operands[0], Type.v128, Constraints.CONV_IMPLICIT);
let arg1 = compiler.compileExpression(operands[1], Type.v128, ContextualFlags.IMPLICIT); let arg1 = compiler.compileExpression(operands[1], Type.v128, Constraints.CONV_IMPLICIT);
compiler.currentType = Type.v128; compiler.currentType = Type.v128;
return module.binary(op, arg0, arg1); return module.binary(op, arg0, arg1);
} }
@ -3333,7 +3334,7 @@ export function compileCall(
compiler.currentType = Type.v128; compiler.currentType = Type.v128;
return module.unreachable(); return module.unreachable();
} }
let arg0 = compiler.compileExpression(operands[0], Type.v128, ContextualFlags.IMPLICIT); let arg0 = compiler.compileExpression(operands[0], Type.v128, Constraints.CONV_IMPLICIT);
compiler.currentType = Type.v128; compiler.currentType = Type.v128;
return module.unary(op, arg0); return module.unary(op, arg0);
} }
@ -3412,8 +3413,8 @@ export function compileCall(
compiler.currentType = Type.v128; compiler.currentType = Type.v128;
return module.unreachable(); return module.unreachable();
} }
let arg0 = compiler.compileExpression(operands[0], Type.v128, ContextualFlags.IMPLICIT); let arg0 = compiler.compileExpression(operands[0], Type.v128, Constraints.CONV_IMPLICIT);
let arg1 = compiler.compileExpression(operands[1], Type.i32, ContextualFlags.IMPLICIT); let arg1 = compiler.compileExpression(operands[1], Type.i32, Constraints.CONV_IMPLICIT);
compiler.currentType = Type.v128; compiler.currentType = Type.v128;
return module.simd_shift(op, arg0, arg1); return module.simd_shift(op, arg0, arg1);
} }
@ -3435,8 +3436,8 @@ export function compileCall(
case BuiltinSymbols.v128_or: { op = BinaryOp.OrVec128; break; } case BuiltinSymbols.v128_or: { op = BinaryOp.OrVec128; break; }
case BuiltinSymbols.v128_xor: { op = BinaryOp.XorVec128; break; } case BuiltinSymbols.v128_xor: { op = BinaryOp.XorVec128; break; }
} }
let arg0 = compiler.compileExpression(operands[0], Type.v128, ContextualFlags.IMPLICIT); let arg0 = compiler.compileExpression(operands[0], Type.v128, Constraints.CONV_IMPLICIT);
let arg1 = compiler.compileExpression(operands[1], Type.v128, ContextualFlags.IMPLICIT); let arg1 = compiler.compileExpression(operands[1], Type.v128, Constraints.CONV_IMPLICIT);
return module.binary(op, arg0, arg1); return module.binary(op, arg0, arg1);
} }
case BuiltinSymbols.v128_not: { // any_bitwise_unary(a: v128) -> v128 case BuiltinSymbols.v128_not: { // any_bitwise_unary(a: v128) -> v128
@ -3448,7 +3449,7 @@ export function compileCall(
compiler.currentType = Type.v128; compiler.currentType = Type.v128;
return module.unreachable(); return module.unreachable();
} }
let arg0 = compiler.compileExpression(operands[0], Type.v128, ContextualFlags.IMPLICIT); let arg0 = compiler.compileExpression(operands[0], Type.v128, Constraints.CONV_IMPLICIT);
return module.unary(UnaryOp.NotVec128, arg0); return module.unary(UnaryOp.NotVec128, arg0);
} }
case BuiltinSymbols.v128_bitselect: { // bitselect(v1: v128, v2: v128, c: v128) -> v128 case BuiltinSymbols.v128_bitselect: { // bitselect(v1: v128, v2: v128, c: v128) -> v128
@ -3460,9 +3461,9 @@ export function compileCall(
compiler.currentType = Type.v128; compiler.currentType = Type.v128;
return module.unreachable(); return module.unreachable();
} }
let arg0 = compiler.compileExpression(operands[0], Type.v128, ContextualFlags.IMPLICIT); let arg0 = compiler.compileExpression(operands[0], Type.v128, Constraints.CONV_IMPLICIT);
let arg1 = compiler.compileExpression(operands[1], Type.v128, ContextualFlags.IMPLICIT); let arg1 = compiler.compileExpression(operands[1], Type.v128, Constraints.CONV_IMPLICIT);
let arg2 = compiler.compileExpression(operands[2], Type.v128, ContextualFlags.IMPLICIT); let arg2 = compiler.compileExpression(operands[2], Type.v128, Constraints.CONV_IMPLICIT);
return module.simd_bitselect(arg0, arg1, arg2); return module.simd_bitselect(arg0, arg1, arg2);
} }
case BuiltinSymbols.v128_any_true: // any_test<T!>(a: v128) -> bool case BuiltinSymbols.v128_any_true: // any_test<T!>(a: v128) -> bool
@ -3535,7 +3536,7 @@ export function compileCall(
compiler.currentType = Type.bool; compiler.currentType = Type.bool;
return module.unreachable(); return module.unreachable();
} }
let arg0 = compiler.compileExpression(operands[0], Type.v128, ContextualFlags.IMPLICIT); let arg0 = compiler.compileExpression(operands[0], Type.v128, Constraints.CONV_IMPLICIT);
compiler.currentType = Type.bool; compiler.currentType = Type.bool;
return module.unary(op, arg0); return module.unary(op, arg0);
} }
@ -3564,7 +3565,7 @@ export function compileCall(
compiler.currentType = Type.void; compiler.currentType = Type.void;
return module.unreachable(); return module.unreachable();
} }
let arg0 = compiler.compileExpression(operands[0], Type.u32, ContextualFlags.IMPLICIT); let arg0 = compiler.compileExpression(operands[0], Type.u32, Constraints.CONV_IMPLICIT);
compiler.runtimeFeatures |= RuntimeFeatures.visitGlobals; compiler.runtimeFeatures |= RuntimeFeatures.visitGlobals;
compiler.currentType = Type.void; compiler.currentType = Type.void;
return module.call(BuiltinSymbols.visit_globals, [ arg0 ], NativeType.None); return module.call(BuiltinSymbols.visit_globals, [ arg0 ], NativeType.None);
@ -3577,8 +3578,8 @@ export function compileCall(
compiler.currentType = Type.void; compiler.currentType = Type.void;
return module.unreachable(); return module.unreachable();
} }
let arg0 = compiler.compileExpression(operands[0], compiler.options.usizeType, ContextualFlags.IMPLICIT); let arg0 = compiler.compileExpression(operands[0], compiler.options.usizeType, Constraints.CONV_IMPLICIT);
let arg1 = compiler.compileExpression(operands[1], Type.u32, ContextualFlags.IMPLICIT); let arg1 = compiler.compileExpression(operands[1], Type.u32, Constraints.CONV_IMPLICIT);
compiler.runtimeFeatures |= RuntimeFeatures.visitMembers; compiler.runtimeFeatures |= RuntimeFeatures.visitMembers;
compiler.currentType = Type.void; compiler.currentType = Type.void;
return module.call(BuiltinSymbols.visit_members, [ arg0, arg1 ], NativeType.None); return module.call(BuiltinSymbols.visit_members, [ arg0, arg1 ], NativeType.None);
@ -3949,7 +3950,7 @@ export function compileAbort(
// assertion succeeds respectively is only being computed if the program actually crashes. // assertion succeeds respectively is only being computed if the program actually crashes.
// Hence, let's make it so that the autorelease is skipped at the end of the current block, // Hence, let's make it so that the autorelease is skipped at the end of the current block,
// essentially ignoring the message GC-wise. Doesn't matter anyway on a crash. // essentially ignoring the message GC-wise. Doesn't matter anyway on a crash.
messageArg = compiler.compileExpression(message, stringInstance.type, ContextualFlags.IMPLICIT | ContextualFlags.SKIP_AUTORELEASE); messageArg = compiler.compileExpression(message, stringInstance.type, Constraints.CONV_IMPLICIT | Constraints.WILL_RETAIN);
} else { } else {
messageArg = stringInstance.type.toNativeZero(module); messageArg = stringInstance.type.toNativeZero(module);
} }
@ -4232,21 +4233,17 @@ function evaluateConstantType(
return typeArguments[0]; return typeArguments[0];
} }
if (operands.length == 1) { // optional type argument if (operands.length == 1) { // optional type argument
if (typeArguments) { if (typeArguments !== null && typeArguments.length) {
if (typeArguments.length == 1) { if (typeArguments.length > 1) {
compiler.compileExpression(operands[0], typeArguments[0], ContextualFlags.IMPLICIT); compiler.error(
} else { DiagnosticCode.Expected_0_type_arguments_but_got_1,
if (typeArguments.length) { reportNode.typeArgumentsRange, "1", typeArguments.length.toString(10)
compiler.error( );
DiagnosticCode.Expected_0_type_arguments_but_got_1, return null;
reportNode.typeArgumentsRange, "1", typeArguments.length.toString(10)
);
return null;
}
compiler.compileExpressionRetainType(operands[0], Type.i32);
} }
compiler.compileExpression(operands[0], typeArguments[0], Constraints.CONV_IMPLICIT);
} else { } else {
compiler.compileExpressionRetainType(operands[0], Type.i32); compiler.compileExpression(operands[0], Type.auto);
} }
return compiler.currentType; return compiler.currentType;
} }
@ -4268,7 +4265,7 @@ function evaluateImmediateOffset(expression: Expression, compiler: Compiler): i3
var expr: ExpressionRef; var expr: ExpressionRef;
var value: i32; var value: i32;
if (compiler.options.isWasm64) { if (compiler.options.isWasm64) {
expr = compiler.precomputeExpression(expression, Type.usize64, ContextualFlags.IMPLICIT); expr = compiler.precomputeExpression(expression, Type.usize64, Constraints.CONV_IMPLICIT);
if ( if (
getExpressionId(expr) != ExpressionId.Const || getExpressionId(expr) != ExpressionId.Const ||
getExpressionType(expr) != NativeType.I64 || getExpressionType(expr) != NativeType.I64 ||
@ -4282,7 +4279,7 @@ function evaluateImmediateOffset(expression: Expression, compiler: Compiler): i3
value = -1; value = -1;
} }
} else { } else {
expr = compiler.precomputeExpression(expression, Type.usize32, ContextualFlags.IMPLICIT); expr = compiler.precomputeExpression(expression, Type.usize32, Constraints.CONV_IMPLICIT);
if ( if (
getExpressionId(expr) != ExpressionId.Const || getExpressionId(expr) != ExpressionId.Const ||
getExpressionType(expr) != NativeType.I32 || getExpressionType(expr) != NativeType.I32 ||

File diff suppressed because it is too large Load Diff

View File

@ -145,6 +145,12 @@ export class Type {
} }
} }
/** Substitutes this type with the auto type if this type is void. */
get exceptVoid(): Type {
if (this.kind == TypeKind.VOID) return Type.auto;
return this;
}
/** Gets this type's logarithmic alignment in memory. */ /** Gets this type's logarithmic alignment in memory. */
get alignLog2(): i32 { get alignLog2(): i32 {
return 31 - clz<i32>(this.byteSize); return 31 - clz<i32>(this.byteSize);
@ -526,6 +532,9 @@ export class Type {
/** No return type. */ /** No return type. */
static readonly void: Type = new Type(TypeKind.VOID, TypeFlags.NONE, 0); static readonly void: Type = new Type(TypeKind.VOID, TypeFlags.NONE, 0);
/** Alias of i32 indicating type inference of locals and globals with just an initializer. */
static readonly auto: Type = new Type(Type.i32.kind, Type.i32.flags, Type.i32.size);
} }
/** Converts an array of types to an array of native types. */ /** Converts an array of types to an array of native types. */

View File

@ -116,6 +116,12 @@
(func $assert-nonnull/testElem (; 8 ;) (type $FUNCSIG$ii) (param $0 i32) (result i32) (func $assert-nonnull/testElem (; 8 ;) (type $FUNCSIG$ii) (param $0 i32) (result i32)
local.get $0 local.get $0
call $~lib/array/Array<assert-nonnull/Foo | null>#__get call $~lib/array/Array<assert-nonnull/Foo | null>#__get
local.tee $0
i32.eqz
if
unreachable
end
local.get $0
) )
(func $assert-nonnull/testAll (; 9 ;) (type $FUNCSIG$ii) (param $0 i32) (result i32) (func $assert-nonnull/testAll (; 9 ;) (type $FUNCSIG$ii) (param $0 i32) (result i32)
local.get $0 local.get $0

View File

@ -179,7 +179,6 @@
) )
(func $assert-nonnull/testElem (; 11 ;) (type $FUNCSIG$ii) (param $0 i32) (result i32) (func $assert-nonnull/testElem (; 11 ;) (type $FUNCSIG$ii) (param $0 i32) (result i32)
(local $1 i32) (local $1 i32)
(local $2 i32)
local.get $0 local.get $0
call $~lib/rt/stub/__retain call $~lib/rt/stub/__retain
drop drop
@ -187,13 +186,16 @@
i32.const 0 i32.const 0
call $~lib/array/Array<assert-nonnull/Foo | null>#__get call $~lib/array/Array<assert-nonnull/Foo | null>#__get
local.tee $1 local.tee $1
if (result i32)
local.get $1
else
unreachable
end
call $~lib/rt/stub/__retain call $~lib/rt/stub/__retain
local.set $2 local.set $1
local.get $1
call $~lib/rt/stub/__release
local.get $0 local.get $0
call $~lib/rt/stub/__release call $~lib/rt/stub/__release
local.get $2 local.get $1
) )
(func $assert-nonnull/testAll (; 12 ;) (type $FUNCSIG$ii) (param $0 i32) (result i32) (func $assert-nonnull/testAll (; 12 ;) (type $FUNCSIG$ii) (param $0 i32) (result i32)
(local $1 i32) (local $1 i32)

View File

@ -6,6 +6,7 @@
(data (i32.const 8) "\1a\00\00\00\01\00\00\00\01\00\00\00\1a\00\00\00r\00e\00t\00a\00i\00n\00-\00i\003\002\00.\00t\00s") (data (i32.const 8) "\1a\00\00\00\01\00\00\00\01\00\00\00\1a\00\00\00r\00e\00t\00a\00i\00n\00-\00i\003\002\00.\00t\00s")
(global $retain-i32/si (mut i32) (i32.const 0)) (global $retain-i32/si (mut i32) (i32.const 0))
(global $retain-i32/ui (mut i32) (i32.const 0)) (global $retain-i32/ui (mut i32) (i32.const 0))
(global $retain-i32/ri (mut i32) (i32.const 0))
(export "memory" (memory $0)) (export "memory" (memory $0))
(start $start) (start $start)
(func $start:retain-i32 (; 1 ;) (type $FUNCSIG$v) (func $start:retain-i32 (; 1 ;) (type $FUNCSIG$v)
@ -254,6 +255,12 @@
call $~lib/builtins/abort call $~lib/builtins/abort
unreachable unreachable
end end
i32.const 0
i32.load8_s
global.set $retain-i32/ri
i32.const 0
i32.load8_s
drop
) )
(func $start (; 2 ;) (type $FUNCSIG$v) (func $start (; 2 ;) (type $FUNCSIG$v)
call $start:retain-i32 call $start:retain-i32

View File

@ -129,3 +129,14 @@ assert(ui == 1);
ui = 255 % 255; ui = 255 % 255;
assert(ui == 0); assert(ui == 0);
// inferring global type from load should still retain T
var ri = load<i8>(0);
assert(ri instanceof i8);
// inferring local type from load should still retain T
function testLocalRetain(): void {
var ri = load<i8>(0);
assert(ri instanceof i8);
}
testLocalRetain();

View File

@ -18,6 +18,7 @@
(global $~lib/builtins/u32.MAX_VALUE i32 (i32.const -1)) (global $~lib/builtins/u32.MAX_VALUE i32 (i32.const -1))
(global $retain-i32/si (mut i32) (i32.const 0)) (global $retain-i32/si (mut i32) (i32.const 0))
(global $retain-i32/ui (mut i32) (i32.const 0)) (global $retain-i32/ui (mut i32) (i32.const 0))
(global $retain-i32/ri (mut i32) (i32.const 0))
(export "memory" (memory $0)) (export "memory" (memory $0))
(start $start) (start $start)
(func $retain-i32/test (; 1 ;) (type $FUNCSIG$vii) (param $0 i32) (param $1 i32) (func $retain-i32/test (; 1 ;) (type $FUNCSIG$vii) (param $0 i32) (param $1 i32)
@ -330,7 +331,25 @@
unreachable unreachable
end end
) )
(func $start:retain-i32 (; 2 ;) (type $FUNCSIG$v) (func $retain-i32/testLocalRetain (; 2 ;) (type $FUNCSIG$v)
(local $0 i32)
i32.const 0
i32.load8_s
local.set $0
local.get $0
drop
i32.const 1
i32.eqz
if
i32.const 0
i32.const 24
i32.const 140
i32.const 2
call $~lib/builtins/abort
unreachable
end
)
(func $start:retain-i32 (; 3 ;) (type $FUNCSIG$v)
(local $0 i32) (local $0 i32)
i32.const 0 i32.const 0
global.get $~lib/builtins/i8.MAX_VALUE global.get $~lib/builtins/i8.MAX_VALUE
@ -786,10 +805,26 @@
call $~lib/builtins/abort call $~lib/builtins/abort
unreachable unreachable
end end
i32.const 0
i32.load8_s
global.set $retain-i32/ri
global.get $retain-i32/ri
drop
i32.const 1
i32.eqz
if
i32.const 0
i32.const 24
i32.const 135
i32.const 0
call $~lib/builtins/abort
unreachable
end
call $retain-i32/testLocalRetain
) )
(func $start (; 3 ;) (type $FUNCSIG$v) (func $start (; 4 ;) (type $FUNCSIG$v)
call $start:retain-i32 call $start:retain-i32
) )
(func $null (; 4 ;) (type $FUNCSIG$v) (func $null (; 5 ;) (type $FUNCSIG$v)
) )
) )

View File

@ -1475,6 +1475,7 @@
call $~lib/string/String.__concat call $~lib/string/String.__concat
) )
(func $start:std/symbol (; 27 ;) (type $FUNCSIG$v) (func $start:std/symbol (; 27 ;) (type $FUNCSIG$v)
(local $0 i32)
i32.const 24 i32.const 24
call $~lib/symbol/Symbol call $~lib/symbol/Symbol
global.set $std/symbol/sym1 global.set $std/symbol/sym1
@ -1537,9 +1538,21 @@
end end
global.get $std/symbol/sym3 global.get $std/symbol/sym3
call $~lib/symbol/_Symbol.keyFor call $~lib/symbol/_Symbol.keyFor
local.tee $0
i32.eqz
if
unreachable
end
local.get $0
global.set $std/symbol/key3 global.set $std/symbol/key3
global.get $std/symbol/sym4 global.get $std/symbol/sym4
call $~lib/symbol/_Symbol.keyFor call $~lib/symbol/_Symbol.keyFor
local.tee $0
i32.eqz
if
unreachable
end
local.get $0
global.set $std/symbol/key4 global.set $std/symbol/key4
global.get $std/symbol/key3 global.get $std/symbol/key3
i32.const 24 i32.const 24

View File

@ -3342,8 +3342,6 @@
(local $1 i32) (local $1 i32)
(local $2 i32) (local $2 i32)
(local $3 i32) (local $3 i32)
(local $4 i32)
(local $5 i32)
i32.const 24 i32.const 24
call $~lib/symbol/Symbol call $~lib/symbol/Symbol
global.set $std/symbol/sym1 global.set $std/symbol/sym1
@ -3423,11 +3421,21 @@
global.get $std/symbol/sym3 global.get $std/symbol/sym3
call $~lib/symbol/_Symbol.keyFor call $~lib/symbol/_Symbol.keyFor
local.tee $0 local.tee $0
if (result i32)
local.get $0
else
unreachable
end
call $~lib/rt/stub/__retain call $~lib/rt/stub/__retain
global.set $std/symbol/key3 global.set $std/symbol/key3
global.get $std/symbol/sym4 global.get $std/symbol/sym4
call $~lib/symbol/_Symbol.keyFor call $~lib/symbol/_Symbol.keyFor
local.tee $1 local.tee $0
if (result i32)
local.get $0
else
unreachable
end
call $~lib/rt/stub/__retain call $~lib/rt/stub/__retain
global.set $std/symbol/key4 global.set $std/symbol/key4
global.get $std/symbol/key3 global.get $std/symbol/key3
@ -3457,7 +3465,7 @@
i32.const 0 i32.const 0
call $~lib/symbol/Symbol call $~lib/symbol/Symbol
call $~lib/symbol/_Symbol#toString call $~lib/symbol/_Symbol#toString
local.tee $2 local.tee $0
i32.const 704 i32.const 704
call $~lib/string/String.__eq call $~lib/string/String.__eq
i32.eqz i32.eqz
@ -3471,7 +3479,7 @@
end end
global.get $std/symbol/sym3 global.get $std/symbol/sym3
call $~lib/symbol/_Symbol#toString call $~lib/symbol/_Symbol#toString
local.tee $3 local.tee $1
i32.const 736 i32.const 736
call $~lib/string/String.__eq call $~lib/string/String.__eq
i32.eqz i32.eqz
@ -3489,7 +3497,7 @@
global.set $std/symbol/isConcatSpreadable global.set $std/symbol/isConcatSpreadable
global.get $std/symbol/hasInstance global.get $std/symbol/hasInstance
call $~lib/symbol/_Symbol#toString call $~lib/symbol/_Symbol#toString
local.tee $4 local.tee $2
i32.const 776 i32.const 776
call $~lib/string/String.__eq call $~lib/string/String.__eq
i32.eqz i32.eqz
@ -3503,7 +3511,7 @@
end end
global.get $std/symbol/isConcatSpreadable global.get $std/symbol/isConcatSpreadable
call $~lib/symbol/_Symbol#toString call $~lib/symbol/_Symbol#toString
local.tee $5 local.tee $3
i32.const 832 i32.const 832
call $~lib/string/String.__eq call $~lib/string/String.__eq
i32.eqz i32.eqz
@ -3527,10 +3535,6 @@
call $~lib/rt/stub/__release call $~lib/rt/stub/__release
local.get $3 local.get $3
call $~lib/rt/stub/__release call $~lib/rt/stub/__release
local.get $4
call $~lib/rt/stub/__release
local.get $5
call $~lib/rt/stub/__release
) )
(func $start (; 34 ;) (type $FUNCSIG$v) (func $start (; 34 ;) (type $FUNCSIG$v)
call $start:std/symbol call $start:std/symbol