clarify contextual flags a bit, rename to constraints

This commit is contained in:
dcode 2019-06-12 12:13:49 +02:00
parent e30fe7e3cb
commit 6a0277bf02
2 changed files with 261 additions and 261 deletions

View File

@ -5,7 +5,7 @@
import { import {
Compiler, Compiler,
ContextualFlags, Constraints,
RuntimeFeatures, RuntimeFeatures,
flatten flatten
} from "./compiler"; } from "./compiler";
@ -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(
@ -1562,7 +1562,7 @@ export function compileCall(
) ? 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
@ -1616,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 (
@ -1705,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) {
@ -1737,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 (
@ -1796,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 (
@ -1861,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) &&
@ -1926,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());
@ -1947,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);
@ -1965,7 +1965,7 @@ 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.compileExpression(operands[0], Type.auto); : 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)) {
@ -1975,7 +1975,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 arg2 = compiler.makeIsTrueish( let arg2 = compiler.makeIsTrueish(
compiler.compileExpression(operands[2], Type.bool), compiler.compileExpression(operands[2], Type.bool),
compiler.currentType // ^ compiler.currentType // ^
@ -2011,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
@ -2027,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);
} }
@ -2046,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);
} }
@ -2085,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.compileExpression(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;
@ -2333,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 ===============================================================
@ -2373,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 (
@ -2383,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 (
@ -2393,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 (
@ -2403,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;
@ -2414,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 (
@ -2424,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 (
@ -2434,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 (
@ -2444,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 (
@ -2454,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;
@ -2465,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 (
@ -2475,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 (
@ -2485,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 (
@ -2495,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 ===================================================================================
@ -2514,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,
@ -2543,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,
@ -2572,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,
@ -2601,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,
@ -2632,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,
@ -2661,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,
@ -2723,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);
} }
@ -2770,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(
@ -2838,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,
@ -2858,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);
} }
@ -2910,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,
@ -3242,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);
} }
@ -3334,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);
} }
@ -3413,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);
} }
@ -3436,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
@ -3449,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
@ -3461,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
@ -3536,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);
} }
@ -3565,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);
@ -3578,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);
@ -3950,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);
} }
@ -4241,7 +4241,7 @@ function evaluateConstantType(
); );
return null; return null;
} }
compiler.compileExpression(operands[0], typeArguments[0], ContextualFlags.IMPLICIT); compiler.compileExpression(operands[0], typeArguments[0], Constraints.CONV_IMPLICIT);
} else { } else {
compiler.compileExpression(operands[0], Type.auto); compiler.compileExpression(operands[0], Type.auto);
} }
@ -4265,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 ||
@ -4279,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 ||

View File

@ -233,23 +233,23 @@ export class Options {
} }
} }
/** Requests or indicates compilation conditions of statements and expressions. */ /** Various constraints in expression compilation. */
export const enum ContextualFlags { export const enum Constraints {
NONE = 0, NONE = 0,
/** Implicit conversion required. */ /** Must implicitly convert to the target type. */
IMPLICIT = 1 << 0, CONV_IMPLICIT = 1 << 0,
/** Explicit conversion required. */ /** Must explicitly convert to the target type. */
EXPLICIT = 1 << 1, CONV_EXPLICIT = 1 << 1,
/** Small integer wrap required. */ /** Must wrap small integer values to match the target type. */
WRAP = 1 << 2, MUST_WRAP = 1 << 2,
/** Value is known to be immediately dropped. */ /** Indicates that the value will be dropped immediately. */
WILL_DROP = 1 << 3, WILL_DROP = 1 << 3,
/** Value is known to be immediately assigned to a retaining target. */ /** Indicates that the value will be retained immediately. */
SKIP_AUTORELEASE = 1 << 4, WILL_RETAIN = 1 << 4,
/** Data can be compiled statically. */ /** Indicates that static data is preferred. */
STATIC_CAPABLE = 1 << 5 PREFER_STATIC = 1 << 5
} }
/** Runtime features to be activated by the compiler. */ /** Runtime features to be activated by the compiler. */
@ -813,7 +813,7 @@ export class Compiler extends DiagnosticEmitter {
this.currentFlow = global.file.startFunction.flow; this.currentFlow = global.file.startFunction.flow;
} }
initExpr = this.compileExpression(initializerNode, Type.auto, // reports initExpr = this.compileExpression(initializerNode, Type.auto, // reports
ContextualFlags.WRAP | ContextualFlags.SKIP_AUTORELEASE Constraints.MUST_WRAP | Constraints.WILL_RETAIN
); );
if (this.skippedAutoreleases.has(initExpr)) initAutoreleaseSkipped = true; if (this.skippedAutoreleases.has(initExpr)) initAutoreleaseSkipped = true;
this.currentFlow = previousFlow; this.currentFlow = previousFlow;
@ -886,7 +886,7 @@ export class Compiler extends DiagnosticEmitter {
this.currentFlow = global.file.startFunction.flow; this.currentFlow = global.file.startFunction.flow;
} }
initExpr = this.compileExpression(initializerNode, type, initExpr = this.compileExpression(initializerNode, type,
ContextualFlags.IMPLICIT | ContextualFlags.WRAP | ContextualFlags.SKIP_AUTORELEASE | ContextualFlags.STATIC_CAPABLE Constraints.CONV_IMPLICIT | Constraints.MUST_WRAP | Constraints.WILL_RETAIN | Constraints.PREFER_STATIC
); );
if (this.skippedAutoreleases.has(initExpr)) initAutoreleaseSkipped = true; if (this.skippedAutoreleases.has(initExpr)) initAutoreleaseSkipped = true;
this.currentFlow = previousFlow; this.currentFlow = previousFlow;
@ -995,7 +995,7 @@ export class Compiler extends DiagnosticEmitter {
let initExpr: ExpressionRef; let initExpr: ExpressionRef;
if (valueNode) { if (valueNode) {
initExpr = this.compileExpression(valueNode, Type.i32, initExpr = this.compileExpression(valueNode, Type.i32,
ContextualFlags.IMPLICIT // autorelease is not applicable in i32 context Constraints.CONV_IMPLICIT // autorelease is not applicable in i32 context
); );
if (getExpressionId(initExpr) != ExpressionId.Const) { if (getExpressionId(initExpr) != ExpressionId.Const) {
initExpr = module.precomputeExpression(initExpr); initExpr = module.precomputeExpression(initExpr);
@ -1138,7 +1138,7 @@ export class Compiler extends DiagnosticEmitter {
assert(!instance.isAny(CommonFlags.CONSTRUCTOR | CommonFlags.GET | CommonFlags.SET | CommonFlags.MAIN)); assert(!instance.isAny(CommonFlags.CONSTRUCTOR | CommonFlags.GET | CommonFlags.SET | CommonFlags.MAIN));
let expr = this.compileExpression((<ExpressionStatement>bodyNode).expression, returnType, let expr = this.compileExpression((<ExpressionStatement>bodyNode).expression, returnType,
ContextualFlags.IMPLICIT Constraints.CONV_IMPLICIT
); );
if (!stmts) stmts = [ expr ]; if (!stmts) stmts = [ expr ];
else stmts.push(expr); else stmts.push(expr);
@ -1965,7 +1965,7 @@ export class Compiler extends DiagnosticEmitter {
compileExpressionStatement( compileExpressionStatement(
statement: ExpressionStatement statement: ExpressionStatement
): ExpressionRef { ): ExpressionRef {
return this.compileExpression(statement.expression, Type.void, ContextualFlags.IMPLICIT); return this.compileExpression(statement.expression, Type.void, Constraints.CONV_IMPLICIT);
} }
compileForStatement( compileForStatement(
@ -2017,7 +2017,7 @@ export class Compiler extends DiagnosticEmitter {
// Compile incrementor // Compile incrementor
var incrementor = statement.incrementor; var incrementor = statement.incrementor;
var incrExpr: ExpressionRef = 0; var incrExpr: ExpressionRef = 0;
if (incrementor) incrExpr = this.compileExpression(incrementor, Type.void, ContextualFlags.IMPLICIT | ContextualFlags.WILL_DROP); if (incrementor) incrExpr = this.compileExpression(incrementor, Type.void, Constraints.CONV_IMPLICIT | Constraints.WILL_DROP);
// Compile body (break: drop out, continue: fall through to incrementor, + loop) // Compile body (break: drop out, continue: fall through to incrementor, + loop)
var breakLabel = innerFlow.breakLabel = "break|" + label; innerFlow.breakLabel = breakLabel; var breakLabel = innerFlow.breakLabel = "break|" + label; innerFlow.breakLabel = breakLabel;
@ -2193,9 +2193,9 @@ export class Compiler extends DiagnosticEmitter {
this.currentType = Type.void; this.currentType = Type.void;
return module.unreachable(); return module.unreachable();
} }
let contextualFlags = ContextualFlags.IMPLICIT; let constraints = Constraints.CONV_IMPLICIT;
if (flow.actualFunction.is(CommonFlags.MODULE_EXPORT)) contextualFlags |= ContextualFlags.WRAP; if (flow.actualFunction.is(CommonFlags.MODULE_EXPORT)) constraints |= Constraints.MUST_WRAP;
expr = this.compileExpression(valueExpression, returnType, contextualFlags | ContextualFlags.SKIP_AUTORELEASE); expr = this.compileExpression(valueExpression, returnType, constraints | Constraints.WILL_RETAIN);
// when returning a local, and it is already retained, skip the final set // when returning a local, and it is already retained, skip the final set
// of retaining it as the return value and releasing it as a variable // of retaining it as the return value and releasing it as a variable
@ -2269,7 +2269,7 @@ export class Compiler extends DiagnosticEmitter {
var numCases = cases.length; var numCases = cases.length;
if (!numCases) { if (!numCases) {
return this.compileExpression(statement.condition, Type.void, return this.compileExpression(statement.condition, Type.void,
ContextualFlags.IMPLICIT Constraints.CONV_IMPLICIT
); );
} }
@ -2286,7 +2286,7 @@ export class Compiler extends DiagnosticEmitter {
breaks[0] = module.local_set( // initializer breaks[0] = module.local_set( // initializer
tempLocalIndex, tempLocalIndex,
this.compileExpression(statement.condition, Type.u32, this.compileExpression(statement.condition, Type.u32,
ContextualFlags.IMPLICIT Constraints.CONV_IMPLICIT
) )
); );
@ -2301,7 +2301,7 @@ export class Compiler extends DiagnosticEmitter {
module.binary(BinaryOp.EqI32, module.binary(BinaryOp.EqI32,
module.local_get(tempLocalIndex, NativeType.I32), module.local_get(tempLocalIndex, NativeType.I32),
this.compileExpression(label, Type.u32, this.compileExpression(label, Type.u32,
ContextualFlags.IMPLICIT Constraints.CONV_IMPLICIT
) )
) )
); );
@ -2437,7 +2437,7 @@ export class Compiler extends DiagnosticEmitter {
if (!type) continue; if (!type) continue;
if (declaration.initializer) { if (declaration.initializer) {
initExpr = this.compileExpression(declaration.initializer, type, // reports initExpr = this.compileExpression(declaration.initializer, type, // reports
ContextualFlags.IMPLICIT | ContextualFlags.SKIP_AUTORELEASE Constraints.CONV_IMPLICIT | Constraints.WILL_RETAIN
); );
initAutoreleaseSkipped = this.skippedAutoreleases.has(initExpr); initAutoreleaseSkipped = this.skippedAutoreleases.has(initExpr);
} }
@ -2445,7 +2445,7 @@ export class Compiler extends DiagnosticEmitter {
// Otherwise infer type from initializer // Otherwise infer type from initializer
} else if (declaration.initializer) { } else if (declaration.initializer) {
initExpr = this.compileExpression(declaration.initializer, Type.auto, initExpr = this.compileExpression(declaration.initializer, Type.auto,
ContextualFlags.SKIP_AUTORELEASE Constraints.WILL_RETAIN
); // reports ); // reports
initAutoreleaseSkipped = this.skippedAutoreleases.has(initExpr); initAutoreleaseSkipped = this.skippedAutoreleases.has(initExpr);
if (this.currentType == Type.void) { if (this.currentType == Type.void) {
@ -2607,7 +2607,7 @@ export class Compiler extends DiagnosticEmitter {
statement: VoidStatement statement: VoidStatement
): ExpressionRef { ): ExpressionRef {
return this.compileExpression(statement.expression, Type.void, return this.compileExpression(statement.expression, Type.void,
ContextualFlags.EXPLICIT | ContextualFlags.WILL_DROP Constraints.CONV_EXPLICIT | Constraints.WILL_DROP
); );
} }
@ -2695,12 +2695,12 @@ export class Compiler extends DiagnosticEmitter {
compileInlineConstant( compileInlineConstant(
element: VariableLikeElement, element: VariableLikeElement,
contextualType: Type, contextualType: Type,
contextualFlags: ContextualFlags constraints: Constraints
): ExpressionRef { ): ExpressionRef {
assert(element.is(CommonFlags.INLINED)); assert(element.is(CommonFlags.INLINED));
var type = element.type; var type = element.type;
switch ( switch (
!(contextualFlags & (ContextualFlags.IMPLICIT | ContextualFlags.EXPLICIT)) && !(constraints & (Constraints.CONV_IMPLICIT | Constraints.CONV_EXPLICIT)) &&
type.is(TypeFlags.INTEGER) && type.is(TypeFlags.INTEGER) &&
contextualType.is(TypeFlags.INTEGER) && contextualType.is(TypeFlags.INTEGER) &&
type.size < contextualType.size type.size < contextualType.size
@ -2775,34 +2775,34 @@ export class Compiler extends DiagnosticEmitter {
compileExpression( compileExpression(
expression: Expression, expression: Expression,
contextualType: Type, contextualType: Type,
contextualFlags: ContextualFlags = ContextualFlags.NONE constraints: Constraints = Constraints.NONE
): ExpressionRef { ): ExpressionRef {
this.currentType = contextualType; this.currentType = contextualType;
var expr: ExpressionRef; var expr: ExpressionRef;
if (contextualType == Type.void) contextualFlags |= ContextualFlags.WILL_DROP; if (contextualType == Type.void) constraints |= Constraints.WILL_DROP;
switch (expression.kind) { switch (expression.kind) {
case NodeKind.ASSERTION: { case NodeKind.ASSERTION: {
expr = this.compileAssertionExpression(<AssertionExpression>expression, contextualType, contextualFlags); expr = this.compileAssertionExpression(<AssertionExpression>expression, contextualType, constraints);
break; break;
} }
case NodeKind.BINARY: { case NodeKind.BINARY: {
expr = this.compileBinaryExpression(<BinaryExpression>expression, contextualType, contextualFlags); expr = this.compileBinaryExpression(<BinaryExpression>expression, contextualType, constraints);
break; break;
} }
case NodeKind.CALL: { case NodeKind.CALL: {
expr = this.compileCallExpression(<CallExpression>expression, contextualType, contextualFlags); expr = this.compileCallExpression(<CallExpression>expression, contextualType, constraints);
break; break;
} }
case NodeKind.COMMA: { case NodeKind.COMMA: {
expr = this.compileCommaExpression(<CommaExpression>expression, contextualType, contextualFlags); expr = this.compileCommaExpression(<CommaExpression>expression, contextualType, constraints);
break; break;
} }
case NodeKind.ELEMENTACCESS: { case NodeKind.ELEMENTACCESS: {
expr = this.compileElementAccessExpression(<ElementAccessExpression>expression, contextualType, contextualFlags); expr = this.compileElementAccessExpression(<ElementAccessExpression>expression, contextualType, constraints);
break; break;
} }
case NodeKind.FUNCTION: { case NodeKind.FUNCTION: {
expr = this.compileFunctionExpression(<FunctionExpression>expression, contextualType.signatureReference, contextualFlags); expr = this.compileFunctionExpression(<FunctionExpression>expression, contextualType.signatureReference, constraints);
break; break;
} }
case NodeKind.IDENTIFIER: case NodeKind.IDENTIFIER:
@ -2811,39 +2811,39 @@ export class Compiler extends DiagnosticEmitter {
case NodeKind.THIS: case NodeKind.THIS:
case NodeKind.SUPER: case NodeKind.SUPER:
case NodeKind.TRUE: { case NodeKind.TRUE: {
expr = this.compileIdentifierExpression(<IdentifierExpression>expression, contextualType, contextualFlags); expr = this.compileIdentifierExpression(<IdentifierExpression>expression, contextualType, constraints);
break; break;
} }
case NodeKind.INSTANCEOF: { case NodeKind.INSTANCEOF: {
expr = this.compileInstanceOfExpression(<InstanceOfExpression>expression, contextualType, contextualFlags); expr = this.compileInstanceOfExpression(<InstanceOfExpression>expression, contextualType, constraints);
break; break;
} }
case NodeKind.LITERAL: { case NodeKind.LITERAL: {
expr = this.compileLiteralExpression(<LiteralExpression>expression, contextualType, contextualFlags); expr = this.compileLiteralExpression(<LiteralExpression>expression, contextualType, constraints);
break; break;
} }
case NodeKind.NEW: { case NodeKind.NEW: {
expr = this.compileNewExpression(<NewExpression>expression, contextualType, contextualFlags); expr = this.compileNewExpression(<NewExpression>expression, contextualType, constraints);
break; break;
} }
case NodeKind.PARENTHESIZED: { case NodeKind.PARENTHESIZED: {
expr = this.compileExpression((<ParenthesizedExpression>expression).expression, contextualType, contextualFlags); expr = this.compileExpression((<ParenthesizedExpression>expression).expression, contextualType, constraints);
break; break;
} }
case NodeKind.PROPERTYACCESS: { case NodeKind.PROPERTYACCESS: {
expr = this.compilePropertyAccessExpression(<PropertyAccessExpression>expression, contextualType, contextualFlags); expr = this.compilePropertyAccessExpression(<PropertyAccessExpression>expression, contextualType, constraints);
break; break;
} }
case NodeKind.TERNARY: { case NodeKind.TERNARY: {
expr = this.compileTernaryExpression(<TernaryExpression>expression, contextualType, contextualFlags); expr = this.compileTernaryExpression(<TernaryExpression>expression, contextualType, constraints);
break; break;
} }
case NodeKind.UNARYPOSTFIX: { case NodeKind.UNARYPOSTFIX: {
expr = this.compileUnaryPostfixExpression(<UnaryPostfixExpression>expression, contextualType, contextualFlags); expr = this.compileUnaryPostfixExpression(<UnaryPostfixExpression>expression, contextualType, constraints);
break; break;
} }
case NodeKind.UNARYPREFIX: { case NodeKind.UNARYPREFIX: {
expr = this.compileUnaryPrefixExpression(<UnaryPrefixExpression>expression, contextualType, contextualFlags); expr = this.compileUnaryPrefixExpression(<UnaryPrefixExpression>expression, contextualType, constraints);
break; break;
} }
default: { default: {
@ -2856,13 +2856,13 @@ export class Compiler extends DiagnosticEmitter {
} }
// ensure conversion and wrapping in case the respective function doesn't on its own // ensure conversion and wrapping in case the respective function doesn't on its own
var currentType = this.currentType; var currentType = this.currentType;
var wrap = (contextualFlags & ContextualFlags.WRAP) != 0; var wrap = (constraints & Constraints.MUST_WRAP) != 0;
if (currentType != contextualType) { if (currentType != contextualType) {
if (contextualFlags & ContextualFlags.EXPLICIT) { if (constraints & Constraints.CONV_EXPLICIT) {
expr = this.convertExpression(expr, currentType, contextualType, true, wrap, expression); expr = this.convertExpression(expr, currentType, contextualType, true, wrap, expression);
wrap = false; wrap = false;
this.currentType = contextualType; this.currentType = contextualType;
} else if (contextualFlags & ContextualFlags.IMPLICIT) { } else if (constraints & Constraints.CONV_IMPLICIT) {
expr = this.convertExpression(expr, currentType, contextualType, false, wrap, expression); expr = this.convertExpression(expr, currentType, contextualType, false, wrap, expression);
wrap = false; wrap = false;
this.currentType = contextualType; this.currentType = contextualType;
@ -2879,10 +2879,10 @@ export class Compiler extends DiagnosticEmitter {
precomputeExpression( precomputeExpression(
expression: Expression, expression: Expression,
contextualType: Type, contextualType: Type,
contextualFlags: ContextualFlags = ContextualFlags.NONE constraints: Constraints = Constraints.NONE
): ExpressionRef { ): ExpressionRef {
return this.module.precomputeExpression( return this.module.precomputeExpression(
this.compileExpression(expression, contextualType, contextualFlags) this.compileExpression(expression, contextualType, constraints)
); );
} }
@ -3082,9 +3082,9 @@ export class Compiler extends DiagnosticEmitter {
compileAssertionExpression( compileAssertionExpression(
expression: AssertionExpression, expression: AssertionExpression,
contextualType: Type, contextualType: Type,
contextualFlags: ContextualFlags constraints: Constraints
): ExpressionRef { ): ExpressionRef {
var inheritedFlags = contextualFlags & ~(ContextualFlags.IMPLICIT | ContextualFlags.EXPLICIT); var inheritedConstraints = constraints & ~(Constraints.CONV_IMPLICIT | Constraints.CONV_EXPLICIT);
switch (expression.assertionKind) { switch (expression.assertionKind) {
case AssertionKind.PREFIX: case AssertionKind.PREFIX:
case AssertionKind.AS: { case AssertionKind.AS: {
@ -3095,11 +3095,11 @@ export class Compiler extends DiagnosticEmitter {
flow.contextualTypeArguments flow.contextualTypeArguments
); );
if (!toType) return this.module.unreachable(); if (!toType) return this.module.unreachable();
return this.compileExpression(expression.expression, toType, inheritedFlags | ContextualFlags.EXPLICIT); return this.compileExpression(expression.expression, toType, inheritedConstraints | Constraints.CONV_EXPLICIT);
} }
case AssertionKind.NONNULL: { case AssertionKind.NONNULL: {
assert(!expression.toType); assert(!expression.toType);
let expr = this.compileExpression(expression.expression, contextualType.exceptVoid, inheritedFlags); let expr = this.compileExpression(expression.expression, contextualType.exceptVoid, inheritedConstraints);
let type = this.currentType; let type = this.currentType;
if (this.currentFlow.isNonnull(expr, type)) { if (this.currentFlow.isNonnull(expr, type)) {
this.info( this.info(
@ -3134,7 +3134,7 @@ export class Compiler extends DiagnosticEmitter {
compileBinaryExpression( compileBinaryExpression(
expression: BinaryExpression, expression: BinaryExpression,
contextualType: Type, contextualType: Type,
contextualFlags: ContextualFlags constraints: Constraints
): ExpressionRef { ): ExpressionRef {
var module = this.module; var module = this.module;
var left = expression.left; var left = expression.left;
@ -3759,7 +3759,7 @@ export class Compiler extends DiagnosticEmitter {
} }
if (compound) { if (compound) {
rightExpr = this.compileExpression(right, leftType, ContextualFlags.IMPLICIT); rightExpr = this.compileExpression(right, leftType, Constraints.CONV_IMPLICIT);
} else { } else {
rightExpr = this.compileExpression(right, leftType); rightExpr = this.compileExpression(right, leftType);
rightType = this.currentType; rightType = this.currentType;
@ -3848,7 +3848,7 @@ export class Compiler extends DiagnosticEmitter {
} }
if (compound) { if (compound) {
rightExpr = this.compileExpression(right, leftType, ContextualFlags.IMPLICIT); rightExpr = this.compileExpression(right, leftType, Constraints.CONV_IMPLICIT);
rightType = this.currentType; rightType = this.currentType;
} else { } else {
rightExpr = this.compileExpression(right, leftType); rightExpr = this.compileExpression(right, leftType);
@ -3939,7 +3939,7 @@ export class Compiler extends DiagnosticEmitter {
if (compound) { if (compound) {
leftExpr = this.ensureSmallIntegerWrap(leftExpr, leftType); leftExpr = this.ensureSmallIntegerWrap(leftExpr, leftType);
rightExpr = this.compileExpression(right, leftType, ContextualFlags.IMPLICIT); rightExpr = this.compileExpression(right, leftType, Constraints.CONV_IMPLICIT);
} else { } else {
rightExpr = this.compileExpression(right, leftType); rightExpr = this.compileExpression(right, leftType);
rightType = this.currentType; rightType = this.currentType;
@ -4031,7 +4031,7 @@ export class Compiler extends DiagnosticEmitter {
// Mathf.pow if lhs is f32 (result is f32) // Mathf.pow if lhs is f32 (result is f32)
if (this.currentType.kind == TypeKind.F32) { if (this.currentType.kind == TypeKind.F32) {
rightExpr = this.compileExpression(right, Type.f32, ContextualFlags.IMPLICIT); rightExpr = this.compileExpression(right, Type.f32, Constraints.CONV_IMPLICIT);
rightType = this.currentType; rightType = this.currentType;
if (!(instance = this.f32PowInstance)) { if (!(instance = this.f32PowInstance)) {
let namespace = this.program.lookupGlobal(CommonSymbols.Mathf); let namespace = this.program.lookupGlobal(CommonSymbols.Mathf);
@ -4065,7 +4065,7 @@ export class Compiler extends DiagnosticEmitter {
left left
); );
leftType = this.currentType; leftType = this.currentType;
rightExpr = this.compileExpression(right, Type.f64, ContextualFlags.IMPLICIT); rightExpr = this.compileExpression(right, Type.f64, Constraints.CONV_IMPLICIT);
rightType = this.currentType; rightType = this.currentType;
if (!(instance = this.f64PowInstance)) { if (!(instance = this.f64PowInstance)) {
let namespace = this.program.lookupGlobal(CommonSymbols.Math); let namespace = this.program.lookupGlobal(CommonSymbols.Math);
@ -4121,7 +4121,7 @@ export class Compiler extends DiagnosticEmitter {
if (compound) { if (compound) {
leftExpr = this.ensureSmallIntegerWrap(leftExpr, leftType); leftExpr = this.ensureSmallIntegerWrap(leftExpr, leftType);
rightExpr = this.compileExpression(right, leftType, ContextualFlags.IMPLICIT); rightExpr = this.compileExpression(right, leftType, Constraints.CONV_IMPLICIT);
rightType = this.currentType; rightType = this.currentType;
} else { } else {
rightExpr = this.compileExpression(right, leftType); rightExpr = this.compileExpression(right, leftType);
@ -4230,7 +4230,7 @@ export class Compiler extends DiagnosticEmitter {
if (compound) { if (compound) {
leftExpr = this.ensureSmallIntegerWrap(leftExpr, leftType); leftExpr = this.ensureSmallIntegerWrap(leftExpr, leftType);
rightExpr = this.compileExpression(right, leftType, ContextualFlags.IMPLICIT); rightExpr = this.compileExpression(right, leftType, Constraints.CONV_IMPLICIT);
rightType = this.currentType; rightType = this.currentType;
} else { } else {
rightExpr = this.compileExpression(right, leftType); rightExpr = this.compileExpression(right, leftType);
@ -4394,7 +4394,7 @@ export class Compiler extends DiagnosticEmitter {
return this.module.unreachable(); return this.module.unreachable();
} }
rightExpr = this.compileExpression(right, leftType, ContextualFlags.IMPLICIT); rightExpr = this.compileExpression(right, leftType, Constraints.CONV_IMPLICIT);
rightType = this.currentType; rightType = this.currentType;
switch (this.currentType.kind) { switch (this.currentType.kind) {
case TypeKind.I8: case TypeKind.I8:
@ -4461,7 +4461,7 @@ export class Compiler extends DiagnosticEmitter {
} }
leftExpr = this.ensureSmallIntegerWrap(leftExpr, leftType); // must clear garbage bits leftExpr = this.ensureSmallIntegerWrap(leftExpr, leftType); // must clear garbage bits
rightExpr = this.compileExpression(right, leftType, ContextualFlags.IMPLICIT); rightExpr = this.compileExpression(right, leftType, Constraints.CONV_IMPLICIT);
rightType = this.currentType; rightType = this.currentType;
switch (this.currentType.kind) { switch (this.currentType.kind) {
case TypeKind.I8: case TypeKind.I8:
@ -4549,7 +4549,7 @@ export class Compiler extends DiagnosticEmitter {
} }
leftExpr = this.ensureSmallIntegerWrap(leftExpr, leftType); // must clear garbage bits leftExpr = this.ensureSmallIntegerWrap(leftExpr, leftType); // must clear garbage bits
rightExpr = this.compileExpression(right, leftType, ContextualFlags.IMPLICIT); rightExpr = this.compileExpression(right, leftType, Constraints.CONV_IMPLICIT);
rightType = this.currentType; rightType = this.currentType;
switch (this.currentType.kind) { switch (this.currentType.kind) {
case TypeKind.U8: case TypeKind.U8:
@ -4618,7 +4618,7 @@ export class Compiler extends DiagnosticEmitter {
} }
if (compound) { if (compound) {
rightExpr = this.compileExpression(right, leftType, ContextualFlags.IMPLICIT); rightExpr = this.compileExpression(right, leftType, Constraints.CONV_IMPLICIT);
rightType = this.currentType; rightType = this.currentType;
} else { } else {
rightExpr = this.compileExpression(right, leftType); rightExpr = this.compileExpression(right, leftType);
@ -4708,7 +4708,7 @@ export class Compiler extends DiagnosticEmitter {
} }
if (compound) { if (compound) {
rightExpr = this.compileExpression(right, leftType, ContextualFlags.IMPLICIT); rightExpr = this.compileExpression(right, leftType, Constraints.CONV_IMPLICIT);
rightType = this.currentType; rightType = this.currentType;
} else { } else {
rightExpr = this.compileExpression(right, leftType); rightExpr = this.compileExpression(right, leftType);
@ -4801,7 +4801,7 @@ export class Compiler extends DiagnosticEmitter {
} }
if (compound) { if (compound) {
rightExpr = this.compileExpression(right, leftType, ContextualFlags.IMPLICIT); rightExpr = this.compileExpression(right, leftType, Constraints.CONV_IMPLICIT);
rightType = this.currentType; rightType = this.currentType;
} else { } else {
rightExpr = this.compileExpression(right, leftType); rightExpr = this.compileExpression(right, leftType);
@ -4876,14 +4876,14 @@ export class Compiler extends DiagnosticEmitter {
case Token.AMPERSAND_AMPERSAND: { // left && right -> (t = left) ? right : t case Token.AMPERSAND_AMPERSAND: { // left && right -> (t = left) ? right : t
let flow = this.currentFlow; let flow = this.currentFlow;
let inheritedFlags = contextualFlags & (ContextualFlags.SKIP_AUTORELEASE | ContextualFlags.WRAP); let inheritedConstraints = constraints & (Constraints.WILL_RETAIN | Constraints.MUST_WRAP);
leftExpr = this.compileExpression(left, contextualType.exceptVoid, inheritedFlags); leftExpr = this.compileExpression(left, contextualType.exceptVoid, inheritedConstraints);
leftType = this.currentType; leftType = this.currentType;
let rightFlow = flow.fork(); let rightFlow = flow.fork();
this.currentFlow = rightFlow; this.currentFlow = rightFlow;
rightFlow.inheritNonnullIfTrue(leftExpr); rightFlow.inheritNonnullIfTrue(leftExpr);
rightExpr = this.compileExpression(right, leftType, inheritedFlags | ContextualFlags.IMPLICIT); rightExpr = this.compileExpression(right, leftType, inheritedConstraints | Constraints.CONV_IMPLICIT);
rightType = leftType; rightType = leftType;
// simplify if only interested in true or false // simplify if only interested in true or false
@ -4915,7 +4915,7 @@ export class Compiler extends DiagnosticEmitter {
rightExpr = this.makeRetain(rightExpr); rightExpr = this.makeRetain(rightExpr);
rightAutoreleaseSkipped = true; rightAutoreleaseSkipped = true;
} }
} else if (!(contextualFlags & ContextualFlags.SKIP_AUTORELEASE)) { // otherwise keep right alive a little longer } else if (!(constraints & Constraints.WILL_RETAIN)) { // otherwise keep right alive a little longer
rightExpr = this.moveAutorelease(rightExpr, rightFlow, flow); rightExpr = this.moveAutorelease(rightExpr, rightFlow, flow);
} }
@ -4974,14 +4974,14 @@ export class Compiler extends DiagnosticEmitter {
} }
case Token.BAR_BAR: { // left || right -> ((t = left) ? t : right) case Token.BAR_BAR: { // left || right -> ((t = left) ? t : right)
let flow = this.currentFlow; let flow = this.currentFlow;
let inheritedFlags = contextualFlags & (ContextualFlags.SKIP_AUTORELEASE | ContextualFlags.WRAP); let inheritedConstraints = constraints & (Constraints.WILL_RETAIN | Constraints.MUST_WRAP);
leftExpr = this.compileExpression(left, contextualType.exceptVoid, inheritedFlags); leftExpr = this.compileExpression(left, contextualType.exceptVoid, inheritedConstraints);
leftType = this.currentType; leftType = this.currentType;
let rightFlow = flow.fork(); let rightFlow = flow.fork();
this.currentFlow = rightFlow; this.currentFlow = rightFlow;
rightFlow.inheritNonnullIfFalse(leftExpr); rightFlow.inheritNonnullIfFalse(leftExpr);
rightExpr = this.compileExpression(right, leftType, inheritedFlags | ContextualFlags.IMPLICIT); rightExpr = this.compileExpression(right, leftType, inheritedConstraints | Constraints.CONV_IMPLICIT);
rightType = leftType; rightType = leftType;
// simplify if only interested in true or false // simplify if only interested in true or false
@ -5013,7 +5013,7 @@ export class Compiler extends DiagnosticEmitter {
rightExpr = this.makeRetain(rightExpr); rightExpr = this.makeRetain(rightExpr);
rightAutoreleaseSkipped = true; rightAutoreleaseSkipped = true;
} }
} else if (!(contextualFlags & ContextualFlags.SKIP_AUTORELEASE)) { // otherwise keep right alive a little longer } else if (!(constraints & Constraints.WILL_RETAIN)) { // otherwise keep right alive a little longer
rightExpr = this.moveAutorelease(rightExpr, rightFlow, flow); rightExpr = this.moveAutorelease(rightExpr, rightFlow, flow);
} }
@ -5124,7 +5124,7 @@ export class Compiler extends DiagnosticEmitter {
// it can actually resolve every kind of expression without ever having to recompile. // it can actually resolve every kind of expression without ever having to recompile.
rightType = operatorInstance.signature.parameterTypes[1]; rightType = operatorInstance.signature.parameterTypes[1];
} }
var rightExpr = this.compileExpression(right, rightType, ContextualFlags.IMPLICIT); var rightExpr = this.compileExpression(right, rightType, Constraints.CONV_IMPLICIT);
return this.makeCallDirect(operatorInstance, [ leftExpr, rightExpr ], reportNode); return this.makeCallDirect(operatorInstance, [ leftExpr, rightExpr ], reportNode);
} }
@ -5232,7 +5232,7 @@ export class Compiler extends DiagnosticEmitter {
assert(targetType != Type.void); assert(targetType != Type.void);
return this.makeAssignment( return this.makeAssignment(
target, target,
this.compileExpression(valueExpression, targetType, ContextualFlags.IMPLICIT | ContextualFlags.SKIP_AUTORELEASE), this.compileExpression(valueExpression, targetType, Constraints.CONV_IMPLICIT | Constraints.WILL_RETAIN),
expression, expression,
thisExpression, thisExpression,
elementExpression, elementExpression,
@ -5388,7 +5388,7 @@ export class Compiler extends DiagnosticEmitter {
} }
let targetType = (<Class>target).type; let targetType = (<Class>target).type;
let thisExpr = this.compileExpression(assert(thisExpression), this.options.usizeType); let thisExpr = this.compileExpression(assert(thisExpression), this.options.usizeType);
let elementExpr = this.compileExpression(indexExpression, Type.i32, ContextualFlags.IMPLICIT); let elementExpr = this.compileExpression(indexExpression, Type.i32, Constraints.CONV_IMPLICIT);
if (tee) { if (tee) {
let tempLocalTarget = flow.getTempLocal(targetType); let tempLocalTarget = flow.getTempLocal(targetType);
let tempLocalElement = flow.getAndFreeTempLocal(this.currentType); let tempLocalElement = flow.getAndFreeTempLocal(this.currentType);
@ -5700,8 +5700,8 @@ export class Compiler extends DiagnosticEmitter {
expression: CallExpression, expression: CallExpression,
/** Contextual type indicating the return type the caller expects, if any. */ /** Contextual type indicating the return type the caller expects, if any. */
contextualType: Type, contextualType: Type,
/** Contextual flags indicating contextual conditions. */ /** Constraints indicating contextual conditions. */
contextualFlags: ContextualFlags constraints: Constraints
): ExpressionRef { ): ExpressionRef {
var module = this.module; var module = this.module;
@ -5740,7 +5740,7 @@ export class Compiler extends DiagnosticEmitter {
this.makeAllocation(<Class>classInstance) this.makeAllocation(<Class>classInstance)
) )
), ),
ContextualFlags.SKIP_AUTORELEASE Constraints.WILL_RETAIN
); );
assert(this.skippedAutoreleases.has(theCall)); // guaranteed assert(this.skippedAutoreleases.has(theCall)); // guaranteed
let stmts: ExpressionRef[] = [ let stmts: ExpressionRef[] = [
@ -5858,7 +5858,7 @@ export class Compiler extends DiagnosticEmitter {
flow.contextualTypeArguments flow.contextualTypeArguments
); );
if (!concreteType) return module.unreachable(); if (!concreteType) return module.unreachable();
argumentExprs[i] = this.compileExpression(argumentExpression, concreteType, ContextualFlags.IMPLICIT); argumentExprs[i] = this.compileExpression(argumentExpression, concreteType, Constraints.CONV_IMPLICIT);
} }
} }
let resolvedTypeArguments = new Array<Type>(numTypeParameters); let resolvedTypeArguments = new Array<Type>(numTypeParameters);
@ -5894,7 +5894,7 @@ export class Compiler extends DiagnosticEmitter {
expression.arguments, expression.arguments,
expression, expression,
thisExpr, thisExpr,
contextualFlags constraints
); );
} }
@ -5950,7 +5950,7 @@ export class Compiler extends DiagnosticEmitter {
} }
case ElementKind.FUNCTION_TARGET: { case ElementKind.FUNCTION_TARGET: {
signature = (<FunctionTarget>target).signature; signature = (<FunctionTarget>target).signature;
indexArg = this.compileExpression(expression.expression, (<FunctionTarget>target).type, ContextualFlags.IMPLICIT); indexArg = this.compileExpression(expression.expression, (<FunctionTarget>target).type, Constraints.CONV_IMPLICIT);
break; break;
} }
@ -6113,7 +6113,7 @@ export class Compiler extends DiagnosticEmitter {
argumentExpressions: Expression[], argumentExpressions: Expression[],
reportNode: Node, reportNode: Node,
thisArg: ExpressionRef = 0, thisArg: ExpressionRef = 0,
contextualFlags: ContextualFlags = ContextualFlags.NONE constraints: Constraints = Constraints.NONE
): ExpressionRef { ): ExpressionRef {
var numArguments = argumentExpressions.length; var numArguments = argumentExpressions.length;
var signature = instance.signature; var signature = instance.signature;
@ -6143,13 +6143,13 @@ export class Compiler extends DiagnosticEmitter {
let args = new Array<ExpressionRef>(numArguments); let args = new Array<ExpressionRef>(numArguments);
for (let i = 0; i < numArguments; ++i) { for (let i = 0; i < numArguments; ++i) {
args[i] = this.compileExpression(argumentExpressions[i], parameterTypes[i], args[i] = this.compileExpression(argumentExpressions[i], parameterTypes[i],
ContextualFlags.IMPLICIT | ContextualFlags.SKIP_AUTORELEASE Constraints.CONV_IMPLICIT | Constraints.WILL_RETAIN
); );
} }
// make the inlined call (is aware of autoreleases) // make the inlined call (is aware of autoreleases)
let expr = this.makeCallInline(instance, args, thisArg, (contextualFlags & ContextualFlags.WILL_DROP) != 0); let expr = this.makeCallInline(instance, args, thisArg, (constraints & Constraints.WILL_DROP) != 0);
if (this.currentType.isManaged) { if (this.currentType.isManaged) {
if (!(contextualFlags & ContextualFlags.SKIP_AUTORELEASE)) { if (!(constraints & Constraints.WILL_RETAIN)) {
expr = this.makeAutorelease(expr, this.currentFlow); expr = this.makeAutorelease(expr, this.currentFlow);
} else { } else {
this.skippedAutoreleases.add(expr); this.skippedAutoreleases.add(expr);
@ -6171,15 +6171,15 @@ export class Compiler extends DiagnosticEmitter {
var parameterTypes = signature.parameterTypes; var parameterTypes = signature.parameterTypes;
for (let i = 0; i < numArguments; ++i, ++index) { for (let i = 0; i < numArguments; ++i, ++index) {
operands[index] = this.compileExpression(argumentExpressions[i], parameterTypes[i], operands[index] = this.compileExpression(argumentExpressions[i], parameterTypes[i],
ContextualFlags.IMPLICIT Constraints.CONV_IMPLICIT
); );
} }
assert(index == numArgumentsInclThis); assert(index == numArgumentsInclThis);
if (signature.returnType.isManaged) { if (signature.returnType.isManaged) {
if (contextualFlags & ContextualFlags.WILL_DROP) { if (constraints & Constraints.WILL_DROP) {
// Skip autorelease and simply release // Skip autorelease and simply release
return this.makeCallDirect(instance, operands, reportNode, true); return this.makeCallDirect(instance, operands, reportNode, true);
} else if (contextualFlags & ContextualFlags.SKIP_AUTORELEASE) { } else if (constraints & Constraints.WILL_RETAIN) {
// Skip autorelease and remember // Skip autorelease and remember
let expr = this.makeCallDirect(instance, operands, reportNode, false, true); let expr = this.makeCallDirect(instance, operands, reportNode, false, true);
this.skippedAutoreleases.add(expr); this.skippedAutoreleases.add(expr);
@ -6189,7 +6189,7 @@ export class Compiler extends DiagnosticEmitter {
} }
} }
return this.makeCallDirect(instance, operands, reportNode, return this.makeCallDirect(instance, operands, reportNode,
(contextualFlags & ContextualFlags.WILL_DROP) != 0 (constraints & Constraints.WILL_DROP) != 0
); );
} }
@ -6256,7 +6256,7 @@ export class Compiler extends DiagnosticEmitter {
let initExpr = this.compileExpression( let initExpr = this.compileExpression(
assert(instance.prototype.signatureNode.parameters[i].initializer), assert(instance.prototype.signatureNode.parameters[i].initializer),
initType, initType,
ContextualFlags.IMPLICIT Constraints.CONV_IMPLICIT
); );
let argumentLocal = flow.addScopedLocal(signature.getParameterName(i), initType); let argumentLocal = flow.addScopedLocal(signature.getParameterName(i), initType);
if (!flow.canOverflow(initExpr, initType)) flow.setLocalFlag(argumentLocal.index, LocalFlags.WRAPPED); if (!flow.canOverflow(initExpr, initType)) flow.setLocalFlag(argumentLocal.index, LocalFlags.WRAPPED);
@ -6398,7 +6398,7 @@ export class Compiler extends DiagnosticEmitter {
this.compileExpression( this.compileExpression(
initializer, initializer,
type, type,
ContextualFlags.IMPLICIT Constraints.CONV_IMPLICIT
) )
); );
} else { } else {
@ -6715,7 +6715,7 @@ export class Compiler extends DiagnosticEmitter {
operands.push(this.compileExpression( operands.push(this.compileExpression(
<Expression>parameterNodes[i].initializer, <Expression>parameterNodes[i].initializer,
parameterTypes[i], parameterTypes[i],
ContextualFlags.IMPLICIT Constraints.CONV_IMPLICIT
)); ));
continue; continue;
} }
@ -6726,7 +6726,7 @@ export class Compiler extends DiagnosticEmitter {
if (this.compileGlobal(global)) { if (this.compileGlobal(global)) {
if (global.is(CommonFlags.INLINED)) { if (global.is(CommonFlags.INLINED)) {
operands.push( operands.push(
this.compileInlineConstant(global, parameterTypes[i], ContextualFlags.IMPLICIT) this.compileInlineConstant(global, parameterTypes[i], Constraints.CONV_IMPLICIT)
); );
} else { } else {
operands.push( operands.push(
@ -6817,7 +6817,7 @@ export class Compiler extends DiagnosticEmitter {
var parameterTypes = signature.parameterTypes; var parameterTypes = signature.parameterTypes;
for (let i = 0; i < numArguments; ++i, ++index) { for (let i = 0; i < numArguments; ++i, ++index) {
operands[index] = this.compileExpression(argumentExpressions[i], parameterTypes[i], operands[index] = this.compileExpression(argumentExpressions[i], parameterTypes[i],
ContextualFlags.IMPLICIT Constraints.CONV_IMPLICIT
); );
} }
assert(index == numArgumentsInclThis); assert(index == numArgumentsInclThis);
@ -6881,24 +6881,24 @@ export class Compiler extends DiagnosticEmitter {
compileCommaExpression( compileCommaExpression(
expression: CommaExpression, expression: CommaExpression,
contextualType: Type, contextualType: Type,
contextualFlags: ContextualFlags constraints: Constraints
): ExpressionRef { ): ExpressionRef {
var expressions = expression.expressions; var expressions = expression.expressions;
var numExpressions = expressions.length; var numExpressions = expressions.length;
var exprs = new Array<ExpressionRef>(numExpressions--); var exprs = new Array<ExpressionRef>(numExpressions--);
for (let i = 0; i < numExpressions; ++i) { for (let i = 0; i < numExpressions; ++i) {
exprs[i] = this.compileExpression(expressions[i], Type.void, // drop all except last exprs[i] = this.compileExpression(expressions[i], Type.void, // drop all except last
ContextualFlags.IMPLICIT | ContextualFlags.WILL_DROP Constraints.CONV_IMPLICIT | Constraints.WILL_DROP
); );
} }
exprs[numExpressions] = this.compileExpression(expressions[numExpressions], contextualType, contextualFlags); exprs[numExpressions] = this.compileExpression(expressions[numExpressions], contextualType, constraints);
return this.module.block(null, exprs, this.currentType.toNativeType()); return this.module.block(null, exprs, this.currentType.toNativeType());
} }
compileElementAccessExpression( compileElementAccessExpression(
expression: ElementAccessExpression, expression: ElementAccessExpression,
contextualType: Type, contextualType: Type,
contextualFlags: ContextualFlags constraints: Constraints
): ExpressionRef { ): ExpressionRef {
var target = this.resolver.resolveElementAccessExpression( var target = this.resolver.resolveElementAccessExpression(
expression, expression,
@ -6917,11 +6917,11 @@ export class Compiler extends DiagnosticEmitter {
return this.module.unreachable(); return this.module.unreachable();
} }
let thisArg = this.compileExpression(expression.expression, (<Class>target).type, let thisArg = this.compileExpression(expression.expression, (<Class>target).type,
ContextualFlags.IMPLICIT Constraints.CONV_IMPLICIT
); );
return this.compileCallDirect(indexedGet, [ return this.compileCallDirect(indexedGet, [
expression.elementExpression expression.elementExpression
], expression, thisArg, contextualFlags & (ContextualFlags.WILL_DROP | ContextualFlags.SKIP_AUTORELEASE)); ], expression, thisArg, constraints);
} }
} }
this.error( this.error(
@ -6934,7 +6934,7 @@ export class Compiler extends DiagnosticEmitter {
compileFunctionExpression( compileFunctionExpression(
expression: FunctionExpression, expression: FunctionExpression,
contextualSignature: Signature | null, contextualSignature: Signature | null,
contextualFlags: ContextualFlags constraints: Constraints
): ExpressionRef { ): ExpressionRef {
var declaration = expression.declaration.clone(); // generic contexts can have multiple var declaration = expression.declaration.clone(); // generic contexts can have multiple
assert(!declaration.typeParameters); // function expression cannot be generic assert(!declaration.typeParameters); // function expression cannot be generic
@ -7088,7 +7088,7 @@ export class Compiler extends DiagnosticEmitter {
compileIdentifierExpression( compileIdentifierExpression(
expression: IdentifierExpression, expression: IdentifierExpression,
contextualType: Type, contextualType: Type,
contextualFlags: ContextualFlags constraints: Constraints
): ExpressionRef { ): ExpressionRef {
var module = this.module; var module = this.module;
var flow = this.currentFlow; var flow = this.currentFlow;
@ -7215,7 +7215,7 @@ export class Compiler extends DiagnosticEmitter {
let type = (<Local>target).type; let type = (<Local>target).type;
assert(type != Type.void); assert(type != Type.void);
if ((<Local>target).is(CommonFlags.INLINED)) { if ((<Local>target).is(CommonFlags.INLINED)) {
return this.compileInlineConstant(<Local>target, contextualType, contextualFlags); return this.compileInlineConstant(<Local>target, contextualType, constraints);
} }
let localIndex = (<Local>target).index; let localIndex = (<Local>target).index;
assert(localIndex >= 0); assert(localIndex >= 0);
@ -7232,7 +7232,7 @@ export class Compiler extends DiagnosticEmitter {
let type = (<Global>target).type; let type = (<Global>target).type;
assert(type != Type.void); assert(type != Type.void);
if ((<Global>target).is(CommonFlags.INLINED)) { if ((<Global>target).is(CommonFlags.INLINED)) {
return this.compileInlineConstant(<Global>target, contextualType, contextualFlags); return this.compileInlineConstant(<Global>target, contextualType, constraints);
} }
this.currentType = type; this.currentType = type;
return this.module.global_get((<Global>target).internalName, type.toNativeType()); return this.module.global_get((<Global>target).internalName, type.toNativeType());
@ -7275,7 +7275,7 @@ export class Compiler extends DiagnosticEmitter {
compileInstanceOfExpression( compileInstanceOfExpression(
expression: InstanceOfExpression, expression: InstanceOfExpression,
contextualType: Type, contextualType: Type,
contextualFlags: ContextualFlags constraints: Constraints
): ExpressionRef { ): ExpressionRef {
var module = this.module; var module = this.module;
// NOTE that this differs from TypeScript in that the rhs is a type, not an expression. at the // NOTE that this differs from TypeScript in that the rhs is a type, not an expression. at the
@ -7291,7 +7291,7 @@ export class Compiler extends DiagnosticEmitter {
// instanceof <basic> - must be exact // instanceof <basic> - must be exact
if (!expectedType.is(TypeFlags.REFERENCE)) { if (!expectedType.is(TypeFlags.REFERENCE)) {
return module.block(null, [ return module.block(null, [
this.convertExpression(expr, actualType, Type.void, (contextualFlags & ContextualFlags.EXPLICIT) != 0, false, expression.expression), module.drop(expr),
module.i32(actualType == expectedType ? 1 : 0) module.i32(actualType == expectedType ? 1 : 0)
], NativeType.I32); ], NativeType.I32);
} }
@ -7299,7 +7299,7 @@ export class Compiler extends DiagnosticEmitter {
// <basic> instanceof <reference> - always false // <basic> instanceof <reference> - always false
if (!actualType.is(TypeFlags.REFERENCE)) { if (!actualType.is(TypeFlags.REFERENCE)) {
return module.block(null, [ return module.block(null, [
this.convertExpression(expr, actualType, Type.void, (contextualFlags & ContextualFlags.EXPLICIT) != 0,false, expression.expression), module.drop(expr),
module.i32(0) module.i32(0)
], NativeType.I32); ], NativeType.I32);
} }
@ -7356,7 +7356,7 @@ export class Compiler extends DiagnosticEmitter {
// downcast - check statically // downcast - check statically
if (actualType.isAssignableTo(expectedType)) { if (actualType.isAssignableTo(expectedType)) {
return module.block(null, [ return module.block(null, [
this.convertExpression(expr, actualType, Type.void, (contextualFlags & ContextualFlags.EXPLICIT) != 0, false, expression.expression), this.convertExpression(expr, actualType, Type.void, false, false, expression.expression),
module.i32(1) module.i32(1)
], NativeType.I32); ], NativeType.I32);
@ -7395,7 +7395,7 @@ export class Compiler extends DiagnosticEmitter {
// false // false
return module.block(null, [ return module.block(null, [
this.convertExpression(expr, actualType, Type.void, (contextualFlags & ContextualFlags.EXPLICIT) != 0, false, expression.expression), module.drop(expr),
module.i32(0) module.i32(0)
], NativeType.I32); ], NativeType.I32);
} }
@ -7403,7 +7403,7 @@ export class Compiler extends DiagnosticEmitter {
compileLiteralExpression( compileLiteralExpression(
expression: LiteralExpression, expression: LiteralExpression,
contextualType: Type, contextualType: Type,
contextualFlags: ContextualFlags, constraints: Constraints,
implicitlyNegate: bool = false implicitlyNegate: bool = false
): ExpressionRef { ): ExpressionRef {
var module = this.module; var module = this.module;
@ -7416,8 +7416,7 @@ export class Compiler extends DiagnosticEmitter {
return this.compileArrayLiteral( return this.compileArrayLiteral(
assert(classType.typeArguments)[0], assert(classType.typeArguments)[0],
(<ArrayLiteralExpression>expression).elementExpressions, (<ArrayLiteralExpression>expression).elementExpressions,
false, // TODO: isConst? constraints,
contextualFlags,
expression expression
); );
} }
@ -7484,8 +7483,7 @@ export class Compiler extends DiagnosticEmitter {
compileArrayLiteral( compileArrayLiteral(
elementType: Type, elementType: Type,
expressions: (Expression | null)[], expressions: (Expression | null)[],
isConst: bool, constraints: Constraints,
contextualFlags: ContextualFlags,
reportNode: Node reportNode: Node
): ExpressionRef { ): ExpressionRef {
var module = this.module; var module = this.module;
@ -7510,7 +7508,7 @@ export class Compiler extends DiagnosticEmitter {
let expr = expression let expr = expression
? module.precomputeExpression( ? module.precomputeExpression(
this.compileExpression(<Expression>expression, elementType, this.compileExpression(<Expression>expression, elementType,
ContextualFlags.IMPLICIT Constraints.CONV_IMPLICIT
) )
) )
: elementType.toNativeZero(module); : elementType.toNativeZero(module);
@ -7533,7 +7531,7 @@ export class Compiler extends DiagnosticEmitter {
// make both the buffer and array header static if assigned to a global. this can't be done // make both the buffer and array header static if assigned to a global. this can't be done
// if inside of a function because each invocation must create a new array reference then. // if inside of a function because each invocation must create a new array reference then.
if (contextualFlags & ContextualFlags.STATIC_CAPABLE) { if (constraints & Constraints.PREFER_STATIC) {
let arraySegment = this.ensureStaticArrayHeader(elementType, bufferSegment); let arraySegment = this.ensureStaticArrayHeader(elementType, bufferSegment);
let arrayAddress = i64_add(arraySegment.offset, i64_new(runtimeHeaderSize)); let arrayAddress = i64_add(arraySegment.offset, i64_new(runtimeHeaderSize));
this.currentType = arrayType; this.currentType = arrayType;
@ -7693,7 +7691,7 @@ export class Compiler extends DiagnosticEmitter {
exprs[i + 1] = this.module.store( // TODO: handle setters as well exprs[i + 1] = this.module.store( // TODO: handle setters as well
type.byteSize, type.byteSize,
this.module.local_get(tempLocal.index, this.options.nativeSizeType), this.module.local_get(tempLocal.index, this.options.nativeSizeType),
this.compileExpression(values[i], (<Field>member).type, ContextualFlags.IMPLICIT), this.compileExpression(values[i], (<Field>member).type, Constraints.CONV_IMPLICIT),
type.toNativeType(), type.toNativeType(),
(<Field>member).memoryOffset (<Field>member).memoryOffset
); );
@ -7719,7 +7717,7 @@ export class Compiler extends DiagnosticEmitter {
compileNewExpression( compileNewExpression(
expression: NewExpression, expression: NewExpression,
contextualType: Type, contextualType: Type,
contextualFlags: ContextualFlags constraints: Constraints
): ExpressionRef { ): ExpressionRef {
var module = this.module; var module = this.module;
var flow = this.currentFlow; var flow = this.currentFlow;
@ -7761,8 +7759,8 @@ export class Compiler extends DiagnosticEmitter {
); );
} }
if (!classInstance) return module.unreachable(); if (!classInstance) return module.unreachable();
if (contextualType == Type.void) contextualFlags |= ContextualFlags.WILL_DROP; if (contextualType == Type.void) constraints |= Constraints.WILL_DROP;
return this.compileInstantiate(classInstance, expression.arguments, contextualFlags, expression); return this.compileInstantiate(classInstance, expression.arguments, constraints, expression);
} }
/** Gets the compiled constructor of the specified class or generates one if none is present. */ /** Gets the compiled constructor of the specified class or generates one if none is present. */
@ -7879,7 +7877,7 @@ export class Compiler extends DiagnosticEmitter {
/** Constructor arguments. */ /** Constructor arguments. */
argumentExpressions: Expression[], argumentExpressions: Expression[],
/** Contextual flags. */ /** Contextual flags. */
contextualFlags: ContextualFlags, constraints: Constraints,
/** Node to report on. */ /** Node to report on. */
reportNode: Node reportNode: Node
): ExpressionRef { ): ExpressionRef {
@ -7889,7 +7887,7 @@ export class Compiler extends DiagnosticEmitter {
argumentExpressions, argumentExpressions,
reportNode, reportNode,
this.options.usizeType.toNativeZero(this.module), this.options.usizeType.toNativeZero(this.module),
contextualFlags constraints
); );
if (getExpressionType(expr) != NativeType.None) { // possibly IMM_DROPPED if (getExpressionType(expr) != NativeType.None) { // possibly IMM_DROPPED
this.currentType = classInstance.type; // important because a super ctor could be called this.currentType = classInstance.type; // important because a super ctor could be called
@ -7905,7 +7903,7 @@ export class Compiler extends DiagnosticEmitter {
compilePropertyAccessExpression( compilePropertyAccessExpression(
propertyAccess: PropertyAccessExpression, propertyAccess: PropertyAccessExpression,
contextualType: Type, contextualType: Type,
contextualFlags: ContextualFlags constraints: Constraints
): ExpressionRef { ): ExpressionRef {
var module = this.module; var module = this.module;
var flow = this.currentFlow; var flow = this.currentFlow;
@ -7923,7 +7921,7 @@ export class Compiler extends DiagnosticEmitter {
let globalType = (<Global>target).type; let globalType = (<Global>target).type;
assert(globalType != Type.void); assert(globalType != Type.void);
if ((<Global>target).is(CommonFlags.INLINED)) { if ((<Global>target).is(CommonFlags.INLINED)) {
return this.compileInlineConstant(<Global>target, contextualType, contextualFlags); return this.compileInlineConstant(<Global>target, contextualType, constraints);
} }
this.currentType = globalType; this.currentType = globalType;
return module.global_get((<Global>target).internalName, globalType.toNativeType()); return module.global_get((<Global>target).internalName, globalType.toNativeType());
@ -7985,7 +7983,7 @@ export class Compiler extends DiagnosticEmitter {
compileTernaryExpression( compileTernaryExpression(
expression: TernaryExpression, expression: TernaryExpression,
contextualType: Type, contextualType: Type,
contextualFlags: ContextualFlags constraints: Constraints
): ExpressionRef { ): ExpressionRef {
var ifThen = expression.ifThen; var ifThen = expression.ifThen;
var ifElse = expression.ifElse; var ifElse = expression.ifElse;
@ -8008,15 +8006,17 @@ export class Compiler extends DiagnosticEmitter {
: this.compileExpression(ifElse, contextualType); : this.compileExpression(ifElse, contextualType);
} }
var inheritedConstraints = constraints & Constraints.WILL_RETAIN;
var ifThenFlow = outerFlow.fork(); var ifThenFlow = outerFlow.fork();
this.currentFlow = ifThenFlow; this.currentFlow = ifThenFlow;
var ifThenExpr = this.compileExpression(ifThen, contextualType, contextualFlags & ContextualFlags.SKIP_AUTORELEASE); var ifThenExpr = this.compileExpression(ifThen, contextualType, inheritedConstraints);
var ifThenType = this.currentType; var ifThenType = this.currentType;
var IfThenAutoreleaseSkipped = this.skippedAutoreleases.has(ifThenExpr); var IfThenAutoreleaseSkipped = this.skippedAutoreleases.has(ifThenExpr);
var ifElseFlow = outerFlow.fork(); var ifElseFlow = outerFlow.fork();
this.currentFlow = ifElseFlow; this.currentFlow = ifElseFlow;
var ifElseExpr = this.compileExpression(ifElse, contextualType, contextualFlags & ContextualFlags.SKIP_AUTORELEASE); var ifElseExpr = this.compileExpression(ifElse, contextualType, inheritedConstraints);
var ifElseType = this.currentType; var ifElseType = this.currentType;
var ifElseAutoreleaseSkipped = this.skippedAutoreleases.has(ifElseExpr); var ifElseAutoreleaseSkipped = this.skippedAutoreleases.has(ifElseExpr);
@ -8052,7 +8052,7 @@ export class Compiler extends DiagnosticEmitter {
ifElseAutoreleaseSkipped = true; ifElseAutoreleaseSkipped = true;
} }
} else if (!IfThenAutoreleaseSkipped && commonType.isManaged) { // keep alive a little longer } else if (!IfThenAutoreleaseSkipped && commonType.isManaged) { // keep alive a little longer
// if (!(contextualFlags & ContextualFlags.SKIP_AUTORELEASE)) { // if (!(constraints & Constraints.WILL_RETAIN)) {
ifThenExpr = this.moveAutorelease(ifThenExpr, ifThenFlow, outerFlow); ifThenExpr = this.moveAutorelease(ifThenExpr, ifThenFlow, outerFlow);
ifElseExpr = this.moveAutorelease(ifElseExpr, ifElseFlow, outerFlow); ifElseExpr = this.moveAutorelease(ifElseExpr, ifElseFlow, outerFlow);
// } // }
@ -8076,7 +8076,7 @@ export class Compiler extends DiagnosticEmitter {
compileUnaryPostfixExpression( compileUnaryPostfixExpression(
expression: UnaryPostfixExpression, expression: UnaryPostfixExpression,
contextualType: Type, contextualType: Type,
contextualFlags: ContextualFlags constraints: Constraints
): ExpressionRef { ): ExpressionRef {
var module = this.module; var module = this.module;
var flow = this.currentFlow; var flow = this.currentFlow;
@ -8085,7 +8085,7 @@ export class Compiler extends DiagnosticEmitter {
var getValue = this.compileExpression( // reports var getValue = this.compileExpression( // reports
expression.operand, expression.operand,
contextualType.exceptVoid, contextualType.exceptVoid,
ContextualFlags.NONE Constraints.NONE
); );
// shortcut if compiling the getter already failed // shortcut if compiling the getter already failed
@ -8306,7 +8306,7 @@ export class Compiler extends DiagnosticEmitter {
compileUnaryPrefixExpression( compileUnaryPrefixExpression(
expression: UnaryPrefixExpression, expression: UnaryPrefixExpression,
contextualType: Type, contextualType: Type,
contextualFlags: ContextualFlags constraints: Constraints
): ExpressionRef { ): ExpressionRef {
var module = this.module; var module = this.module;
var compound = false; var compound = false;
@ -8317,7 +8317,7 @@ export class Compiler extends DiagnosticEmitter {
expr = this.compileExpression( expr = this.compileExpression(
expression.operand, expression.operand,
contextualType.exceptVoid, contextualType.exceptVoid,
ContextualFlags.NONE Constraints.NONE
); );
// check operator overload // check operator overload
@ -8346,7 +8346,7 @@ export class Compiler extends DiagnosticEmitter {
(<LiteralExpression>expression.operand).literalKind == LiteralKind.FLOAT (<LiteralExpression>expression.operand).literalKind == LiteralKind.FLOAT
)) { )) {
// implicitly negate integer and float literals. also enables proper checking of literal ranges. // implicitly negate integer and float literals. also enables proper checking of literal ranges.
expr = this.compileLiteralExpression(<LiteralExpression>expression.operand, contextualType, ContextualFlags.NONE, true); expr = this.compileLiteralExpression(<LiteralExpression>expression.operand, contextualType, Constraints.NONE, true);
// compileExpression normally does this: // compileExpression normally does this:
if (this.options.sourceMap) this.addDebugLocation(expr, expression.range); if (this.options.sourceMap) this.addDebugLocation(expr, expression.range);
break; break;
@ -8355,7 +8355,7 @@ export class Compiler extends DiagnosticEmitter {
expr = this.compileExpression( expr = this.compileExpression(
expression.operand, expression.operand,
contextualType.exceptVoid, contextualType.exceptVoid,
ContextualFlags.NONE Constraints.NONE
); );
// check operator overload // check operator overload
@ -8422,7 +8422,7 @@ export class Compiler extends DiagnosticEmitter {
expr = this.compileExpression( expr = this.compileExpression(
expression.operand, expression.operand,
contextualType.exceptVoid, contextualType.exceptVoid,
ContextualFlags.NONE Constraints.NONE
); );
// check operator overload // check operator overload
@ -8489,7 +8489,7 @@ export class Compiler extends DiagnosticEmitter {
expr = this.compileExpression( expr = this.compileExpression(
expression.operand, expression.operand,
contextualType.exceptVoid, contextualType.exceptVoid,
ContextualFlags.NONE Constraints.NONE
); );
// check operator overload // check operator overload
@ -8555,7 +8555,7 @@ export class Compiler extends DiagnosticEmitter {
expr = this.compileExpression( expr = this.compileExpression(
expression.operand, expression.operand,
contextualType.exceptVoid, contextualType.exceptVoid,
ContextualFlags.NONE Constraints.NONE
); );
// check operator overload // check operator overload
@ -8583,7 +8583,7 @@ export class Compiler extends DiagnosticEmitter {
: contextualType.is(TypeFlags.FLOAT) : contextualType.is(TypeFlags.FLOAT)
? Type.i64 ? Type.i64
: contextualType, : contextualType,
ContextualFlags.NONE Constraints.NONE
); );
// check operator overload // check operator overload
@ -8873,7 +8873,7 @@ export class Compiler extends DiagnosticEmitter {
let initializerNode = field.prototype.initializerNode; let initializerNode = field.prototype.initializerNode;
if (initializerNode) { // use initializer if (initializerNode) { // use initializer
let initExpr = this.compileExpression(initializerNode, fieldType, // reports let initExpr = this.compileExpression(initializerNode, fieldType, // reports
ContextualFlags.IMPLICIT | ContextualFlags.SKIP_AUTORELEASE Constraints.CONV_IMPLICIT | Constraints.WILL_RETAIN
); );
if (fieldType.isManaged && !this.skippedAutoreleases.has(initExpr)) { if (fieldType.isManaged && !this.skippedAutoreleases.has(initExpr)) {
initExpr = this.makeRetain(initExpr); initExpr = this.makeRetain(initExpr);