summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/wasm-type.h50
-rw-r--r--src/wasm/wasm-binary.cpp10
-rw-r--r--src/wasm/wasm-s-parser.cpp21
-rw-r--r--src/wasm/wasm-type.cpp66
4 files changed, 115 insertions, 32 deletions
diff --git a/src/wasm-type.h b/src/wasm-type.h
index b638108fc..befac3c1a 100644
--- a/src/wasm-type.h
+++ b/src/wasm-type.h
@@ -499,28 +499,70 @@ struct TypeBuilder {
std::unique_ptr<Impl> impl;
TypeBuilder(size_t n);
+ TypeBuilder() : TypeBuilder(0) {}
~TypeBuilder();
TypeBuilder(TypeBuilder& other) = delete;
TypeBuilder(TypeBuilder&& other) = delete;
TypeBuilder& operator=(TypeBuilder&) = delete;
+ // Append `n` new uninitialized HeapType slots to the end of the TypeBuilder.
+ void grow(size_t n);
+
+ // The number of HeapType slots in the TypeBuilder.
+ size_t size();
+
// Sets the heap type at index `i`. May only be called before `build`.
+ void setHeapType(size_t i, HeapType::BasicHeapType basic);
void setHeapType(size_t i, Signature signature);
void setHeapType(size_t i, const Struct& struct_);
void setHeapType(size_t i, Struct&& struct_);
void setHeapType(size_t i, Array array);
+ // Gets the temporary HeapType at index `i`. This HeapType should only be used
+ // to construct temporary Types using the methods below.
+ HeapType getTempHeapType(size_t i);
+
// Gets a temporary type or heap type for use in initializing the
- // TypeBuilder's HeapTypes. Temporary Ref and Rtt types are backed by the
- // HeapType at index `i`.
+ // TypeBuilder's HeapTypes. For Ref and Rtt types, the HeapType may be a
+ // temporary HeapType owned by this builder or a canonical HeapType. HeapType
Type getTempTupleType(const Tuple&);
- Type getTempRefType(size_t i, Nullability nullable);
- Type getTempRttType(size_t i, uint32_t depth);
+ Type getTempRefType(HeapType heapType, Nullability nullable);
+ Type getTempRttType(Rtt rtt);
// Canonicalizes and returns all of the heap types. May only be called once
// all of the heap types have been initialized with `setHeapType`.
std::vector<HeapType> build();
+
+ // Utility for ergonomically using operator[] instead of explicit setHeapType
+ // and getTempHeapType methods.
+ struct Entry {
+ TypeBuilder& builder;
+ size_t index;
+ operator HeapType() const { return builder.getTempHeapType(index); }
+ Entry& operator=(HeapType::BasicHeapType basic) {
+ builder.setHeapType(index, basic);
+ return *this;
+ }
+ Entry& operator=(Signature signature) {
+ builder.setHeapType(index, signature);
+ return *this;
+ }
+ Entry& operator=(const Struct& struct_) {
+ builder.setHeapType(index, struct_);
+ return *this;
+ }
+ Entry& operator=(Struct&& struct_) {
+ builder.setHeapType(index, std::move(struct_));
+ return *this;
+ }
+ Entry& operator=(Array array) {
+ builder.setHeapType(index, array);
+ return *this;
+ }
+ };
+
+ Entry operator[](size_t i) { return Entry{*this, i}; }
};
std::ostream& operator<<(std::ostream&, Type);
diff --git a/src/wasm/wasm-binary.cpp b/src/wasm/wasm-binary.cpp
index 5fff58045..5bd368e17 100644
--- a/src/wasm/wasm-binary.cpp
+++ b/src/wasm/wasm-binary.cpp
@@ -1816,7 +1816,7 @@ void WasmBinaryBuilder::readTypes() {
if (size_t(htCode) >= numTypes) {
throwError("invalid type index: " + std::to_string(htCode));
}
- return builder.getTempRefType(size_t(htCode), nullability);
+ return builder.getTempRefType(builder[size_t(htCode)], nullability);
}
case BinaryConsts::EncodedType::rtt_n:
case BinaryConsts::EncodedType::rtt: {
@@ -1826,7 +1826,7 @@ void WasmBinaryBuilder::readTypes() {
if (size_t(htCode) >= numTypes) {
throwError("invalid type index: " + std::to_string(htCode));
}
- return builder.getTempRttType(htCode, depth);
+ return builder.getTempRttType(Rtt(depth, builder[htCode]));
}
default:
throwError("unexpected type index: " + std::to_string(typeCode));
@@ -1896,11 +1896,11 @@ void WasmBinaryBuilder::readTypes() {
BYN_TRACE("read one\n");
auto form = getS32LEB();
if (form == BinaryConsts::EncodedType::Func) {
- builder.setHeapType(i, readSignatureDef());
+ builder[i] = readSignatureDef();
} else if (form == BinaryConsts::EncodedType::Struct) {
- builder.setHeapType(i, readStructDef());
+ builder[i] = readStructDef();
} else if (form == BinaryConsts::EncodedType::Array) {
- builder.setHeapType(i, Array(readFieldDef()));
+ builder[i] = Array(readFieldDef());
} else {
throwError("bad type form " + std::to_string(form));
}
diff --git a/src/wasm/wasm-s-parser.cpp b/src/wasm/wasm-s-parser.cpp
index 7774eac3e..32f555d5a 100644
--- a/src/wasm/wasm-s-parser.cpp
+++ b/src/wasm/wasm-s-parser.cpp
@@ -691,13 +691,13 @@ void SExpressionWasmBuilder::preParseHeapTypes(Element& module) {
auto& referent = nullable ? *elem[2] : *elem[1];
const char* name = referent.c_str();
if (referent.dollared()) {
- return builder.getTempRefType(typeIndices[name], nullable);
+ return builder.getTempRefType(builder[typeIndices[name]], nullable);
} else if (String::isNumber(name)) {
size_t index = atoi(name);
if (index >= numTypes) {
throw ParseException("invalid type index", elem.line, elem.col);
}
- return builder.getTempRefType(index, nullable);
+ return builder.getTempRefType(builder[index], nullable);
} else {
return Type(stringToHeapType(name), nullable);
}
@@ -725,12 +725,15 @@ void SExpressionWasmBuilder::preParseHeapTypes(Element& module) {
break;
}
if (idx->dollared()) {
- return builder.getTempRttType(typeIndices[idx->c_str()], depth);
+ HeapType type = builder[typeIndices[idx->c_str()]];
+ return builder.getTempRttType(Rtt(depth, type));
} else if (String::isNumber(idx->c_str())) {
- return builder.getTempRttType(atoi(idx->c_str()), depth);
- } else {
- throw ParseException("invalid type index", idx->line, idx->col);
+ size_t index = atoi(idx->c_str());
+ if (index < numTypes) {
+ return builder.getTempRttType(Rtt(depth, builder[index]));
+ }
}
+ throw ParseException("invalid type index", idx->line, idx->col);
};
auto parseValType = [&](Element& elem) {
@@ -840,12 +843,12 @@ void SExpressionWasmBuilder::preParseHeapTypes(Element& module) {
Element& def = elem[1]->dollared() ? *elem[2] : *elem[1];
Element& kind = *def[0];
if (kind == FUNC) {
- builder.setHeapType(index++, parseSignatureDef(def));
+ builder[index++] = parseSignatureDef(def);
} else if (kind == STRUCT) {
- builder.setHeapType(index, parseStructDef(def, index));
+ builder[index] = parseStructDef(def, index);
index++;
} else if (kind == ARRAY) {
- builder.setHeapType(index++, parseArrayDef(def));
+ builder[index++] = parseArrayDef(def);
} else {
throw ParseException("unknown heaptype kind", kind.line, kind.col);
}
diff --git a/src/wasm/wasm-type.cpp b/src/wasm/wasm-type.cpp
index 12b223707..73ff47ee8 100644
--- a/src/wasm/wasm-type.cpp
+++ b/src/wasm/wasm-type.cpp
@@ -80,16 +80,19 @@ struct HeapTypeInfo {
// TypeBuilder interface, so hashing and equality use pointer identity.
bool isFinalized = true;
enum Kind {
+ BasicKind,
SignatureKind,
StructKind,
ArrayKind,
} kind;
union {
+ HeapType::BasicHeapType basic;
Signature signature;
Struct struct_;
Array array;
};
+ HeapTypeInfo(HeapType::BasicHeapType basic) : kind(BasicKind), basic(basic) {}
HeapTypeInfo(Signature sig) : kind(SignatureKind), signature(sig) {}
HeapTypeInfo(const Struct& struct_) : kind(StructKind), struct_(struct_) {}
HeapTypeInfo(Struct&& struct_)
@@ -323,6 +326,9 @@ bool TypeInfo::operator==(const TypeInfo& other) const {
HeapTypeInfo::HeapTypeInfo(const HeapTypeInfo& other) {
kind = other.kind;
switch (kind) {
+ case BasicKind:
+ new (&basic) auto(other.basic);
+ return;
case SignatureKind:
new (&signature) auto(other.signature);
return;
@@ -338,6 +344,8 @@ HeapTypeInfo::HeapTypeInfo(const HeapTypeInfo& other) {
HeapTypeInfo::~HeapTypeInfo() {
switch (kind) {
+ case BasicKind:
+ return;
case SignatureKind:
signature.~Signature();
return;
@@ -385,8 +393,11 @@ struct TypeStore : Store<TypeInfo> {
};
struct HeapTypeStore : Store<HeapTypeInfo> {
- HeapType canonicalize(const HeapTypeInfo& other) {
- return Store<HeapTypeInfo>::canonicalize(other);
+ HeapType canonicalize(const HeapTypeInfo& info) {
+ if (info.kind == HeapTypeInfo::BasicKind) {
+ return info.basic;
+ }
+ return Store<HeapTypeInfo>::canonicalize(info);
}
HeapType canonicalize(std::unique_ptr<HeapTypeInfo>&& info);
};
@@ -438,6 +449,9 @@ typename Info::type_t Store<Info>::canonicalize(const Info& info) {
}
HeapType HeapTypeStore::canonicalize(std::unique_ptr<HeapTypeInfo>&& info) {
+ if (info->kind == HeapTypeInfo::BasicKind) {
+ return info->basic;
+ }
std::lock_guard<std::mutex> lock(mutex);
auto indexIt = typeIDs.find(std::cref(*info));
if (indexIt != typeIDs.end()) {
@@ -993,6 +1007,8 @@ bool TypeComparator::lessThan(const HeapTypeInfo& a, const HeapTypeInfo& b) {
return a.kind < b.kind;
}
switch (a.kind) {
+ case HeapTypeInfo::BasicKind:
+ return a.basic < b.basic;
case HeapTypeInfo::SignatureKind:
return lessThan(a.signature, b.signature);
case HeapTypeInfo::StructKind:
@@ -1411,6 +1427,9 @@ size_t FiniteShapeHasher::hash(const HeapTypeInfo& info) {
}
rehash(digest, info.kind);
switch (info.kind) {
+ case HeapTypeInfo::BasicKind:
+ hash_combine(digest, wasm::hash(info.basic));
+ return digest;
case HeapTypeInfo::SignatureKind:
hash_combine(digest, hash(info.signature));
return digest;
@@ -1523,6 +1542,8 @@ bool FiniteShapeEquator::eq(const HeapTypeInfo& a, const HeapTypeInfo& b) {
return false;
}
switch (a.kind) {
+ case HeapTypeInfo::BasicKind:
+ return a.basic == b.basic;
case HeapTypeInfo::SignatureKind:
return eq(a.signature, b.signature);
case HeapTypeInfo::StructKind:
@@ -1601,26 +1622,43 @@ TypeBuilder::TypeBuilder(size_t n) {
TypeBuilder::~TypeBuilder() = default;
+void TypeBuilder::grow(size_t n) {
+ assert(size() + n > size());
+ impl->entries.resize(size() + n);
+}
+
+size_t TypeBuilder::size() { return impl->entries.size(); }
+
+void TypeBuilder::setHeapType(size_t i, HeapType::BasicHeapType basic) {
+ assert(i < size() && "Index out of bounds");
+ impl->entries[i].set(basic);
+}
+
void TypeBuilder::setHeapType(size_t i, Signature signature) {
- assert(i < impl->entries.size() && "Index out of bounds");
+ assert(i < size() && "Index out of bounds");
impl->entries[i].set(signature);
}
void TypeBuilder::setHeapType(size_t i, const Struct& struct_) {
- assert(i < impl->entries.size() && "index out of bounds");
+ assert(i < size() && "index out of bounds");
impl->entries[i].set(struct_);
}
void TypeBuilder::setHeapType(size_t i, Struct&& struct_) {
- assert(i < impl->entries.size() && "index out of bounds");
+ assert(i < size() && "index out of bounds");
impl->entries[i].set(std::move(struct_));
}
void TypeBuilder::setHeapType(size_t i, Array array) {
- assert(i < impl->entries.size() && "index out of bounds");
+ assert(i < size() && "index out of bounds");
impl->entries[i].set(array);
}
+HeapType TypeBuilder::getTempHeapType(size_t i) {
+ assert(i < size() && "index out of bounds");
+ return impl->entries[i].get();
+}
+
Type TypeBuilder::getTempTupleType(const Tuple& tuple) {
Type ret = impl->typeStore.canonicalize(tuple);
if (tuple.types.size() > 1) {
@@ -1631,16 +1669,12 @@ Type TypeBuilder::getTempTupleType(const Tuple& tuple) {
}
}
-Type TypeBuilder::getTempRefType(size_t i, Nullability nullable) {
- assert(i < impl->entries.size() && "Index out of bounds");
- return markTemp(
- impl->typeStore.canonicalize(TypeInfo(impl->entries[i].get(), nullable)));
+Type TypeBuilder::getTempRefType(HeapType type, Nullability nullable) {
+ return markTemp(impl->typeStore.canonicalize(TypeInfo(type, nullable)));
}
-Type TypeBuilder::getTempRttType(size_t i, uint32_t depth) {
- assert(i < impl->entries.size() && "Index out of bounds");
- return markTemp(
- impl->typeStore.canonicalize(Rtt(depth, impl->entries[i].get())));
+Type TypeBuilder::getTempRttType(Rtt rtt) {
+ return markTemp(impl->typeStore.canonicalize(rtt));
}
namespace {
@@ -1879,6 +1913,8 @@ std::vector<HeapType*> ShapeCanonicalizer::getChildren(HeapType heapType) {
assert(!heapType.isBasic() && "Cannot have basic defined HeapType");
auto* info = getHeapTypeInfo(heapType);
switch (info->kind) {
+ case HeapTypeInfo::BasicKind:
+ return children;
case HeapTypeInfo::SignatureKind:
scanType(info->signature.params);
scanType(info->signature.results);
@@ -2049,6 +2085,8 @@ void GlobalCanonicalizer::scanHeapType(HeapType* ht) {
auto* info = getHeapTypeInfo(*ht);
switch (info->kind) {
+ case HeapTypeInfo::BasicKind:
+ break;
case HeapTypeInfo::SignatureKind:
noteChild(*ht, &info->signature.params);
noteChild(*ht, &info->signature.results);