diff options
Diffstat (limited to 'src/wasm-interpreter.h')
-rw-r--r-- | src/wasm-interpreter.h | 62 |
1 files changed, 62 insertions, 0 deletions
diff --git a/src/wasm-interpreter.h b/src/wasm-interpreter.h index 8f7418719..9599d81cd 100644 --- a/src/wasm-interpreter.h +++ b/src/wasm-interpreter.h @@ -1700,6 +1700,7 @@ public: return Literal(std::make_shared<GCData>(curr->type.getHeapType(), data), curr->type.getHeapType()); } + Flow visitArrayNewSeg(ArrayNewSeg* curr) { WASM_UNREACHABLE("unimp"); } Flow visitArrayInit(ArrayInit* curr) { NOTE_ENTER("ArrayInit"); Index num = curr->values.size(); @@ -2187,6 +2188,10 @@ public: NOTE_ENTER("SIMDLoadStoreLane"); return Flow(NONCONSTANT_FLOW); } + Flow visitArrayNewSeg(ArrayNewSeg* curr) { + NOTE_ENTER("ArrayNewSeg"); + return Flow(NONCONSTANT_FLOW); + } Flow visitPop(Pop* curr) { NOTE_ENTER("Pop"); return Flow(NONCONSTANT_FLOW); @@ -3494,6 +3499,63 @@ public: } return {}; } + Flow visitArrayNewSeg(ArrayNewSeg* curr) { + NOTE_ENTER("ArrayNewSeg"); + auto offsetFlow = self()->visit(curr->offset); + if (offsetFlow.breaking()) { + return offsetFlow; + } + auto sizeFlow = self()->visit(curr->size); + if (sizeFlow.breaking()) { + return sizeFlow; + } + + auto offset = offsetFlow.getSingleValue().geti32(); + auto size = sizeFlow.getSingleValue().geti32(); + + auto heapType = curr->type.getHeapType(); + const auto& element = heapType.getArray().element; + auto elemType = heapType.getArray().element.type; + + Literals contents; + contents.reserve(size); + + switch (curr->op) { + case NewData: { + assert(curr->segment < wasm.dataSegments.size()); + assert(elemType.isNumber()); + const auto& seg = *wasm.dataSegments[curr->segment]; + auto elemBytes = element.getByteSize(); + auto end = (uint64_t)offset + size * elemBytes; + if ((size != 0ull && droppedSegments.count(curr->segment)) || + end > seg.data.size()) { + trap("out of bounds segment access in array.new_data"); + } + for (Index i = offset; i < end; i += elemBytes) { + auto addr = (void*)&seg.data[i]; + contents.push_back(Literal::makeFromMemory(addr, element)); + } + break; + } + case NewElem: { + assert(curr->segment < wasm.elementSegments.size()); + const auto& seg = *wasm.elementSegments[curr->segment]; + auto end = (uint64_t)offset + size; + // TODO: Handle dropped element segments once we support those. + if (end > seg.data.size()) { + trap("out of bounds segment access in array.new_elem"); + } + for (Index i = offset; i < end; ++i) { + auto val = self()->visit(seg.data[i]).getSingleValue(); + contents.push_back(val); + } + break; + } + default: + WASM_UNREACHABLE("unexpected op"); + } + return Literal(std::make_shared<GCData>(heapType, contents), heapType); + } Flow visitTry(Try* curr) { NOTE_ENTER("Try"); try { |