From e761198190d5c5e6e0a3735c3dab59d02c970e43 Mon Sep 17 00:00:00 2001 From: Thomas Lively Date: Tue, 3 Jan 2023 16:22:54 -0600 Subject: [Parser] Parse array access instructions (#5375) * [NFC][Parser] Track definition indices For each definition in a module, record that definition's index in the relevant index space. Previously the index was inferred from its position in a list of module definitions, but that scheme does not scale to data segments defined inline inside memory definitions because these data segments occupy a slot in the data segment index space but do not have their own independent definitions. * clarify comment * [Parser] Parse data segments Parse active and passive data segments, including all their variations and abbreviations as well as data segments declared inline in memory declarations. Switch to parsing data strings, memory limits, and memory types during the ParseDecls phase so that the inline data segments can be completely parsed during that phase and never revisited. Parsing the inline data segments in a later phase would not work because they would be incorrectly inserted at the end of the data segment index space. Also update the printer to print a memory use on active data segments that are initialized in a non-default memory. * [Parser] Parse array creation and data segment instructions * [Parser] Parse array access instructions --- src/wasm/wat-parser.cpp | 87 ++++++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 82 insertions(+), 5 deletions(-) (limited to 'src/wasm/wat-parser.cpp') diff --git a/src/wasm/wat-parser.cpp b/src/wasm/wat-parser.cpp index 15e193a31..b1be9b75e 100644 --- a/src/wasm/wat-parser.cpp +++ b/src/wasm/wat-parser.cpp @@ -491,6 +491,7 @@ struct NullTypeParserCtx { HeapTypeT makeEq() { return Ok{}; } HeapTypeT makeI31() { return Ok{}; } HeapTypeT makeData() { return Ok{}; } + HeapTypeT makeArrayType() { return Ok{}; } TypeT makeI32() { return Ok{}; } TypeT makeI64() { return Ok{}; } @@ -565,6 +566,7 @@ template struct TypeParserCtx { HeapTypeT makeEq() { return HeapType::eq; } HeapTypeT makeI31() { return HeapType::i31; } HeapTypeT makeData() { return HeapType::data; } + HeapTypeT makeArrayType() { return HeapType::array; } TypeT makeI32() { return Type::i32; } TypeT makeI64() { return Type::i64; } @@ -767,6 +769,17 @@ struct NullInstrParserCtx { InstrT makeArrayNewData(Index, HeapTypeT, DataIdxT) { return Ok{}; } + template InstrT makeArrayGet(Index, HeapTypeT, bool) { + return Ok{}; + } + template InstrT makeArraySet(Index, HeapTypeT) { + return Ok{}; + } + InstrT makeArrayLen(Index) { return Ok{}; } + template + InstrT makeArrayCopy(Index, HeapTypeT, HeapTypeT) { + return Ok{}; + } }; // Phase 1: Parse definition spans for top-level module elements and determine @@ -2060,6 +2073,62 @@ struct ParseDefsCtx : TypeParserCtx { return push(pos, builder.makeArrayNewSeg(NewData, type, data, *offset, *size)); } + + Result<> makeArrayGet(Index pos, HeapType type, bool signed_) { + if (!type.isArray()) { + return in.err(pos, "expected array type annotation"); + } + auto elemType = type.getArray().element.type; + auto index = pop(pos); + CHECK_ERR(index); + auto ref = pop(pos); + CHECK_ERR(ref); + CHECK_ERR(validateTypeAnnotation(pos, type, *ref)); + return push(pos, builder.makeArrayGet(*ref, *index, elemType, signed_)); + } + + Result<> makeArraySet(Index pos, HeapType type) { + if (!type.isArray()) { + return in.err(pos, "expected array type annotation"); + } + auto val = pop(pos); + CHECK_ERR(val); + auto index = pop(pos); + CHECK_ERR(index); + auto ref = pop(pos); + CHECK_ERR(ref); + CHECK_ERR(validateTypeAnnotation(pos, type, *ref)); + return push(pos, builder.makeArraySet(*ref, *index, *val)); + } + + Result<> makeArrayLen(Index pos) { + auto ref = pop(pos); + CHECK_ERR(ref); + return push(pos, builder.makeArrayLen(*ref)); + } + + Result<> makeArrayCopy(Index pos, HeapType destType, HeapType srcType) { + if (!destType.isArray()) { + return in.err(pos, "expected array destination type annotation"); + } + if (!srcType.isArray()) { + return in.err(pos, "expected array source type annotation"); + } + auto len = pop(pos); + CHECK_ERR(len); + auto srcIdx = pop(pos); + CHECK_ERR(srcIdx); + auto srcRef = pop(pos); + CHECK_ERR(srcRef); + auto destIdx = pop(pos); + CHECK_ERR(destIdx); + auto destRef = pop(pos); + CHECK_ERR(destRef); + CHECK_ERR(validateTypeAnnotation(pos, srcType, *srcRef)); + CHECK_ERR(validateTypeAnnotation(pos, destType, *destRef)); + return push( + pos, builder.makeArrayCopy(*destRef, *destIdx, *srcRef, *srcIdx, *len)); + } }; // ================ @@ -2289,7 +2358,7 @@ template Result heaptype(Ctx& ctx) { return ctx.makeData(); } if (ctx.in.takeKeyword("array"sv)) { - return ctx.in.err("array heap type not yet supported"); + return ctx.makeArrayType(); } auto type = typeidx(ctx); CHECK_ERR(type); @@ -3235,22 +3304,30 @@ Result makeArrayInitStatic(Ctx& ctx, Index pos) { template Result makeArrayGet(Ctx& ctx, Index pos, bool signed_) { - return ctx.in.err("unimplemented instruction"); + auto type = typeidx(ctx); + CHECK_ERR(type); + return ctx.makeArrayGet(pos, *type, signed_); } template Result makeArraySet(Ctx& ctx, Index pos) { - return ctx.in.err("unimplemented instruction"); + auto type = typeidx(ctx); + CHECK_ERR(type); + return ctx.makeArraySet(pos, *type); } template Result makeArrayLen(Ctx& ctx, Index pos) { - return ctx.in.err("unimplemented instruction"); + return ctx.makeArrayLen(pos); } template Result makeArrayCopy(Ctx& ctx, Index pos) { - return ctx.in.err("unimplemented instruction"); + auto destType = typeidx(ctx); + CHECK_ERR(destType); + auto srcType = typeidx(ctx); + CHECK_ERR(srcType); + return ctx.makeArrayCopy(pos, *destType, *srcType); } template -- cgit v1.2.3