Skip to content

Commit

Permalink
Implement changes in reference types proposal
Browse files Browse the repository at this point in the history
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.
  • Loading branch information
aheejin committed Aug 31, 2020
1 parent fecfa92 commit b8733ac
Show file tree
Hide file tree
Showing 42 changed files with 219 additions and 427 deletions.
5 changes: 1 addition & 4 deletions check.py
Original file line number Diff line number Diff line change
Expand Up @@ -240,10 +240,7 @@ def check_expected(actual, expected):
# some wast files cannot be split:
# * comments.wast: contains characters that are not valid utf-8,
# so our string splitting code fails there

# FIXME Remove reference type tests from this list after nullref is
# implemented in V8
if base not in ['comments.wast', 'ref_null.wast', 'ref_is_null.wast', 'ref_func.wast', 'old_select.wast']:
if base not in ['comments.wast', 'old_select.wast']:
split_num = 0
actual = ''
for module, asserts in support.split_wast(wast):
Expand Down
1 change: 0 additions & 1 deletion scripts/gen-s-parser.py
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,6 @@
("v128.pop", "makePop(Type::v128)"),
("funcref.pop", "makePop(Type::funcref)"),
("externref.pop", "makePop(Type::externref)"),
("nullref.pop", "makePop(Type::nullref)"),
("exnref.pop", "makePop(Type::exnref)"),
("i32.load", "makeLoad(s, Type::i32, /*isAtomic=*/false)"),
("i64.load", "makeLoad(s, Type::i64, /*isAtomic=*/false)"),
Expand Down
6 changes: 2 additions & 4 deletions scripts/test/wasm_opt.py
Original file line number Diff line number Diff line change
Expand Up @@ -113,10 +113,8 @@ def check():

shared.fail_if_not_identical_to_file(actual, f)

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

shared.minify_check(t)

Expand Down
3 changes: 0 additions & 3 deletions src/asmjs/asm_v_wasm.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,6 @@ AsmType wasmToAsmType(Type type) {
assert(false && "v128 not implemented yet");
case Type::funcref:
case Type::externref:
case Type::nullref:
case Type::exnref:
assert(false && "reference types are not supported by asm2wasm");
case Type::none:
Expand Down Expand Up @@ -84,8 +83,6 @@ char getSig(Type type) {
return 'F';
case Type::externref:
return 'X';
case Type::nullref:
return 'N';
case Type::exnref:
return 'E';
case Type::none:
Expand Down
11 changes: 4 additions & 7 deletions src/binaryen-c.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -71,8 +71,6 @@ BinaryenLiteral toBinaryenLiteral(Literal x) {
case Type::funcref:
ret.func = x.getFunc().c_str();
break;
case Type::nullref:
break;
case Type::externref:
case Type::exnref:
case Type::none:
Expand All @@ -96,8 +94,6 @@ Literal fromBinaryenLiteral(BinaryenLiteral x) {
return Literal(x.v128);
case Type::funcref:
return Literal::makeFuncref(x.func);
case Type::nullref:
return Literal::makeNullref();
case Type::externref:
case Type::exnref:
case Type::none:
Expand Down Expand Up @@ -133,7 +129,6 @@ BinaryenType BinaryenTypeFloat64(void) { return Type::f64; }
BinaryenType BinaryenTypeVec128(void) { return Type::v128; }
BinaryenType BinaryenTypeFuncref(void) { return Type::funcref; }
BinaryenType BinaryenTypeExternref(void) { return Type::externref; }
BinaryenType BinaryenTypeNullref(void) { return Type::nullref; }
BinaryenType BinaryenTypeExnref(void) { return Type::exnref; }
BinaryenType BinaryenTypeUnreachable(void) { return Type::unreachable; }
BinaryenType BinaryenTypeAuto(void) { return uintptr_t(-1); }
Expand Down Expand Up @@ -1264,8 +1259,10 @@ BinaryenExpressionRef BinaryenPop(BinaryenModuleRef module, BinaryenType type) {
Builder(*(Module*)module).makePop(Type(type)));
}

BinaryenExpressionRef BinaryenRefNull(BinaryenModuleRef module) {
return static_cast<Expression*>(Builder(*(Module*)module).makeRefNull());
BinaryenExpressionRef BinaryenRefNull(BinaryenModuleRef module,
BinaryenType type) {
return static_cast<Expression*>(
Builder(*(Module*)module).makeRefNull(Type(type)));
}

BinaryenExpressionRef BinaryenRefIsNull(BinaryenModuleRef module,
Expand Down
4 changes: 2 additions & 2 deletions src/binaryen-c.h
Original file line number Diff line number Diff line change
Expand Up @@ -100,7 +100,6 @@ BINARYEN_API BinaryenType BinaryenTypeFloat64(void);
BINARYEN_API BinaryenType BinaryenTypeVec128(void);
BINARYEN_API BinaryenType BinaryenTypeFuncref(void);
BINARYEN_API BinaryenType BinaryenTypeExternref(void);
BINARYEN_API BinaryenType BinaryenTypeNullref(void);
BINARYEN_API BinaryenType BinaryenTypeExnref(void);
BINARYEN_API BinaryenType BinaryenTypeUnreachable(void);
// Not a real type. Used as the last parameter to BinaryenBlock to let
Expand Down Expand Up @@ -826,7 +825,8 @@ BinaryenMemoryFill(BinaryenModuleRef module,
BinaryenExpressionRef dest,
BinaryenExpressionRef value,
BinaryenExpressionRef size);
BINARYEN_API BinaryenExpressionRef BinaryenRefNull(BinaryenModuleRef module);
BINARYEN_API BinaryenExpressionRef BinaryenRefNull(BinaryenModuleRef module,
BinaryenType type);
BINARYEN_API BinaryenExpressionRef
BinaryenRefIsNull(BinaryenModuleRef module, BinaryenExpressionRef value);
BINARYEN_API BinaryenExpressionRef BinaryenRefFunc(BinaryenModuleRef module,
Expand Down
14 changes: 3 additions & 11 deletions src/gen-s-parser.inc
Original file line number Diff line number Diff line change
Expand Up @@ -2560,17 +2560,9 @@ switch (op[0]) {
default: goto parse_error;
}
}
case 'n': {
switch (op[1]) {
case 'o':
if (strcmp(op, "nop") == 0) { return makeNop(); }
goto parse_error;
case 'u':
if (strcmp(op, "nullref.pop") == 0) { return makePop(Type::nullref); }
goto parse_error;
default: goto parse_error;
}
}
case 'n':
if (strcmp(op, "nop") == 0) { return makeNop(); }
goto parse_error;
case 'r': {
switch (op[2]) {
case 'f': {
Expand Down
4 changes: 3 additions & 1 deletion src/ir/ExpressionManipulator.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -227,7 +227,9 @@ flexibleCopy(Expression* original, Module& wasm, CustomCopier custom) {
builder.makeHost(curr->op, curr->nameOperand, std::move(operands));
return ret;
}
Expression* visitRefNull(RefNull* curr) { return builder.makeRefNull(); }
Expression* visitRefNull(RefNull* curr) {
return builder.makeRefNull(curr->type);
}
Expression* visitRefIsNull(RefIsNull* curr) {
return builder.makeRefIsNull(copy(curr->value));
}
Expand Down
2 changes: 0 additions & 2 deletions src/ir/abstract.h
Original file line number Diff line number Diff line change
Expand Up @@ -103,7 +103,6 @@ inline UnaryOp getUnary(Type type, Op op) {
}
case Type::funcref:
case Type::externref:
case Type::nullref:
case Type::exnref:
case Type::none:
case Type::unreachable: {
Expand Down Expand Up @@ -268,7 +267,6 @@ inline BinaryOp getBinary(Type type, Op op) {
}
case Type::funcref:
case Type::externref:
case Type::nullref:
case Type::exnref:
case Type::none:
case Type::unreachable: {
Expand Down
2 changes: 1 addition & 1 deletion src/ir/properties.h
Original file line number Diff line number Diff line change
Expand Up @@ -94,7 +94,7 @@ inline Literal getSingleLiteral(const Expression* curr) {
if (auto* c = curr->dynCast<Const>()) {
return c->value;
} else if (curr->is<RefNull>()) {
return Literal(Type::nullref);
return Literal::makeNull(curr->type);
} else if (auto* c = curr->dynCast<RefFunc>()) {
return Literal(c->func);
} else {
Expand Down
11 changes: 2 additions & 9 deletions src/js/binaryen.js-post.js
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,6 @@ function initializeConstants() {
['v128', 'Vec128'],
['funcref', 'Funcref'],
['externref', 'Externref'],
['nullref', 'Nullref'],
['exnref', 'Exnref'],
['unreachable', 'Unreachable'],
['auto', 'Auto']
Expand Down Expand Up @@ -2058,21 +2057,15 @@ function wrapModule(module, self = {}) {
}
};

self['nullref'] = {
'pop'() {
return Module['_BinaryenPop'](module, Module['nullref']);
}
};

self['exnref'] = {
'pop'() {
return Module['_BinaryenPop'](module, Module['exnref']);
}
};

self['ref'] = {
'null'() {
return Module['_BinaryenRefNull'](module);
'null'(type) {
return Module['_BinaryenRefNull'](module, type);
},
'is_null'(value) {
return Module['_BinaryenRefIsNull'](module, value);
Expand Down
26 changes: 19 additions & 7 deletions src/literal.h
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ class Literal {
int32_t i32;
int64_t i64;
uint8_t v128[16];
Name func; // function name for funcref
std::unique_ptr<Name> func; // function name for funcref
std::unique_ptr<ExceptionPackage> exn;
};

Expand All @@ -66,19 +66,25 @@ class Literal {
explicit Literal(const std::array<Literal, 8>&);
explicit Literal(const std::array<Literal, 4>&);
explicit Literal(const std::array<Literal, 2>&);
explicit Literal(Name func) : func(func), type(Type::funcref) {}
explicit Literal(Name func) : func(new Name(func)), type(Type::funcref) {}
explicit Literal(std::unique_ptr<ExceptionPackage> exn)
: exn(std::move(exn)), type(Type::exnref) {}
Literal(const Literal& other);
Literal& operator=(const Literal& other);
~Literal() {
if (type == Type::funcref) {
func.~unique_ptr();
}
if (type == Type::exnref) {
exn.~unique_ptr();
}
}

bool isConcrete() const { return type != Type::none; }
bool isNone() const { return type == Type::none; }
bool isNull() const {
return (type == Type::funcref && !func) || (type == Type::exnref && !exn);
}

static Literal makeFromInt32(int32_t x, Type type) {
switch (type.getBasic()) {
Expand All @@ -103,7 +109,11 @@ class Literal {
static Literals makeZero(Type type);
static Literal makeSingleZero(Type type);

static Literal makeNullref() { return Literal(Type(Type::nullref)); }
static Literal makeNull(Type type) {
assert(type == Type::funcref || type == Type::exnref);
// This creates a literal with null pointer for its func / exn
return Literal(type);
}
static Literal makeFuncref(Name func) { return Literal(func.c_str()); }
static Literal makeExnref(std::unique_ptr<ExceptionPackage> exn) {
return Literal(std::move(exn));
Expand Down Expand Up @@ -132,11 +142,11 @@ class Literal {
}
std::array<uint8_t, 16> getv128() const;
Name getFunc() const {
assert(type == Type::funcref);
return func;
assert(type == Type::funcref && func);
return *func.get();
}
const ExceptionPackage& getExceptionPackage() const {
assert(type == Type::exnref);
assert(type == Type::exnref && exn);
return *exn.get();
}

Expand Down Expand Up @@ -503,6 +513,9 @@ class Literals : public SmallVector<Literal, 1> {
struct ExceptionPackage {
Name event;
Literals values;
bool operator==(const ExceptionPackage& other) const {
return event == other.event && values == other.values;
}
};

std::ostream& operator<<(std::ostream& o, wasm::Literal literal);
Expand Down Expand Up @@ -555,7 +568,6 @@ template<> struct less<wasm::Literal> {
return memcmp(a.getv128Ptr(), b.getv128Ptr(), 16) < 0;
case wasm::Type::funcref:
case wasm::Type::externref:
case wasm::Type::nullref:
case wasm::Type::exnref:
case wasm::Type::none:
case wasm::Type::unreachable:
Expand Down
1 change: 0 additions & 1 deletion src/parsing.h
Original file line number Diff line number Diff line change
Expand Up @@ -265,7 +265,6 @@ parseConst(cashew::IString s, Type type, MixedArena& allocator) {
case Type::v128:
case Type::funcref:
case Type::externref:
case Type::nullref:
case Type::exnref:
WASM_UNREACHABLE("unexpected const type");
case Type::none:
Expand Down
1 change: 0 additions & 1 deletion src/passes/ConstHoisting.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -96,7 +96,6 @@ struct ConstHoisting : public WalkerPass<PostWalker<ConstHoisting>> {
case Type::v128:
case Type::funcref:
case Type::externref:
case Type::nullref:
case Type::exnref: {
return false;
}
Expand Down
16 changes: 8 additions & 8 deletions src/passes/Flatten.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -210,20 +210,20 @@ struct Flatten
// out. The local we created using 'getTempForBreakTarget' returns
// the return type of the block this branch is targetting, which may
// not be the same with the innermost block's return type. For
// example,
// (block $any (result externref)
// (block (result nullref)
// example, when 'subtype' is a subtype of 'supertype',
// (block $super (result supertype)
// (block (result subtype)
// (local.tee $0
// (br_if $any
// (ref.null)
// (br_if $super
// (produce_subtype_value) ;; pseudo instruction
// (i32.const 0)
// )
// )
// )
// )
// In this case we need two locals to store (ref.null); one with
// externref type that's for the target block ($label0) and one more
// with nullref type in case for flowing out. Here we create the
// In this case we need two locals to store (produce_subtype_value);
// one with supertype that's for the target block ($super) and one
// more with subtype in case for flowing out. Here we create the
// second 'flowing out' local in case two block's types are
// different.
if (type != blockType) {
Expand Down
2 changes: 0 additions & 2 deletions src/passes/FuncCastEmulation.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,6 @@ static Expression* toABI(Expression* value, Module* module) {
}
case Type::funcref:
case Type::externref:
case Type::nullref:
case Type::exnref: {
WASM_UNREACHABLE("reference types cannot be converted to i64");
}
Expand Down Expand Up @@ -111,7 +110,6 @@ static Expression* fromABI(Expression* value, Type type, Module* module) {
}
case Type::funcref:
case Type::externref:
case Type::nullref:
case Type::exnref: {
WASM_UNREACHABLE("reference types cannot be converted from i64");
}
Expand Down
16 changes: 0 additions & 16 deletions src/passes/InstrumentLocals.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,6 @@ Name get_f32("get_f32");
Name get_f64("get_f64");
Name get_funcref("get_funcref");
Name get_externref("get_externref");
Name get_nullref("get_nullref");
Name get_exnref("get_exnref");
Name get_v128("get_v128");

Expand All @@ -68,7 +67,6 @@ Name set_f32("set_f32");
Name set_f64("set_f64");
Name set_funcref("set_funcref");
Name set_externref("set_externref");
Name set_nullref("set_nullref");
Name set_exnref("set_exnref");
Name set_v128("set_v128");

Expand Down Expand Up @@ -98,9 +96,6 @@ struct InstrumentLocals : public WalkerPass<PostWalker<InstrumentLocals>> {
case Type::externref:
import = get_externref;
break;
case Type::nullref:
import = get_nullref;
break;
case Type::exnref:
import = get_exnref;
break;
Expand Down Expand Up @@ -147,9 +142,6 @@ struct InstrumentLocals : public WalkerPass<PostWalker<InstrumentLocals>> {
case Type::externref:
import = set_externref;
break;
case Type::nullref:
import = set_nullref;
break;
case Type::exnref:
import = set_exnref;
break;
Expand Down Expand Up @@ -192,14 +184,6 @@ struct InstrumentLocals : public WalkerPass<PostWalker<InstrumentLocals>> {
set_externref,
{Type::i32, Type::i32, Type::externref},
Type::externref);
addImport(curr,
get_nullref,
{Type::i32, Type::i32, Type::nullref},
Type::nullref);
addImport(curr,
set_nullref,
{Type::i32, Type::i32, Type::nullref},
Type::nullref);
}
if (curr->features.hasExceptionHandling()) {
addImport(
Expand Down
Loading

0 comments on commit b8733ac

Please sign in to comment.