summaryrefslogtreecommitdiff
path: root/src/wasm-builder.h
diff options
context:
space:
mode:
Diffstat (limited to 'src/wasm-builder.h')
-rw-r--r--src/wasm-builder.h38
1 files changed, 24 insertions, 14 deletions
diff --git a/src/wasm-builder.h b/src/wasm-builder.h
index cc3b99138..b07af4627 100644
--- a/src/wasm-builder.h
+++ b/src/wasm-builder.h
@@ -699,10 +699,11 @@ public:
}
RefNull* makeRefNull(HeapType type) {
auto* ret = wasm.allocator.alloc<RefNull>();
- ret->finalize(Type(type, Nullable));
+ ret->finalize(Type(type.getBottom(), Nullable));
return ret;
}
RefNull* makeRefNull(Type type) {
+ assert(type.isNullable() && type.isNull());
auto* ret = wasm.allocator.alloc<RefNull>();
ret->finalize(type);
return ret;
@@ -942,11 +943,14 @@ public:
ret->finalize();
return ret;
}
- ArrayGet*
- makeArrayGet(Expression* ref, Expression* index, bool signed_ = false) {
+ ArrayGet* makeArrayGet(Expression* ref,
+ Expression* index,
+ Type type,
+ bool signed_ = false) {
auto* ret = wasm.allocator.alloc<ArrayGet>();
ret->ref = ref;
ret->index = index;
+ ret->type = type;
ret->signed_ = signed_;
ret->finalize();
return ret;
@@ -1262,7 +1266,7 @@ public:
if (curr->type.isTuple() && curr->type.isDefaultable()) {
return makeConstantExpression(Literal::makeZeros(curr->type));
}
- if (curr->type.isNullable()) {
+ if (curr->type.isNullable() && curr->type.isNull()) {
return ExpressionManipulator::refNull(curr, curr->type);
}
if (curr->type.isRef() && curr->type.getHeapType() == HeapType::i31) {
@@ -1329,18 +1333,24 @@ public:
Expression* validateAndMakeCallRef(Expression* target,
const T& args,
bool isReturn = false) {
- if (!target->type.isRef()) {
- if (target->type == Type::unreachable) {
- // An unreachable target is not supported. Similiar to br_on_cast, just
- // emit an unreachable sequence, since we don't have enough information
- // to create a full call_ref.
- auto* block = makeBlock(args);
- block->list.push_back(target);
- block->finalize(Type::unreachable);
- return block;
- }
+ if (target->type != Type::unreachable && !target->type.isRef()) {
throw ParseException("Non-reference type for a call_ref", line, col);
}
+ // TODO: This won't be necessary once type annotations are mandatory on
+ // call_ref.
+ if (target->type == Type::unreachable ||
+ target->type.getHeapType() == HeapType::nofunc) {
+ // An unreachable target is not supported. Similiar to br_on_cast, just
+ // emit an unreachable sequence, since we don't have enough information
+ // to create a full call_ref.
+ std::vector<Expression*> children;
+ for (auto* arg : args) {
+ children.push_back(makeDrop(arg));
+ }
+ children.push_back(makeDrop(target));
+ children.push_back(makeUnreachable());
+ return makeBlock(children, Type::unreachable);
+ }
auto heapType = target->type.getHeapType();
if (!heapType.isSignature()) {
throw ParseException("Invalid reference type for a call_ref", line, col);