Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Update reference types #3084

Merged
merged 32 commits into from
Sep 9, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
32 commits
Select commit Hold shift + click to select a range
3b1fc52
Update basic reference types
dcodeIO Aug 29, 2020
6800818
fix equality, fix test, make Literal::type immutable, don't use smart…
dcodeIO Aug 30, 2020
28a042a
revert ExceptionPackage
dcodeIO Aug 31, 2020
f7efeb6
add TODO for s33 encoding
dcodeIO Aug 31, 2020
043c87b
fix fuzzing
dcodeIO Aug 31, 2020
83fe597
update translate-to-fuzz test
dcodeIO Sep 1, 2020
794a11b
fix it like a pro
dcodeIO Sep 1, 2020
b5a6ad0
tidy
dcodeIO Sep 1, 2020
0ef68e6
fuzzer not quite happy, so
dcodeIO Sep 1, 2020
8e53478
simplify, revert getSingleValue by ref
dcodeIO Sep 1, 2020
dfaa112
prepare for clean merge
dcodeIO Sep 1, 2020
9de7293
Merge branch 'master' into gc-xref
dcodeIO Sep 2, 2020
3607ef6
Merge branch 'master' into gc-xref
dcodeIO Sep 3, 2020
4bae64e
revert GC-only functionality
dcodeIO Sep 3, 2020
c5e11db
update js kitchen-sink test
dcodeIO Sep 4, 2020
83e336c
fix left-over TranslateToFuzzReader::getSubType
dcodeIO Sep 4, 2020
97ebb0c
update and disable two more subtyping tests
dcodeIO Sep 4, 2020
05ce530
fix ExpressionManipulator::refNull not applying the type
dcodeIO Sep 4, 2020
c24f90c
address comments
dcodeIO Sep 7, 2020
cfc4ca2
rm -r gc
dcodeIO Sep 7, 2020
b335c64
update TODO comment
dcodeIO Sep 7, 2020
ad384ba
make sure to initialize BinaryenLiteral::func
dcodeIO Sep 7, 2020
4a0465e
provide type explicitly when manipulating an expression to RefNull
dcodeIO Sep 7, 2020
2bd5976
replace unnecessary getSubType code with a TODO in the fuzzer
dcodeIO Sep 7, 2020
47dd183
make check for null `exn` more obvious
dcodeIO Sep 7, 2020
d2009e4
add assertion message when trying to print non-null externref literal
dcodeIO Sep 7, 2020
d3cf93e
add TODO to Type::isSubType just reimplementing equality currently
dcodeIO Sep 7, 2020
395067b
add trailing newline to reference-types.wast
dcodeIO Sep 7, 2020
121abe3
remove unused allowError in s-parser
dcodeIO Sep 7, 2020
2506877
add a TODO to Literal::getBits when dealing with reference types
dcodeIO Sep 7, 2020
0596965
revert removing allowError in s-parser stringToType, is actually used
dcodeIO Sep 7, 2020
b89ec05
Merge branch 'master' into gc-xref
dcodeIO Sep 8, 2020
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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
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
19 changes: 10 additions & 9 deletions src/binaryen-c.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -69,12 +69,12 @@ BinaryenLiteral toBinaryenLiteral(Literal x) {
memcpy(&ret.v128, x.getv128Ptr(), 16);
break;
case Type::funcref:
ret.func = x.getFunc().c_str();
break;
case Type::nullref:
ret.func = x.isNull() ? nullptr : x.getFunc().c_str();
break;
case Type::externref:
case Type::exnref:
assert(x.isNull());
break;
case Type::none:
case Type::unreachable:
WASM_UNREACHABLE("unexpected type");
Expand All @@ -95,11 +95,10 @@ Literal fromBinaryenLiteral(BinaryenLiteral x) {
case Type::v128:
return Literal(x.v128);
case Type::funcref:
return Literal::makeFuncref(x.func);
case Type::nullref:
return Literal::makeNullref();
return Literal::makeFunc(x.func);
case Type::externref:
case Type::exnref:
return Literal::makeNull(Type(x.type));
case Type::none:
case Type::unreachable:
WASM_UNREACHABLE("unexpected type");
Expand Down Expand Up @@ -133,7 +132,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 +1262,11 @@ 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) {
Type type_(type);
assert(type_.isNullable());
return static_cast<Expression*>(Builder(*(Module*)module).makeRefNull(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
5 changes: 3 additions & 2 deletions src/ir/manipulation.h
Original file line number Diff line number Diff line change
Expand Up @@ -40,9 +40,10 @@ template<typename InputType> inline Nop* nop(InputType* target) {
return ret;
}

template<typename InputType> inline RefNull* refNull(InputType* target) {
template<typename InputType>
inline RefNull* refNull(InputType* target, Type type) {
auto* ret = convert<InputType, RefNull>(target);
ret->finalize();
ret->finalize(type);
return ret;
}

Expand Down
8 changes: 4 additions & 4 deletions src/ir/properties.h
Original file line number Diff line number Diff line change
Expand Up @@ -93,10 +93,10 @@ inline bool isConstantExpression(const Expression* curr) {
inline Literal getSingleLiteral(const Expression* curr) {
if (auto* c = curr->dynCast<Const>()) {
return c->value;
} else if (curr->is<RefNull>()) {
return Literal(Type::nullref);
} else if (auto* c = curr->dynCast<RefFunc>()) {
return Literal(c->func);
} else if (auto* n = curr->dynCast<RefNull>()) {
return Literal(n->type);
} else if (auto* r = curr->dynCast<RefFunc>()) {
return Literal(r->func);
} else {
WASM_UNREACHABLE("non-constant expression");
}
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
45 changes: 34 additions & 11 deletions src/literal.h
Original file line number Diff line number Diff line change
Expand Up @@ -39,19 +39,22 @@ class Literal {
int32_t i32;
int64_t i64;
uint8_t v128[16];
Name func; // function name for funcref
// funcref function name. `isNull()` indicates a `null` value.
Name func;
// exnref package. `nullptr` indicates a `null` value.
std::unique_ptr<ExceptionPackage> exn;
// TODO: Literals of type `externref` can only be `null` currently but we
// will need to represent extern values eventually, to
// 1) run the spec tests and fuzzer with reference types enabled and
// 2) avoid bailing out when seeing a reference typed value in precompute
};

public:
// Type of the literal. Immutable because the literal's payload depends on it.
const Type type;

Literal() : v128(), type(Type::none) {}
explicit Literal(Type type) : v128(), type(type) {
assert(type != Type::unreachable && type != Type::funcref &&
type != Type::exnref);
}
explicit Literal(Type type);
explicit Literal(Type::BasicID typeId) : Literal(Type(typeId)) {}
explicit Literal(int32_t init) : i32(init), type(Type::i32) {}
explicit Literal(uint32_t init) : i32(init), type(Type::i32) {}
Expand All @@ -74,13 +77,25 @@ class Literal {
Literal(const Literal& other);
Literal& operator=(const Literal& other);
~Literal() {
if (type == Type::exnref) {
if (type.isException()) {
exn.~unique_ptr();
}
}

bool isConcrete() const { return type != Type::none; }
bool isNone() const { return type == Type::none; }
bool isNull() const {
if (type.isNullable()) {
if (type.isFunction()) {
return func.isNull();
}
if (type.isException()) {
return !exn;
}
return true;
}
return false;
}

static Literal makeFromInt32(int32_t x, Type type) {
switch (type.getBasic()) {
Expand All @@ -105,9 +120,12 @@ class Literal {
static Literals makeZero(Type type);
static Literal makeSingleZero(Type type);

static Literal makeNullref() { return Literal(Type(Type::nullref)); }
static Literal makeFuncref(Name func) { return Literal(func.c_str()); }
static Literal makeExnref(std::unique_ptr<ExceptionPackage>&& exn) {
static Literal makeNull(Type type) {
assert(type.isNullable());
return Literal(type);
}
static Literal makeFunc(Name func) { return Literal(func.c_str()); }
static Literal makeExn(std::unique_ptr<ExceptionPackage>&& exn) {
return Literal(std::move(exn));
}

Expand All @@ -134,7 +152,7 @@ class Literal {
}
std::array<uint8_t, 16> getv128() const;
Name getFunc() const {
assert(type == Type::funcref);
assert(type.isFunction() && !func.isNull());
return func;
}
ExceptionPackage getExceptionPackage() const;
Expand Down Expand Up @@ -502,6 +520,12 @@ 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;
}
bool operator!=(const ExceptionPackage& other) const {
return !(*this == other);
}
};

std::ostream& operator<<(std::ostream& o, wasm::Literal literal);
Expand Down Expand Up @@ -554,7 +578,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
10 changes: 5 additions & 5 deletions src/passes/Flatten.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -211,19 +211,19 @@ struct Flatten
// 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)
// (block $any (result anyref)
// (block (result funcref)
// (local.tee $0
// (br_if $any
// (ref.null)
// (ref.null func)
// (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
// funcref type that's for the target block ($label0) and one more
// with anyref type 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
Loading