summaryrefslogtreecommitdiff
path: root/src/wasm
diff options
context:
space:
mode:
Diffstat (limited to 'src/wasm')
-rw-r--r--src/wasm/wasm-binary.cpp10
-rw-r--r--src/wasm/wasm-s-parser.cpp46
-rw-r--r--src/wasm/wasm-validator.cpp8
-rw-r--r--src/wasm/wasm.cpp2
4 files changed, 46 insertions, 20 deletions
diff --git a/src/wasm/wasm-binary.cpp b/src/wasm/wasm-binary.cpp
index 20b0899a5..170aa17bb 100644
--- a/src/wasm/wasm-binary.cpp
+++ b/src/wasm/wasm-binary.cpp
@@ -1357,7 +1357,8 @@ Type WasmBinaryBuilder::getType() {
case BinaryConsts::EncodedType::nullable:
return Type(getHeapType(), /* nullable = */ true);
case BinaryConsts::EncodedType::nonnullable:
- return Type(getHeapType(), /* nullable = */ false);
+ // FIXME: for now, force all inputs to be nullable
+ return Type(getHeapType(), /* nullable = */ true);
case BinaryConsts::EncodedType::i31ref:
return Type::i31ref;
default:
@@ -5291,6 +5292,7 @@ void WasmBinaryBuilder::visitRefFunc(RefFunc* curr) {
functionRefs[index].push_back(curr); // we don't know function names yet
// To support typed function refs, we give the reference not just a general
// funcref, but a specific subtype with the actual signature.
+ // FIXME: for now, emit a nullable type here
curr->finalize(
Type(HeapType(getFunctionSignatureByIndex(index)), /* nullable = */ true));
}
@@ -5440,6 +5442,12 @@ void WasmBinaryBuilder::visitCallRef(CallRef* curr) {
BYN_TRACE("zz node: CallRef\n");
curr->target = popNonVoidExpression();
auto type = curr->target->type;
+ if (type == Type::unreachable) {
+ // If our input is unreachable, then we cannot even find out how many inputs
+ // we have, and just set ourselves to unreachable as well.
+ curr->finalize(type);
+ return;
+ }
if (!type.isRef()) {
throwError("Non-ref type for a call_ref: " + type.toString());
}
diff --git a/src/wasm/wasm-s-parser.cpp b/src/wasm/wasm-s-parser.cpp
index d8d9fa779..434dec9d7 100644
--- a/src/wasm/wasm-s-parser.cpp
+++ b/src/wasm/wasm-s-parser.cpp
@@ -536,14 +536,10 @@ SExpressionWasmBuilder::parseParamOrLocal(Element& s, size_t& localIndex) {
}
localIndex++;
Type type;
- if (s[i]->isStr()) {
- type = stringToType(s[i]->str());
- } else {
- type = elementToType(*s[i]);
- if (elementStartsWith(s, PARAM) && type.isTuple()) {
- throw ParseException(
- "params may not have tuple types", s[i]->line, s[i]->col);
- }
+ type = elementToType(*s[i]);
+ if (elementStartsWith(s, PARAM) && type.isTuple()) {
+ throw ParseException(
+ "params may not have tuple types", s[i]->line, s[i]->col);
}
namedParams.emplace_back(name, type);
}
@@ -555,7 +551,7 @@ std::vector<Type> SExpressionWasmBuilder::parseResults(Element& s) {
assert(elementStartsWith(s, RESULT));
std::vector<Type> types;
for (size_t i = 1; i < s.size(); i++) {
- types.push_back(stringToType(s[i]->str()));
+ types.push_back(elementToType(*s[i]));
}
return types;
}
@@ -923,7 +919,7 @@ HeapType SExpressionWasmBuilder::stringToHeapType(const char* str,
Type SExpressionWasmBuilder::elementToType(Element& s) {
if (s.isStr()) {
- return stringToType(s.str(), false, false);
+ return stringToType(s.str());
}
auto& list = s.list();
auto size = list.size();
@@ -942,7 +938,8 @@ Type SExpressionWasmBuilder::elementToType(Element& s) {
throw ParseException(
std::string("invalid reference type qualifier"), s.line, s.col);
}
- bool nullable = false;
+ // FIXME: for now, force all inputs to be nullable
+ bool nullable = true;
size_t i = 1;
if (size == 3) {
nullable = true;
@@ -966,7 +963,7 @@ Type SExpressionWasmBuilder::elementToType(Element& s) {
// It's a tuple.
std::vector<Type> types;
for (size_t i = 0; i < s.size(); ++i) {
- types.push_back(stringToType(list[i]->str()));
+ types.push_back(elementToType(*list[i]));
}
return Type(types);
}
@@ -1911,9 +1908,30 @@ Expression* SExpressionWasmBuilder::makeRefNull(Element& s) {
if (s.size() != 2) {
throw ParseException("invalid heap type reference", s.line, s.col);
}
- auto heapType = stringToHeapType(s[1]->str());
auto ret = allocator.alloc<RefNull>();
- ret->finalize(heapType);
+ if (s[1]->isStr()) {
+ // For example, this parses
+ // (ref.null func)
+ ret->finalize(stringToHeapType(s[1]->str()));
+ } else {
+ // To parse a heap type, create an element around it, and call that method.
+ // That is, given (func) we wrap to (ref (func)).
+ // For example, this parses
+ // (ref.null (func (param i32)))
+ // TODO add a helper method, but this is the only user atm, and we are
+ // waiting on https://github.com/WebAssembly/function-references/issues/42
+ Element wrapper(wasm.allocator);
+ auto& list = wrapper.list();
+ list.resize(3);
+ Element ref(wasm.allocator);
+ ref.setString(REF, false, false);
+ Element null(wasm.allocator);
+ null.setString(NULL_, false, false);
+ list[0] = &ref;
+ list[1] = &null;
+ list[2] = s[1];
+ ret->finalize(elementToType(wrapper));
+ }
return ret;
}
diff --git a/src/wasm/wasm-validator.cpp b/src/wasm/wasm-validator.cpp
index 5faa8b2f5..fb55417d5 100644
--- a/src/wasm/wasm-validator.cpp
+++ b/src/wasm/wasm-validator.cpp
@@ -1963,6 +1963,8 @@ void FunctionValidator::visitRefNull(RefNull* curr) {
shouldBeTrue(getModule()->features.hasReferenceTypes(),
curr,
"ref.null requires reference-types to be enabled");
+ shouldBeTrue(
+ curr->type.isNullable(), curr, "ref.null types must be nullable");
}
void FunctionValidator::visitRefIsNull(RefIsNull* curr) {
@@ -2158,10 +2160,10 @@ void FunctionValidator::visitCallRef(CallRef* curr) {
shouldBeTrue(getModule()->features.hasTypedFunctionReferences(),
curr,
"call_ref requires typed-function-references to be enabled");
- shouldBeTrue(curr->target->type.isFunction(),
- curr,
- "call_ref target must be a function reference");
if (curr->target->type != Type::unreachable) {
+ shouldBeTrue(curr->target->type.isFunction(),
+ curr,
+ "call_ref target must be a function reference");
validateCallParamsAndResult(
curr, curr->target->type.getHeapType().getSignature());
}
diff --git a/src/wasm/wasm.cpp b/src/wasm/wasm.cpp
index ac76a63ac..cbf573950 100644
--- a/src/wasm/wasm.cpp
+++ b/src/wasm/wasm.cpp
@@ -973,12 +973,10 @@ void MemoryGrow::finalize() {
void RefNull::finalize(HeapType heapType) { type = Type(heapType, true); }
void RefNull::finalize(Type type_) {
- assert(type_ == Type::unreachable || type_.isNullable());
type = type_;
}
void RefNull::finalize() {
- assert(type == Type::unreachable || type.isNullable());
}
void RefIsNull::finalize() {