diff options
Diffstat (limited to 'src/wasm-interpreter.h')
-rw-r--r-- | src/wasm-interpreter.h | 111 |
1 files changed, 92 insertions, 19 deletions
diff --git a/src/wasm-interpreter.h b/src/wasm-interpreter.h index bf02b7987..d701aaf15 100644 --- a/src/wasm-interpreter.h +++ b/src/wasm-interpreter.h @@ -1403,8 +1403,7 @@ public: return rtt; } const auto& fields = curr->rtt->type.getHeapType().getStruct().fields; - Literals data; - data.resize(fields.size()); + Literals data(fields.size()); for (Index i = 0; i < fields.size(); i++) { if (curr->isWithDefault()) { data[i] = Literal::makeZero(fields[i].type); @@ -1416,8 +1415,7 @@ public: data[i] = value.getSingleValue(); } } - return Flow( - Literal(std::shared_ptr<Literals>(new Literals(data)), curr->type)); + return Flow(Literal(std::make_shared<Literals>(data), curr->type)); } Flow visitStructGet(StructGet* curr) { NOTE_ENTER("StructGet"); @@ -1445,40 +1443,115 @@ public: if (!data) { trap("null ref"); } - // Truncate the value if we need to. The storage is just a list of Literals, - // so we can't just write the value like we would to a C struct field. auto field = curr->ref->type.getHeapType().getStruct().fields[curr->index]; - auto setValue = value.getSingleValue(); - if (field.type == Type::i32) { - if (field.packedType == Field::i8) { - setValue = setValue.and_(Literal(int32_t(0xff))); - } else if (field.packedType == Field::i16) { - setValue = setValue.and_(Literal(int32_t(0xffff))); - } - } - (*data)[curr->index] = setValue; + (*data)[curr->index] = getMaybePackedValue(value.getSingleValue(), field); return Flow(); } Flow visitArrayNew(ArrayNew* curr) { NOTE_ENTER("ArrayNew"); - WASM_UNREACHABLE("TODO (gc): array.new"); + auto rtt = this->visit(curr->rtt); + if (rtt.breaking()) { + return rtt; + } + auto size = this->visit(curr->size); + if (size.breaking()) { + return size; + } + const auto& element = curr->rtt->type.getHeapType().getArray().element; + Index num = size.getSingleValue().geti32(); + Literals data(num); + if (curr->isWithDefault()) { + for (Index i = 0; i < num; i++) { + data[i] = Literal::makeZero(element.type); + } + } else { + auto init = this->visit(curr->init); + if (init.breaking()) { + return init; + } + auto value = init.getSingleValue(); + for (Index i = 0; i < num; i++) { + data[i] = value; + } + } + return Flow(Literal(std::make_shared<Literals>(data), curr->type)); } Flow visitArrayGet(ArrayGet* curr) { NOTE_ENTER("ArrayGet"); - WASM_UNREACHABLE("TODO (gc): array.get"); + Flow ref = this->visit(curr->ref); + if (ref.breaking()) { + return ref; + } + Flow index = this->visit(curr->index); + if (index.breaking()) { + return index; + } + auto data = ref.getSingleValue().getGCData(); + if (!data) { + trap("null ref"); + } + Index i = index.getSingleValue().geti32(); + if (i >= data->size()) { + trap("array oob"); + } + return (*data)[i]; } Flow visitArraySet(ArraySet* curr) { NOTE_ENTER("ArraySet"); - WASM_UNREACHABLE("TODO (gc): array.set"); + Flow ref = this->visit(curr->ref); + if (ref.breaking()) { + return ref; + } + Flow index = this->visit(curr->index); + if (index.breaking()) { + return index; + } + Flow value = this->visit(curr->value); + if (value.breaking()) { + return value; + } + auto data = ref.getSingleValue().getGCData(); + if (!data) { + trap("null ref"); + } + Index i = index.getSingleValue().geti32(); + if (i >= data->size()) { + trap("array oob"); + } + auto field = curr->ref->type.getHeapType().getArray().element; + (*data)[i] = getMaybePackedValue(value.getSingleValue(), field); + return Flow(); } Flow visitArrayLen(ArrayLen* curr) { NOTE_ENTER("ArrayLen"); - WASM_UNREACHABLE("TODO (gc): array.len"); + Flow ref = this->visit(curr->ref); + if (ref.breaking()) { + return ref; + } + auto data = ref.getSingleValue().getGCData(); + if (!data) { + trap("null ref"); + } + return Literal(int32_t(data->size())); } virtual void trap(const char* why) { WASM_UNREACHABLE("unimp"); } virtual void throwException(Literal exn) { WASM_UNREACHABLE("unimp"); } + +private: + // Truncate the value if we need to. The storage is just a list of Literals, + // so we can't just write the value like we would to a C struct field. + Literal getMaybePackedValue(Literal value, const Field& field) { + if (field.type == Type::i32) { + if (field.packedType == Field::i8) { + value = value.and_(Literal(int32_t(0xff))); + } else if (field.packedType == Field::i16) { + value = value.and_(Literal(int32_t(0xffff))); + } + } + return value; + } }; // Execute a suspected constant expression (precompute and C-API). |