guard, info on never null, more general array rt

This commit is contained in:
dcode
2019-03-22 15:43:07 +01:00
parent c2ac1a0375
commit 7c0dc66849
69 changed files with 6066 additions and 4930 deletions

View File

@ -189,7 +189,7 @@ export namespace LibrarySymbols {
export const REGISTER = "REGISTER";
export const RETAIN = "RETAIN";
export const RELEASE = "RELEASE";
export const WRAPARRAY = "WRAPARRAY";
export const MAKEARRAY = "MAKEARRAY";
// other
export const length = "length";
export const byteLength = "byteLength";

View File

@ -2689,10 +2689,11 @@ export class Compiler extends DiagnosticEmitter {
switch (expression.assertionKind) {
case AssertionKind.PREFIX:
case AssertionKind.AS: {
let flow = this.currentFlow;
let toType = this.resolver.resolveType( // reports
assert(expression.toType),
this.currentFlow.actualFunction,
this.currentFlow.contextualTypeArguments
flow.actualFunction,
flow.contextualTypeArguments
);
if (!toType) return this.module.createUnreachable();
return this.compileExpression(expression.expression, toType, ConversionKind.EXPLICIT, WrapMode.NONE);
@ -2700,6 +2701,22 @@ export class Compiler extends DiagnosticEmitter {
case AssertionKind.NONNULL: {
assert(!expression.toType);
let expr = this.compileExpressionRetainType(expression.expression, contextualType, WrapMode.NONE);
let type = this.currentType;
if (!type.is(TypeFlags.NULLABLE | TypeFlags.REFERENCE)) {
this.info(
DiagnosticCode.Expression_is_never_null,
expression.expression.range
);
} else if (!this.options.noAssert) {
let module = this.module;
let flow = this.currentFlow;
let tempIndex = flow.getAndFreeTempLocal(type, !flow.canOverflow(expr, type)).index;
expr = module.createIf(
module.createTeeLocal(tempIndex, expr),
module.createGetLocal(tempIndex, type.toNativeType()),
module.createUnreachable()
);
}
this.currentType = this.currentType.nonNullableType;
return expr;
}
@ -6741,13 +6758,13 @@ export class Compiler extends DiagnosticEmitter {
// otherwise allocate a new array header and make it wrap a copy of the static buffer
} else {
let wrapArrayPrototype = assert(program.wrapArrayPrototype);
let wrapArrayInstance = this.resolver.resolveFunction(wrapArrayPrototype, [ elementType ]);
if (!wrapArrayInstance) {
let makeArrayInstance = this.resolver.resolveFunction(assert(program.makeArrayPrototype), [ elementType ]);
if (!makeArrayInstance) {
this.currentType = arrayType;
return module.createUnreachable();
}
let body = this.makeCallInlinePrechecked(wrapArrayInstance, [
let body = this.makeCallInlinePrechecked(makeArrayInstance, [
this.module.createI32(length),
program.options.isWasm64
? this.module.createI64(i64_low(bufferAddress), i64_high(bufferAddress))
: this.module.createI32(i64_low(bufferAddress))
@ -6771,14 +6788,18 @@ export class Compiler extends DiagnosticEmitter {
var flow = this.currentFlow;
var tempThis = flow.getTempLocal(arrayType, false);
var tempDataStart = flow.getTempLocal(arrayBufferInstance.type);
var makeArrayInstance = this.resolver.resolveFunction(assert(program.makeArrayPrototype), [ elementType ]);
if (!makeArrayInstance) {
this.currentType = arrayType;
return module.createUnreachable();
}
var stmts = new Array<ExpressionRef>();
// tempThis = new Array<T>(length)
// tempThis = MAKEARRAY<T>(length)
stmts.push(
module.createSetLocal(tempThis.index,
this.makeCallDirect(assert(arrayInstance.constructorInstance), [
module.createI32(0), // this
this.makeCallInlinePrechecked(makeArrayInstance, [
module.createI32(length)
], reportNode)
], 0, true),
)
);
// tempData = tempThis.dataStart

View File

@ -35,6 +35,7 @@ export enum DiagnosticCode {
_0_must_be_a_value_between_1_and_2_inclusive = 222,
_0_must_be_a_power_of_two = 223,
TODO_Cannot_inline_inferred_calls_and_specific_internals_yet = 224,
Expression_is_never_null = 225,
Unterminated_string_literal = 1002,
Identifier_expected = 1003,
_0_expected = 1005,
@ -171,6 +172,7 @@ export function diagnosticCodeToString(code: DiagnosticCode): string {
case 222: return "'{0}' must be a value between '{1}' and '{2}' inclusive.";
case 223: return "'{0}' must be a power of two.";
case 224: return "TODO: Cannot inline inferred calls and specific internals yet.";
case 225: return "Expression is never 'null'.";
case 1002: return "Unterminated string literal.";
case 1003: return "Identifier expected.";
case 1005: return "'{0}' expected.";

View File

@ -27,6 +27,7 @@
"'{0}' must be a value between '{1}' and '{2}' inclusive.": 222,
"'{0}' must be a power of two.": 223,
"TODO: Cannot inline inferred calls and specific internals yet.": 224,
"Expression is never 'null'.": 225,
"Unterminated string literal.": 1002,
"Identifier expected.": 1003,

View File

@ -368,8 +368,8 @@ export class Program extends DiagnosticEmitter {
retainPrototype: FunctionPrototype | null = null;
/** Runtime release function. */
releasePrototype: FunctionPrototype | null = null;
/** Runtime wrap array function. */
wrapArrayPrototype: FunctionPrototype | null = null;
/** Runtime make array function. */
makeArrayPrototype: FunctionPrototype | null = null;
/** Next class id. */
nextClassId: u32 = 1;
@ -838,9 +838,9 @@ export class Program extends DiagnosticEmitter {
assert(element.kind == ElementKind.FUNCTION_PROTOTYPE);
this.releasePrototype = <FunctionPrototype>element;
}
if (element = this.lookupGlobal(LibrarySymbols.WRAPARRAY)) {
if (element = this.lookupGlobal(LibrarySymbols.MAKEARRAY)) {
assert(element.kind == ElementKind.FUNCTION_PROTOTYPE);
this.wrapArrayPrototype = <FunctionPrototype>element;
this.makeArrayPrototype = <FunctionPrototype>element;
}
}