Skip to content

Commit fa9deca

Browse files
committed
Merge branch 'main' into stringref
2 parents f0ae1fc + b248254 commit fa9deca

24 files changed

+427
-397
lines changed

cli/index.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -372,7 +372,7 @@ export async function main(argv, options) {
372372
let name = features[i].trim();
373373
let flag = assemblyscript[`FEATURE_${toUpperSnakeCase(name)}`];
374374
if (!flag) return prepareResult(Error(`Feature '${name}' is unknown.`));
375-
assemblyscript.disableFeature(compilerOptions, flag);
375+
assemblyscript.setFeature(compilerOptions, flag, false);
376376
}
377377
}
378378

@@ -383,7 +383,7 @@ export async function main(argv, options) {
383383
let name = features[i].trim();
384384
let flag = assemblyscript[`FEATURE_${toUpperSnakeCase(name)}`];
385385
if (!flag) return prepareResult(Error(`Feature '${name}' is unknown.`));
386-
assemblyscript.enableFeature(compilerOptions, flag);
386+
assemblyscript.setFeature(compilerOptions, flag, true);
387387
}
388388
}
389389

src/builtins.ts

Lines changed: 61 additions & 60 deletions
Large diffs are not rendered by default.

src/common.ts

Lines changed: 22 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -81,7 +81,9 @@ export const enum CommonFlags {
8181
// Other
8282

8383
/** Is quoted. */
84-
Quoted = 1 << 30
84+
Quoted = 1 << 30,
85+
/** Is internally nullable. */
86+
InternallyNullable = 1 << 31
8587
}
8688

8789
/** Path delimiter inserted between file system levels. */
@@ -126,17 +128,17 @@ export namespace CommonNames {
126128
export const f32 = "f32";
127129
export const f64 = "f64";
128130
export const v128 = "v128";
129-
export const funcref = "funcref";
130-
export const externref = "externref";
131-
export const anyref = "anyref";
132-
export const eqref = "eqref";
133-
export const structref = "structref";
134-
export const arrayref = "arrayref";
135-
export const i31ref = "i31ref";
136-
export const stringref = "stringref";
137-
export const stringview_wtf8 = "stringview_wtf8";
138-
export const stringview_wtf16 = "stringview_wtf16";
139-
export const stringview_iter = "stringview_iter";
131+
export const ref_func = "ref_func";
132+
export const ref_extern = "ref_extern";
133+
export const ref_any = "ref_any";
134+
export const ref_eq = "ref_eq";
135+
export const ref_struct = "ref_struct";
136+
export const ref_array = "ref_array";
137+
export const ref_i31 = "ref_i31";
138+
export const ref_string = "ref_string";
139+
export const ref_stringview_wtf8 = "ref_stringview_wtf8";
140+
export const ref_stringview_wtf16 = "ref_stringview_wtf16";
141+
export const ref_stringview_iter = "ref_stringview_iter";
140142
export const i8x16 = "i8x16";
141143
export const u8x16 = "u8x16";
142144
export const i16x8 = "i16x8";
@@ -207,14 +209,14 @@ export namespace CommonNames {
207209
export const F32 = "F32";
208210
export const F64 = "F64";
209211
export const V128 = "V128";
210-
export const Funcref = "Funcref";
211-
export const Externref = "Externref";
212-
export const Anyref = "Anyref";
213-
export const Eqref = "Eqref";
214-
export const Structref = "Structref";
215-
export const Arrayref = "Arrayref";
216-
export const I31ref = "I31ref";
217-
export const Stringref = "Stringref";
212+
export const RefFunc = "RefFunc";
213+
export const RefExtern = "RefExtern";
214+
export const RefAny = "RefAny";
215+
export const RefEq = "RefEq";
216+
export const RefStruct = "RefStruct";
217+
export const RefArray = "RefArray";
218+
export const RefI31 = "RefI31";
219+
export const RefString = "RefString";
218220
export const StringviewWTF8 = "StringviewWTF8";
219221
export const StringviewWTF16 = "StringviewWTF16";
220222
export const StringviewIter = "StringviewIter";

src/compiler.ts

Lines changed: 89 additions & 48 deletions
Original file line numberDiff line numberDiff line change
@@ -221,6 +221,12 @@ import {
221221
lowerRequiresExportRuntime
222222
} from "./bindings/js";
223223

224+
/** Features enabled by default. */
225+
export const defaultFeatures = Feature.MutableGlobals
226+
| Feature.SignExtension
227+
| Feature.NontrappingF2I
228+
| Feature.BulkMemory;
229+
224230
/** Compiler options. */
225231
export class Options {
226232
constructor() { /* as internref */ }
@@ -261,11 +267,8 @@ export class Options {
261267
tableBase: u32 = 0;
262268
/** Global aliases, mapping alias names as the key to internal names to be aliased as the value. */
263269
globalAliases: Map<string,string> | null = null;
264-
/** Features to activate by default. These are the finished proposals. */
265-
features: Feature = Feature.MutableGlobals
266-
| Feature.SignExtension
267-
| Feature.NontrappingF2I
268-
| Feature.BulkMemory;
270+
/** Features to activate by default. */
271+
features: Feature = defaultFeatures;
269272
/** If true, disallows unsafe features in user code. */
270273
noUnsafe: bool = false;
271274
/** If true, enables pedantic diagnostics. */
@@ -317,6 +320,27 @@ export class Options {
317320
return this.optimizeLevelHint > 0 || this.shrinkLevelHint > 0;
318321
}
319322

323+
/** Sets whether a feature is enabled. */
324+
setFeature(feature: Feature, on: bool = true): void {
325+
if (on) {
326+
// Enabling Stringref also enables GC
327+
if (feature & Feature.Stringref) feature |= Feature.GC;
328+
// Enabling GC also enables Reference Types
329+
if (feature & Feature.GC) feature |= Feature.ReferenceTypes;
330+
// Enabling Relaxed SIMD also enables SIMD
331+
if (feature & Feature.RelaxedSimd) feature |= Feature.Simd;
332+
this.features |= feature;
333+
} else {
334+
// Disabling Reference Types also disables GC
335+
if (feature & Feature.ReferenceTypes) feature |= Feature.GC;
336+
// Disabling GC also disables Stringref
337+
if (feature & Feature.GC) feature |= Feature.Stringref;
338+
// Disabling SIMD also disables Relaxed SIMD
339+
if (feature & Feature.Simd) feature |= Feature.RelaxedSimd;
340+
this.features &= ~feature;
341+
}
342+
}
343+
320344
/** Tests if a specific feature is activated. */
321345
hasFeature(feature: Feature): bool {
322346
return (this.features & feature) != 0;
@@ -1357,7 +1381,14 @@ export class Compiler extends DiagnosticEmitter {
13571381
findDecorator(DecoratorKind.Inline, global.decoratorNodes)!.range, "inline"
13581382
);
13591383
}
1360-
module.addGlobal(internalName, typeRef, true, this.makeZero(type));
1384+
let internalType = type;
1385+
if (type.isExternalReference && !type.is(TypeFlags.Nullable)) {
1386+
// There is no default value for non-nullable external references, so
1387+
// make the global nullable internally and use `null`.
1388+
global.set(CommonFlags.InternallyNullable);
1389+
internalType = type.asNullable();
1390+
}
1391+
module.addGlobal(internalName, internalType.toRef(), true, this.makeZero(internalType));
13611392
this.currentBody.push(
13621393
module.global_set(internalName, initExpr)
13631394
);
@@ -1757,7 +1788,7 @@ export class Compiler extends DiagnosticEmitter {
17571788
// Implicitly return `this` if the flow falls through
17581789
if (!flow.is(FlowFlags.Terminates)) {
17591790
stmts.push(
1760-
module.local_get(thisLocal.index, this.options.sizeTypeRef)
1791+
module.local_get(thisLocal.index, thisLocal.type.toRef())
17611792
);
17621793
flow.set(FlowFlags.Returns | FlowFlags.ReturnsNonNull | FlowFlags.Terminates);
17631794
}
@@ -4854,17 +4885,17 @@ export class Compiler extends DiagnosticEmitter {
48544885
module.binary(BinaryOp.EqI8x16, leftExpr, rightExpr)
48554886
);
48564887
}
4857-
case TypeKind.Eqref:
4858-
case TypeKind.Structref:
4859-
case TypeKind.Arrayref:
4860-
case TypeKind.I31ref: return module.ref_eq(leftExpr, rightExpr);
4861-
case TypeKind.Stringref: return module.string_eq(leftExpr, rightExpr);
4888+
case TypeKind.Eq:
4889+
case TypeKind.Struct:
4890+
case TypeKind.Array:
4891+
case TypeKind.I31: return module.ref_eq(leftExpr, rightExpr);
4892+
case TypeKind.String: return module.string_eq(leftExpr, rightExpr);
48624893
case TypeKind.StringviewWTF8:
48634894
case TypeKind.StringviewWTF16:
48644895
case TypeKind.StringviewIter:
4865-
case TypeKind.Funcref:
4866-
case TypeKind.Externref:
4867-
case TypeKind.Anyref: {
4896+
case TypeKind.Func:
4897+
case TypeKind.Extern:
4898+
case TypeKind.Any: {
48684899
this.error(
48694900
DiagnosticCode.Operation_0_cannot_be_applied_to_type_1,
48704901
reportNode.range,
@@ -4904,25 +4935,25 @@ export class Compiler extends DiagnosticEmitter {
49044935
module.binary(BinaryOp.NeI8x16, leftExpr, rightExpr)
49054936
);
49064937
}
4907-
case TypeKind.Eqref:
4908-
case TypeKind.Structref:
4909-
case TypeKind.Arrayref:
4910-
case TypeKind.I31ref: {
4938+
case TypeKind.Eq:
4939+
case TypeKind.Struct:
4940+
case TypeKind.Array:
4941+
case TypeKind.I31: {
49114942
return module.unary(UnaryOp.EqzI32,
49124943
module.ref_eq(leftExpr, rightExpr)
49134944
);
49144945
}
4915-
case TypeKind.Stringref: {
4946+
case TypeKind.String: {
49164947
return module.unary(UnaryOp.EqzI32,
49174948
module.string_eq(leftExpr, rightExpr)
49184949
);
49194950
}
49204951
case TypeKind.StringviewWTF8:
49214952
case TypeKind.StringviewWTF16:
49224953
case TypeKind.StringviewIter:
4923-
case TypeKind.Funcref:
4924-
case TypeKind.Externref:
4925-
case TypeKind.Anyref: {
4954+
case TypeKind.Func:
4955+
case TypeKind.Extern:
4956+
case TypeKind.Any: {
49264957
this.error(
49274958
DiagnosticCode.Operation_0_cannot_be_applied_to_type_1,
49284959
reportNode.range,
@@ -7332,10 +7363,12 @@ export class Compiler extends DiagnosticEmitter {
73327363
);
73337364
}
73347365
assert(localIndex >= 0);
7335-
if (localType.isNullableReference && flow.isLocalFlag(localIndex, LocalFlags.NonNull, false)) {
7336-
localType = localType.nonNullableType;
7366+
let isNonNull = flow.isLocalFlag(localIndex, LocalFlags.NonNull, false);
7367+
if (localType.isNullableReference && isNonNull && (!localType.isExternalReference || this.options.hasFeature(Feature.GC))) {
7368+
this.currentType = localType.nonNullableType;
7369+
} else {
7370+
this.currentType = localType;
73377371
}
7338-
this.currentType = localType;
73397372

73407373
if (target.parent != flow.targetFunction) {
73417374
// TODO: closures
@@ -7346,7 +7379,14 @@ export class Compiler extends DiagnosticEmitter {
73467379
);
73477380
return module.unreachable();
73487381
}
7349-
return module.local_get(localIndex, localType.toRef());
7382+
let expr = module.local_get(localIndex, localType.toRef());
7383+
if (isNonNull && localType.isNullableExternalReference && this.options.hasFeature(Feature.GC)) {
7384+
// If the local's type is nullable, but its value is known to be non-null, propagate
7385+
// non-nullability info to Binaryen. Only applicable if GC is enabled, since without
7386+
// GC, here incl. typed function references, there is no nullability dimension.
7387+
expr = module.ref_as_nonnull(expr);
7388+
}
7389+
return expr;
73507390
}
73517391
case ElementKind.Global: {
73527392
let global = <Global>target;
@@ -7424,7 +7464,7 @@ export class Compiler extends DiagnosticEmitter {
74247464
// TODO: Concrete function types currently map to first class functions implemented in
74257465
// linear memory (on top of `usize`), leaving only generic `funcref` for use here. In the
74267466
// future, once functions become Wasm GC objects, the actual signature type can be used.
7427-
this.currentType = Type.funcref;
7467+
this.currentType = Type.func;
74287468
return module.ref_func(functionInstance.internalName, ensureType(functionInstance.type));
74297469
}
74307470
let offset = this.ensureRuntimeFunction(functionInstance);
@@ -9897,20 +9937,21 @@ export class Compiler extends DiagnosticEmitter {
98979937
case TypeKind.F32: return module.f32(0);
98989938
case TypeKind.F64: return module.f64(0);
98999939
case TypeKind.V128: return module.v128(v128_zero);
9900-
case TypeKind.Funcref:
9901-
case TypeKind.Externref:
9902-
case TypeKind.Anyref:
9903-
case TypeKind.Eqref:
9904-
case TypeKind.Structref:
9905-
case TypeKind.Arrayref:
9906-
case TypeKind.Stringref:
9940+
case TypeKind.Func:
9941+
case TypeKind.Extern:
9942+
case TypeKind.Any:
9943+
case TypeKind.Eq:
9944+
case TypeKind.Struct:
9945+
case TypeKind.Array:
9946+
case TypeKind.String:
99079947
case TypeKind.StringviewWTF8:
99089948
case TypeKind.StringviewWTF16:
99099949
case TypeKind.StringviewIter: {
9910-
// TODO: what if not nullable?
9911-
return module.ref_null(type.toRef());
9950+
if (type.is(TypeFlags.Nullable)) return module.ref_null(type.toRef());
9951+
assert(false); // TODO: check that refs are nullable in callers?
9952+
return module.unreachable();
99129953
}
9913-
case TypeKind.I31ref: {
9954+
case TypeKind.I31: {
99149955
if (type.is(TypeFlags.Nullable)) return module.ref_null(type.toRef());
99159956
return module.i31_new(module.i32(0));
99169957
}
@@ -9935,7 +9976,7 @@ export class Compiler extends DiagnosticEmitter {
99359976
case TypeKind.U64: return module.i64(1);
99369977
case TypeKind.F32: return module.f32(1);
99379978
case TypeKind.F64: return module.f64(1);
9938-
case TypeKind.I31ref: return module.i31_new(module.i32(1));
9979+
case TypeKind.I31: return module.i31_new(module.i32(1));
99399980
}
99409981
}
99419982

@@ -9957,7 +9998,7 @@ export class Compiler extends DiagnosticEmitter {
99579998
case TypeKind.F32: return module.f32(-1);
99589999
case TypeKind.F64: return module.f64(-1);
995910000
case TypeKind.V128: return module.v128(v128_ones);
9960-
case TypeKind.I31ref: return module.i31_new(module.i32(-1));
10001+
case TypeKind.I31: return module.i31_new(module.i32(-1));
996110002
}
996210003
}
996310004

@@ -10056,14 +10097,14 @@ export class Compiler extends DiagnosticEmitter {
1005610097
case TypeKind.V128: {
1005710098
return module.unary(UnaryOp.AnyTrueV128, expr);
1005810099
}
10059-
case TypeKind.Funcref:
10060-
case TypeKind.Externref:
10061-
case TypeKind.Anyref:
10062-
case TypeKind.Eqref:
10063-
case TypeKind.Structref:
10064-
case TypeKind.Arrayref:
10065-
case TypeKind.I31ref:
10066-
case TypeKind.Stringref:
10100+
case TypeKind.Func:
10101+
case TypeKind.Extern:
10102+
case TypeKind.Any:
10103+
case TypeKind.Eq:
10104+
case TypeKind.Struct:
10105+
case TypeKind.Array:
10106+
case TypeKind.I31:
10107+
case TypeKind.String:
1006710108
case TypeKind.StringviewWTF8:
1006810109
case TypeKind.StringviewWTF16:
1006910110
case TypeKind.StringviewIter: {

src/index-wasm.ts

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,8 @@ import {
2323
import {
2424
Compiler,
2525
Options,
26-
UncheckedBehavior
26+
UncheckedBehavior,
27+
defaultFeatures
2728
} from "./compiler";
2829

2930
import {
@@ -201,15 +202,14 @@ export const FEATURE_RELAXED_SIMD = Feature.RelaxedSimd;
201202
export const FEATURE_EXTENDED_CONST = Feature.ExtendedConst;
202203
/** String references. */
203204
export const FEATURE_STRINGREF = Feature.Stringref;
204-
205-
/** Enables a specific feature. */
206-
export function enableFeature(options: Options, feature: Feature): void {
207-
options.features |= feature;
208-
}
209-
210-
/** Disables a specific feature. */
211-
export function disableFeature(options: Options, feature: Feature): void {
212-
options.features &= ~feature;
205+
/** All features. */
206+
export const FEATURES_ALL = Feature.All;
207+
/** Default features. */
208+
export const FEATURES_DEFAULT = defaultFeatures;
209+
210+
/** Sets whether a specific feature is enabled. */
211+
export function setFeature(options: Options, feature: Feature, on: bool): void {
212+
options.setFeature(feature, on);
213213
}
214214

215215
/** Gives the compiler a hint at the optimize levels that will be used later on. */

0 commit comments

Comments
 (0)