diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/wasm-type.h | 2 | ||||
-rw-r--r-- | src/wasm/wasm-type.cpp | 69 |
2 files changed, 53 insertions, 18 deletions
diff --git a/src/wasm-type.h b/src/wasm-type.h index 95c3605a5..51d945b53 100644 --- a/src/wasm-type.h +++ b/src/wasm-type.h @@ -671,6 +671,8 @@ struct TypeBuilder { ForwardChildReference, // A continuation reference that does not refer to a function type. InvalidFuncType, + // A non-shared field of a shared heap type. + InvalidUnsharedField, }; struct Error { diff --git a/src/wasm/wasm-type.cpp b/src/wasm/wasm-type.cpp index ae6fd4b30..92c68d8be 100644 --- a/src/wasm/wasm-type.cpp +++ b/src/wasm/wasm-type.cpp @@ -1697,6 +1697,8 @@ std::ostream& operator<<(std::ostream& os, TypeBuilder::ErrorReason reason) { return os << "Heap type has an undeclared child"; case TypeBuilder::ErrorReason::InvalidFuncType: return os << "Continuation has invalid function type"; + case TypeBuilder::ErrorReason::InvalidUnsharedField: + return os << "Heap type has an invalid unshared field"; } WASM_UNREACHABLE("Unexpected error reason"); } @@ -2628,6 +2630,53 @@ bool isValidSupertype(const HeapTypeInfo& sub, const HeapTypeInfo& super) { WASM_UNREACHABLE("unknown kind"); } +std::optional<TypeBuilder::ErrorReason> +validateType(HeapTypeInfo& info, std::unordered_set<HeapType>& seenTypes) { + if (auto* super = info.supertype) { + // The supertype must be canonical (i.e. defined in a previous rec group) + // or have already been defined in this rec group. + if (super->isTemp && !seenTypes.count(HeapType(uintptr_t(super)))) { + return TypeBuilder::ErrorReason::ForwardSupertypeReference; + } + // The supertype must have a valid structure. + if (!isValidSupertype(info, *super)) { + return TypeBuilder::ErrorReason::InvalidSupertype; + } + } + if (info.isContinuation()) { + if (!info.continuation.type.isSignature()) { + return TypeBuilder::ErrorReason::InvalidFuncType; + } + } + if (info.share == Shared) { + switch (info.kind) { + case HeapTypeInfo::SignatureKind: + // TODO: Figure out and enforce shared function rules. + break; + case HeapTypeInfo::ContinuationKind: + if (!info.continuation.type.isShared()) { + return TypeBuilder::ErrorReason::InvalidFuncType; + } + break; + case HeapTypeInfo::StructKind: + for (auto& field : info.struct_.fields) { + if (field.type.isRef() && !field.type.getHeapType().isShared()) { + return TypeBuilder::ErrorReason::InvalidUnsharedField; + } + } + break; + case HeapTypeInfo::ArrayKind: { + auto elem = info.array.element.type; + if (elem.isRef() && !elem.getHeapType().isShared()) { + return TypeBuilder::ErrorReason::InvalidUnsharedField; + } + break; + } + } + } + return std::nullopt; +} + void updateReferencedHeapTypes( std::unique_ptr<HeapTypeInfo>& info, const std::unordered_map<HeapType, HeapType>& canonicalized) { @@ -2695,24 +2744,8 @@ buildRecGroup(std::unique_ptr<RecGroupInfo>&& groupInfo, std::unordered_set<HeapType> seenTypes; for (size_t i = 0; i < typeInfos.size(); ++i) { auto& info = typeInfos[i]; - if (auto* super = info->supertype) { - // The supertype must be canonical (i.e. defined in a previous rec group) - // or have already been defined in this rec group. - if (super->isTemp && !seenTypes.count(HeapType(uintptr_t(super)))) { - return {TypeBuilder::Error{ - i, TypeBuilder::ErrorReason::ForwardSupertypeReference}}; - } - // The supertype must have a valid structure. - if (!isValidSupertype(*info, *super)) { - return { - TypeBuilder::Error{i, TypeBuilder::ErrorReason::InvalidSupertype}}; - } - } - if (info->isContinuation()) { - if (!info->continuation.type.isSignature()) { - return { - TypeBuilder::Error{i, TypeBuilder::ErrorReason::InvalidFuncType}}; - } + if (auto err = validateType(*info, seenTypes)) { + return {TypeBuilder::Error{i, *err}}; } seenTypes.insert(asHeapType(info)); } |