Skip to content

Commit 6e7c8f4

Browse files
authored
fix: Fix crash on reference typed constant (#2238)
1 parent 1c806f5 commit 6e7c8f4

File tree

9 files changed

+56
-20
lines changed

9 files changed

+56
-20
lines changed

src/builtins.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -907,7 +907,7 @@ function builtin_isConstant(ctx: BuiltinContext): ExpressionRef {
907907
var expr = compiler.compileExpression(ctx.operands[0], Type.auto);
908908
compiler.currentType = Type.bool;
909909
if (!mustPreserveSideEffects(expr, module.ref)) {
910-
return module.i32(getExpressionId(expr) == ExpressionId.Const ? 1 : 0);
910+
return module.i32(module.isConstExpression(expr) ? 1 : 0);
911911
}
912912
return module.block(null, [
913913
module.maybeDrop(expr),

src/compiler.ts

Lines changed: 7 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1158,16 +1158,14 @@ export class Compiler extends DiagnosticEmitter {
11581158
this.currentFlow = previousFlow;
11591159
}
11601160

1161-
// If not a constant, attempt to precompute
1162-
if (getExpressionId(initExpr) != ExpressionId.Const) {
1161+
// If not a constant expression, attempt to precompute
1162+
if (!module.isConstExpression(initExpr)) {
11631163
if (isDeclaredConstant) {
1164-
if (getExpressionId(initExpr) != ExpressionId.Const) {
1165-
let precomp = module.runExpression(initExpr, ExpressionRunnerFlags.PreserveSideeffects);
1166-
if (precomp) {
1167-
initExpr = precomp;
1168-
} else {
1169-
initializeInStart = true;
1170-
}
1164+
let precomp = module.runExpression(initExpr, ExpressionRunnerFlags.PreserveSideeffects);
1165+
if (precomp) {
1166+
initExpr = precomp;
1167+
} else {
1168+
initializeInStart = true;
11711169
}
11721170
} else {
11731171
initializeInStart = true;

src/module.ts

Lines changed: 24 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2582,12 +2582,35 @@ export class Module {
25822582
var runner = binaryen._ExpressionRunnerCreate(this.ref, flags, maxDepth, maxLoopIterations);
25832583
var precomp = binaryen._ExpressionRunnerRunAndDispose(runner, expr);
25842584
if (precomp) {
2585-
assert(getExpressionId(precomp) == ExpressionId.Const);
2585+
if (!this.isConstExpression(precomp)) return 0;
25862586
assert(getExpressionType(precomp) == getExpressionType(expr));
25872587
}
25882588
return precomp;
25892589
}
25902590

2591+
isConstExpression(expr: ExpressionRef, features: FeatureFlags = 0): bool {
2592+
switch (getExpressionId(expr)) {
2593+
case ExpressionId.Const:
2594+
case ExpressionId.RefNull:
2595+
case ExpressionId.RefFunc:
2596+
case ExpressionId.I31New: return true;
2597+
case ExpressionId.Binary: {
2598+
if (this.getFeatures() & FeatureFlags.ExtendedConst) {
2599+
switch (getBinaryOp(expr)) {
2600+
case BinaryOp.AddI32:
2601+
case BinaryOp.SubI32:
2602+
case BinaryOp.MulI32:
2603+
case BinaryOp.AddI64:
2604+
case BinaryOp.SubI64:
2605+
case BinaryOp.MulI64: return this.isConstExpression(getBinaryLeft(expr)) && this.isConstExpression(getBinaryRight(expr));
2606+
}
2607+
}
2608+
break;
2609+
}
2610+
}
2611+
return false;
2612+
}
2613+
25912614
// source map generation
25922615

25932616
addDebugInfoFile(name: string): Index {

tests/compiler/features/gc.debug.wat

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
(type $none_=>_none (func))
33
(type $i32_i32_i32_i32_=>_none (func (param i32 i32 i32 i32)))
44
(import "env" "abort" (func $~lib/builtins/abort (param i32 i32 i32 i32)))
5+
(global $features/gc/a anyref (ref.null any))
56
(global $~lib/memory/__data_end i32 (i32.const 60))
67
(global $~lib/memory/__stack_pointer (mut i32) (i32.const 16444))
78
(global $~lib/memory/__heap_base i32 (i32.const 16444))
@@ -10,6 +11,7 @@
1011
(data (i32.const 12) ",\00\00\00\00\00\00\00\00\00\00\00\01\00\00\00\1c\00\00\00f\00e\00a\00t\00u\00r\00e\00s\00/\00g\00c\00.\00t\00s\00")
1112
(table $0 1 funcref)
1213
(elem $0 (i32.const 1))
14+
(export "a" (global $features/gc/a))
1315
(export "memory" (memory $0))
1416
(export "_start" (func $~start))
1517
(func $features/gc/test_i31

tests/compiler/features/gc.release.wat

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,10 @@
11
(module
22
(type $none_=>_none (func))
3+
(global $features/gc/a anyref (ref.null any))
34
(memory $0 1)
45
(data (i32.const 1036) ",")
56
(data (i32.const 1048) "\01\00\00\00\1c\00\00\00f\00e\00a\00t\00u\00r\00e\00s\00/\00g\00c\00.\00t\00s")
7+
(export "a" (global $features/gc/a))
68
(export "memory" (memory $0))
79
(export "_start" (func $~start))
810
(func $~start

tests/compiler/features/gc.ts

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,3 +6,9 @@ function test_i31(): void {
66
}
77

88
test_i31();
9+
10+
// constant globals
11+
12+
export const a: anyref = null;
13+
// export const b: i31ref = null; // TODO: not yet nullable in Binaryen
14+
// export const c: dataref = null; // TODO: not yet nullable in Binaryen

tests/compiler/features/reference-types.debug.wat

Lines changed: 5 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,9 @@
1313
(global $features/reference-types/externGlobalInit (mut externref) (ref.null extern))
1414
(global $features/reference-types/anyGlobal (mut anyref) (ref.null any))
1515
(global $features/reference-types/anyGlobalInit (mut anyref) (ref.null any))
16-
(global $features/reference-types/otherFuncGlobal (mut funcref) (ref.null func))
16+
(global $features/reference-types/otherFuncGlobal (mut funcref) (ref.func $features/reference-types/someFunc))
17+
(global $features/reference-types/a externref (ref.null extern))
18+
(global $features/reference-types/b funcref (ref.null func))
1719
(global $~lib/memory/__data_end i32 (i32.const 92))
1820
(global $~lib/memory/__stack_pointer (mut i32) (i32.const 16476))
1921
(global $~lib/memory/__heap_base i32 (i32.const 16476))
@@ -26,6 +28,8 @@
2628
(export "somethingReal" (func $features/reference-types/somethingReal))
2729
(export "somethingNull" (func $features/reference-types/somethingNull))
2830
(export "internal" (func $features/reference-types/internal))
31+
(export "a" (global $features/reference-types/a))
32+
(export "b" (global $features/reference-types/b))
2933
(export "memory" (memory $0))
3034
(start $~start)
3135
(func $features/reference-types/testLocal<funcref>
@@ -268,8 +272,6 @@
268272
call $~lib/builtins/abort
269273
unreachable
270274
end
271-
ref.null func
272-
global.set $features/reference-types/funcGlobalInit
273275
global.get $features/reference-types/funcGlobalInit
274276
ref.is_null
275277
i32.eqz
@@ -311,8 +313,6 @@
311313
call $~lib/builtins/abort
312314
unreachable
313315
end
314-
ref.null extern
315-
global.set $features/reference-types/externGlobalInit
316316
global.get $features/reference-types/externGlobalInit
317317
ref.is_null
318318
i32.eqz
@@ -354,8 +354,6 @@
354354
call $~lib/builtins/abort
355355
unreachable
356356
end
357-
ref.null any
358-
global.set $features/reference-types/anyGlobalInit
359357
global.get $features/reference-types/anyGlobalInit
360358
ref.is_null
361359
i32.eqz
@@ -384,8 +382,6 @@
384382
call $~lib/builtins/abort
385383
unreachable
386384
end
387-
ref.func $features/reference-types/someFunc
388-
global.set $features/reference-types/otherFuncGlobal
389385
global.get $features/reference-types/otherFuncGlobal
390386
ref.is_null
391387
if

tests/compiler/features/reference-types.release.wat

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,8 @@
99
(import "reference-types" "external" (func $features/reference-types/external (param externref) (result externref)))
1010
(global $features/reference-types/funcGlobal (mut funcref) (ref.null func))
1111
(global $features/reference-types/anyGlobal (mut anyref) (ref.null any))
12+
(global $features/reference-types/a externref (ref.null extern))
13+
(global $features/reference-types/b funcref (ref.null func))
1214
(memory $0 1)
1315
(data (i32.const 1036) "L")
1416
(data (i32.const 1048) "\01\00\00\006\00\00\00f\00e\00a\00t\00u\00r\00e\00s\00/\00r\00e\00f\00e\00r\00e\00n\00c\00e\00-\00t\00y\00p\00e\00s\00.\00t\00s")
@@ -17,6 +19,8 @@
1719
(export "somethingReal" (func $features/reference-types/somethingReal))
1820
(export "somethingNull" (func $features/reference-types/somethingNull))
1921
(export "internal" (func $features/reference-types/internal))
22+
(export "a" (global $features/reference-types/a))
23+
(export "b" (global $features/reference-types/b))
2024
(export "memory" (memory $0))
2125
(start $~start)
2226
(func $features/reference-types/someFunc

tests/compiler/features/reference-types.ts

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -99,3 +99,8 @@ assert(otherFuncGlobal);
9999
// can assign any reference type to anyref
100100

101101
anyGlobal = funcGlobal;
102+
103+
// constant globals
104+
105+
export const a: externref = null;
106+
export const b: funcref = null;

0 commit comments

Comments
 (0)