Skip to content

Commit b8733ac

Browse files
committed
Implement changes in reference types proposal
This updates reference types proposal up-to-date, per WebAssembly/reference-types#87. Only maybe half of tests have been updated, so CI will not pass. I was in the process of updating them fully, but I noticed WebAssembly#3084, so I'm not sure if I continue to do this anymore. I asked him if he wanted to do it himself to prevent this situation but apparently my questions weren't answered and I didn't know that he was working on this at the same time. I'm uploading this anyway in case this is necessary for discussions.
1 parent fecfa92 commit b8733ac

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

42 files changed

+219
-427
lines changed

check.py

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -240,10 +240,7 @@ def check_expected(actual, expected):
240240
# some wast files cannot be split:
241241
# * comments.wast: contains characters that are not valid utf-8,
242242
# so our string splitting code fails there
243-
244-
# FIXME Remove reference type tests from this list after nullref is
245-
# implemented in V8
246-
if base not in ['comments.wast', 'ref_null.wast', 'ref_is_null.wast', 'ref_func.wast', 'old_select.wast']:
243+
if base not in ['comments.wast', 'old_select.wast']:
247244
split_num = 0
248245
actual = ''
249246
for module, asserts in support.split_wast(wast):

scripts/gen-s-parser.py

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,6 @@
5050
("v128.pop", "makePop(Type::v128)"),
5151
("funcref.pop", "makePop(Type::funcref)"),
5252
("externref.pop", "makePop(Type::externref)"),
53-
("nullref.pop", "makePop(Type::nullref)"),
5453
("exnref.pop", "makePop(Type::exnref)"),
5554
("i32.load", "makeLoad(s, Type::i32, /*isAtomic=*/false)"),
5655
("i64.load", "makeLoad(s, Type::i64, /*isAtomic=*/false)"),

scripts/test/wasm_opt.py

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -113,10 +113,8 @@ def check():
113113

114114
shared.fail_if_not_identical_to_file(actual, f)
115115

116-
# FIXME Remove this condition after nullref is implemented in V8
117-
if 'reference-types.wast' not in t:
118-
shared.binary_format_check(t, wasm_as_args=['-g']) # test with debuginfo
119-
shared.binary_format_check(t, wasm_as_args=[], binary_suffix='.fromBinary.noDebugInfo') # test without debuginfo
116+
shared.binary_format_check(t, wasm_as_args=['-g']) # test with debuginfo
117+
shared.binary_format_check(t, wasm_as_args=[], binary_suffix='.fromBinary.noDebugInfo') # test without debuginfo
120118

121119
shared.minify_check(t)
122120

src/asmjs/asm_v_wasm.cpp

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -56,7 +56,6 @@ AsmType wasmToAsmType(Type type) {
5656
assert(false && "v128 not implemented yet");
5757
case Type::funcref:
5858
case Type::externref:
59-
case Type::nullref:
6059
case Type::exnref:
6160
assert(false && "reference types are not supported by asm2wasm");
6261
case Type::none:
@@ -84,8 +83,6 @@ char getSig(Type type) {
8483
return 'F';
8584
case Type::externref:
8685
return 'X';
87-
case Type::nullref:
88-
return 'N';
8986
case Type::exnref:
9087
return 'E';
9188
case Type::none:

src/binaryen-c.cpp

Lines changed: 4 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -71,8 +71,6 @@ BinaryenLiteral toBinaryenLiteral(Literal x) {
7171
case Type::funcref:
7272
ret.func = x.getFunc().c_str();
7373
break;
74-
case Type::nullref:
75-
break;
7674
case Type::externref:
7775
case Type::exnref:
7876
case Type::none:
@@ -96,8 +94,6 @@ Literal fromBinaryenLiteral(BinaryenLiteral x) {
9694
return Literal(x.v128);
9795
case Type::funcref:
9896
return Literal::makeFuncref(x.func);
99-
case Type::nullref:
100-
return Literal::makeNullref();
10197
case Type::externref:
10298
case Type::exnref:
10399
case Type::none:
@@ -133,7 +129,6 @@ BinaryenType BinaryenTypeFloat64(void) { return Type::f64; }
133129
BinaryenType BinaryenTypeVec128(void) { return Type::v128; }
134130
BinaryenType BinaryenTypeFuncref(void) { return Type::funcref; }
135131
BinaryenType BinaryenTypeExternref(void) { return Type::externref; }
136-
BinaryenType BinaryenTypeNullref(void) { return Type::nullref; }
137132
BinaryenType BinaryenTypeExnref(void) { return Type::exnref; }
138133
BinaryenType BinaryenTypeUnreachable(void) { return Type::unreachable; }
139134
BinaryenType BinaryenTypeAuto(void) { return uintptr_t(-1); }
@@ -1264,8 +1259,10 @@ BinaryenExpressionRef BinaryenPop(BinaryenModuleRef module, BinaryenType type) {
12641259
Builder(*(Module*)module).makePop(Type(type)));
12651260
}
12661261

1267-
BinaryenExpressionRef BinaryenRefNull(BinaryenModuleRef module) {
1268-
return static_cast<Expression*>(Builder(*(Module*)module).makeRefNull());
1262+
BinaryenExpressionRef BinaryenRefNull(BinaryenModuleRef module,
1263+
BinaryenType type) {
1264+
return static_cast<Expression*>(
1265+
Builder(*(Module*)module).makeRefNull(Type(type)));
12691266
}
12701267

12711268
BinaryenExpressionRef BinaryenRefIsNull(BinaryenModuleRef module,

src/binaryen-c.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -100,7 +100,6 @@ BINARYEN_API BinaryenType BinaryenTypeFloat64(void);
100100
BINARYEN_API BinaryenType BinaryenTypeVec128(void);
101101
BINARYEN_API BinaryenType BinaryenTypeFuncref(void);
102102
BINARYEN_API BinaryenType BinaryenTypeExternref(void);
103-
BINARYEN_API BinaryenType BinaryenTypeNullref(void);
104103
BINARYEN_API BinaryenType BinaryenTypeExnref(void);
105104
BINARYEN_API BinaryenType BinaryenTypeUnreachable(void);
106105
// Not a real type. Used as the last parameter to BinaryenBlock to let
@@ -826,7 +825,8 @@ BinaryenMemoryFill(BinaryenModuleRef module,
826825
BinaryenExpressionRef dest,
827826
BinaryenExpressionRef value,
828827
BinaryenExpressionRef size);
829-
BINARYEN_API BinaryenExpressionRef BinaryenRefNull(BinaryenModuleRef module);
828+
BINARYEN_API BinaryenExpressionRef BinaryenRefNull(BinaryenModuleRef module,
829+
BinaryenType type);
830830
BINARYEN_API BinaryenExpressionRef
831831
BinaryenRefIsNull(BinaryenModuleRef module, BinaryenExpressionRef value);
832832
BINARYEN_API BinaryenExpressionRef BinaryenRefFunc(BinaryenModuleRef module,

src/gen-s-parser.inc

Lines changed: 3 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -2560,17 +2560,9 @@ switch (op[0]) {
25602560
default: goto parse_error;
25612561
}
25622562
}
2563-
case 'n': {
2564-
switch (op[1]) {
2565-
case 'o':
2566-
if (strcmp(op, "nop") == 0) { return makeNop(); }
2567-
goto parse_error;
2568-
case 'u':
2569-
if (strcmp(op, "nullref.pop") == 0) { return makePop(Type::nullref); }
2570-
goto parse_error;
2571-
default: goto parse_error;
2572-
}
2573-
}
2563+
case 'n':
2564+
if (strcmp(op, "nop") == 0) { return makeNop(); }
2565+
goto parse_error;
25742566
case 'r': {
25752567
switch (op[2]) {
25762568
case 'f': {

src/ir/ExpressionManipulator.cpp

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -227,7 +227,9 @@ flexibleCopy(Expression* original, Module& wasm, CustomCopier custom) {
227227
builder.makeHost(curr->op, curr->nameOperand, std::move(operands));
228228
return ret;
229229
}
230-
Expression* visitRefNull(RefNull* curr) { return builder.makeRefNull(); }
230+
Expression* visitRefNull(RefNull* curr) {
231+
return builder.makeRefNull(curr->type);
232+
}
231233
Expression* visitRefIsNull(RefIsNull* curr) {
232234
return builder.makeRefIsNull(copy(curr->value));
233235
}

src/ir/abstract.h

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -103,7 +103,6 @@ inline UnaryOp getUnary(Type type, Op op) {
103103
}
104104
case Type::funcref:
105105
case Type::externref:
106-
case Type::nullref:
107106
case Type::exnref:
108107
case Type::none:
109108
case Type::unreachable: {
@@ -268,7 +267,6 @@ inline BinaryOp getBinary(Type type, Op op) {
268267
}
269268
case Type::funcref:
270269
case Type::externref:
271-
case Type::nullref:
272270
case Type::exnref:
273271
case Type::none:
274272
case Type::unreachable: {

src/ir/properties.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -94,7 +94,7 @@ inline Literal getSingleLiteral(const Expression* curr) {
9494
if (auto* c = curr->dynCast<Const>()) {
9595
return c->value;
9696
} else if (curr->is<RefNull>()) {
97-
return Literal(Type::nullref);
97+
return Literal::makeNull(curr->type);
9898
} else if (auto* c = curr->dynCast<RefFunc>()) {
9999
return Literal(c->func);
100100
} else {

src/js/binaryen.js-post.js

Lines changed: 2 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,6 @@ function initializeConstants() {
3535
['v128', 'Vec128'],
3636
['funcref', 'Funcref'],
3737
['externref', 'Externref'],
38-
['nullref', 'Nullref'],
3938
['exnref', 'Exnref'],
4039
['unreachable', 'Unreachable'],
4140
['auto', 'Auto']
@@ -2058,21 +2057,15 @@ function wrapModule(module, self = {}) {
20582057
}
20592058
};
20602059

2061-
self['nullref'] = {
2062-
'pop'() {
2063-
return Module['_BinaryenPop'](module, Module['nullref']);
2064-
}
2065-
};
2066-
20672060
self['exnref'] = {
20682061
'pop'() {
20692062
return Module['_BinaryenPop'](module, Module['exnref']);
20702063
}
20712064
};
20722065

20732066
self['ref'] = {
2074-
'null'() {
2075-
return Module['_BinaryenRefNull'](module);
2067+
'null'(type) {
2068+
return Module['_BinaryenRefNull'](module, type);
20762069
},
20772070
'is_null'(value) {
20782071
return Module['_BinaryenRefIsNull'](module, value);

src/literal.h

Lines changed: 19 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,7 @@ class Literal {
3939
int32_t i32;
4040
int64_t i64;
4141
uint8_t v128[16];
42-
Name func; // function name for funcref
42+
std::unique_ptr<Name> func; // function name for funcref
4343
std::unique_ptr<ExceptionPackage> exn;
4444
};
4545

@@ -66,19 +66,25 @@ class Literal {
6666
explicit Literal(const std::array<Literal, 8>&);
6767
explicit Literal(const std::array<Literal, 4>&);
6868
explicit Literal(const std::array<Literal, 2>&);
69-
explicit Literal(Name func) : func(func), type(Type::funcref) {}
69+
explicit Literal(Name func) : func(new Name(func)), type(Type::funcref) {}
7070
explicit Literal(std::unique_ptr<ExceptionPackage> exn)
7171
: exn(std::move(exn)), type(Type::exnref) {}
7272
Literal(const Literal& other);
7373
Literal& operator=(const Literal& other);
7474
~Literal() {
75+
if (type == Type::funcref) {
76+
func.~unique_ptr();
77+
}
7578
if (type == Type::exnref) {
7679
exn.~unique_ptr();
7780
}
7881
}
7982

8083
bool isConcrete() const { return type != Type::none; }
8184
bool isNone() const { return type == Type::none; }
85+
bool isNull() const {
86+
return (type == Type::funcref && !func) || (type == Type::exnref && !exn);
87+
}
8288

8389
static Literal makeFromInt32(int32_t x, Type type) {
8490
switch (type.getBasic()) {
@@ -103,7 +109,11 @@ class Literal {
103109
static Literals makeZero(Type type);
104110
static Literal makeSingleZero(Type type);
105111

106-
static Literal makeNullref() { return Literal(Type(Type::nullref)); }
112+
static Literal makeNull(Type type) {
113+
assert(type == Type::funcref || type == Type::exnref);
114+
// This creates a literal with null pointer for its func / exn
115+
return Literal(type);
116+
}
107117
static Literal makeFuncref(Name func) { return Literal(func.c_str()); }
108118
static Literal makeExnref(std::unique_ptr<ExceptionPackage> exn) {
109119
return Literal(std::move(exn));
@@ -132,11 +142,11 @@ class Literal {
132142
}
133143
std::array<uint8_t, 16> getv128() const;
134144
Name getFunc() const {
135-
assert(type == Type::funcref);
136-
return func;
145+
assert(type == Type::funcref && func);
146+
return *func.get();
137147
}
138148
const ExceptionPackage& getExceptionPackage() const {
139-
assert(type == Type::exnref);
149+
assert(type == Type::exnref && exn);
140150
return *exn.get();
141151
}
142152

@@ -503,6 +513,9 @@ class Literals : public SmallVector<Literal, 1> {
503513
struct ExceptionPackage {
504514
Name event;
505515
Literals values;
516+
bool operator==(const ExceptionPackage& other) const {
517+
return event == other.event && values == other.values;
518+
}
506519
};
507520

508521
std::ostream& operator<<(std::ostream& o, wasm::Literal literal);
@@ -555,7 +568,6 @@ template<> struct less<wasm::Literal> {
555568
return memcmp(a.getv128Ptr(), b.getv128Ptr(), 16) < 0;
556569
case wasm::Type::funcref:
557570
case wasm::Type::externref:
558-
case wasm::Type::nullref:
559571
case wasm::Type::exnref:
560572
case wasm::Type::none:
561573
case wasm::Type::unreachable:

src/parsing.h

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -265,7 +265,6 @@ parseConst(cashew::IString s, Type type, MixedArena& allocator) {
265265
case Type::v128:
266266
case Type::funcref:
267267
case Type::externref:
268-
case Type::nullref:
269268
case Type::exnref:
270269
WASM_UNREACHABLE("unexpected const type");
271270
case Type::none:

src/passes/ConstHoisting.cpp

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -96,7 +96,6 @@ struct ConstHoisting : public WalkerPass<PostWalker<ConstHoisting>> {
9696
case Type::v128:
9797
case Type::funcref:
9898
case Type::externref:
99-
case Type::nullref:
10099
case Type::exnref: {
101100
return false;
102101
}

src/passes/Flatten.cpp

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -210,20 +210,20 @@ struct Flatten
210210
// out. The local we created using 'getTempForBreakTarget' returns
211211
// the return type of the block this branch is targetting, which may
212212
// not be the same with the innermost block's return type. For
213-
// example,
214-
// (block $any (result externref)
215-
// (block (result nullref)
213+
// example, when 'subtype' is a subtype of 'supertype',
214+
// (block $super (result supertype)
215+
// (block (result subtype)
216216
// (local.tee $0
217-
// (br_if $any
218-
// (ref.null)
217+
// (br_if $super
218+
// (produce_subtype_value) ;; pseudo instruction
219219
// (i32.const 0)
220220
// )
221221
// )
222222
// )
223223
// )
224-
// In this case we need two locals to store (ref.null); one with
225-
// externref type that's for the target block ($label0) and one more
226-
// with nullref type in case for flowing out. Here we create the
224+
// In this case we need two locals to store (produce_subtype_value);
225+
// one with supertype that's for the target block ($super) and one
226+
// more with subtype in case for flowing out. Here we create the
227227
// second 'flowing out' local in case two block's types are
228228
// different.
229229
if (type != blockType) {

src/passes/FuncCastEmulation.cpp

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -67,7 +67,6 @@ static Expression* toABI(Expression* value, Module* module) {
6767
}
6868
case Type::funcref:
6969
case Type::externref:
70-
case Type::nullref:
7170
case Type::exnref: {
7271
WASM_UNREACHABLE("reference types cannot be converted to i64");
7372
}
@@ -111,7 +110,6 @@ static Expression* fromABI(Expression* value, Type type, Module* module) {
111110
}
112111
case Type::funcref:
113112
case Type::externref:
114-
case Type::nullref:
115113
case Type::exnref: {
116114
WASM_UNREACHABLE("reference types cannot be converted from i64");
117115
}

src/passes/InstrumentLocals.cpp

Lines changed: 0 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -58,7 +58,6 @@ Name get_f32("get_f32");
5858
Name get_f64("get_f64");
5959
Name get_funcref("get_funcref");
6060
Name get_externref("get_externref");
61-
Name get_nullref("get_nullref");
6261
Name get_exnref("get_exnref");
6362
Name get_v128("get_v128");
6463

@@ -68,7 +67,6 @@ Name set_f32("set_f32");
6867
Name set_f64("set_f64");
6968
Name set_funcref("set_funcref");
7069
Name set_externref("set_externref");
71-
Name set_nullref("set_nullref");
7270
Name set_exnref("set_exnref");
7371
Name set_v128("set_v128");
7472

@@ -98,9 +96,6 @@ struct InstrumentLocals : public WalkerPass<PostWalker<InstrumentLocals>> {
9896
case Type::externref:
9997
import = get_externref;
10098
break;
101-
case Type::nullref:
102-
import = get_nullref;
103-
break;
10499
case Type::exnref:
105100
import = get_exnref;
106101
break;
@@ -147,9 +142,6 @@ struct InstrumentLocals : public WalkerPass<PostWalker<InstrumentLocals>> {
147142
case Type::externref:
148143
import = set_externref;
149144
break;
150-
case Type::nullref:
151-
import = set_nullref;
152-
break;
153145
case Type::exnref:
154146
import = set_exnref;
155147
break;
@@ -192,14 +184,6 @@ struct InstrumentLocals : public WalkerPass<PostWalker<InstrumentLocals>> {
192184
set_externref,
193185
{Type::i32, Type::i32, Type::externref},
194186
Type::externref);
195-
addImport(curr,
196-
get_nullref,
197-
{Type::i32, Type::i32, Type::nullref},
198-
Type::nullref);
199-
addImport(curr,
200-
set_nullref,
201-
{Type::i32, Type::i32, Type::nullref},
202-
Type::nullref);
203187
}
204188
if (curr->features.hasExceptionHandling()) {
205189
addImport(

0 commit comments

Comments
 (0)