diff --git a/src/parser/WASMComponentParser.cpp b/src/parser/WASMComponentParser.cpp index 21aed7549..634c91fa9 100644 --- a/src/parser/WASMComponentParser.cpp +++ b/src/parser/WASMComponentParser.cpp @@ -26,12 +26,218 @@ namespace wabt { class WASMComponentBinaryReader : public wabt::WASMComponentBinaryReaderDelegate { private: - Walrus::TypeStore& m_typeStore; + // Depth data for each component. + struct ComponentTypeInfo { + ComponentTypeInfo(ComponentTypeInfo* parent, Walrus::ComponentType* parentComponentType, Walrus::Component* parentComponent) + : parent(parent) + , parentComponentType(parentComponentType) + , parentComponent(parentComponent) + { + } + + ComponentTypeInfo* parent; + Walrus::ComponentType* parentComponentType; + Walrus::Component* parentComponent; + std::vector funcTypes; + std::vector componentTypes; + std::vector instanceTypes; + }; + + Walrus::ComponentTypeRef::Type getValueType(const ComponentType& type) + { + switch (type.GetType()) { + case ComponentType::Bool: + return Walrus::ComponentTypeRef::Bool; + case ComponentType::S8: + return Walrus::ComponentTypeRef::S8; + case ComponentType::U8: + return Walrus::ComponentTypeRef::U8; + case ComponentType::S16: + return Walrus::ComponentTypeRef::S16; + case ComponentType::U16: + return Walrus::ComponentTypeRef::U16; + case ComponentType::S32: + return Walrus::ComponentTypeRef::S32; + case ComponentType::U32: + return Walrus::ComponentTypeRef::U32; + case ComponentType::S64: + return Walrus::ComponentTypeRef::S64; + case ComponentType::U64: + return Walrus::ComponentTypeRef::U64; + case ComponentType::F32: + return Walrus::ComponentTypeRef::F32; + case ComponentType::F64: + return Walrus::ComponentTypeRef::F64; + case ComponentType::Char: + return Walrus::ComponentTypeRef::Char; + case ComponentType::String: + return Walrus::ComponentTypeRef::String; + default: + ASSERT(type.GetType() == ComponentType::ErrorContext); + return Walrus::ComponentTypeRef::ErrorContext; + } + } + + Walrus::ComponentSort getSort(ComponentSort sort) + { + switch (sort) { + case ComponentSort::CoreFunc: + return Walrus::ComponentSort::CoreFunc; + case ComponentSort::CoreTable: + return Walrus::ComponentSort::CoreTable; + case ComponentSort::CoreMemory: + return Walrus::ComponentSort::CoreMemory; + case ComponentSort::CoreGlobal: + return Walrus::ComponentSort::CoreGlobal; + case ComponentSort::CoreType: + return Walrus::ComponentSort::CoreType; + case ComponentSort::CoreModule: + return Walrus::ComponentSort::CoreModule; + case ComponentSort::CoreInstance: + return Walrus::ComponentSort::CoreInstance; + case ComponentSort::Func: + return Walrus::ComponentSort::Func; + case ComponentSort::Value: + return Walrus::ComponentSort::Value; + case ComponentSort::Type: + return Walrus::ComponentSort::Type; + case ComponentSort::Component: + return Walrus::ComponentSort::Component; + case ComponentSort::Instance: + return Walrus::ComponentSort::Instance; + default: + return Walrus::ComponentSort::Invalid; + } + } + + Walrus::ComponentTypeRef refType(const ComponentType& type) + { + if (type.IsIndex()) { + Walrus::ComponentRefCounted* ref = m_current->getType(type.GetIndex()); + ref->addRef(); + return Walrus::ComponentTypeRef(ref); + } + return Walrus::ComponentTypeRef(getValueType(type.GetType())); + } + + Walrus::ComponentTypeRef refAnyType(const ComponentType& type) + { + if (type.IsNone()) { + return Walrus::ComponentTypeRef(); + } + return refType(type); + } + + Walrus::CanonicalOptions parseCanonOptions(uint32_t optionCount, ComponentCanonOption* options) + { + Walrus::CanonicalOptions::StringEncoding encoding = Walrus::CanonicalOptions::Utf8; + bool isAsync = false; + uint32_t memoryIndex = Walrus::CanonicalOptions::NoIndex; + uint32_t reallocIndex = Walrus::CanonicalOptions::NoIndex; + uint32_t postReturnIndex = Walrus::CanonicalOptions::NoIndex; + uint32_t callbackIndex = Walrus::CanonicalOptions::NoIndex; + + while (optionCount > 0) { + switch (options->option) { + case ComponentCanonOption::StrEncUtf8: + encoding = Walrus::CanonicalOptions::Utf8; + break; + case ComponentCanonOption::StrEncUtf16: + encoding = Walrus::CanonicalOptions::Utf16; + break; + case ComponentCanonOption::StrEncLatin1Utf16: + encoding = Walrus::CanonicalOptions::Latin1Utf16; + break; + case ComponentCanonOption::Memory: + memoryIndex = options->index; + break; + case ComponentCanonOption::Realloc: + reallocIndex = options->index; + break; + case ComponentCanonOption::PostReturn: + postReturnIndex = options->index; + break; + case ComponentCanonOption::Async: + isAsync = true; + break; + case ComponentCanonOption::Callback: + callbackIndex = options->index; + break; + } + optionCount--; + options++; + } + return Walrus::CanonicalOptions(encoding, isAsync, memoryIndex, reallocIndex, postReturnIndex, callbackIndex); + } + + Walrus::ComponentRefCounted* getTypeRef(ComponentSort sort, uint32_t index) + { + switch (sort) { + case ComponentSort::Func: + ASSERT(index < m_currentInfo->funcTypes.size()); + return m_currentInfo->funcTypes[index]; + case ComponentSort::Type: + ASSERT(index < m_current->types().size()); + return m_current->getType(index); + case ComponentSort::Component: + ASSERT(index < m_currentInfo->componentTypes.size()); + return m_currentInfo->componentTypes[index]; + case ComponentSort::Instance: + ASSERT(index < m_currentInfo->instanceTypes.size()); + return m_currentInfo->instanceTypes[index]; + default: + return nullptr; + } + } + + Walrus::ComponentRefCounted* pushExternalType(const ComponentExternalInfo& externalInfo) + { + Walrus::ComponentRefCounted* type; + switch (externalInfo.sort) { + case ComponentSort::Func: + type = m_current->getType(externalInfo.index.index)->asTypeFunc(); + m_currentInfo->funcTypes.push_back(type->asTypeFunc()); + break; + case ComponentSort::Type: + if (externalInfo.external == ComponentExternalDesc::TypeSubRes) { + type = new Walrus::ComponentTypeResource(Walrus::ComponentRefCounted::ResourceKind, false); + } else { + type = m_current->getType(externalInfo.index.index); + type->addRef(); + } + m_current->pushType(type); + break; + case ComponentSort::Component: + type = m_current->getType(externalInfo.index.index); + m_currentInfo->componentTypes.push_back(type->asComponentType()); + break; + case ComponentSort::Instance: + type = m_current->getType(externalInfo.index.index); + m_currentInfo->instanceTypes.push_back(type->asComponentType()); + break; + default: + return nullptr; + } + type->addRef(); + return type; + } public: WASMComponentBinaryReader(Walrus::TypeStore& typeStore) : m_typeStore(typeStore) + , m_current(nullptr) + , m_currentComponent(nullptr) + , m_currentInfo(nullptr) + { + } + + ~WASMComponentBinaryReader() { + while (m_currentInfo != nullptr) { + ComponentTypeInfo* info = m_currentInfo; + m_currentInfo = m_currentInfo->parent; + delete info; + } } void OnCoreModule(const void* data, @@ -42,14 +248,33 @@ class WASMComponentBinaryReader : public wabt::WASMComponentBinaryReaderDelegate void BeginComponent(uint32_t version, size_t depth) { + ASSERT(m_currentInfo != nullptr || (m_current == nullptr && m_currentComponent == nullptr)); + Walrus::Component* parentComponent = m_currentComponent; + m_currentInfo = new ComponentTypeInfo(m_currentInfo, m_current, m_currentComponent); + m_currentComponent = new Walrus::Component(); + m_current = m_currentComponent->type(); + + if (parentComponent != nullptr) { + parentComponent->pushDeclaration(m_currentComponent); + m_currentInfo->parent->componentTypes.push_back(m_current); + } } void EndComponent() { + ComponentTypeInfo* info = m_currentInfo; + // Keep the last component. + if (m_currentInfo->parentComponent != nullptr) { + m_currentComponent = m_currentInfo->parentComponent; + } + m_current = m_currentInfo->parentComponentType; + ASSERT(m_current == nullptr || (m_currentComponent != nullptr && m_currentComponent->type() == m_current)); + m_currentInfo = m_currentInfo->parent; + delete info; } - void BeginCoreInstance(Index module_index, - uint32_t argument_count) + void BeginCoreInstance(Index moduleIndex, + uint32_t argumentCount) { } @@ -63,7 +288,7 @@ class WASMComponentBinaryReader : public wabt::WASMComponentBinaryReaderDelegate { } - void BeginInlineCoreInstance(uint32_t argument_count) + void BeginInlineCoreInstance(uint32_t argumentCount) { } @@ -77,30 +302,43 @@ class WASMComponentBinaryReader : public wabt::WASMComponentBinaryReaderDelegate { } - void BeginInstance(Index component_index, - uint32_t argument_count) + void BeginInstance(Index componentIndex, + uint32_t argumentCount) { + m_currentInfo->instanceTypes.push_back(m_currentInfo->componentTypes[componentIndex]); + m_currentComponent->pushDeclaration(new Walrus::ComponentInstantiate(componentIndex)); } void OnInstanceArg(const ComponentStringLoc& name, ComponentSort sort, Index index) { + Walrus::ComponentInstantiate* instance = m_currentComponent->declarations().back()->asInstantiate(); + instance->arguments().push_back(Walrus::ComponentInstantiate::Argument{ name.str.to_string(), getSort(sort), index }); } void EndInstance() { } - void BeginInlineInstance(uint32_t argument_count) + void BeginInlineInstance(uint32_t argumentCount) { + m_currentComponent->pushDeclaration(new Walrus::ComponentInstantiateInline()); } void OnInlineInstanceArg(const ComponentStringLoc& name, - nonstd::string_view* version_suffix, + nonstd::string_view* versionSuffix, ComponentSort sort, Index index) { + Walrus::ComponentRefCounted* type = getTypeRef(sort, index); + if (type == nullptr) { + return; + } + type->addRef(); + Walrus::ComponentInstantiateInline* instance = m_currentComponent->declarations().back()->asInstantiateInline(); + instance->type()->exports().push_back(Walrus::ComponentType::External{ name.str.to_string(), type }); + instance->arguments().push_back(Walrus::ComponentInstantiateInline::Argument{ getSort(sort), index }); } void EndInlineInstance() @@ -108,13 +346,36 @@ class WASMComponentBinaryReader : public wabt::WASMComponentBinaryReaderDelegate } void OnAliasExport(ComponentSort sort, - Index instance_index, + Index instanceIndex, const ComponentStringLoc& name) { + for (auto it : m_currentInfo->instanceTypes[instanceIndex]->exports()) { + if (name.str == it.name) { + switch (sort) { + case ComponentSort::Func: + m_currentInfo->funcTypes.push_back(it.type->asTypeFunc()); + break; + case ComponentSort::Type: + it.type->addRef(); + m_current->pushType(it.type); + break; + case ComponentSort::Component: + m_currentInfo->componentTypes.push_back(it.type->asComponentType()); + break; + case ComponentSort::Instance: + m_currentInfo->instanceTypes.push_back(it.type->asComponentType()); + break; + default: + ASSERT(sort == ComponentSort::CoreModule); + break; + } + return; + } + } } void OnAliasCoreExport(ComponentSort sort, - Index core_instance_index, + Index coreInstanceIndex, const ComponentStringLoc& name) { } @@ -123,32 +384,55 @@ class WASMComponentBinaryReader : public wabt::WASMComponentBinaryReaderDelegate uint32_t counter, uint32_t index) { + ComponentTypeInfo* info = m_currentInfo; + Walrus::ComponentType* target = m_current; + + while (counter > 0) { + target = info->parentComponentType; + info = info->parent; + counter--; + } + + if (sort == ComponentSort::Type) { + Walrus::ComponentRefCounted* type = target->getType(index); + type->addRef(); + m_current->pushType(type); + } else if (sort == ComponentSort::Component) { + m_currentInfo->componentTypes.push_back(info->componentTypes[index]); + } } void OnPrimitiveType(const ComponentType& type) { + m_current->pushType(new Walrus::ComponentValueType(getValueType(type))); } - void BeginRecordType(uint32_t field_count) + void BeginRecordType(uint32_t fieldCount) { + m_current->pushType(new Walrus::ComponentTypeItems(Walrus::ComponentRefCounted::RecordKind)); } - void OnRecordField(const ComponentStringLoc& field_name, - const ComponentType& field_type) + void OnRecordField(const ComponentStringLoc& fieldName, + const ComponentType& fieldType) { + Walrus::ComponentTypeRef ref = refType(fieldType); + m_current->lastType()->asTypeItems()->items().push_back(Walrus::ComponentTypeItems::Item{ fieldName.str.to_string(), ref }); } void EndRecordType() { } - void BeginVariantType(uint32_t case_count) + void BeginVariantType(uint32_t caseCount) { + m_current->pushType(new Walrus::ComponentTypeItems(Walrus::ComponentRefCounted::VariantKind)); } - void OnVariantCase(const ComponentStringLoc& case_name, - const ComponentType& case_type) + void OnVariantCase(const ComponentStringLoc& caseName, + const ComponentType& caseType) { + Walrus::ComponentTypeRef ref = refAnyType(caseType); + m_current->lastType()->asTypeItems()->items().push_back(Walrus::ComponentTypeItems::Item{ caseName.str.to_string(), ref }); } void EndVariantType() @@ -157,43 +441,51 @@ class WASMComponentBinaryReader : public wabt::WASMComponentBinaryReaderDelegate void OnListType(const ComponentType& type) { + m_current->pushType(new Walrus::ComponentValueTypeRef(Walrus::ComponentRefCounted::ListKind, refType(type))); } void OnListFixedType(const ComponentType& type, uint32_t size) { + m_current->pushType(new Walrus::ComponentTypeListFixed(refType(type), size)); } - void BeginTupleType(uint32_t item_count) + void BeginTupleType(uint32_t itemCount) { + m_current->pushType(new Walrus::ComponentTypeTuple()); } void OnTupleItem(const ComponentType& item) { + m_current->lastType()->asTypeTuple()->items().push_back(refType(item)); } void EndTupleType() { } - void BeginFlagsType(uint32_t label_count) + void BeginFlagsType(uint32_t labelCount) { + m_current->pushType(new Walrus::ComponentTypeLabels(Walrus::ComponentRefCounted::FlagsKind)); } void OnFlagsLabel(const ComponentStringLoc& label) { + m_current->lastType()->asTypeLabels()->labels().push_back(label.str.to_string()); } void EndFlagsType() { } - void BeginEnumType(uint32_t label_count) + void BeginEnumType(uint32_t labelCount) { + m_current->pushType(new Walrus::ComponentTypeLabels(Walrus::ComponentRefCounted::EnumKind)); } void OnEnumLabel(const ComponentStringLoc& label) { + m_current->lastType()->asTypeLabels()->labels().push_back(label.str.to_string()); } void EndEnumType() @@ -202,41 +494,59 @@ class WASMComponentBinaryReader : public wabt::WASMComponentBinaryReaderDelegate void OnOptionType(const ComponentType& type) { + m_current->pushType(new Walrus::ComponentValueTypeRef(Walrus::ComponentRefCounted::OptionKind, refType(type))); } - void OnResultType(const ComponentType& result_type, - const ComponentType& error_type) + void OnResultType(const ComponentType& resultType, + const ComponentType& errorType) { + m_current->pushType(new Walrus::ComponentTypeResult(refAnyType(resultType), refAnyType(errorType))); } void OnOwnType(Index index) { + Walrus::ComponentTypeResource* ref = m_current->getType(index)->asTypeResource(); + ref->addRef(); + m_current->pushType(new Walrus::ComponentTypeResourceRef(Walrus::ComponentRefCounted::OwnKind, ref)); } void OnBorrowType(Index index) { + Walrus::ComponentTypeResource* ref = m_current->getType(index)->asTypeResource(); + ref->addRef(); + m_current->pushType(new Walrus::ComponentTypeResourceRef(Walrus::ComponentRefCounted::BorrowKind, ref)); } void OnStreamType(const ComponentType& type) { + m_current->pushType(new Walrus::ComponentValueTypeRef(Walrus::ComponentRefCounted::StreamKind, refType(type))); } void OnFutureType(const ComponentType& type) { + m_current->pushType(new Walrus::ComponentValueTypeRef(Walrus::ComponentRefCounted::FutureKind, refType(type))); } void BeginFuncType(ComponentTypeDef type, - uint32_t param_count) + uint32_t paramCount) { + Walrus::ComponentRefCounted::Kind kind = Walrus::ComponentRefCounted::FuncKind; + if (type == ComponentTypeDef::AsyncFunc) { + kind = Walrus::ComponentRefCounted::AsyncFuncKind; + } + m_current->pushType(new Walrus::ComponentTypeFunc(kind)); } void OnFuncParam(ComponentStringLoc name, const ComponentType& type) { + Walrus::ComponentTypeRef ref = refType(type); + m_current->lastType()->asTypeFunc()->params().push_back(Walrus::ComponentTypeFunc::Param{ name.str.to_string(), ref }); } void OnFuncResult(const ComponentType& type) { + m_current->lastType()->asTypeFunc()->result() = refAnyType(type); } void EndFuncType() @@ -246,60 +556,123 @@ class WASMComponentBinaryReader : public wabt::WASMComponentBinaryReaderDelegate void OnResourceType(ComponentResourceRep rep, Index dtor) { + m_current->pushType(new Walrus::ComponentTypeResource(Walrus::ComponentRefCounted::ResourceKind, rep == ComponentResourceRep::I64)); } void OnResourceAsyncType(ComponentResourceRep rep, Index dtor, Index callback) { + m_current->pushType(new Walrus::ComponentTypeResource(Walrus::ComponentRefCounted::ResourceAsyncKind, rep == ComponentResourceRep::I64)); } void BeginInstanceType(uint32_t count) { + ASSERT(m_currentInfo != nullptr || m_current == nullptr); + Walrus::ComponentType* current = m_current; + m_currentInfo = new ComponentTypeInfo(m_currentInfo, m_current, m_currentComponent); + m_current = new Walrus::ComponentType(Walrus::ComponentRefCounted::InstanceTypeKind); + m_currentComponent = nullptr; + current->pushType(m_current); } void EndInstanceType() { + ComponentTypeInfo* info = m_currentInfo; + m_current = m_currentInfo->parentComponentType; + m_currentComponent = m_currentInfo->parentComponent; + ASSERT(m_currentComponent == nullptr || m_currentComponent->type() == m_current); + m_currentInfo = m_currentInfo->parent; + delete info; } void BeginComponentType(uint32_t count) { + ASSERT(m_currentInfo != nullptr || m_current == nullptr); + Walrus::ComponentType* current = m_current; + m_currentInfo = new ComponentTypeInfo(m_currentInfo, m_current, m_currentComponent); + m_current = new Walrus::ComponentType(Walrus::ComponentRefCounted::ComponentTypeKind); + m_currentComponent = nullptr; + current->pushType(m_current); } void EndComponentType() { + ComponentTypeInfo* info = m_currentInfo; + m_current = m_currentInfo->parentComponentType; + m_currentComponent = m_currentInfo->parentComponent; + ASSERT(m_currentComponent == nullptr || m_currentComponent->type() == m_current); + m_currentInfo = m_currentInfo->parent; + delete info; } - void OnCanonLift(Index core_func_index, - uint32_t option_count, + void OnCanonLift(Index coreFuncIndex, + uint32_t optionCount, ComponentCanonOption* options, - Index type_index) + Index typeIndex) { + Walrus::CanonicalOptions canonOptions = parseCanonOptions(optionCount, options); + Walrus::ComponentTypeFunc* funcType = m_current->getType(typeIndex)->asTypeFunc(); + m_currentComponent->pushDeclaration(new Walrus::ComponentCanonLift(coreFuncIndex, canonOptions, funcType)); + m_currentInfo->funcTypes.push_back(funcType); } - void OnCanonLower(Index func_index, - uint32_t option_count, + void OnCanonLower(Index funcIndex, + uint32_t optionCount, ComponentCanonOption* options) { + Walrus::CanonicalOptions canonOptions = parseCanonOptions(optionCount, options); + m_currentComponent->pushDeclaration(new Walrus::ComponentCanonLower(funcIndex, canonOptions)); } void OnCanonType(ComponentCanon canon, - Index type_index) + Index typeIndex) { + Walrus::ComponentDeclaration::Kind kind = Walrus::ComponentDeclaration::CanonResourceNew; + if (canon == ComponentCanon::ResourceDrop) { + kind = Walrus::ComponentDeclaration::CanonResourceDrop; + } else if (canon == ComponentCanon::ResourceRep) { + kind = Walrus::ComponentDeclaration::CanonResourceRep; + } + + Walrus::ComponentRefCounted* ref = m_current->getType(typeIndex); + m_currentComponent->pushDeclaration(new Walrus::ComponentCanonType(kind, ref)); } void OnImport(const ComponentStringLoc& name, - nonstd::string_view* version_suffix, - const ComponentExternalInfo& external_info) + nonstd::string_view* versionSuffix, + const ComponentExternalInfo& externalInfo) { + if (m_currentComponent != nullptr) { + m_currentComponent->pushDeclaration(new Walrus::ComponentImport(static_cast(m_current->imports().size()))); + } + m_current->imports().push_back(Walrus::ComponentType::External{ name.str.to_string(), pushExternalType(externalInfo) }); } void OnExport(const ComponentStringLoc& name, - nonstd::string_view* version_suffix, - ComponentExternalInfo* external_info, - ComponentExportInfo* export_info) + nonstd::string_view* versionSuffix, + ComponentExternalInfo* externalInfo, + ComponentExportInfo* exportInfo) + { + if (externalInfo != nullptr) { + m_current->exports().push_back(Walrus::ComponentType::External{ name.str.to_string(), pushExternalType(*externalInfo) }); + return; + } + + ComponentExternalInfo info{ exportInfo->sort, ComponentExternalDesc::Unused, exportInfo->index }; + m_current->exports().push_back(Walrus::ComponentType::External{ name.str.to_string(), pushExternalType(info) }); + } + + Walrus::Component* parsingResult() { + return m_currentComponent; } + +private: + Walrus::TypeStore& m_typeStore; + Walrus::ComponentType* m_current; + Walrus::Component* m_currentComponent; + ComponentTypeInfo* m_currentInfo; }; } // namespace wabt @@ -315,6 +688,7 @@ std::pair, std::string> WASMComponentParser::parseBinary(St return std::make_pair(nullptr, error); } + delete delegate.parsingResult(); return std::make_pair(nullptr, std::string()); } diff --git a/src/runtime/Component.cpp b/src/runtime/Component.cpp new file mode 100644 index 000000000..d21a9ff07 --- /dev/null +++ b/src/runtime/Component.cpp @@ -0,0 +1,94 @@ +/* + * Copyright (c) 2022-present Samsung Electronics Co., Ltd + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#include "Walrus.h" + +#include "Component.h" + +namespace Walrus { + +void ComponentRefCounted::releaseAllRefs(ComponentRefCounted* ref) +{ + ref->m_nextFree = nullptr; + do { + switch (ref->kind()) { + case RecordKind: + case VariantKind: + for (auto& it : ref->asTypeItems()->items()) { + releaseAndInsert(ref, it.type.ref()); + } + break; + case ListKind: + case OptionKind: + case StreamKind: + case FutureKind: + releaseAndInsert(ref, ref->asValueTypeRef()->type().ref()); + break; + case ListFixedKind: + releaseAndInsert(ref, ref->asTypeListFixed()->type().ref()); + break; + case TupleKind: + for (auto& it : ref->asTypeTuple()->items()) { + releaseAndInsert(ref, it.ref()); + } + break; + case ResultKind: + releaseAndInsert(ref, ref->asTypeResult()->result().ref()); + releaseAndInsert(ref, ref->asTypeResult()->error().ref()); + break; + case OwnKind: + case BorrowKind: + releaseAndInsert(ref, ref->asTypeResourceRef()->ref()); + break; + case FuncKind: + for (auto& it : ref->asTypeFunc()->params()) { + releaseAndInsert(ref, it.type.ref()); + } + releaseAndInsert(ref, ref->asTypeFunc()->result().ref()); + break; + case InstanceTypeKind: + case ComponentTypeKind: { + ComponentType* componentType = ref->asComponentType(); + for (auto& it : componentType->types()) { + releaseAndInsert(ref, it); + } + for (auto& it : componentType->exports()) { + releaseAndInsert(ref, it.type); + } + for (auto& it : componentType->imports()) { + releaseAndInsert(ref, it.type); + } + break; + } + default: + ASSERT(ref->isValueType() || ref->isTypeLabels() || ref->isTypeResource()); + break; + } + + ComponentRefCounted* nextRef = ref->m_nextFree; + delete ref; + ref = nextRef; + } while (ref != nullptr); +} + +Component::~Component() +{ + for (auto it : m_declarations) { + delete it; + } + m_type->releaseRef(); +} + +} // namespace Walrus diff --git a/src/runtime/Component.h b/src/runtime/Component.h index ef814ae2b..2058fc7a8 100644 --- a/src/runtime/Component.h +++ b/src/runtime/Component.h @@ -25,11 +25,820 @@ class WASMComponentBinaryReader; namespace Walrus { -class Component { +enum class ComponentSort : uint8_t { + CoreFunc, + CoreTable, + CoreMemory, + CoreGlobal, + CoreType, + CoreModule, + CoreInstance, + Func, + Value, + Type, + Component, + Instance, + Invalid, +}; + +class ComponentValueType; +class ComponentValueTypeRef; +class ComponentTypeItems; +class ComponentTypeListFixed; +class ComponentTypeTuple; +class ComponentTypeLabels; +class ComponentTypeResult; +class ComponentTypeFunc; +class ComponentTypeResource; +class ComponentTypeResourceRef; +class ComponentType; + +class ComponentRefCounted { +public: + enum Kind : uint8_t { + ValueTypeKind, + RecordKind, + VariantKind, + ListKind, + ListFixedKind, + TupleKind, + FlagsKind, + EnumKind, + OptionKind, + ResultKind, + OwnKind, + BorrowKind, + StreamKind, + FutureKind, + FuncKind, + AsyncFuncKind, + InstanceTypeKind, + ComponentTypeKind, + InstanceKind, + ResourceKind, + ResourceAsyncKind, + }; + + ComponentRefCounted(Kind kind) + : m_refCount(1) + , m_kind(kind) + { + } + + virtual ~ComponentRefCounted() {} + + void addRef() + { + ASSERT(m_refCount > 0); + m_refCount++; + } + + void releaseRef() + { + ASSERT(m_refCount > 0); + m_refCount--; + if (m_refCount == 0) { + releaseAllRefs(this); + } + } + + Kind kind() const + { + return m_kind; + } + + bool isValueType() const + { + return kind() == ValueTypeKind; + } + + ComponentValueType* asValueType() + { + ASSERT(isValueType()); + return reinterpret_cast(this); + } + + bool isValueTypeRef() const + { + return kind() == ListKind || kind() == OptionKind + || kind() == StreamKind || kind() == FutureKind; + } + + ComponentValueTypeRef* asValueTypeRef() + { + ASSERT(isValueTypeRef()); + return reinterpret_cast(this); + } + + bool isTypeItems() const + { + return kind() == RecordKind || kind() == VariantKind; + } + + ComponentTypeItems* asTypeItems() + { + ASSERT(isTypeItems()); + return reinterpret_cast(this); + } + + ComponentTypeListFixed* asTypeListFixed() + { + ASSERT(kind() == ListFixedKind); + return reinterpret_cast(this); + } + + ComponentTypeTuple* asTypeTuple() + { + ASSERT(kind() == TupleKind); + return reinterpret_cast(this); + } + + bool isTypeLabels() const + { + return kind() == FlagsKind || kind() == EnumKind; + } + + ComponentTypeLabels* asTypeLabels() + { + ASSERT(isTypeLabels()); + return reinterpret_cast(this); + } + + ComponentTypeResult* asTypeResult() + { + ASSERT(kind() == ResultKind); + return reinterpret_cast(this); + } + + bool isTypeResourceRef() const + { + return kind() == OwnKind || kind() == BorrowKind; + } + + ComponentTypeResourceRef* asTypeResourceRef() + { + ASSERT(isTypeResourceRef()); + return reinterpret_cast(this); + } + + bool isTypeFunc() const + { + return kind() == FuncKind || kind() == AsyncFuncKind; + } + + ComponentTypeFunc* asTypeFunc() + { + ASSERT(isTypeFunc()); + return reinterpret_cast(this); + } + + bool isTypeResource() const + { + return kind() == ResourceKind || kind() == ResourceAsyncKind; + } + + ComponentTypeResource* asTypeResource() + { + ASSERT(isTypeResource()); + return reinterpret_cast(this); + } + + bool isComponentType() const + { + return kind() == InstanceTypeKind || kind() == ComponentTypeKind; + } + + ComponentType* asComponentType() + { + ASSERT(isComponentType()); + return reinterpret_cast(this); + } + +private: + static void releaseAndInsert(ComponentRefCounted* current, ComponentRefCounted* ref) + { + if (ref != nullptr) { + ref->m_refCount--; + if (ref->m_refCount == 0) { + ref->m_nextFree = current->m_nextFree; + current->m_nextFree = ref; + } + } + } + + static void releaseAllRefs(ComponentRefCounted* ref); + + union { + size_t m_refCount; + // Only used during object destruction. + ComponentRefCounted* m_nextFree; + }; + Kind m_kind; +}; + +class ComponentTypeRef { +public: + enum Type : uint8_t { + Bool, + S8, + U8, + S16, + U16, + S32, + U32, + S64, + U64, + F32, + F64, + Char, + String, + ErrorContext, + + TypeIndex, + TypeNone, + }; + + ComponentTypeRef() + : m_type(TypeNone) + , m_ref(nullptr) + { + } + + ComponentTypeRef(ComponentRefCounted* ref) + : m_type(TypeIndex) + , m_ref(ref) + { + } + + ComponentTypeRef(Type type) + : m_type(type) + , m_ref(nullptr) + { + ASSERT(type != TypeIndex && type != TypeNone); + } + + Type type() const { return m_type; } + ComponentRefCounted* ref() const { return m_ref; } + + bool equals(const ComponentTypeRef& other) const + { + return m_type == other.m_type && m_ref == other.m_ref; + } + +private: + Type m_type; + ComponentRefCounted* m_ref; +}; + +class ComponentValueType : public ComponentRefCounted { +public: + ComponentValueType(ComponentTypeRef::Type type) + : ComponentRefCounted(ValueTypeKind) + , m_type(type) + { + ASSERT(type != ComponentTypeRef::TypeIndex && type != ComponentTypeRef::TypeNone); + } + +private: + ComponentTypeRef::Type m_type; +}; + +class ComponentValueTypeRef : public ComponentRefCounted { +public: + ComponentValueTypeRef(Kind kind, const ComponentTypeRef& type) + : ComponentRefCounted(kind) + , m_type(type) + { + ASSERT(isValueTypeRef()); + } + + const ComponentTypeRef& type() const + { + return m_type; + } + +private: + ComponentTypeRef m_type; +}; + +class ComponentTypeItems : public ComponentRefCounted { +public: + struct Item { + std::string name; + ComponentTypeRef type; + }; + + ComponentTypeItems(Kind kind) + : ComponentRefCounted(kind) + { + ASSERT(isTypeItems()); + } + + std::vector& items() + { + return m_items; + } + +private: + std::vector m_items; +}; + +class ComponentTypeListFixed : public ComponentRefCounted { +public: + ComponentTypeListFixed(const ComponentTypeRef& type, uint32_t size) + : ComponentRefCounted(ListFixedKind) + , m_type(type) + , m_size(size) + { + } + + const ComponentTypeRef& type() const + { + return m_type; + } + + uint32_t size() const + { + return m_size; + } + +private: + ComponentTypeRef m_type; + uint32_t m_size; +}; + +class ComponentTypeTuple : public ComponentRefCounted { +public: + ComponentTypeTuple() + : ComponentRefCounted(TupleKind) + { + } + + std::vector& items() + { + return m_items; + } + +private: + std::vector m_items; +}; + +class ComponentTypeLabels : public ComponentRefCounted { +public: + ComponentTypeLabels(Kind kind) + : ComponentRefCounted(kind) + { + ASSERT(isTypeLabels()); + } + + std::vector& labels() + { + return m_labels; + } + +private: + std::vector m_labels; +}; + +class ComponentTypeResult : public ComponentRefCounted { +public: + ComponentTypeResult(const ComponentTypeRef& result, const ComponentTypeRef& error) + : ComponentRefCounted(ResultKind) + , m_result(result) + , m_error(error) + { + } + + const ComponentTypeRef& result() const + { + return m_result; + } + + const ComponentTypeRef& error() const + { + return m_error; + } + +private: + ComponentTypeRef m_result; + ComponentTypeRef m_error; +}; + +class ComponentTypeFunc : public ComponentRefCounted { +public: + struct Param { + std::string name; + ComponentTypeRef type; + }; + + ComponentTypeFunc(Kind kind) + : ComponentRefCounted(kind) + { + ASSERT(isTypeFunc()); + } + + std::vector& params() + { + return m_params; + } + + ComponentTypeRef& result() + { + return m_result; + } + +private: + std::vector m_params; + ComponentTypeRef m_result; +}; + +class ComponentTypeResource : public ComponentRefCounted { +public: + ComponentTypeResource(Kind kind, bool i64) + : ComponentRefCounted(kind) + , m_i64(i64) + { + ASSERT(isTypeResource()); + } + + bool i64() const + { + return m_i64; + } + +private: + bool m_i64; +}; + +class ComponentTypeResourceRef : public ComponentRefCounted { +public: + ComponentTypeResourceRef(Kind kind, ComponentTypeResource* ref) + : ComponentRefCounted(kind) + , m_ref(ref) + { + ASSERT(isTypeResourceRef()); + } + + ComponentTypeResource* ref() const + { + return m_ref; + } + +private: + ComponentTypeResource* m_ref; +}; + +// Immutable type declarations for components, instances +class ComponentType : public ComponentRefCounted { +public: + struct External { + std::string name; + ComponentRefCounted* type; + }; + + ComponentType(Kind kind) + : ComponentRefCounted(kind) + { + ASSERT(isComponentType()); + } + + void pushType(ComponentRefCounted* type) + { + m_types.push_back(type); + } + + ComponentRefCounted* getType(size_t index) + { + return m_types[index]; + } + + ComponentRefCounted* lastType() + { + ASSERT(m_types.size() > 0); + return m_types.back(); + } + + std::vector& types() + { + return m_types; + } + + std::vector& exports() + { + return m_exports; + } + + std::vector& imports() + { + return m_imports; + } + +private: + std::vector m_types; + std::vector m_exports; + std::vector m_imports; +}; + +class CanonicalOptions { +public: + enum StringEncoding { + Utf8, + Utf16, + Latin1Utf16, + }; + + static constexpr uint32_t NoIndex = ~static_cast(0); + + CanonicalOptions(StringEncoding encoding, bool isAsync, uint32_t memoryIndex, + uint32_t reallocIndex, uint32_t postReturnIndex, uint32_t callbackIndex) + : m_encoding(encoding) + , m_isAsync(isAsync) + , m_memoryIndex(memoryIndex) + , m_reallocIndex(reallocIndex) + , m_postReturnIndex(postReturnIndex) + , m_callbackIndex(callbackIndex) + { + } + + StringEncoding encoding() const + { + return m_encoding; + } + + uint32_t memoryIndex() const + { + return m_memoryIndex; + } + + uint32_t reallocIndex() const + { + return m_reallocIndex; + } + + uint32_t postReturnIndex() const + { + return m_postReturnIndex; + } + +private: + StringEncoding m_encoding; + bool m_isAsync; + uint32_t m_memoryIndex; + uint32_t m_reallocIndex; + uint32_t m_postReturnIndex; + uint32_t m_callbackIndex; +}; + +class ComponentInstantiate; +class ComponentInstantiateInline; +class ComponentCanonLift; +class ComponentCanonLower; +class ComponentCanonType; + +class ComponentDeclaration { +public: + enum Kind : uint8_t { + ComponentKind, + InstantiateKind, + InstantiateInlineKind, + CanonLiftKind, + CanonLowerKind, + CanonResourceNew, + CanonResourceDrop, + CanonResourceRep, + ImportKind, + }; + + ComponentDeclaration(Kind kind) + : m_kind(kind) + { + } + + virtual ~ComponentDeclaration() {} + + Kind kind() const + { + return m_kind; + } + + ComponentInstantiate* asInstantiate() + { + ASSERT(kind() == InstantiateKind); + return reinterpret_cast(this); + } + + ComponentInstantiateInline* asInstantiateInline() + { + ASSERT(kind() == InstantiateInlineKind); + return reinterpret_cast(this); + } + + ComponentCanonLift* asCanonLift() + { + ASSERT(kind() == CanonLiftKind); + return reinterpret_cast(this); + } + + ComponentCanonLower* asCanonLower() + { + ASSERT(kind() == CanonLowerKind); + return reinterpret_cast(this); + } + + bool isCanonType() + { + return kind() == CanonResourceNew || kind() == CanonResourceDrop || kind() == CanonResourceRep; + } + + ComponentCanonType* asCanonType() + { + ASSERT(isCanonType()); + return reinterpret_cast(this); + } + +private: + Kind m_kind; +}; + +class ComponentInstantiate : public ComponentDeclaration { +public: + struct Argument { + std::string name; + ComponentSort sort; + uint32_t index; + }; + + ComponentInstantiate(uint32_t componentIndex) + : ComponentDeclaration(InstantiateKind) + , m_componentIndex(componentIndex) + { + } + + uint32_t componentIndex() + { + return m_componentIndex; + } + + std::vector& arguments() + { + return m_arguments; + } + +private: + uint32_t m_componentIndex; + std::vector m_arguments; +}; + +class ComponentInstantiateInline : public ComponentDeclaration { +public: + struct Argument { + ComponentSort sort; + uint32_t index; + }; + + ComponentInstantiateInline() + : ComponentDeclaration(InstantiateInlineKind) + { + m_type = new ComponentType(ComponentRefCounted::InstanceTypeKind); + } + + ComponentType* type() + { + return m_type; + } + + std::vector& arguments() + { + return m_arguments; + } + +private: + ComponentType* m_type; + std::vector m_arguments; +}; + +class ComponentCanonLift : public ComponentDeclaration { +public: + ComponentCanonLift(uint32_t coreFuncIndex, const CanonicalOptions& options, ComponentTypeFunc* funcType) + : ComponentDeclaration(CanonLiftKind) + , m_options(options) + , m_coreFuncIndex(coreFuncIndex) + , m_funcType(funcType) + { + } + + const CanonicalOptions& options() const + { + return m_options; + } + + uint32_t coreFuncIndex() const + { + return m_coreFuncIndex; + } + + ComponentTypeFunc* funcType() const + { + return m_funcType; + } + +private: + CanonicalOptions m_options; + uint32_t m_coreFuncIndex; + ComponentTypeFunc* m_funcType; +}; + +class ComponentCanonLower : public ComponentDeclaration { +public: + ComponentCanonLower(uint32_t funcIndex, const CanonicalOptions& options) + : ComponentDeclaration(CanonLowerKind) + , m_options(options) + , m_funcIndex(funcIndex) + { + } + + const CanonicalOptions& options() const + { + return m_options; + } + + uint32_t funcIndex() const + { + return m_funcIndex; + } + +private: + CanonicalOptions m_options; + uint32_t m_funcIndex; +}; + +class ComponentCanonType : public ComponentDeclaration { +public: + ComponentCanonType(Kind kind, ComponentRefCounted* type) + : ComponentDeclaration(kind) + , m_type(type) + { + ASSERT(isCanonType()); + type->addRef(); + } + + ~ComponentCanonType() + { + m_type->releaseRef(); + } + +private: + ComponentRefCounted* m_type; +}; + +class ComponentImport : public ComponentDeclaration { +public: + ComponentImport(uint32_t importIndex) + : ComponentDeclaration(ImportKind) + , m_importIndex(importIndex) + { + } + + uint32_t importIndex() const + { + return m_importIndex; + } + +private: + uint32_t m_importIndex; +}; + +class Component : public ComponentDeclaration { friend class wabt::WASMComponentBinaryReader; public: - virtual ~Component() {} + Component() + : ComponentDeclaration(ComponentKind) + { + m_type = new ComponentType(ComponentRefCounted::ComponentTypeKind); + } + + ~Component(); + + ComponentType* type() + { + return m_type; + } + + void pushDeclaration(ComponentDeclaration* declaration) + { + m_declarations.push_back(declaration); + } + + std::vector& declarations() + { + return m_declarations; + } + +private: + // Declarations for instantiation. + ComponentType* m_type; + std::vector m_declarations; }; } // namespace Walrus diff --git a/third_party/wabt/include/wabt/walrus/binary-reader-walrus.h b/third_party/wabt/include/wabt/walrus/binary-reader-walrus.h index 055bfabe1..d1ed45bb4 100644 --- a/third_party/wabt/include/wabt/walrus/binary-reader-walrus.h +++ b/third_party/wabt/include/wabt/walrus/binary-reader-walrus.h @@ -255,71 +255,71 @@ class WASMComponentBinaryReaderDelegate { virtual void BeginComponent(uint32_t version, size_t depth) = 0; virtual void EndComponent() = 0; - virtual void BeginCoreInstance(Index module_index, - uint32_t argument_count) = 0; + virtual void BeginCoreInstance(Index moduleIndex, + uint32_t argumentCount) = 0; virtual void OnCoreInstanceArg(const ComponentStringLoc& name, ComponentSort sort, Index index) = 0; virtual void EndCoreInstance() = 0; - virtual void BeginInlineCoreInstance(uint32_t argument_count) = 0; + virtual void BeginInlineCoreInstance(uint32_t argumentCount) = 0; virtual void OnInlineCoreInstanceArg(const ComponentStringLoc& name, ComponentSort sort, Index index) = 0; virtual void EndInlineCoreInstance() = 0; - virtual void BeginInstance(Index component_index, - uint32_t argument_count) = 0; + virtual void BeginInstance(Index componentIndex, + uint32_t argumentCount) = 0; virtual void OnInstanceArg(const ComponentStringLoc& name, ComponentSort sort, Index index) = 0; virtual void EndInstance() = 0; - virtual void BeginInlineInstance(uint32_t argument_count) = 0; + virtual void BeginInlineInstance(uint32_t argumentCount) = 0; virtual void OnInlineInstanceArg(const ComponentStringLoc& name, - nonstd::string_view* version_suffix, + nonstd::string_view* versionSuffix, ComponentSort sort, Index index) = 0; virtual void EndInlineInstance() = 0; virtual void OnAliasExport(ComponentSort sort, - Index instance_index, + Index instanceIndex, const ComponentStringLoc& name) = 0; virtual void OnAliasCoreExport(ComponentSort sort, - Index core_instance_index, + Index coreInstanceIndex, const ComponentStringLoc& name) = 0; virtual void OnAliasOuter(ComponentSort sort, uint32_t counter, uint32_t index) = 0; virtual void OnPrimitiveType(const ComponentType& type) = 0; - virtual void BeginRecordType(uint32_t field_count) = 0; - virtual void OnRecordField(const ComponentStringLoc& field_name, - const ComponentType& field_type) = 0; + virtual void BeginRecordType(uint32_t fieldCount) = 0; + virtual void OnRecordField(const ComponentStringLoc& fieldName, + const ComponentType& fieldType) = 0; virtual void EndRecordType() = 0; - virtual void BeginVariantType(uint32_t case_count) = 0; - virtual void OnVariantCase(const ComponentStringLoc& case_name, - const ComponentType& case_type) = 0; + virtual void BeginVariantType(uint32_t caseCount) = 0; + virtual void OnVariantCase(const ComponentStringLoc& caseName, + const ComponentType& caseType) = 0; virtual void EndVariantType() = 0; virtual void OnListType(const ComponentType& type) = 0; virtual void OnListFixedType(const ComponentType& type, uint32_t size) = 0; - virtual void BeginTupleType(uint32_t item_count) = 0; + virtual void BeginTupleType(uint32_t itemCount) = 0; virtual void OnTupleItem(const ComponentType& item) = 0; virtual void EndTupleType() = 0; - virtual void BeginFlagsType(uint32_t label_count) = 0; + virtual void BeginFlagsType(uint32_t labelCount) = 0; virtual void OnFlagsLabel(const ComponentStringLoc& label) = 0; virtual void EndFlagsType() = 0; - virtual void BeginEnumType(uint32_t label_count) = 0; + virtual void BeginEnumType(uint32_t labelCount) = 0; virtual void OnEnumLabel(const ComponentStringLoc& label) = 0; virtual void EndEnumType() = 0; virtual void OnOptionType(const ComponentType& type) = 0; - virtual void OnResultType(const ComponentType& result_type, - const ComponentType& error_type) = 0; + virtual void OnResultType(const ComponentType& resultType, + const ComponentType& errorType) = 0; virtual void OnOwnType(Index index) = 0; virtual void OnBorrowType(Index index) = 0; virtual void OnStreamType(const ComponentType& type) = 0; virtual void OnFutureType(const ComponentType& type) = 0; virtual void BeginFuncType(ComponentTypeDef type, - uint32_t param_count) = 0; + uint32_t paramCount) = 0; virtual void OnFuncParam(ComponentStringLoc name, const ComponentType& type) = 0; virtual void OnFuncResult(const ComponentType& type) = 0; @@ -334,24 +334,24 @@ class WASMComponentBinaryReaderDelegate { virtual void BeginComponentType(uint32_t count) = 0; virtual void EndComponentType() = 0; - virtual void OnCanonLift(Index core_func_index, - uint32_t option_count, + virtual void OnCanonLift(Index coreFuncIndex, + uint32_t optionCount, ComponentCanonOption* options, - Index type_index) = 0; - virtual void OnCanonLower(Index func_index, - uint32_t option_count, + Index typeIndex) = 0; + virtual void OnCanonLower(Index funcIndex, + uint32_t optionCount, ComponentCanonOption* options) = 0; virtual void OnCanonType(ComponentCanon canon, - Index type_index) = 0; + Index typeIndex) = 0; virtual void OnImport(const ComponentStringLoc& name, - nonstd::string_view* version_suffix, - const ComponentExternalInfo& external_info) = 0; + nonstd::string_view* versionSuffix, + const ComponentExternalInfo& externalInfo) = 0; virtual void OnExport(const ComponentStringLoc& name, - nonstd::string_view* version_suffix, - ComponentExternalInfo* external_info, - ComponentExportInfo* export_info) = 0; + nonstd::string_view* versionSuffix, + ComponentExternalInfo* externalInfo, + ComponentExportInfo* exportInfo) = 0; const std::string& WalrusParseError() {