diff options
Diffstat (limited to 'src/wasm')
-rw-r--r-- | src/wasm/wasm-binary.cpp | 32 | ||||
-rw-r--r-- | src/wasm/wasm-s-parser.cpp | 21 | ||||
-rw-r--r-- | src/wasm/wasm-type.cpp | 12 |
3 files changed, 54 insertions, 11 deletions
diff --git a/src/wasm/wasm-binary.cpp b/src/wasm/wasm-binary.cpp index db253fa6e..a4df4ed16 100644 --- a/src/wasm/wasm-binary.cpp +++ b/src/wasm/wasm-binary.cpp @@ -219,8 +219,11 @@ void WasmBinaryWriter::writeTypes() { for (Index i = 0; i < types.size(); ++i) { auto type = types[i]; BYN_TRACE("write " << type << std::endl); + HeapType super; + bool hasSuper = type.getSuperType(super); if (type.isSignature()) { - o << S32LEB(BinaryConsts::EncodedType::Func); + o << S32LEB(hasSuper ? BinaryConsts::EncodedType::FuncExtending + : BinaryConsts::EncodedType::Func); auto sig = type.getSignature(); for (auto& sigType : {sig.params, sig.results}) { o << U32LEB(sigType.size()); @@ -229,18 +232,23 @@ void WasmBinaryWriter::writeTypes() { } } } else if (type.isStruct()) { - o << S32LEB(BinaryConsts::EncodedType::Struct); + o << S32LEB(hasSuper ? BinaryConsts::EncodedType::StructExtending + : BinaryConsts::EncodedType::Struct); auto fields = type.getStruct().fields; o << U32LEB(fields.size()); for (const auto& field : fields) { writeField(field); } } else if (type.isArray()) { - o << S32LEB(BinaryConsts::EncodedType::Array); + o << S32LEB(hasSuper ? BinaryConsts::EncodedType::ArrayExtending + : BinaryConsts::EncodedType::Array); writeField(type.getArray().element); } else { WASM_UNREACHABLE("TODO GC type writing"); } + if (hasSuper) { + o << U32LEB(getTypeIndex(super)); + } } finishSection(start); } @@ -1901,15 +1909,27 @@ void WasmBinaryBuilder::readTypes() { for (size_t i = 0; i < numTypes; i++) { BYN_TRACE("read one\n"); auto form = getS32LEB(); - if (form == BinaryConsts::EncodedType::Func) { + if (form == BinaryConsts::EncodedType::Func || + form == BinaryConsts::EncodedType::FuncExtending) { builder[i] = readSignatureDef(); - } else if (form == BinaryConsts::EncodedType::Struct) { + } else if (form == BinaryConsts::EncodedType::Struct || + form == BinaryConsts::EncodedType::StructExtending) { builder[i] = readStructDef(); - } else if (form == BinaryConsts::EncodedType::Array) { + } else if (form == BinaryConsts::EncodedType::Array || + form == BinaryConsts::EncodedType::ArrayExtending) { builder[i] = Array(readFieldDef()); } else { throwError("bad type form " + std::to_string(form)); } + if (form == BinaryConsts::EncodedType::FuncExtending || + form == BinaryConsts::EncodedType::StructExtending || + form == BinaryConsts::EncodedType::ArrayExtending) { + auto superIndex = getU32LEB(); + if (superIndex >= numTypes) { + throwError("bad supertype index " + std::to_string(superIndex)); + } + builder[i].subTypeOf(builder[superIndex]); + } } types = builder.build(); diff --git a/src/wasm/wasm-s-parser.cpp b/src/wasm/wasm-s-parser.cpp index 8c0fb9b2d..6ca0bcfd1 100644 --- a/src/wasm/wasm-s-parser.cpp +++ b/src/wasm/wasm-s-parser.cpp @@ -50,8 +50,9 @@ int unhex(char c) { namespace wasm { -static Name STRUCT("struct"), FIELD("field"), ARRAY("array"), I8("i8"), - I16("i16"), RTT("rtt"), DECLARE("declare"), ITEM("item"), OFFSET("offset"); +static Name STRUCT("struct"), FIELD("field"), ARRAY("array"), + EXTENDS("extends"), I8("i8"), I16("i16"), RTT("rtt"), DECLARE("declare"), + ITEM("item"), OFFSET("offset"); static Address getAddress(const Element* s) { return atoll(s->c_str()); } @@ -857,15 +858,25 @@ void SExpressionWasmBuilder::preParseHeapTypes(Element& module) { Element& def = elem[1]->dollared() ? *elem[2] : *elem[1]; Element& kind = *def[0]; if (kind == FUNC) { - builder[index++] = parseSignatureDef(def); + builder[index] = parseSignatureDef(def); } else if (kind == STRUCT) { builder[index] = parseStructDef(def, index); - index++; } else if (kind == ARRAY) { - builder[index++] = parseArrayDef(def); + builder[index] = parseArrayDef(def); } else { throw ParseException("unknown heaptype kind", kind.line, kind.col); } + if (elementStartsWith(elem[elem.size() - 1], EXTENDS)) { + // '(' 'extends' $supertype ')' + Element& extends = *elem[elem.size() - 1]; + auto it = typeIndices.find(extends[1]->c_str()); + if (it == typeIndices.end()) { + throw ParseException( + "unknown dollared function type", elem.line, elem.col); + } + builder[index].subTypeOf(builder[it->second]); + } + ++index; }); types = builder.build(); diff --git a/src/wasm/wasm-type.cpp b/src/wasm/wasm-type.cpp index 96cb0b557..9bae42e98 100644 --- a/src/wasm/wasm-type.cpp +++ b/src/wasm/wasm-type.cpp @@ -1176,6 +1176,18 @@ Array HeapType::getArray() const { return getHeapTypeInfo(*this)->array; } +bool HeapType::getSuperType(HeapType& out) const { + if (isBasic()) { + return false; + } + HeapTypeInfo* super = getHeapTypeInfo(*this)->supertype; + if (super != nullptr) { + out = HeapType(uintptr_t(super)); + return true; + } + return false; +} + bool HeapType::isSubType(HeapType left, HeapType right) { return SubTyper().isSubType(left, right); } |